Initial 800x480 cabbiev2 port, based on 480x800x16 one
[kugel-rb.git] / apps / metadata / oma.c
blobb82c0a4f734559978754ea98c6e8ecd158c76dd9
1 /*
2 * Sony OpenMG (OMA) demuxer
4 * Copyright (c) 2008 Maxim Poliakovski
5 * 2008 Benjamin Larsson
7 * This file is part of FFmpeg.
9 * FFmpeg is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * FFmpeg is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with FFmpeg; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 /**
25 * @file oma.c
26 * This is a demuxer for Sony OpenMG Music files
28 * Known file extensions: ".oma", "aa3"
29 * The format of such files consists of three parts:
30 * - "ea3" header carrying overall info and metadata.
31 * - "EA3" header is a Sony-specific header containing information about
32 * the OpenMG file: codec type (usually ATRAC, can also be MP3 or WMA),
33 * codec specific info (packet size, sample rate, channels and so on)
34 * and DRM related info (file encryption, content id).
35 * - Sound data organized in packets follow the EA3 header
36 * (can be encrypted using the Sony DRM!).
38 * LIMITATIONS: This version supports only plain (unencrypted) OMA files.
39 * If any DRM-protected (encrypted) file is encountered you will get the
40 * corresponding error message. Try to remove the encryption using any
41 * Sony software (for example SonicStage).
42 * CODEC SUPPORT: Only ATRAC3 codec is currently supported!
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <inttypes.h>
48 #include <string.h>
49 #include "metadata.h"
50 #include "metadata_parsers.h"
52 #define EA3_HEADER_SIZE 96
54 #if 0
55 #define DEBUGF printf
56 #else
57 #define DEBUGF(...)
58 #endif
60 /* Various helper macros taken from ffmpeg for reading *
61 * and writing buffers with a specified endianess. */
62 # define AV_RB16(x) \
63 ((((const uint8_t*)(x))[0] << 8) | \
64 ((const uint8_t*)(x))[1])
65 # define AV_RB24(x) \
66 ((((const uint8_t*)(x))[0] << 16) | \
67 (((const uint8_t*)(x))[1] << 8) | \
68 ((const uint8_t*)(x))[2])
69 # define AV_RB32(x) \
70 ((((const uint8_t*)(x))[0] << 24) | \
71 (((const uint8_t*)(x))[1] << 16) | \
72 (((const uint8_t*)(x))[2] << 8) | \
73 ((const uint8_t*)(x))[3])
74 # define AV_WL32(p, d) do { \
75 ((uint8_t*)(p))[0] = (d); \
76 ((uint8_t*)(p))[1] = (d)>>8; \
77 ((uint8_t*)(p))[2] = (d)>>16; \
78 ((uint8_t*)(p))[3] = (d)>>24; \
79 } while(0)
80 # define AV_WL16(p, d) do { \
81 ((uint8_t*)(p))[0] = (d); \
82 ((uint8_t*)(p))[1] = (d)>>8; \
83 } while(0)
85 /* Different codecs that could be present in a Sony OMA *
86 * container file. */
87 enum {
88 OMA_CODECID_ATRAC3 = 0,
89 OMA_CODECID_ATRAC3P = 1,
90 OMA_CODECID_MP3 = 3,
91 OMA_CODECID_LPCM = 4,
92 OMA_CODECID_WMA = 5,
95 /* FIXME: This functions currently read different file *
96 * parameters required for decoding. It still *
97 * does not read the metadata - which should be *
98 * present in the ea3 (first) header. The *
99 * metadata in ea3 is stored as a variation of *
100 * the ID3v2 metadata format. */
101 static int oma_read_header(int fd, struct mp3entry* id3)
103 static const uint16_t srate_tab[6] = {320,441,480,882,960,0};
104 int ret, ea3_taglen, EA3_pos, jsflag;
105 uint32_t codec_params;
106 int16_t eid;
107 uint8_t buf[EA3_HEADER_SIZE];
109 ret = read(fd, buf, 10);
110 if (ret != 10)
111 return -1;
113 ea3_taglen = ((buf[6] & 0x7f) << 21) | ((buf[7] & 0x7f) << 14) | ((buf[8] & 0x7f) << 7) | (buf[9] & 0x7f);
115 EA3_pos = ea3_taglen + 10;
116 if (buf[5] & 0x10)
117 EA3_pos += 10;
119 lseek(fd, EA3_pos, SEEK_SET);
120 ret = read(fd, buf, EA3_HEADER_SIZE);
121 if (ret != EA3_HEADER_SIZE)
122 return -1;
124 if (memcmp(buf, ((const uint8_t[]){'E', 'A', '3'}),3) || buf[4] != 0 || buf[5] != EA3_HEADER_SIZE) {
125 DEBUGF("Couldn't find the EA3 header !\n");
126 return -1;
129 eid = AV_RB16(&buf[6]);
130 if (eid != -1 && eid != -128) {
131 DEBUGF("Encrypted file! Eid: %d\n", eid);
132 return -1;
135 codec_params = AV_RB24(&buf[33]);
137 switch (buf[32]) {
138 case OMA_CODECID_ATRAC3:
139 id3->frequency = srate_tab[(codec_params >> 13) & 7]*100;
140 if (id3->frequency != 44100) {
141 DEBUGF("Unsupported sample rate, send sample file to developers: %d\n", id3->frequency);
142 return -1;
145 id3->bytesperframe = (codec_params & 0x3FF) * 8;
146 id3->codectype = AFMT_OMA_ATRAC3;
147 jsflag = (codec_params >> 17) & 1; /* get stereo coding mode, 1 for joint-stereo */
149 id3->bitrate = id3->frequency * id3->bytesperframe * 8 / (1024 * 1000);
151 /* fake the atrac3 extradata (wav format, makes stream copy to wav work) */
152 /* ATRAC3 expects and extra-data size of 14 bytes for wav format, and *
153 * looks for that in the id3v2buf. */
154 id3->extradata_size = 14;
155 AV_WL16(&id3->id3v2buf[0], 1); // always 1
156 AV_WL32(&id3->id3v2buf[2], id3->frequency); // samples rate
157 AV_WL16(&id3->id3v2buf[6], jsflag); // coding mode
158 AV_WL16(&id3->id3v2buf[8], jsflag); // coding mode
159 AV_WL16(&id3->id3v2buf[10], 1); // always 1
160 AV_WL16(&id3->id3v2buf[12], 0); // always 0
162 id3->channels = 2;
163 DEBUGF("sample_rate = %d\n", id3->frequency);
164 DEBUGF("frame_size = %d\n", id3->bytesperframe);
165 DEBUGF("stereo_coding_mode = %d\n", jsflag);
166 break;
167 default:
168 DEBUGF("Unsupported codec %d!\n",buf[32]);
169 return -1;
170 break;
173 /* Store the the offset of the first audio frame, to be able to seek to it *
174 * directly in atrac3_oma.codec. */
175 id3->first_frame_offset = EA3_pos + EA3_HEADER_SIZE;
176 return 0;
179 bool get_oma_metadata(int fd, struct mp3entry* id3)
181 if(oma_read_header(fd, id3) < 0)
182 return false;
184 /* Currently, there's no means of knowing the duration *
185 * directly from the the file so we calculate it. */
186 id3->filesize = filesize(fd);
187 id3->length = ((id3->filesize - id3->first_frame_offset) * 8) / id3->bitrate;
188 return true;