Imported Debian version 2.4.3~trusty1
[deb_ffmpeg.git] / ffmpeg / libavformat / electronicarts.c
CommitLineData
2ba45a60
DM
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 <inttypes.h>
29
30#include "libavutil/intreadwrite.h"
31#include "avformat.h"
32#include "internal.h"
33
34#define SCHl_TAG MKTAG('S', 'C', 'H', 'l')
35#define SEAD_TAG MKTAG('S', 'E', 'A', 'D') /* Sxxx header */
36#define SNDC_TAG MKTAG('S', 'N', 'D', 'C') /* Sxxx data */
37#define SEND_TAG MKTAG('S', 'E', 'N', 'D') /* Sxxx end */
38#define SHEN_TAG MKTAG('S', 'H', 'E', 'N') /* SxEN header */
39#define SDEN_TAG MKTAG('S', 'D', 'E', 'N') /* SxEN data */
40#define SEEN_TAG MKTAG('S', 'E', 'E', 'N') /* SxEN end */
41#define ISNh_TAG MKTAG('1', 'S', 'N', 'h') /* 1SNx header */
42#define EACS_TAG MKTAG('E', 'A', 'C', 'S')
43#define ISNd_TAG MKTAG('1', 'S', 'N', 'd') /* 1SNx data */
44#define ISNe_TAG MKTAG('1', 'S', 'N', 'e') /* 1SNx end */
45#define PT00_TAG MKTAG('P', 'T', 0x0, 0x0)
46#define GSTR_TAG MKTAG('G', 'S', 'T', 'R')
47#define SCDl_TAG MKTAG('S', 'C', 'D', 'l')
48#define SCEl_TAG MKTAG('S', 'C', 'E', 'l')
49#define kVGT_TAG MKTAG('k', 'V', 'G', 'T') /* TGV I-frame */
50#define fVGT_TAG MKTAG('f', 'V', 'G', 'T') /* TGV P-frame */
51#define mTCD_TAG MKTAG('m', 'T', 'C', 'D') /* MDEC */
52#define MADk_TAG MKTAG('M', 'A', 'D', 'k') /* MAD I-frame */
53#define MADm_TAG MKTAG('M', 'A', 'D', 'm') /* MAD P-frame */
54#define MADe_TAG MKTAG('M', 'A', 'D', 'e') /* MAD lqp-frame */
55#define MPCh_TAG MKTAG('M', 'P', 'C', 'h') /* MPEG-2 */
56#define TGQs_TAG MKTAG('T', 'G', 'Q', 's') /* TGQ I-frame (appears in .TGQ files) */
57#define pQGT_TAG MKTAG('p', 'Q', 'G', 'T') /* TGQ I-frame (appears in .UV files) */
58#define pIQT_TAG MKTAG('p', 'I', 'Q', 'T') /* TQI/UV2 I-frame (.UV2/.WVE) */
59#define MVhd_TAG MKTAG('M', 'V', 'h', 'd')
60#define MV0K_TAG MKTAG('M', 'V', '0', 'K')
61#define MV0F_TAG MKTAG('M', 'V', '0', 'F')
62#define MVIh_TAG MKTAG('M', 'V', 'I', 'h') /* CMV header */
63#define MVIf_TAG MKTAG('M', 'V', 'I', 'f') /* CMV I-frame */
64
65typedef struct EaDemuxContext {
66 int big_endian;
67
68 enum AVCodecID video_codec;
69 AVRational time_base;
70 int width, height;
71 int nb_frames;
72 int video_stream_index;
73
74 enum AVCodecID audio_codec;
75 int audio_stream_index;
76
77 int bytes;
78 int sample_rate;
79 int num_channels;
80 int num_samples;
81} EaDemuxContext;
82
83static uint32_t read_arbitrary(AVIOContext *pb)
84{
85 uint8_t size, byte;
86 int i;
87 uint32_t word;
88
89 size = avio_r8(pb);
90
91 word = 0;
92 for (i = 0; i < size; i++) {
93 byte = avio_r8(pb);
94 word <<= 8;
95 word |= byte;
96 }
97
98 return word;
99}
100
101static int process_audio_header_elements(AVFormatContext *s)
102{
103 EaDemuxContext *ea = s->priv_data;
104 AVIOContext *pb = s->pb;
105 int in_header = 1;
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 (!avio_feof(pb) && in_header) {
113 int in_subheader;
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 in_subheader = 1;
121 while (!avio_feof(pb) && in_subheader) {
122 uint8_t subbyte;
123 subbyte = avio_r8(pb);
124
125 switch (subbyte) {
126 case 0x80:
127 revision = read_arbitrary(pb);
128 av_log(s, AV_LOG_DEBUG,
129 "revision (element 0x80) set to 0x%08x\n", revision);
130 break;
131 case 0x82:
132 ea->num_channels = read_arbitrary(pb);
133 av_log(s, AV_LOG_DEBUG,
134 "num_channels (element 0x82) set to 0x%08x\n",
135 ea->num_channels);
136 break;
137 case 0x83:
138 compression_type = read_arbitrary(pb);
139 av_log(s, AV_LOG_DEBUG,
140 "compression_type (element 0x83) set to 0x%08x\n",
141 compression_type);
142 break;
143 case 0x84:
144 ea->sample_rate = read_arbitrary(pb);
145 av_log(s, AV_LOG_DEBUG,
146 "sample_rate (element 0x84) set to %i\n",
147 ea->sample_rate);
148 break;
149 case 0x85:
150 ea->num_samples = read_arbitrary(pb);
151 av_log(s, AV_LOG_DEBUG,
152 "num_samples (element 0x85) set to 0x%08x\n",
153 ea->num_samples);
154 break;
155 case 0x8A:
156 av_log(s, AV_LOG_DEBUG,
157 "element 0x%02x set to 0x%08"PRIx32"\n",
158 subbyte, read_arbitrary(pb));
159 av_log(s, AV_LOG_DEBUG, "exited audio subheader\n");
160 in_subheader = 0;
161 break;
162 case 0xA0:
163 revision2 = read_arbitrary(pb);
164 av_log(s, AV_LOG_DEBUG,
165 "revision2 (element 0xA0) set to 0x%08x\n",
166 revision2);
167 break;
168 case 0xFF:
169 av_log(s, AV_LOG_DEBUG,
170 "end of header block reached (within audio subheader)\n");
171 in_subheader = 0;
172 in_header = 0;
173 break;
174 default:
175 av_log(s, AV_LOG_DEBUG,
176 "element 0x%02x set to 0x%08"PRIx32"\n",
177 subbyte, read_arbitrary(pb));
178 break;
179 }
180 }
181 break;
182 case 0xFF:
183 av_log(s, AV_LOG_DEBUG, "end of header block reached\n");
184 in_header = 0;
185 break;
186 default:
187 av_log(s, AV_LOG_DEBUG,
188 "header element 0x%02x set to 0x%08"PRIx32"\n",
189 byte, read_arbitrary(pb));
190 break;
191 }
192 }
193
194 switch (compression_type) {
195 case 0:
196 ea->audio_codec = AV_CODEC_ID_PCM_S16LE;
197 break;
198 case 7:
199 ea->audio_codec = AV_CODEC_ID_ADPCM_EA;
200 break;
201 case -1:
202 switch (revision) {
203 case 1:
204 ea->audio_codec = AV_CODEC_ID_ADPCM_EA_R1;
205 break;
206 case 2:
207 ea->audio_codec = AV_CODEC_ID_ADPCM_EA_R2;
208 break;
209 case 3:
210 ea->audio_codec = AV_CODEC_ID_ADPCM_EA_R3;
211 break;
212 case -1:
213 break;
214 default:
215 avpriv_request_sample(s, "stream type; revision=%i", revision);
216 return 0;
217 }
218 switch (revision2) {
219 case 8:
220 ea->audio_codec = AV_CODEC_ID_PCM_S16LE_PLANAR;
221 break;
222 case 10:
223 switch (revision) {
224 case -1:
225 case 2: ea->audio_codec = AV_CODEC_ID_ADPCM_EA_R1; break;
226 case 3: ea->audio_codec = AV_CODEC_ID_ADPCM_EA_R2; break;
227 default:
228 avpriv_request_sample(s, "stream type; revision=%i, revision2=%i", revision, revision2);
229 return 0;
230 }
231 break;
232 case 16:
233 ea->audio_codec = AV_CODEC_ID_MP3;
234 break;
235 case -1:
236 break;
237 default:
238 ea->audio_codec = AV_CODEC_ID_NONE;
239 avpriv_request_sample(s, "stream type; revision2=%i", revision2);
240 return 0;
241 }
242 break;
243 default:
244 avpriv_request_sample(s,
245 "stream type; compression_type=%i",
246 compression_type);
247 return 0;
248 }
249
250 if (ea->sample_rate == -1)
251 ea->sample_rate = revision == 3 ? 48000 : 22050;
252
253 return 1;
254}
255
256static void process_audio_header_eacs(AVFormatContext *s)
257{
258 EaDemuxContext *ea = s->priv_data;
259 AVIOContext *pb = s->pb;
260 int compression_type;
261
262 ea->sample_rate = ea->big_endian ? avio_rb32(pb) : avio_rl32(pb);
263 ea->bytes = avio_r8(pb); /* 1=8-bit, 2=16-bit */
264 ea->num_channels = avio_r8(pb);
265 compression_type = avio_r8(pb);
266 avio_skip(pb, 13);
267
268 switch (compression_type) {
269 case 0:
270 switch (ea->bytes) {
271 case 1:
272 ea->audio_codec = AV_CODEC_ID_PCM_S8;
273 break;
274 case 2:
275 ea->audio_codec = AV_CODEC_ID_PCM_S16LE;
276 break;
277 }
278 break;
279 case 1:
280 ea->audio_codec = AV_CODEC_ID_PCM_MULAW;
281 ea->bytes = 1;
282 break;
283 case 2:
284 ea->audio_codec = AV_CODEC_ID_ADPCM_IMA_EA_EACS;
285 break;
286 default:
287 avpriv_request_sample(s,
288 "stream type; audio compression_type=%i",
289 compression_type);
290 }
291}
292
293static void process_audio_header_sead(AVFormatContext *s)
294{
295 EaDemuxContext *ea = s->priv_data;
296 AVIOContext *pb = s->pb;
297
298 ea->sample_rate = avio_rl32(pb);
299 ea->bytes = avio_rl32(pb); /* 1=8-bit, 2=16-bit */
300 ea->num_channels = avio_rl32(pb);
301 ea->audio_codec = AV_CODEC_ID_ADPCM_IMA_EA_SEAD;
302}
303
304static void process_video_header_mdec(AVFormatContext *s)
305{
306 EaDemuxContext *ea = s->priv_data;
307 AVIOContext *pb = s->pb;
308 avio_skip(pb, 4);
309 ea->width = avio_rl16(pb);
310 ea->height = avio_rl16(pb);
311 ea->time_base = (AVRational) { 1, 15 };
312 ea->video_codec = AV_CODEC_ID_MDEC;
313}
314
315static int process_video_header_vp6(AVFormatContext *s)
316{
317 EaDemuxContext *ea = s->priv_data;
318 AVIOContext *pb = s->pb;
319
320 avio_skip(pb, 8);
321 ea->nb_frames = avio_rl32(pb);
322 avio_skip(pb, 4);
323 ea->time_base.den = avio_rl32(pb);
324 ea->time_base.num = avio_rl32(pb);
325 if (ea->time_base.den <= 0 || ea->time_base.num <= 0) {
326 av_log(s, AV_LOG_ERROR, "Timebase is invalid\n");
327 return AVERROR_INVALIDDATA;
328 }
329 ea->video_codec = AV_CODEC_ID_VP6;
330
331 return 1;
332}
333
334static void process_video_header_cmv(AVFormatContext *s)
335{
336 EaDemuxContext *ea = s->priv_data;
337 int fps;
338
339 avio_skip(s->pb, 10);
340 fps = avio_rl16(s->pb);
341 if (fps)
342 ea->time_base = (AVRational) { 1, fps };
343 ea->video_codec = AV_CODEC_ID_CMV;
344}
345
346/* Process EA file header.
347 * Return 1 if the EA file is valid and successfully opened, 0 otherwise. */
348static int process_ea_header(AVFormatContext *s)
349{
350 uint32_t blockid, size = 0;
351 EaDemuxContext *ea = s->priv_data;
352 AVIOContext *pb = s->pb;
353 int i;
354
355 for (i = 0; i < 5 && (!ea->audio_codec || !ea->video_codec); i++) {
356 uint64_t startpos = avio_tell(pb);
357 int err = 0;
358
359 blockid = avio_rl32(pb);
360 size = avio_rl32(pb);
361 if (i == 0)
362 ea->big_endian = size > av_bswap32(size);
363 if (ea->big_endian)
364 size = av_bswap32(size);
365
366 if (size < 8) {
367 av_log(s, AV_LOG_ERROR, "chunk size too small\n");
368 return AVERROR_INVALIDDATA;
369 }
370
371 switch (blockid) {
372 case ISNh_TAG:
373 if (avio_rl32(pb) != EACS_TAG) {
374 avpriv_request_sample(s, "unknown 1SNh headerid");
375 return 0;
376 }
377 process_audio_header_eacs(s);
378 break;
379
380 case SCHl_TAG:
381 case SHEN_TAG:
382 blockid = avio_rl32(pb);
383 if (blockid == GSTR_TAG) {
384 avio_skip(pb, 4);
385 } else if ((blockid & 0xFFFF) != PT00_TAG) {
386 avpriv_request_sample(s, "unknown SCHl headerid");
387 return 0;
388 }
389 err = process_audio_header_elements(s);
390 break;
391
392 case SEAD_TAG:
393 process_audio_header_sead(s);
394 break;
395
396 case MVIh_TAG:
397 process_video_header_cmv(s);
398 break;
399
400 case kVGT_TAG:
401 ea->video_codec = AV_CODEC_ID_TGV;
402 break;
403
404 case mTCD_TAG:
405 process_video_header_mdec(s);
406 break;
407
408 case MPCh_TAG:
409 ea->video_codec = AV_CODEC_ID_MPEG2VIDEO;
410 break;
411
412 case pQGT_TAG:
413 case TGQs_TAG:
414 ea->video_codec = AV_CODEC_ID_TGQ;
415 ea->time_base = (AVRational) { 1, 15 };
416 break;
417
418 case pIQT_TAG:
419 ea->video_codec = AV_CODEC_ID_TQI;
420 ea->time_base = (AVRational) { 1, 15 };
421 break;
422
423 case MADk_TAG:
424 ea->video_codec = AV_CODEC_ID_MAD;
425 avio_skip(pb, 6);
426 ea->time_base = (AVRational) { avio_rl16(pb), 1000 };
427 break;
428
429 case MVhd_TAG:
430 err = process_video_header_vp6(s);
431 break;
432 }
433
434 if (err < 0) {
435 av_log(s, AV_LOG_ERROR, "error parsing header: %i\n", err);
436 return err;
437 }
438
439 avio_seek(pb, startpos + size, SEEK_SET);
440 }
441
442 avio_seek(pb, 0, SEEK_SET);
443
444 return 1;
445}
446
447static int ea_probe(AVProbeData *p)
448{
449 unsigned big_endian, size;
450
451 switch (AV_RL32(&p->buf[0])) {
452 case ISNh_TAG:
453 case SCHl_TAG:
454 case SEAD_TAG:
455 case SHEN_TAG:
456 case kVGT_TAG:
457 case MADk_TAG:
458 case MPCh_TAG:
459 case MVhd_TAG:
460 case MVIh_TAG:
461 break;
462 default:
463 return 0;
464 }
465 size = AV_RL32(&p->buf[4]);
466 big_endian = size > 0x000FFFFF;
467 if (big_endian)
468 size = av_bswap32(size);
469 if (size > 0xfffff || size < 8)
470 return 0;
471
472 return AVPROBE_SCORE_MAX;
473}
474
475static int ea_read_header(AVFormatContext *s)
476{
477 EaDemuxContext *ea = s->priv_data;
478 AVStream *st;
479
480 if (process_ea_header(s)<=0)
481 return AVERROR(EIO);
482
483 if (ea->video_codec) {
484 /* initialize the video decoder stream */
485 st = avformat_new_stream(s, NULL);
486 if (!st)
487 return AVERROR(ENOMEM);
488 ea->video_stream_index = st->index;
489 st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
490 st->codec->codec_id = ea->video_codec;
491 // parsing is necessary to make FFmpeg generate correct timestamps
492 if (st->codec->codec_id == AV_CODEC_ID_MPEG2VIDEO)
493 st->need_parsing = AVSTREAM_PARSE_HEADERS;
494 st->codec->codec_tag = 0; /* no fourcc */
495 st->codec->width = ea->width;
496 st->codec->height = ea->height;
497 st->duration = st->nb_frames = ea->nb_frames;
498 if (ea->time_base.num)
499 avpriv_set_pts_info(st, 64, ea->time_base.num, ea->time_base.den);
500 st->r_frame_rate =
501 st->avg_frame_rate = av_inv_q(ea->time_base);
502 }
503
504 if (ea->audio_codec) {
505 if (ea->num_channels <= 0 || ea->num_channels > 2) {
506 av_log(s, AV_LOG_WARNING,
507 "Unsupported number of channels: %d\n", ea->num_channels);
508 ea->audio_codec = 0;
509 return 1;
510 }
511 if (ea->sample_rate <= 0) {
512 av_log(s, AV_LOG_ERROR,
513 "Unsupported sample rate: %d\n", ea->sample_rate);
514 ea->audio_codec = 0;
515 return 1;
516 }
517 if (ea->bytes <= 0) {
518 av_log(s, AV_LOG_ERROR,
519 "Invalid number of bytes per sample: %d\n", ea->bytes);
520 ea->audio_codec = AV_CODEC_ID_NONE;
521 return 1;
522 }
523
524 /* initialize the audio decoder stream */
525 st = avformat_new_stream(s, NULL);
526 if (!st)
527 return AVERROR(ENOMEM);
528 avpriv_set_pts_info(st, 33, 1, ea->sample_rate);
529 st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
530 st->codec->codec_id = ea->audio_codec;
531 st->codec->codec_tag = 0; /* no tag */
532 st->codec->channels = ea->num_channels;
533 st->codec->sample_rate = ea->sample_rate;
534 st->codec->bits_per_coded_sample = ea->bytes * 8;
535 st->codec->bit_rate = st->codec->channels *
536 st->codec->sample_rate *
537 st->codec->bits_per_coded_sample / 4;
538 st->codec->block_align = st->codec->channels *
539 st->codec->bits_per_coded_sample;
540 ea->audio_stream_index = st->index;
541 st->start_time = 0;
542 }
543
544 return 1;
545}
546
547static int ea_read_packet(AVFormatContext *s, AVPacket *pkt)
548{
549 EaDemuxContext *ea = s->priv_data;
550 AVIOContext *pb = s->pb;
551 int partial_packet = 0;
552 unsigned int chunk_type, chunk_size;
553 int ret = 0, packet_read = 0, key = 0;
554 int av_uninit(num_samples);
555
556 while (!packet_read || partial_packet) {
557 chunk_type = avio_rl32(pb);
558 chunk_size = ea->big_endian ? avio_rb32(pb) : avio_rl32(pb);
559 if (chunk_size < 8)
560 return AVERROR_INVALIDDATA;
561 chunk_size -= 8;
562
563 switch (chunk_type) {
564 /* audio data */
565 case ISNh_TAG:
566 /* header chunk also contains data; skip over the header portion */
567 if (chunk_size < 32)
568 return AVERROR_INVALIDDATA;
569 avio_skip(pb, 32);
570 chunk_size -= 32;
571 case ISNd_TAG:
572 case SCDl_TAG:
573 case SNDC_TAG:
574 case SDEN_TAG:
575 if (!ea->audio_codec) {
576 avio_skip(pb, chunk_size);
577 break;
578 } else if (ea->audio_codec == AV_CODEC_ID_PCM_S16LE_PLANAR ||
579 ea->audio_codec == AV_CODEC_ID_MP3) {
580 num_samples = avio_rl32(pb);
581 avio_skip(pb, 8);
582 chunk_size -= 12;
583 }
584
585 if (partial_packet) {
586 avpriv_request_sample(s, "video header followed by audio packet");
587 av_free_packet(pkt);
588 partial_packet = 0;
589 }
590
591 if (!chunk_size)
592 continue;
593
594 ret = av_get_packet(pb, pkt, chunk_size);
595 if (ret < 0)
596 return ret;
597 pkt->stream_index = ea->audio_stream_index;
598
599 switch (ea->audio_codec) {
600 case AV_CODEC_ID_ADPCM_EA:
601 case AV_CODEC_ID_ADPCM_EA_R1:
602 case AV_CODEC_ID_ADPCM_EA_R2:
603 case AV_CODEC_ID_ADPCM_IMA_EA_EACS:
604 case AV_CODEC_ID_ADPCM_EA_R3:
605 if (pkt->size < 4) {
606 av_log(s, AV_LOG_ERROR, "Packet is too short\n");
607 av_free_packet(pkt);
608 return AVERROR_INVALIDDATA;
609 }
610 if (ea->audio_codec == AV_CODEC_ID_ADPCM_EA_R3)
611 pkt->duration = AV_RB32(pkt->data);
612 else
613 pkt->duration = AV_RL32(pkt->data);
614 break;
615 case AV_CODEC_ID_ADPCM_IMA_EA_SEAD:
616 pkt->duration = ret * 2 / ea->num_channels;
617 break;
618 case AV_CODEC_ID_PCM_S16LE_PLANAR:
619 case AV_CODEC_ID_MP3:
620 pkt->duration = num_samples;
621 break;
622 default:
623 pkt->duration = chunk_size / (ea->bytes * ea->num_channels);
624 }
625
626 packet_read = 1;
627 break;
628
629 /* ending tag */
630 case 0:
631 case ISNe_TAG:
632 case SCEl_TAG:
633 case SEND_TAG:
634 case SEEN_TAG:
635 ret = AVERROR(EIO);
636 packet_read = 1;
637 break;
638
639 case MVIh_TAG:
640 case kVGT_TAG:
641 case pQGT_TAG:
642 case TGQs_TAG:
643 case MADk_TAG:
644 key = AV_PKT_FLAG_KEY;
645 case MVIf_TAG:
646 case fVGT_TAG:
647 case MADm_TAG:
648 case MADe_TAG:
649 avio_seek(pb, -8, SEEK_CUR); // include chunk preamble
650 chunk_size += 8;
651 goto get_video_packet;
652
653 case mTCD_TAG:
654 if (chunk_size < 8)
655 return AVERROR_INVALIDDATA;
656
657 avio_skip(pb, 8); // skip ea DCT header
658 chunk_size -= 8;
659 goto get_video_packet;
660
661 case MV0K_TAG:
662 case MPCh_TAG:
663 case pIQT_TAG:
664 key = AV_PKT_FLAG_KEY;
665 case MV0F_TAG:
666get_video_packet:
667 if (!chunk_size)
668 continue;
669
670 if (partial_packet) {
671 ret = av_append_packet(pb, pkt, chunk_size);
672 } else
673 ret = av_get_packet(pb, pkt, chunk_size);
674 if (ret < 0) {
675 packet_read = 1;
676 break;
677 }
678 partial_packet = chunk_type == MVIh_TAG;
679 pkt->stream_index = ea->video_stream_index;
680 pkt->flags |= key;
681 packet_read = 1;
682 break;
683
684 default:
685 avio_skip(pb, chunk_size);
686 break;
687 }
688 }
689
690 if (ret < 0 && partial_packet)
691 av_free_packet(pkt);
692 return ret;
693}
694
695AVInputFormat ff_ea_demuxer = {
696 .name = "ea",
697 .long_name = NULL_IF_CONFIG_SMALL("Electronic Arts Multimedia"),
698 .priv_data_size = sizeof(EaDemuxContext),
699 .read_probe = ea_probe,
700 .read_header = ea_read_header,
701 .read_packet = ea_read_packet,
702};