Mercurial > libavformat.hg
annotate oma.c @ 6240:8333d7ea7257 libavformat
Ignore extradata & w/h in asf/dvr.
The w/h values are wrong and extradata contains a fake seq header that causes
decoding to fail later, a valid seq header is in the stream itself.
Partially fixes issue658
author | michael |
---|---|
date | Wed, 07 Jul 2010 10:39:05 +0000 |
parents | 0abe94ef06ce |
children | 4aaed59641ff |
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 /** | |
5969
178de7695c6c
Remove explicit filename from Doxygen @file commands.
diego
parents:
5910
diff
changeset
|
25 * @file |
3439 | 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: | |
6140 | 30 * - "ea3" header carrying overall info and metadata. Except for starting with |
31 * "ea" instead of "ID", it's an ID3v2 header. | |
3439 | 32 * - "EA3" header is a Sony-specific header containing information about |
33 * the OpenMG file: codec type (usually ATRAC, can also be MP3 or WMA), | |
34 * codec specific info (packet size, sample rate, channels and so on) | |
35 * and DRM related info (file encryption, content id). | |
36 * - Sound data organized in packets follow the EA3 header | |
37 * (can be encrypted using the Sony DRM!). | |
38 * | |
39 * LIMITATIONS: This version supports only plain (unencrypted) OMA files. | |
40 * If any DRM-protected (encrypted) file is encountered you will get the | |
41 * corresponding error message. Try to remove the encryption using any | |
42 * Sony software (for example SonicStage). | |
43 * CODEC SUPPORT: Only ATRAC3 codec is currently supported! | |
44 */ | |
45 | |
46 #include "avformat.h" | |
47 #include "libavutil/intreadwrite.h" | |
48 #include "raw.h" | |
49 #include "riff.h" | |
6140 | 50 #include "id3v2.h" |
3439 | 51 |
52 #define EA3_HEADER_SIZE 96 | |
53 | |
54 enum { | |
55 OMA_CODECID_ATRAC3 = 0, | |
56 OMA_CODECID_ATRAC3P = 1, | |
3505 | 57 OMA_CODECID_MP3 = 3, |
58 OMA_CODECID_LPCM = 4, | |
59 OMA_CODECID_WMA = 5, | |
3439 | 60 }; |
61 | |
62 static const AVCodecTag codec_oma_tags[] = { | |
63 { CODEC_ID_ATRAC3, OMA_CODECID_ATRAC3 }, | |
64 { CODEC_ID_ATRAC3P, OMA_CODECID_ATRAC3P }, | |
3505 | 65 { CODEC_ID_MP3, OMA_CODECID_MP3 }, |
3439 | 66 }; |
67 | |
6140 | 68 #define ID3v2_EA3_MAGIC "ea3" |
69 | |
3439 | 70 static int oma_read_header(AVFormatContext *s, |
71 AVFormatParameters *ap) | |
72 { | |
73 static const uint16_t srate_tab[6] = {320,441,480,882,960,0}; | |
6140 | 74 int ret, framesize, jsflag, samplerate; |
3439 | 75 uint32_t codec_params; |
76 int16_t eid; | |
77 uint8_t buf[EA3_HEADER_SIZE]; | |
78 uint8_t *edata; | |
79 AVStream *st; | |
80 | |
6140 | 81 ff_id3v2_read(s, ID3v2_EA3_MAGIC); |
82 ret = get_buffer(s->pb, buf, EA3_HEADER_SIZE); | |
3439 | 83 |
4943 | 84 if (memcmp(buf, ((const uint8_t[]){'E', 'A', '3'}),3) || buf[4] != 0 || buf[5] != EA3_HEADER_SIZE) { |
3439 | 85 av_log(s, AV_LOG_ERROR, "Couldn't find the EA3 header !\n"); |
86 return -1; | |
87 } | |
88 | |
89 eid = AV_RB16(&buf[6]); | |
90 if (eid != -1 && eid != -128) { | |
91 av_log(s, AV_LOG_ERROR, "Encrypted file! Eid: %d\n", eid); | |
92 return -1; | |
93 } | |
94 | |
95 codec_params = AV_RB24(&buf[33]); | |
96 | |
97 st = av_new_stream(s, 0); | |
98 if (!st) | |
99 return AVERROR(ENOMEM); | |
100 | |
3506 | 101 st->start_time = 0; |
5910
536e5527c1e0
Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents:
5554
diff
changeset
|
102 st->codec->codec_type = AVMEDIA_TYPE_AUDIO; |
3506 | 103 st->codec->codec_tag = buf[32]; |
5058
33a244b7ca65
Add ff_ prefixes to exported symbols in libavformat/riff.h.
diego
parents:
4943
diff
changeset
|
104 st->codec->codec_id = ff_codec_get_id(codec_oma_tags, st->codec->codec_tag); |
3506 | 105 |
3439 | 106 switch (buf[32]) { |
107 case OMA_CODECID_ATRAC3: | |
3506 | 108 samplerate = srate_tab[(codec_params >> 13) & 7]*100; |
3439 | 109 if (samplerate != 44100) |
110 av_log(s, AV_LOG_ERROR, "Unsupported sample rate, send sample file to developers: %d\n", samplerate); | |
111 | |
112 framesize = (codec_params & 0x3FF) * 8; | |
113 jsflag = (codec_params >> 17) & 1; /* get stereo coding mode, 1 for joint-stereo */ | |
3506 | 114 st->codec->channels = 2; |
115 st->codec->sample_rate = samplerate; | |
116 st->codec->bit_rate = st->codec->sample_rate * framesize * 8 / 1024; | |
3439 | 117 |
118 /* fake the atrac3 extradata (wav format, makes stream copy to wav work) */ | |
119 st->codec->extradata_size = 14; | |
120 edata = av_mallocz(14 + FF_INPUT_BUFFER_PADDING_SIZE); | |
121 if (!edata) | |
122 return AVERROR(ENOMEM); | |
123 | |
124 st->codec->extradata = edata; | |
125 AV_WL16(&edata[0], 1); // always 1 | |
126 AV_WL32(&edata[2], samplerate); // samples rate | |
127 AV_WL16(&edata[6], jsflag); // coding mode | |
128 AV_WL16(&edata[8], jsflag); // coding mode | |
129 AV_WL16(&edata[10], 1); // always 1 | |
130 // AV_WL16(&edata[12], 0); // always 0 | |
3506 | 131 |
132 av_set_pts_info(st, 64, 1, st->codec->sample_rate); | |
3439 | 133 break; |
134 case OMA_CODECID_ATRAC3P: | |
3506 | 135 st->codec->channels = (codec_params >> 10) & 7; |
3439 | 136 framesize = ((codec_params & 0x3FF) * 8) + 8; |
3506 | 137 st->codec->sample_rate = srate_tab[(codec_params >> 13) & 7]*100; |
138 st->codec->bit_rate = st->codec->sample_rate * framesize * 8 / 1024; | |
139 av_set_pts_info(st, 64, 1, st->codec->sample_rate); | |
3439 | 140 av_log(s, AV_LOG_ERROR, "Unsupported codec ATRAC3+!\n"); |
141 break; | |
3507 | 142 case OMA_CODECID_MP3: |
143 st->need_parsing = AVSTREAM_PARSE_FULL; | |
144 framesize = 1024; | |
145 break; | |
3439 | 146 default: |
147 av_log(s, AV_LOG_ERROR, "Unsupported codec %d!\n",buf[32]); | |
148 return -1; | |
149 break; | |
150 } | |
151 | |
152 st->codec->block_align = framesize; | |
153 | |
154 return 0; | |
155 } | |
156 | |
157 | |
158 static int oma_read_packet(AVFormatContext *s, AVPacket *pkt) | |
159 { | |
160 int ret = av_get_packet(s->pb, pkt, s->streams[0]->codec->block_align); | |
161 | |
162 pkt->stream_index = 0; | |
163 if (ret <= 0) | |
164 return AVERROR(EIO); | |
165 | |
166 return ret; | |
167 } | |
168 | |
169 static int oma_read_probe(AVProbeData *p) | |
170 { | |
6140 | 171 const uint8_t *buf; |
172 unsigned tag_len = 0; | |
173 | |
174 buf = p->buf; | |
175 /* version must be 3 and flags byte zero */ | |
176 if (ff_id3v2_match(buf, ID3v2_EA3_MAGIC) && buf[3] == 3 && !buf[4]) | |
177 tag_len = ff_id3v2_tag_len(buf); | |
178 | |
179 // This check cannot overflow as tag_len has at most 28 bits | |
180 if (p->buf_size < tag_len + 5) | |
181 return 0; | |
182 | |
183 buf += tag_len; | |
184 | |
185 if (!memcmp(buf, "EA3", 3) && !buf[4] && buf[5] == EA3_HEADER_SIZE) | |
3439 | 186 return AVPROBE_SCORE_MAX; |
187 else | |
188 return 0; | |
189 } | |
190 | |
191 | |
192 AVInputFormat oma_demuxer = { | |
193 "oma", | |
194 NULL_IF_CONFIG_SMALL("Sony OpenMG audio"), | |
195 0, | |
196 oma_read_probe, | |
197 oma_read_header, | |
198 oma_read_packet, | |
199 0, | |
200 pcm_read_seek, | |
201 .flags= AVFMT_GENERIC_INDEX, | |
202 .extensions = "oma,aa3", | |
3766
f062deeedb8d
Change codec_tag type from const struct AVCodecTag ** to const struct AVCodecTag * const *
reimar
parents:
3507
diff
changeset
|
203 .codec_tag= (const AVCodecTag* const []){codec_oma_tags, 0}, |
6140 | 204 .metadata_conv = ff_id3v2_metadata_conv, |
3439 | 205 }; |
206 |