Mercurial > libavformat.hg
annotate oma.c @ 6454:9ba950e0e021 libavformat
Optimize/simplify ebml_read_num.
| author | reimar |
|---|---|
| date | Thu, 02 Sep 2010 19:17:46 +0000 |
| parents | 4aaed59641ff |
| children |
| 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" | |
| 6445 | 48 #include "pcm.h" |
| 3439 | 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 |
