ffmpeg / libavformat / electronicarts.c @ a2704c97
History | View | Annotate | Download (17.9 KB)
1 |
/* Electronic Arts Multimedia File Demuxer
|
---|---|
2 |
* Copyright (c) 2004 The ffmpeg Project
|
3 |
* Copyright (c) 2006-2008 Peter Ross
|
4 |
*
|
5 |
* This file is part of FFmpeg.
|
6 |
*
|
7 |
* FFmpeg is free software; you can redistribute it and/or
|
8 |
* modify it under the terms of the GNU Lesser General Public
|
9 |
* License as published by the Free Software Foundation; either
|
10 |
* version 2.1 of the License, or (at your option) any later version.
|
11 |
*
|
12 |
* FFmpeg is distributed in the hope that it will be useful,
|
13 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
15 |
* Lesser General Public License for more details.
|
16 |
*
|
17 |
* You should have received a copy of the GNU Lesser General Public
|
18 |
* License along with FFmpeg; if not, write to the Free Software
|
19 |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
20 |
*/
|
21 |
|
22 |
/**
|
23 |
* @file
|
24 |
* Electronic Arts Multimedia file demuxer (WVE/UV2/etc.)
|
25 |
* by Robin Kay (komadori at gekkou.co.uk)
|
26 |
*/
|
27 |
|
28 |
#include "libavutil/intreadwrite.h" |
29 |
#include "avformat.h" |
30 |
|
31 |
#define SCHl_TAG MKTAG('S', 'C', 'H', 'l') |
32 |
#define SEAD_TAG MKTAG('S', 'E', 'A', 'D') /* Sxxx header */ |
33 |
#define SNDC_TAG MKTAG('S', 'N', 'D', 'C') /* Sxxx data */ |
34 |
#define SEND_TAG MKTAG('S', 'E', 'N', 'D') /* Sxxx end */ |
35 |
#define SHEN_TAG MKTAG('S', 'H', 'E', 'N') /* SxEN header */ |
36 |
#define SDEN_TAG MKTAG('S', 'D', 'E', 'N') /* SxEN data */ |
37 |
#define SEEN_TAG MKTAG('S', 'E', 'E', 'N') /* SxEN end */ |
38 |
#define ISNh_TAG MKTAG('1', 'S', 'N', 'h') /* 1SNx header */ |
39 |
#define EACS_TAG MKTAG('E', 'A', 'C', 'S') |
40 |
#define ISNd_TAG MKTAG('1', 'S', 'N', 'd') /* 1SNx data */ |
41 |
#define ISNe_TAG MKTAG('1', 'S', 'N', 'e') /* 1SNx end */ |
42 |
#define PT00_TAG MKTAG('P', 'T', 0x0, 0x0) |
43 |
#define GSTR_TAG MKTAG('G', 'S', 'T', 'R') |
44 |
#define SCDl_TAG MKTAG('S', 'C', 'D', 'l') |
45 |
#define SCEl_TAG MKTAG('S', 'C', 'E', 'l') |
46 |
#define kVGT_TAG MKTAG('k', 'V', 'G', 'T') /* TGV i-frame */ |
47 |
#define fVGT_TAG MKTAG('f', 'V', 'G', 'T') /* TGV p-frame */ |
48 |
#define mTCD_TAG MKTAG('m', 'T', 'C', 'D') /* MDEC */ |
49 |
#define MADk_TAG MKTAG('M', 'A', 'D', 'k') /* MAD i-frame */ |
50 |
#define MADm_TAG MKTAG('M', 'A', 'D', 'm') /* MAD p-frame */ |
51 |
#define MADe_TAG MKTAG('M', 'A', 'D', 'e') /* MAD lqp-frame */ |
52 |
#define MPCh_TAG MKTAG('M', 'P', 'C', 'h') /* MPEG2 */ |
53 |
#define TGQs_TAG MKTAG('T', 'G', 'Q', 's') /* TGQ i-frame (appears in .TGQ files) */ |
54 |
#define pQGT_TAG MKTAG('p', 'Q', 'G', 'T') /* TGQ i-frame (appears in .UV files) */ |
55 |
#define pIQT_TAG MKTAG('p', 'I', 'Q', 'T') /* TQI/UV2 i-frame (.UV2/.WVE) */ |
56 |
#define MVhd_TAG MKTAG('M', 'V', 'h', 'd') |
57 |
#define MV0K_TAG MKTAG('M', 'V', '0', 'K') |
58 |
#define MV0F_TAG MKTAG('M', 'V', '0', 'F') |
59 |
#define MVIh_TAG MKTAG('M', 'V', 'I', 'h') /* CMV header */ |
60 |
#define MVIf_TAG MKTAG('M', 'V', 'I', 'f') /* CMV i-frame */ |
61 |
|
62 |
typedef struct EaDemuxContext { |
63 |
int big_endian;
|
64 |
|
65 |
enum CodecID video_codec;
|
66 |
AVRational time_base; |
67 |
int width, height;
|
68 |
int video_stream_index;
|
69 |
|
70 |
enum CodecID audio_codec;
|
71 |
int audio_stream_index;
|
72 |
int audio_frame_counter;
|
73 |
|
74 |
int bytes;
|
75 |
int sample_rate;
|
76 |
int num_channels;
|
77 |
int num_samples;
|
78 |
} EaDemuxContext; |
79 |
|
80 |
static uint32_t read_arbitary(AVIOContext *pb) {
|
81 |
uint8_t size, byte; |
82 |
int i;
|
83 |
uint32_t word; |
84 |
|
85 |
size = avio_r8(pb); |
86 |
|
87 |
word = 0;
|
88 |
for (i = 0; i < size; i++) { |
89 |
byte = avio_r8(pb); |
90 |
word <<= 8;
|
91 |
word |= byte; |
92 |
} |
93 |
|
94 |
return word;
|
95 |
} |
96 |
|
97 |
/*
|
98 |
* Process PT/GSTR sound header
|
99 |
* return 1 if success, 0 if invalid format, otherwise AVERROR_xxx
|
100 |
*/
|
101 |
static int process_audio_header_elements(AVFormatContext *s) |
102 |
{ |
103 |
int inHeader = 1; |
104 |
EaDemuxContext *ea = s->priv_data; |
105 |
AVIOContext *pb = s->pb; |
106 |
int compression_type = -1, revision = -1, revision2 = -1; |
107 |
|
108 |
ea->bytes = 2;
|
109 |
ea->sample_rate = -1;
|
110 |
ea->num_channels = 1;
|
111 |
|
112 |
while (!url_feof(pb) && inHeader) {
|
113 |
int inSubheader;
|
114 |
uint8_t byte; |
115 |
byte = avio_r8(pb); |
116 |
|
117 |
switch (byte) {
|
118 |
case 0xFD: |
119 |
av_log (s, AV_LOG_DEBUG, "entered audio subheader\n");
|
120 |
inSubheader = 1;
|
121 |
while (!url_feof(pb) && inSubheader) {
|
122 |
uint8_t subbyte; |
123 |
subbyte = avio_r8(pb); |
124 |
|
125 |
switch (subbyte) {
|
126 |
case 0x80: |
127 |
revision = read_arbitary(pb); |
128 |
av_log (s, AV_LOG_DEBUG, "revision (element 0x80) set to 0x%08x\n", revision);
|
129 |
break;
|
130 |
case 0x82: |
131 |
ea->num_channels = read_arbitary(pb); |
132 |
av_log (s, AV_LOG_DEBUG, "num_channels (element 0x82) set to 0x%08x\n", ea->num_channels);
|
133 |
break;
|
134 |
case 0x83: |
135 |
compression_type = read_arbitary(pb); |
136 |
av_log (s, AV_LOG_DEBUG, "compression_type (element 0x83) set to 0x%08x\n", compression_type);
|
137 |
break;
|
138 |
case 0x84: |
139 |
ea->sample_rate = read_arbitary(pb); |
140 |
av_log (s, AV_LOG_DEBUG, "sample_rate (element 0x84) set to %i\n", ea->sample_rate);
|
141 |
break;
|
142 |
case 0x85: |
143 |
ea->num_samples = read_arbitary(pb); |
144 |
av_log (s, AV_LOG_DEBUG, "num_samples (element 0x85) set to 0x%08x\n", ea->num_samples);
|
145 |
break;
|
146 |
case 0x8A: |
147 |
av_log (s, AV_LOG_DEBUG, "element 0x%02x set to 0x%08x\n", subbyte, read_arbitary(pb));
|
148 |
av_log (s, AV_LOG_DEBUG, "exited audio subheader\n");
|
149 |
inSubheader = 0;
|
150 |
break;
|
151 |
case 0xA0: |
152 |
revision2 = read_arbitary(pb); |
153 |
av_log (s, AV_LOG_DEBUG, "revision2 (element 0xA0) set to 0x%08x\n", revision2);
|
154 |
break;
|
155 |
case 0xFF: |
156 |
av_log (s, AV_LOG_DEBUG, "end of header block reached (within audio subheader)\n");
|
157 |
inSubheader = 0;
|
158 |
inHeader = 0;
|
159 |
break;
|
160 |
default:
|
161 |
av_log (s, AV_LOG_DEBUG, "element 0x%02x set to 0x%08x\n", subbyte, read_arbitary(pb));
|
162 |
break;
|
163 |
} |
164 |
} |
165 |
break;
|
166 |
case 0xFF: |
167 |
av_log (s, AV_LOG_DEBUG, "end of header block reached\n");
|
168 |
inHeader = 0;
|
169 |
break;
|
170 |
default:
|
171 |
av_log (s, AV_LOG_DEBUG, "header element 0x%02x set to 0x%08x\n", byte, read_arbitary(pb));
|
172 |
break;
|
173 |
} |
174 |
} |
175 |
|
176 |
switch (compression_type) {
|
177 |
case 0: ea->audio_codec = CODEC_ID_PCM_S16LE; break; |
178 |
case 7: ea->audio_codec = CODEC_ID_ADPCM_EA; break; |
179 |
case -1: |
180 |
switch (revision) {
|
181 |
case 1: ea->audio_codec = CODEC_ID_ADPCM_EA_R1; break; |
182 |
case 2: ea->audio_codec = CODEC_ID_ADPCM_EA_R2; break; |
183 |
case 3: ea->audio_codec = CODEC_ID_ADPCM_EA_R3; break; |
184 |
case -1: break; |
185 |
default:
|
186 |
av_log(s, AV_LOG_ERROR, "unsupported stream type; revision=%i\n", revision);
|
187 |
return 0; |
188 |
} |
189 |
switch (revision2) {
|
190 |
case 8: ea->audio_codec = CODEC_ID_PCM_S16LE_PLANAR; break; |
191 |
case 10: ea->audio_codec = CODEC_ID_ADPCM_EA_R2; break; |
192 |
case 16: ea->audio_codec = CODEC_ID_MP3; break; |
193 |
case -1: break; |
194 |
default:
|
195 |
ea->audio_codec = CODEC_ID_NONE; |
196 |
av_log(s, AV_LOG_ERROR, "unsupported stream type; revision2=%i\n", revision2);
|
197 |
return 0; |
198 |
} |
199 |
break;
|
200 |
default:
|
201 |
av_log(s, AV_LOG_ERROR, "unsupported stream type; compression_type=%i\n", compression_type);
|
202 |
return 0; |
203 |
} |
204 |
|
205 |
if (ea->sample_rate == -1) |
206 |
ea->sample_rate = revision==3 ? 48000 : 22050; |
207 |
|
208 |
return 1; |
209 |
} |
210 |
|
211 |
/*
|
212 |
* Process EACS sound header
|
213 |
* return 1 if success, 0 if invalid format, otherwise AVERROR_xxx
|
214 |
*/
|
215 |
static int process_audio_header_eacs(AVFormatContext *s) |
216 |
{ |
217 |
EaDemuxContext *ea = s->priv_data; |
218 |
AVIOContext *pb = s->pb; |
219 |
int compression_type;
|
220 |
|
221 |
ea->sample_rate = ea->big_endian ? avio_rb32(pb) : avio_rl32(pb); |
222 |
ea->bytes = avio_r8(pb); /* 1=8-bit, 2=16-bit */
|
223 |
ea->num_channels = avio_r8(pb); |
224 |
compression_type = avio_r8(pb); |
225 |
avio_seek(pb, 13, SEEK_CUR);
|
226 |
|
227 |
switch (compression_type) {
|
228 |
case 0: |
229 |
switch (ea->bytes) {
|
230 |
case 1: ea->audio_codec = CODEC_ID_PCM_S8; break; |
231 |
case 2: ea->audio_codec = CODEC_ID_PCM_S16LE; break; |
232 |
} |
233 |
break;
|
234 |
case 1: ea->audio_codec = CODEC_ID_PCM_MULAW; ea->bytes = 1; break; |
235 |
case 2: ea->audio_codec = CODEC_ID_ADPCM_IMA_EA_EACS; break; |
236 |
default:
|
237 |
av_log (s, AV_LOG_ERROR, "unsupported stream type; audio compression_type=%i\n", compression_type);
|
238 |
} |
239 |
|
240 |
return 1; |
241 |
} |
242 |
|
243 |
/*
|
244 |
* Process SEAD sound header
|
245 |
* return 1 if success, 0 if invalid format, otherwise AVERROR_xxx
|
246 |
*/
|
247 |
static int process_audio_header_sead(AVFormatContext *s) |
248 |
{ |
249 |
EaDemuxContext *ea = s->priv_data; |
250 |
AVIOContext *pb = s->pb; |
251 |
|
252 |
ea->sample_rate = avio_rl32(pb); |
253 |
ea->bytes = avio_rl32(pb); /* 1=8-bit, 2=16-bit */
|
254 |
ea->num_channels = avio_rl32(pb); |
255 |
ea->audio_codec = CODEC_ID_ADPCM_IMA_EA_SEAD; |
256 |
|
257 |
return 1; |
258 |
} |
259 |
|
260 |
static int process_video_header_mdec(AVFormatContext *s) |
261 |
{ |
262 |
EaDemuxContext *ea = s->priv_data; |
263 |
AVIOContext *pb = s->pb; |
264 |
avio_seek(pb, 4, SEEK_CUR);
|
265 |
ea->width = avio_rl16(pb); |
266 |
ea->height = avio_rl16(pb); |
267 |
ea->time_base = (AVRational){1,15}; |
268 |
ea->video_codec = CODEC_ID_MDEC; |
269 |
return 1; |
270 |
} |
271 |
|
272 |
static int process_video_header_vp6(AVFormatContext *s) |
273 |
{ |
274 |
EaDemuxContext *ea = s->priv_data; |
275 |
AVIOContext *pb = s->pb; |
276 |
|
277 |
avio_seek(pb, 16, SEEK_CUR);
|
278 |
ea->time_base.den = avio_rl32(pb); |
279 |
ea->time_base.num = avio_rl32(pb); |
280 |
ea->video_codec = CODEC_ID_VP6; |
281 |
|
282 |
return 1; |
283 |
} |
284 |
|
285 |
/*
|
286 |
* Process EA file header
|
287 |
* Returns 1 if the EA file is valid and successfully opened, 0 otherwise
|
288 |
*/
|
289 |
static int process_ea_header(AVFormatContext *s) { |
290 |
uint32_t blockid, size = 0;
|
291 |
EaDemuxContext *ea = s->priv_data; |
292 |
AVIOContext *pb = s->pb; |
293 |
int i;
|
294 |
|
295 |
for (i=0; i<5 && (!ea->audio_codec || !ea->video_codec); i++) { |
296 |
unsigned int startpos = avio_tell(pb); |
297 |
int err = 0; |
298 |
|
299 |
blockid = avio_rl32(pb); |
300 |
size = avio_rl32(pb); |
301 |
if (i == 0) |
302 |
ea->big_endian = size > 0x000FFFFF;
|
303 |
if (ea->big_endian)
|
304 |
size = av_bswap32(size); |
305 |
|
306 |
switch (blockid) {
|
307 |
case ISNh_TAG:
|
308 |
if (avio_rl32(pb) != EACS_TAG) {
|
309 |
av_log (s, AV_LOG_ERROR, "unknown 1SNh headerid\n");
|
310 |
return 0; |
311 |
} |
312 |
err = process_audio_header_eacs(s); |
313 |
break;
|
314 |
|
315 |
case SCHl_TAG :
|
316 |
case SHEN_TAG :
|
317 |
blockid = avio_rl32(pb); |
318 |
if (blockid == GSTR_TAG) {
|
319 |
avio_seek(pb, 4, SEEK_CUR);
|
320 |
} else if ((blockid & 0xFFFF)!=PT00_TAG) { |
321 |
av_log (s, AV_LOG_ERROR, "unknown SCHl headerid\n");
|
322 |
return 0; |
323 |
} |
324 |
err = process_audio_header_elements(s); |
325 |
break;
|
326 |
|
327 |
case SEAD_TAG:
|
328 |
err = process_audio_header_sead(s); |
329 |
break;
|
330 |
|
331 |
case MVIh_TAG :
|
332 |
ea->video_codec = CODEC_ID_CMV; |
333 |
ea->time_base = (AVRational){0,0}; |
334 |
break;
|
335 |
|
336 |
case kVGT_TAG:
|
337 |
ea->video_codec = CODEC_ID_TGV; |
338 |
ea->time_base = (AVRational){0,0}; |
339 |
break;
|
340 |
|
341 |
case mTCD_TAG :
|
342 |
err = process_video_header_mdec(s); |
343 |
break;
|
344 |
|
345 |
case MPCh_TAG:
|
346 |
ea->video_codec = CODEC_ID_MPEG2VIDEO; |
347 |
break;
|
348 |
|
349 |
case pQGT_TAG:
|
350 |
case TGQs_TAG:
|
351 |
ea->video_codec = CODEC_ID_TGQ; |
352 |
break;
|
353 |
|
354 |
case pIQT_TAG:
|
355 |
ea->video_codec = CODEC_ID_TQI; |
356 |
break;
|
357 |
|
358 |
case MADk_TAG :
|
359 |
ea->video_codec = CODEC_ID_MAD; |
360 |
break;
|
361 |
|
362 |
case MVhd_TAG :
|
363 |
err = process_video_header_vp6(s); |
364 |
break;
|
365 |
} |
366 |
|
367 |
if (err < 0) { |
368 |
av_log(s, AV_LOG_ERROR, "error parsing header: %i\n", err);
|
369 |
return err;
|
370 |
} |
371 |
|
372 |
avio_seek(pb, startpos + size, SEEK_SET); |
373 |
} |
374 |
|
375 |
avio_seek(pb, 0, SEEK_SET);
|
376 |
|
377 |
return 1; |
378 |
} |
379 |
|
380 |
|
381 |
static int ea_probe(AVProbeData *p) |
382 |
{ |
383 |
switch (AV_RL32(&p->buf[0])) { |
384 |
case ISNh_TAG:
|
385 |
case SCHl_TAG:
|
386 |
case SEAD_TAG:
|
387 |
case SHEN_TAG:
|
388 |
case kVGT_TAG:
|
389 |
case MADk_TAG:
|
390 |
case MPCh_TAG:
|
391 |
case MVhd_TAG:
|
392 |
case MVIh_TAG:
|
393 |
break;
|
394 |
default:
|
395 |
return 0; |
396 |
} |
397 |
if (AV_RL32(&p->buf[4]) > 0xfffff && AV_RB32(&p->buf[4]) > 0xfffff) |
398 |
return 0; |
399 |
return AVPROBE_SCORE_MAX;
|
400 |
} |
401 |
|
402 |
static int ea_read_header(AVFormatContext *s, |
403 |
AVFormatParameters *ap) |
404 |
{ |
405 |
EaDemuxContext *ea = s->priv_data; |
406 |
AVStream *st; |
407 |
|
408 |
if (!process_ea_header(s))
|
409 |
return AVERROR(EIO);
|
410 |
|
411 |
if (ea->video_codec) {
|
412 |
/* initialize the video decoder stream */
|
413 |
st = av_new_stream(s, 0);
|
414 |
if (!st)
|
415 |
return AVERROR(ENOMEM);
|
416 |
ea->video_stream_index = st->index; |
417 |
st->codec->codec_type = AVMEDIA_TYPE_VIDEO; |
418 |
st->codec->codec_id = ea->video_codec; |
419 |
st->codec->codec_tag = 0; /* no fourcc */ |
420 |
st->codec->time_base = ea->time_base; |
421 |
st->codec->width = ea->width; |
422 |
st->codec->height = ea->height; |
423 |
} |
424 |
|
425 |
if (ea->audio_codec) {
|
426 |
if (ea->num_channels <= 0) { |
427 |
av_log(s, AV_LOG_WARNING, "Unsupported number of channels: %d\n", ea->num_channels);
|
428 |
ea->audio_codec = 0;
|
429 |
return 1; |
430 |
} |
431 |
if (ea->sample_rate <= 0) { |
432 |
av_log(s, AV_LOG_ERROR, "Unsupported sample rate: %d\n", ea->sample_rate);
|
433 |
ea->audio_codec = 0;
|
434 |
return 1; |
435 |
} |
436 |
|
437 |
/* initialize the audio decoder stream */
|
438 |
st = av_new_stream(s, 0);
|
439 |
if (!st)
|
440 |
return AVERROR(ENOMEM);
|
441 |
av_set_pts_info(st, 33, 1, ea->sample_rate); |
442 |
st->codec->codec_type = AVMEDIA_TYPE_AUDIO; |
443 |
st->codec->codec_id = ea->audio_codec; |
444 |
st->codec->codec_tag = 0; /* no tag */ |
445 |
st->codec->channels = ea->num_channels; |
446 |
st->codec->sample_rate = ea->sample_rate; |
447 |
st->codec->bits_per_coded_sample = ea->bytes * 8;
|
448 |
st->codec->bit_rate = st->codec->channels * st->codec->sample_rate * |
449 |
st->codec->bits_per_coded_sample / 4;
|
450 |
st->codec->block_align = st->codec->channels*st->codec->bits_per_coded_sample; |
451 |
ea->audio_stream_index = st->index; |
452 |
ea->audio_frame_counter = 0;
|
453 |
} |
454 |
|
455 |
return 1; |
456 |
} |
457 |
|
458 |
static int ea_read_packet(AVFormatContext *s, |
459 |
AVPacket *pkt) |
460 |
{ |
461 |
EaDemuxContext *ea = s->priv_data; |
462 |
AVIOContext *pb = s->pb; |
463 |
int ret = 0; |
464 |
int packet_read = 0; |
465 |
unsigned int chunk_type, chunk_size; |
466 |
int key = 0; |
467 |
int av_uninit(num_samples);
|
468 |
|
469 |
while (!packet_read) {
|
470 |
chunk_type = avio_rl32(pb); |
471 |
chunk_size = (ea->big_endian ? avio_rb32(pb) : avio_rl32(pb)) - 8;
|
472 |
|
473 |
switch (chunk_type) {
|
474 |
/* audio data */
|
475 |
case ISNh_TAG:
|
476 |
/* header chunk also contains data; skip over the header portion*/
|
477 |
avio_seek(pb, 32, SEEK_CUR);
|
478 |
chunk_size -= 32;
|
479 |
case ISNd_TAG:
|
480 |
case SCDl_TAG:
|
481 |
case SNDC_TAG:
|
482 |
case SDEN_TAG:
|
483 |
if (!ea->audio_codec) {
|
484 |
avio_seek(pb, chunk_size, SEEK_CUR); |
485 |
break;
|
486 |
} else if (ea->audio_codec == CODEC_ID_PCM_S16LE_PLANAR || |
487 |
ea->audio_codec == CODEC_ID_MP3) { |
488 |
num_samples = avio_rl32(pb); |
489 |
avio_seek(pb, 8, SEEK_CUR);
|
490 |
chunk_size -= 12;
|
491 |
} |
492 |
ret = av_get_packet(pb, pkt, chunk_size); |
493 |
if (ret < 0) |
494 |
return ret;
|
495 |
pkt->stream_index = ea->audio_stream_index; |
496 |
pkt->pts = 90000;
|
497 |
pkt->pts *= ea->audio_frame_counter; |
498 |
pkt->pts /= ea->sample_rate; |
499 |
|
500 |
switch (ea->audio_codec) {
|
501 |
case CODEC_ID_ADPCM_EA:
|
502 |
/* 2 samples/byte, 1 or 2 samples per frame depending
|
503 |
* on stereo; chunk also has 12-byte header */
|
504 |
ea->audio_frame_counter += ((chunk_size - 12) * 2) / |
505 |
ea->num_channels; |
506 |
break;
|
507 |
case CODEC_ID_PCM_S16LE_PLANAR:
|
508 |
case CODEC_ID_MP3:
|
509 |
ea->audio_frame_counter += num_samples; |
510 |
break;
|
511 |
default:
|
512 |
ea->audio_frame_counter += chunk_size / |
513 |
(ea->bytes * ea->num_channels); |
514 |
} |
515 |
|
516 |
packet_read = 1;
|
517 |
break;
|
518 |
|
519 |
/* ending tag */
|
520 |
case 0: |
521 |
case ISNe_TAG:
|
522 |
case SCEl_TAG:
|
523 |
case SEND_TAG:
|
524 |
case SEEN_TAG:
|
525 |
ret = AVERROR(EIO); |
526 |
packet_read = 1;
|
527 |
break;
|
528 |
|
529 |
case MVIh_TAG:
|
530 |
case kVGT_TAG:
|
531 |
case pQGT_TAG:
|
532 |
case TGQs_TAG:
|
533 |
case MADk_TAG:
|
534 |
key = AV_PKT_FLAG_KEY; |
535 |
case MVIf_TAG:
|
536 |
case fVGT_TAG:
|
537 |
case MADm_TAG:
|
538 |
case MADe_TAG:
|
539 |
avio_seek(pb, -8, SEEK_CUR); // include chunk preamble |
540 |
chunk_size += 8;
|
541 |
goto get_video_packet;
|
542 |
|
543 |
case mTCD_TAG:
|
544 |
avio_seek(pb, 8, SEEK_CUR); // skip ea dct header |
545 |
chunk_size -= 8;
|
546 |
goto get_video_packet;
|
547 |
|
548 |
case MV0K_TAG:
|
549 |
case MPCh_TAG:
|
550 |
case pIQT_TAG:
|
551 |
key = AV_PKT_FLAG_KEY; |
552 |
case MV0F_TAG:
|
553 |
get_video_packet:
|
554 |
ret = av_get_packet(pb, pkt, chunk_size); |
555 |
if (ret < 0) |
556 |
return ret;
|
557 |
pkt->stream_index = ea->video_stream_index; |
558 |
pkt->flags |= key; |
559 |
packet_read = 1;
|
560 |
break;
|
561 |
|
562 |
default:
|
563 |
avio_seek(pb, chunk_size, SEEK_CUR); |
564 |
break;
|
565 |
} |
566 |
} |
567 |
|
568 |
return ret;
|
569 |
} |
570 |
|
571 |
AVInputFormat ff_ea_demuxer = { |
572 |
"ea",
|
573 |
NULL_IF_CONFIG_SMALL("Electronic Arts Multimedia Format"),
|
574 |
sizeof(EaDemuxContext),
|
575 |
ea_probe, |
576 |
ea_read_header, |
577 |
ea_read_packet, |
578 |
}; |