diff options
author | Mohamed Tarek <mt@rockbox.org> | 2010-02-12 03:21:37 +0000 |
---|---|---|
committer | Mohamed Tarek <mt@rockbox.org> | 2010-02-12 03:21:37 +0000 |
commit | 23ac6ffaa1efeea6417f7d064c0b8f4f280aa0cd (patch) | |
tree | a8a71c484048b6d199f587875c15a856e8910640 | |
parent | 5039cc716de37035a60cc62585f534dcdd7fa903 (diff) | |
download | rockbox-23ac6ffaa1efeea6417f7d064c0b8f4f280aa0cd.tar.gz rockbox-23ac6ffaa1efeea6417f7d064c0b8f4f280aa0cd.zip |
Add support for Sony OMA file format. Currently only supports ATRAC3 (without DRM), and seeks. Tested on sansa
e200.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@24615 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r-- | apps/SOURCES | 1 | ||||
-rw-r--r-- | apps/codecs/SOURCES | 1 | ||||
-rw-r--r-- | apps/codecs/atrac3_oma.c | 158 | ||||
-rw-r--r-- | apps/codecs/codecs.make | 1 | ||||
-rw-r--r-- | apps/filetypes.c | 2 | ||||
-rw-r--r-- | apps/metadata.c | 10 | ||||
-rw-r--r-- | apps/metadata.h | 1 | ||||
-rw-r--r-- | apps/metadata/metadata_parsers.h | 1 | ||||
-rw-r--r-- | apps/metadata/oma.c | 188 |
9 files changed, 363 insertions, 0 deletions
diff --git a/apps/SOURCES b/apps/SOURCES index f99c2bc640..7580caabc9 100644 --- a/apps/SOURCES +++ b/apps/SOURCES | |||
@@ -181,6 +181,7 @@ metadata/a52.c | |||
181 | metadata/asap.c | 181 | metadata/asap.c |
182 | metadata/rm.c | 182 | metadata/rm.c |
183 | metadata/nsf.c | 183 | metadata/nsf.c |
184 | metadata/oma.c | ||
184 | #endif | 185 | #endif |
185 | #ifdef HAVE_TAGCACHE | 186 | #ifdef HAVE_TAGCACHE |
186 | tagcache.c | 187 | tagcache.c |
diff --git a/apps/codecs/SOURCES b/apps/codecs/SOURCES index 75d74ab33b..4c847c23e0 100644 --- a/apps/codecs/SOURCES +++ b/apps/codecs/SOURCES | |||
@@ -13,6 +13,7 @@ cook.c | |||
13 | raac.c | 13 | raac.c |
14 | a52_rm.c | 14 | a52_rm.c |
15 | atrac3_rm.c | 15 | atrac3_rm.c |
16 | atrac3_oma.c | ||
16 | mpc.c | 17 | mpc.c |
17 | wma.c | 18 | wma.c |
18 | sid.c | 19 | sid.c |
diff --git a/apps/codecs/atrac3_oma.c b/apps/codecs/atrac3_oma.c new file mode 100644 index 0000000000..b080b71524 --- /dev/null +++ b/apps/codecs/atrac3_oma.c | |||
@@ -0,0 +1,158 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2009 Mohamed Tarek | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | |||
22 | #include <string.h> | ||
23 | |||
24 | #include "logf.h" | ||
25 | #include "codeclib.h" | ||
26 | #include "inttypes.h" | ||
27 | #include "libatrac/atrac3.h" | ||
28 | |||
29 | CODEC_HEADER | ||
30 | |||
31 | #define FRAMESIZE ci->id3->bytesperframe | ||
32 | #define BITRATE ci->id3->bitrate | ||
33 | |||
34 | /* The codec has nothing to do with RM, it just uses an RMContext struct to * | ||
35 | * store the data needs to be passed to the decoder initializing function. */ | ||
36 | RMContext rmctx; | ||
37 | ATRAC3Context q IBSS_ATTR; | ||
38 | |||
39 | static void init_rm(RMContext *rmctx, struct mp3entry *id3) | ||
40 | { | ||
41 | rmctx->sample_rate = id3->frequency; | ||
42 | rmctx->nb_channels = 2; | ||
43 | rmctx->bit_rate = id3->bitrate; | ||
44 | rmctx->block_align = id3->bytesperframe; | ||
45 | |||
46 | /* 14-byte extra-data was faked in the metadata parser so that * | ||
47 | * the ATRAC3 decoder would parse it as WAV format extra-data. */ | ||
48 | rmctx->extradata_size = 14; | ||
49 | memcpy(rmctx->codec_extradata, &id3->id3v1buf[0][0], 14); | ||
50 | } | ||
51 | |||
52 | /* this is the codec entry point */ | ||
53 | enum codec_status codec_main(void) | ||
54 | { | ||
55 | static size_t buff_size; | ||
56 | int datasize, res, frame_counter, total_frames, seek_frame_offset; | ||
57 | uint8_t *bit_buffer; | ||
58 | int elapsed = 0; | ||
59 | size_t resume_offset = ci->id3->offset; | ||
60 | |||
61 | next_track: | ||
62 | if (codec_init()) { | ||
63 | DEBUGF("codec init failed\n"); | ||
64 | return CODEC_ERROR; | ||
65 | } | ||
66 | while (!*ci->taginfo_ready && !ci->stop_codec) | ||
67 | ci->sleep(1); | ||
68 | |||
69 | codec_set_replaygain(ci->id3); | ||
70 | ci->memset(&rmctx,0,sizeof(RMContext)); | ||
71 | ci->memset(&q,0,sizeof(ATRAC3Context)); | ||
72 | |||
73 | init_rm(&rmctx, ci->id3); | ||
74 | |||
75 | ci->configure(DSP_SET_FREQUENCY, ci->id3->frequency); | ||
76 | ci->configure(DSP_SET_SAMPLE_DEPTH, 17); /* Remark: atrac3 uses s15.0 by default, s15.2 was hacked. */ | ||
77 | ci->configure(DSP_SET_STEREO_MODE, rmctx.nb_channels == 1 ? | ||
78 | STEREO_MONO : STEREO_NONINTERLEAVED); | ||
79 | |||
80 | res =atrac3_decode_init(&q, &rmctx); | ||
81 | if(res < 0) { | ||
82 | DEBUGF("failed to initialize atrac decoder\n"); | ||
83 | return CODEC_ERROR; | ||
84 | } | ||
85 | |||
86 | /* check for a mid-track resume and force a seek time accordingly */ | ||
87 | if(resume_offset > ci->id3->first_frame_offset) { | ||
88 | resume_offset -= ci->id3->first_frame_offset; | ||
89 | /* calculate resume_offset in frames */ | ||
90 | resume_offset = (int)resume_offset / FRAMESIZE; | ||
91 | ci->seek_time = (int)resume_offset * ((FRAMESIZE * 8)/BITRATE); | ||
92 | } | ||
93 | total_frames = (ci->id3->filesize - ci->id3->first_frame_offset) / FRAMESIZE; | ||
94 | frame_counter = 0; | ||
95 | |||
96 | ci->set_elapsed(0); | ||
97 | ci->advance_buffer(ci->id3->first_frame_offset); | ||
98 | |||
99 | /* The main decoder loop */ | ||
100 | seek_start : | ||
101 | while(frame_counter < total_frames) | ||
102 | { | ||
103 | bit_buffer = (uint8_t *) ci->request_buffer(&buff_size, FRAMESIZE); | ||
104 | |||
105 | ci->yield(); | ||
106 | if (ci->stop_codec || ci->new_track) | ||
107 | goto done; | ||
108 | |||
109 | if (ci->seek_time) { | ||
110 | ci->set_elapsed(ci->seek_time); | ||
111 | |||
112 | /* Do not allow seeking beyond the file's length */ | ||
113 | if ((unsigned) ci->seek_time > ci->id3->length) { | ||
114 | ci->seek_complete(); | ||
115 | goto done; | ||
116 | } | ||
117 | |||
118 | /* Seek to the start of the track */ | ||
119 | if (ci->seek_time == 1) { | ||
120 | ci->set_elapsed(0); | ||
121 | ci->seek_complete(); | ||
122 | ci->seek_buffer(ci->id3->first_frame_offset); | ||
123 | elapsed = 0; | ||
124 | goto seek_start; | ||
125 | } | ||
126 | seek_frame_offset = (ci->seek_time * BITRATE) / (8 * FRAMESIZE); | ||
127 | frame_counter = seek_frame_offset; | ||
128 | ci->seek_buffer(ci->id3->first_frame_offset + seek_frame_offset* FRAMESIZE); | ||
129 | bit_buffer = (uint8_t *) ci->request_buffer(&buff_size, FRAMESIZE); | ||
130 | elapsed = ci->seek_time; | ||
131 | |||
132 | ci->set_elapsed(elapsed); | ||
133 | ci->seek_complete(); | ||
134 | } | ||
135 | |||
136 | res = atrac3_decode_frame(&rmctx, &q, &datasize, bit_buffer, FRAMESIZE); | ||
137 | |||
138 | if(res != (int)FRAMESIZE) { | ||
139 | DEBUGF("codec error\n"); | ||
140 | return CODEC_ERROR; | ||
141 | } | ||
142 | |||
143 | if(datasize) | ||
144 | ci->pcmbuf_insert(q.outSamples, q.outSamples + 1024, q.samples_per_frame / rmctx.nb_channels); | ||
145 | |||
146 | elapsed += (FRAMESIZE * 8) / BITRATE; | ||
147 | ci->set_elapsed(elapsed); | ||
148 | |||
149 | ci->advance_buffer(FRAMESIZE); | ||
150 | frame_counter++; | ||
151 | } | ||
152 | |||
153 | done: | ||
154 | if (ci->request_next_track()) | ||
155 | goto next_track; | ||
156 | |||
157 | return CODEC_OK; | ||
158 | } | ||
diff --git a/apps/codecs/codecs.make b/apps/codecs/codecs.make index 0c3d2fade0..633f35b273 100644 --- a/apps/codecs/codecs.make +++ b/apps/codecs/codecs.make | |||
@@ -87,6 +87,7 @@ $(CODECDIR)/cook.codec : $(CODECDIR)/libcook.a $(CODECDIR)/librm.a | |||
87 | $(CODECDIR)/raac.codec : $(CODECDIR)/libfaad.a $(CODECDIR)/librm.a | 87 | $(CODECDIR)/raac.codec : $(CODECDIR)/libfaad.a $(CODECDIR)/librm.a |
88 | $(CODECDIR)/a52_rm.codec : $(CODECDIR)/liba52.a $(CODECDIR)/librm.a | 88 | $(CODECDIR)/a52_rm.codec : $(CODECDIR)/liba52.a $(CODECDIR)/librm.a |
89 | $(CODECDIR)/atrac3_rm.codec : $(CODECDIR)/libatrac.a $(CODECDIR)/librm.a | 89 | $(CODECDIR)/atrac3_rm.codec : $(CODECDIR)/libatrac.a $(CODECDIR)/librm.a |
90 | $(CODECDIR)/atrac3_oma.codec : $(CODECDIR)/libatrac.a | ||
90 | $(CODECDIR)/aiff.codec : $(CODECDIR)/libpcm.a | 91 | $(CODECDIR)/aiff.codec : $(CODECDIR)/libpcm.a |
91 | $(CODECDIR)/wav.codec : $(CODECDIR)/libpcm.a | 92 | $(CODECDIR)/wav.codec : $(CODECDIR)/libpcm.a |
92 | 93 | ||
diff --git a/apps/filetypes.c b/apps/filetypes.c index 671a8d5f1b..3feb0f5ab8 100644 --- a/apps/filetypes.c +++ b/apps/filetypes.c | |||
@@ -98,6 +98,8 @@ static const struct filetype inbuilt_filetypes[] = { | |||
98 | { "tmc", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, | 98 | { "tmc", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, |
99 | { "tm8", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, | 99 | { "tm8", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, |
100 | { "tm2", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, | 100 | { "tm2", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, |
101 | { "oma", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, | ||
102 | { "aa3", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, | ||
101 | #endif | 103 | #endif |
102 | { "m3u", FILE_ATTR_M3U, Icon_Playlist, LANG_PLAYLIST }, | 104 | { "m3u", FILE_ATTR_M3U, Icon_Playlist, LANG_PLAYLIST }, |
103 | { "m3u8",FILE_ATTR_M3U, Icon_Playlist, LANG_PLAYLIST }, | 105 | { "m3u8",FILE_ATTR_M3U, Icon_Playlist, LANG_PLAYLIST }, |
diff --git a/apps/metadata.c b/apps/metadata.c index 6281a8526c..619a06e72d 100644 --- a/apps/metadata.c +++ b/apps/metadata.c | |||
@@ -162,6 +162,9 @@ const struct afmt_entry audio_formats[AFMT_NUM_CODECS] = | |||
162 | /* Atari TM2 File */ | 162 | /* Atari TM2 File */ |
163 | [AFMT_TM2] = | 163 | [AFMT_TM2] = |
164 | AFMT_ENTRY("TM2", "asap", NULL, "tm2\0" ), | 164 | AFMT_ENTRY("TM2", "asap", NULL, "tm2\0" ), |
165 | /* Atrac3 in Sony OMA Container */ | ||
166 | [AFMT_OMA_ATRAC3] = | ||
167 | AFMT_ENTRY("ATRAC3", "atrac3_oma", NULL, "oma\0aa3\0" ), | ||
165 | #endif | 168 | #endif |
166 | }; | 169 | }; |
167 | 170 | ||
@@ -437,6 +440,13 @@ bool get_metadata(struct mp3entry* id3, int fd, const char* trackname) | |||
437 | return false; | 440 | return false; |
438 | } | 441 | } |
439 | break; | 442 | break; |
443 | case AFMT_OMA_ATRAC3: | ||
444 | if (!get_oma_metadata(fd, id3)) | ||
445 | { | ||
446 | DEBUGF("get_oma_metadata error\n"); | ||
447 | return false; | ||
448 | } | ||
449 | break; | ||
440 | 450 | ||
441 | #endif /* CONFIG_CODEC == SWCODEC */ | 451 | #endif /* CONFIG_CODEC == SWCODEC */ |
442 | 452 | ||
diff --git a/apps/metadata.h b/apps/metadata.h index 9b9cf9dfd1..b83c5497bf 100644 --- a/apps/metadata.h +++ b/apps/metadata.h | |||
@@ -77,6 +77,7 @@ enum | |||
77 | AFMT_TMC, /* Atari 8bit tmc format */ | 77 | AFMT_TMC, /* Atari 8bit tmc format */ |
78 | AFMT_TM8, /* Atari 8bit tm8 format */ | 78 | AFMT_TM8, /* Atari 8bit tm8 format */ |
79 | AFMT_TM2, /* Atari 8bit tm2 format */ | 79 | AFMT_TM2, /* Atari 8bit tm2 format */ |
80 | AFMT_OMA_ATRAC3, /* Atrac3 in Sony OMA container */ | ||
80 | #endif | 81 | #endif |
81 | 82 | ||
82 | /* add new formats at any index above this line to have a sensible order - | 83 | /* add new formats at any index above this line to have a sensible order - |
diff --git a/apps/metadata/metadata_parsers.h b/apps/metadata/metadata_parsers.h index e8f1832b87..aa07101269 100644 --- a/apps/metadata/metadata_parsers.h +++ b/apps/metadata/metadata_parsers.h | |||
@@ -41,4 +41,5 @@ bool get_asf_metadata(int fd, struct mp3entry* id3); | |||
41 | bool get_asap_metadata(int fd, struct mp3entry* id3); | 41 | bool get_asap_metadata(int fd, struct mp3entry* id3); |
42 | bool get_rm_metadata(int fd, struct mp3entry* id3); | 42 | bool get_rm_metadata(int fd, struct mp3entry* id3); |
43 | bool get_nsf_metadata(int fd, struct mp3entry* id3); | 43 | bool get_nsf_metadata(int fd, struct mp3entry* id3); |
44 | bool get_oma_metadata(int fd, struct mp3entry* id3); | ||
44 | 45 | ||
diff --git a/apps/metadata/oma.c b/apps/metadata/oma.c new file mode 100644 index 0000000000..695ae0b114 --- /dev/null +++ b/apps/metadata/oma.c | |||
@@ -0,0 +1,188 @@ | |||
1 | /* | ||
2 | * Sony OpenMG (OMA) demuxer | ||
3 | * | ||
4 | * Copyright (c) 2008 Maxim Poliakovski | ||
5 | * 2008 Benjamin Larsson | ||
6 | * | ||
7 | * This file is part of FFmpeg. | ||
8 | * | ||
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. | ||
13 | * | ||
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. | ||
18 | * | ||
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 | ||
22 | */ | ||
23 | |||
24 | /** | ||
25 | * @file oma.c | ||
26 | * This is a demuxer for Sony OpenMG Music files | ||
27 | * | ||
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!). | ||
37 | * | ||
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! | ||
43 | */ | ||
44 | |||
45 | #include <stdlib.h> | ||
46 | #include <inttypes.h> | ||
47 | #include <string.h> | ||
48 | #include "metadata.h" | ||
49 | #include "metadata_parsers.h" | ||
50 | |||
51 | #define EA3_HEADER_SIZE 96 | ||
52 | |||
53 | #if 0 | ||
54 | #define DEBUGF printf | ||
55 | #else | ||
56 | #define DEBUGF(...) | ||
57 | #endif | ||
58 | |||
59 | /* Various helper macros taken from ffmpeg for reading * | ||
60 | * and writing buffers with a specified endianess. */ | ||
61 | # define AV_RB16(x) \ | ||
62 | ((((const uint8_t*)(x))[0] << 8) | \ | ||
63 | ((const uint8_t*)(x))[1]) | ||
64 | # define AV_RB24(x) \ | ||
65 | ((((const uint8_t*)(x))[0] << 16) | \ | ||
66 | (((const uint8_t*)(x))[1] << 8) | \ | ||
67 | ((const uint8_t*)(x))[2]) | ||
68 | # define AV_RB32(x) \ | ||
69 | ((((const uint8_t*)(x))[0] << 24) | \ | ||
70 | (((const uint8_t*)(x))[1] << 16) | \ | ||
71 | (((const uint8_t*)(x))[2] << 8) | \ | ||
72 | ((const uint8_t*)(x))[3]) | ||
73 | # define AV_WL32(p, d) do { \ | ||
74 | ((uint8_t*)(p))[0] = (d); \ | ||
75 | ((uint8_t*)(p))[1] = (d)>>8; \ | ||
76 | ((uint8_t*)(p))[2] = (d)>>16; \ | ||
77 | ((uint8_t*)(p))[3] = (d)>>24; \ | ||
78 | } while(0) | ||
79 | # define AV_WL16(p, d) do { \ | ||
80 | ((uint8_t*)(p))[0] = (d); \ | ||
81 | ((uint8_t*)(p))[1] = (d)>>8; \ | ||
82 | } while(0) | ||
83 | |||
84 | /* Different codecs that could be present in a Sony OMA * | ||
85 | * container file. */ | ||
86 | enum { | ||
87 | OMA_CODECID_ATRAC3 = 0, | ||
88 | OMA_CODECID_ATRAC3P = 1, | ||
89 | OMA_CODECID_MP3 = 3, | ||
90 | OMA_CODECID_LPCM = 4, | ||
91 | OMA_CODECID_WMA = 5, | ||
92 | }; | ||
93 | |||
94 | /* FIXME: This functions currently read different file * | ||
95 | * parameters required for decoding. It still * | ||
96 | * does not read the metadata - which should be * | ||
97 | * present in the ea3 (first) header. The * | ||
98 | * metadata in ea3 is stored as a variation of * | ||
99 | * the ID3v2 metadata format. */ | ||
100 | int oma_read_header(int fd, struct mp3entry* id3) | ||
101 | { | ||
102 | static const uint16_t srate_tab[6] = {320,441,480,882,960,0}; | ||
103 | int ret, ea3_taglen, EA3_pos, jsflag; | ||
104 | uint32_t codec_params; | ||
105 | int16_t eid; | ||
106 | uint8_t buf[EA3_HEADER_SIZE]; | ||
107 | |||
108 | ret = read(fd, buf, 10); | ||
109 | if (ret != 10) | ||
110 | return -1; | ||
111 | |||
112 | ea3_taglen = ((buf[6] & 0x7f) << 21) | ((buf[7] & 0x7f) << 14) | ((buf[8] & 0x7f) << 7) | (buf[9] & 0x7f); | ||
113 | |||
114 | EA3_pos = ea3_taglen + 10; | ||
115 | if (buf[5] & 0x10) | ||
116 | EA3_pos += 10; | ||
117 | |||
118 | lseek(fd, EA3_pos, SEEK_SET); | ||
119 | ret = read(fd, buf, EA3_HEADER_SIZE); | ||
120 | if (ret != EA3_HEADER_SIZE) | ||
121 | return -1; | ||
122 | |||
123 | if (memcmp(buf, ((const uint8_t[]){'E', 'A', '3'}),3) || buf[4] != 0 || buf[5] != EA3_HEADER_SIZE) { | ||
124 | DEBUGF("Couldn't find the EA3 header !\n"); | ||
125 | return -1; | ||
126 | } | ||
127 | |||
128 | eid = AV_RB16(&buf[6]); | ||
129 | if (eid != -1 && eid != -128) { | ||
130 | DEBUGF("Encrypted file! Eid: %d\n", eid); | ||
131 | return -1; | ||
132 | } | ||
133 | |||
134 | codec_params = AV_RB24(&buf[33]); | ||
135 | |||
136 | switch (buf[32]) { | ||
137 | case OMA_CODECID_ATRAC3: | ||
138 | id3->frequency = srate_tab[(codec_params >> 13) & 7]*100; | ||
139 | if (id3->frequency != 44100) { | ||
140 | DEBUGF("Unsupported sample rate, send sample file to developers: %d\n", samplerate); | ||
141 | return -1; | ||
142 | } | ||
143 | |||
144 | id3->bytesperframe = (codec_params & 0x3FF) * 8; | ||
145 | id3->codectype = AFMT_OMA_ATRAC3; | ||
146 | jsflag = (codec_params >> 17) & 1; /* get stereo coding mode, 1 for joint-stereo */ | ||
147 | |||
148 | id3->bitrate = id3->frequency * id3->bytesperframe * 8 / (1024 * 1000); | ||
149 | |||
150 | /* fake the atrac3 extradata (wav format, makes stream copy to wav work) */ | ||
151 | /* ATRAC3 expects and extra-data size of 14 bytes for wav format; extra-data size * | ||
152 | * is stored in ATRAC3Context before initializing the decoder. See atrac3_oma.codec. * | ||
153 | * We use id3v2buf to hold the (fake) extra-data provided from the container. */ | ||
154 | |||
155 | AV_WL16(&id3->id3v1buf[0][0], 1); // always 1 | ||
156 | AV_WL32(&id3->id3v1buf[0][2], id3->frequency); // samples rate | ||
157 | AV_WL16(&id3->id3v1buf[0][6], jsflag); // coding mode | ||
158 | AV_WL16(&id3->id3v1buf[0][8], jsflag); // coding mode | ||
159 | AV_WL16(&id3->id3v1buf[0][10], 1); // always 1 | ||
160 | AV_WL16(&id3->id3v1buf[0][12], 0); // always 0 | ||
161 | |||
162 | DEBUGF("sample_rate = %d\n", id3->frequency); | ||
163 | DEBUGF("frame_size = %d\n", id3->bytesperframe); | ||
164 | DEBUGF("stereo_coding_mode = %d\n", jsflag); | ||
165 | break; | ||
166 | default: | ||
167 | DEBUGF("Unsupported codec %d!\n",buf[32]); | ||
168 | return -1; | ||
169 | break; | ||
170 | } | ||
171 | |||
172 | /* Store the the offset of the first audio frame, to be able to seek to it * | ||
173 | * directly in atrac3_oma.codec. */ | ||
174 | id3->first_frame_offset = EA3_pos + EA3_HEADER_SIZE; | ||
175 | return 0; | ||
176 | } | ||
177 | |||
178 | bool get_oma_metadata(int fd, struct mp3entry* id3) | ||
179 | { | ||
180 | if(oma_read_header(fd, id3) < 0) | ||
181 | return false; | ||
182 | |||
183 | /* Currently, there's no means of knowing the duration * | ||
184 | * directly from the the file so we calculate it. */ | ||
185 | id3->filesize = filesize(fd); | ||
186 | id3->length = ((id3->filesize - id3->first_frame_offset) * 8) / id3->bitrate; | ||
187 | return true; | ||
188 | } | ||