Mercurial > libavformat.hg
annotate oma.c @ 4105:8f778b7c07d0 libavformat
oggflac: fix bitstream reader usage
author | mru |
---|---|
date | Sun, 14 Dec 2008 17:30:18 +0000 |
parents | 93d4898d9b6e |
children | 49c1d3b27727 |
rev | line source |
---|---|
3439 | 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 "avformat.h" | |
46 #include "libavutil/intreadwrite.h" | |
47 #include "raw.h" | |
48 #include "riff.h" | |
49 | |
50 #define EA3_HEADER_SIZE 96 | |
51 | |
52 enum { | |
53 OMA_CODECID_ATRAC3 = 0, | |
54 OMA_CODECID_ATRAC3P = 1, | |
3505 | 55 OMA_CODECID_MP3 = 3, |
56 OMA_CODECID_LPCM = 4, | |
57 OMA_CODECID_WMA = 5, | |
3439 | 58 }; |
59 | |
60 static const AVCodecTag codec_oma_tags[] = { | |
61 { CODEC_ID_ATRAC3, OMA_CODECID_ATRAC3 }, | |
62 { CODEC_ID_ATRAC3P, OMA_CODECID_ATRAC3P }, | |
3505 | 63 { CODEC_ID_MP3, OMA_CODECID_MP3 }, |
3439 | 64 }; |
65 | |
66 static int oma_read_header(AVFormatContext *s, | |
67 AVFormatParameters *ap) | |
68 { | |
69 static const uint16_t srate_tab[6] = {320,441,480,882,960,0}; | |
3506 | 70 int ret, ea3_taglen, EA3_pos, framesize, jsflag, samplerate; |
3439 | 71 uint32_t codec_params; |
72 int16_t eid; | |
73 uint8_t buf[EA3_HEADER_SIZE]; | |
74 uint8_t *edata; | |
75 AVStream *st; | |
76 | |
77 ret = get_buffer(s->pb, buf, 10); | |
78 if (ret != 10) | |
79 return -1; | |
80 | |
81 ea3_taglen = ((buf[6] & 0x7f) << 21) | ((buf[7] & 0x7f) << 14) | ((buf[8] & 0x7f) << 7) | (buf[9] & 0x7f); | |
82 | |
83 EA3_pos = ea3_taglen + 10; | |
84 if (buf[5] & 0x10) | |
85 EA3_pos += 10; | |
86 | |
87 url_fseek(s->pb, EA3_pos, SEEK_SET); | |
88 ret = get_buffer(s->pb, buf, EA3_HEADER_SIZE); | |
89 if (ret != EA3_HEADER_SIZE) | |
90 return -1; | |
91 | |
3769 | 92 if (memcmp(buf, (const uint8_t[]){'E', 'A', '3'},3) || buf[4] != 0 || buf[5] != EA3_HEADER_SIZE) { |
3439 | 93 av_log(s, AV_LOG_ERROR, "Couldn't find the EA3 header !\n"); |
94 return -1; | |
95 } | |
96 | |
97 eid = AV_RB16(&buf[6]); | |
98 if (eid != -1 && eid != -128) { | |
99 av_log(s, AV_LOG_ERROR, "Encrypted file! Eid: %d\n", eid); | |
100 return -1; | |
101 } | |
102 | |
103 codec_params = AV_RB24(&buf[33]); | |
104 | |
105 st = av_new_stream(s, 0); | |
106 if (!st) | |
107 return AVERROR(ENOMEM); | |
108 | |
3506 | 109 st->start_time = 0; |
110 st->codec->codec_type = CODEC_TYPE_AUDIO; | |
111 st->codec->codec_tag = buf[32]; | |
112 st->codec->codec_id = codec_get_id(codec_oma_tags, st->codec->codec_tag); | |
113 | |
3439 | 114 switch (buf[32]) { |
115 case OMA_CODECID_ATRAC3: | |
3506 | 116 samplerate = srate_tab[(codec_params >> 13) & 7]*100; |
3439 | 117 if (samplerate != 44100) |
118 av_log(s, AV_LOG_ERROR, "Unsupported sample rate, send sample file to developers: %d\n", samplerate); | |
119 | |
120 framesize = (codec_params & 0x3FF) * 8; | |
121 jsflag = (codec_params >> 17) & 1; /* get stereo coding mode, 1 for joint-stereo */ | |
3506 | 122 st->codec->channels = 2; |
123 st->codec->sample_rate = samplerate; | |
124 st->codec->bit_rate = st->codec->sample_rate * framesize * 8 / 1024; | |
3439 | 125 |
126 /* fake the atrac3 extradata (wav format, makes stream copy to wav work) */ | |
127 st->codec->extradata_size = 14; | |
128 edata = av_mallocz(14 + FF_INPUT_BUFFER_PADDING_SIZE); | |
129 if (!edata) | |
130 return AVERROR(ENOMEM); | |
131 | |
132 st->codec->extradata = edata; | |
133 AV_WL16(&edata[0], 1); // always 1 | |
134 AV_WL32(&edata[2], samplerate); // samples rate | |
135 AV_WL16(&edata[6], jsflag); // coding mode | |
136 AV_WL16(&edata[8], jsflag); // coding mode | |
137 AV_WL16(&edata[10], 1); // always 1 | |
138 // AV_WL16(&edata[12], 0); // always 0 | |
3506 | 139 |
140 av_set_pts_info(st, 64, 1, st->codec->sample_rate); | |
3439 | 141 break; |
142 case OMA_CODECID_ATRAC3P: | |
3506 | 143 st->codec->channels = (codec_params >> 10) & 7; |
3439 | 144 framesize = ((codec_params & 0x3FF) * 8) + 8; |
3506 | 145 st->codec->sample_rate = srate_tab[(codec_params >> 13) & 7]*100; |
146 st->codec->bit_rate = st->codec->sample_rate * framesize * 8 / 1024; | |
147 av_set_pts_info(st, 64, 1, st->codec->sample_rate); | |
3439 | 148 av_log(s, AV_LOG_ERROR, "Unsupported codec ATRAC3+!\n"); |
149 break; | |
3507 | 150 case OMA_CODECID_MP3: |
151 st->need_parsing = AVSTREAM_PARSE_FULL; | |
152 framesize = 1024; | |
153 break; | |
3439 | 154 default: |
155 av_log(s, AV_LOG_ERROR, "Unsupported codec %d!\n",buf[32]); | |
156 return -1; | |
157 break; | |
158 } | |
159 | |
160 st->codec->block_align = framesize; | |
161 url_fseek(s->pb, EA3_pos + EA3_HEADER_SIZE, SEEK_SET); | |
162 | |
163 return 0; | |
164 } | |
165 | |
166 | |
167 static int oma_read_packet(AVFormatContext *s, AVPacket *pkt) | |
168 { | |
169 int ret = av_get_packet(s->pb, pkt, s->streams[0]->codec->block_align); | |
170 | |
171 pkt->stream_index = 0; | |
172 if (ret <= 0) | |
173 return AVERROR(EIO); | |
174 | |
175 return ret; | |
176 } | |
177 | |
178 static int oma_read_probe(AVProbeData *p) | |
179 { | |
3769 | 180 if (!memcmp(p->buf, (const uint8_t[]){'e', 'a', '3', 3, 0},5)) |
3439 | 181 return AVPROBE_SCORE_MAX; |
182 else | |
183 return 0; | |
184 } | |
185 | |
186 | |
187 AVInputFormat oma_demuxer = { | |
188 "oma", | |
189 NULL_IF_CONFIG_SMALL("Sony OpenMG audio"), | |
190 0, | |
191 oma_read_probe, | |
192 oma_read_header, | |
193 oma_read_packet, | |
194 0, | |
195 pcm_read_seek, | |
196 .flags= AVFMT_GENERIC_INDEX, | |
197 .extensions = "oma,aa3", | |
3766
f062deeedb8d
Change codec_tag type from const struct AVCodecTag ** to const struct AVCodecTag * const *
reimar
parents:
3507
diff
changeset
|
198 .codec_tag= (const AVCodecTag* const []){codec_oma_tags, 0}, |
3439 | 199 }; |
200 |