Mercurial > libavformat.hg
comparison oma.c @ 3439:0dfc37ba9453 libavformat
Oma demuxer
author | banan |
---|---|
date | Sun, 08 Jun 2008 17:12:25 +0000 |
parents | |
children | ad7e9ad3c19a |
comparison
equal
deleted
inserted
replaced
3438:40995a9455e3 | 3439:0dfc37ba9453 |
---|---|
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, | |
55 }; | |
56 | |
57 static const AVCodecTag codec_oma_tags[] = { | |
58 { CODEC_ID_ATRAC3, OMA_CODECID_ATRAC3 }, | |
59 { CODEC_ID_ATRAC3P, OMA_CODECID_ATRAC3P }, | |
60 }; | |
61 | |
62 static int oma_read_header(AVFormatContext *s, | |
63 AVFormatParameters *ap) | |
64 { | |
65 static const uint16_t srate_tab[6] = {320,441,480,882,960,0}; | |
66 int ret, ea3_taglen, EA3_pos, framesize, jsflag, samplerate, channel_id; | |
67 uint32_t codec_params; | |
68 int16_t eid; | |
69 uint8_t buf[EA3_HEADER_SIZE]; | |
70 uint8_t *edata; | |
71 AVStream *st; | |
72 | |
73 ret = get_buffer(s->pb, buf, 10); | |
74 if (ret != 10) | |
75 return -1; | |
76 | |
77 ea3_taglen = ((buf[6] & 0x7f) << 21) | ((buf[7] & 0x7f) << 14) | ((buf[8] & 0x7f) << 7) | (buf[9] & 0x7f); | |
78 | |
79 EA3_pos = ea3_taglen + 10; | |
80 if (buf[5] & 0x10) | |
81 EA3_pos += 10; | |
82 | |
83 url_fseek(s->pb, EA3_pos, SEEK_SET); | |
84 ret = get_buffer(s->pb, buf, EA3_HEADER_SIZE); | |
85 if (ret != EA3_HEADER_SIZE) | |
86 return -1; | |
87 | |
88 if (memcmp(buf, (uint8_t[]){'E', 'A', '3'},3) || buf[4] != 0 || buf[5] != EA3_HEADER_SIZE) { | |
89 av_log(s, AV_LOG_ERROR, "Couldn't find the EA3 header !\n"); | |
90 return -1; | |
91 } | |
92 | |
93 eid = AV_RB16(&buf[6]); | |
94 if (eid != -1 && eid != -128) { | |
95 av_log(s, AV_LOG_ERROR, "Encrypted file! Eid: %d\n", eid); | |
96 return -1; | |
97 } | |
98 | |
99 codec_params = AV_RB24(&buf[33]); | |
100 channel_id = (codec_params >> 10) & 7; | |
101 samplerate = srate_tab[(codec_params >> 13) & 7]*100; | |
102 | |
103 st = av_new_stream(s, 0); | |
104 if (!st) | |
105 return AVERROR(ENOMEM); | |
106 | |
107 switch (buf[32]) { | |
108 case OMA_CODECID_ATRAC3: | |
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 */ | |
114 channel_id = 2; | |
115 | |
116 /* fake the atrac3 extradata (wav format, makes stream copy to wav work) */ | |
117 st->codec->extradata_size = 14; | |
118 edata = av_mallocz(14 + FF_INPUT_BUFFER_PADDING_SIZE); | |
119 if (!edata) | |
120 return AVERROR(ENOMEM); | |
121 | |
122 st->codec->extradata = edata; | |
123 AV_WL16(&edata[0], 1); // always 1 | |
124 AV_WL32(&edata[2], samplerate); // samples rate | |
125 AV_WL16(&edata[6], jsflag); // coding mode | |
126 AV_WL16(&edata[8], jsflag); // coding mode | |
127 AV_WL16(&edata[10], 1); // always 1 | |
128 // AV_WL16(&edata[12], 0); // always 0 | |
129 break; | |
130 case OMA_CODECID_ATRAC3P: | |
131 framesize = ((codec_params & 0x3FF) * 8) + 8; | |
132 av_log(s, AV_LOG_ERROR, "Unsupported codec ATRAC3+!\n"); | |
133 break; | |
134 default: | |
135 av_log(s, AV_LOG_ERROR, "Unsupported codec %d!\n",buf[32]); | |
136 return -1; | |
137 break; | |
138 } | |
139 | |
140 st->codec->codec_type = CODEC_TYPE_AUDIO; | |
141 st->codec->codec_tag = buf[32]; | |
142 st->codec->codec_id = codec_get_id(codec_oma_tags, st->codec->codec_tag); | |
143 st->codec->channels = channel_id; | |
144 st->codec->sample_rate = samplerate; | |
145 st->codec->bit_rate = samplerate * framesize * 8 / 1024; | |
146 st->codec->block_align = framesize; | |
147 | |
148 st->start_time = 0; | |
149 av_set_pts_info(st, 64, 1, st->codec->sample_rate); | |
150 | |
151 url_fseek(s->pb, EA3_pos + EA3_HEADER_SIZE, SEEK_SET); | |
152 | |
153 return 0; | |
154 } | |
155 | |
156 | |
157 static int oma_read_packet(AVFormatContext *s, AVPacket *pkt) | |
158 { | |
159 int ret = av_get_packet(s->pb, pkt, s->streams[0]->codec->block_align); | |
160 | |
161 pkt->stream_index = 0; | |
162 if (ret <= 0) | |
163 return AVERROR(EIO); | |
164 | |
165 return ret; | |
166 } | |
167 | |
168 static int oma_read_probe(AVProbeData *p) | |
169 { | |
170 if (!memcmp(p->buf, (uint8_t[]){'e', 'a', '3', 3, 0},5)) | |
171 return AVPROBE_SCORE_MAX; | |
172 else | |
173 return 0; | |
174 } | |
175 | |
176 | |
177 AVInputFormat oma_demuxer = { | |
178 "oma", | |
179 NULL_IF_CONFIG_SMALL("Sony OpenMG audio"), | |
180 0, | |
181 oma_read_probe, | |
182 oma_read_header, | |
183 oma_read_packet, | |
184 0, | |
185 pcm_read_seek, | |
186 .flags= AVFMT_GENERIC_INDEX, | |
187 .extensions = "oma,aa3", | |
188 .codec_tag= (const AVCodecTag*[]){codec_oma_tags, 0}, | |
189 }; | |
190 |