X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavformat%2Felectronicarts.c;h=0fb66970d609ecfaf99c4fa075af1adf3c7123c6;hb=b7ce3242f8000ad497a17c3288a59aa508cef31c;hp=a0007d2982265915c08c1f8cd0c77494f6d25d1a;hpb=e986a5d10d95b62cd85aaefc7d4da34699fbedeb;p=ffmpeg diff --git a/libavformat/electronicarts.c b/libavformat/electronicarts.c index a0007d29822..0fb66970d60 100644 --- a/libavformat/electronicarts.c +++ b/libavformat/electronicarts.c @@ -66,11 +66,11 @@ typedef struct EaDemuxContext { enum CodecID video_codec; AVRational time_base; int width, height; + int nb_frames; int video_stream_index; enum CodecID audio_codec; int audio_stream_index; - int audio_frame_counter; int bytes; int sample_rate; @@ -275,7 +275,9 @@ static int process_video_header_vp6(AVFormatContext *s) EaDemuxContext *ea = s->priv_data; AVIOContext *pb = s->pb; - avio_skip(pb, 16); + avio_skip(pb, 8); + ea->nb_frames = avio_rl32(pb); + avio_skip(pb, 4); ea->time_base.den = avio_rl32(pb); ea->time_base.num = avio_rl32(pb); ea->video_codec = CODEC_ID_VP6; @@ -283,6 +285,20 @@ static int process_video_header_vp6(AVFormatContext *s) return 1; } +static int process_video_header_cmv(AVFormatContext *s) +{ + EaDemuxContext *ea = s->priv_data; + int fps; + + avio_skip(s->pb, 10); + fps = avio_rl16(s->pb); + if (fps) + ea->time_base = (AVRational){1, fps}; + ea->video_codec = CODEC_ID_CMV; + + return 0; +} + /* * Process EA file header * Returns 1 if the EA file is valid and successfully opened, 0 otherwise @@ -330,7 +346,7 @@ static int process_ea_header(AVFormatContext *s) { break; case MVIh_TAG : - ea->video_codec = CODEC_ID_CMV; + err = process_video_header_cmv(s); break; case kVGT_TAG: @@ -398,8 +414,7 @@ static int ea_probe(AVProbeData *p) return AVPROBE_SCORE_MAX; } -static int ea_read_header(AVFormatContext *s, - AVFormatParameters *ap) +static int ea_read_header(AVFormatContext *s) { EaDemuxContext *ea = s->priv_data; AVStream *st; @@ -419,10 +434,13 @@ static int ea_read_header(AVFormatContext *s, if (st->codec->codec_id == CODEC_ID_MPEG2VIDEO) st->need_parsing = AVSTREAM_PARSE_HEADERS; st->codec->codec_tag = 0; /* no fourcc */ - if (ea->time_base.num) - avpriv_set_pts_info(st, 64, ea->time_base.num, ea->time_base.den); st->codec->width = ea->width; st->codec->height = ea->height; + st->duration = st->nb_frames = ea->nb_frames; + if (ea->time_base.num) + avpriv_set_pts_info(st, 64, ea->time_base.num, ea->time_base.den); + st->r_frame_rate = st->avg_frame_rate = (AVRational){ea->time_base.den, + ea->time_base.num}; } if (ea->audio_codec) { @@ -457,7 +475,7 @@ static int ea_read_header(AVFormatContext *s, st->codec->bits_per_coded_sample / 4; st->codec->block_align = st->codec->channels*st->codec->bits_per_coded_sample; ea->audio_stream_index = st->index; - ea->audio_frame_counter = 0; + st->start_time = 0; } return 1; @@ -470,11 +488,12 @@ static int ea_read_packet(AVFormatContext *s, AVIOContext *pb = s->pb; int ret = 0; int packet_read = 0; + int partial_packet = 0; unsigned int chunk_type, chunk_size; int key = 0; int av_uninit(num_samples); - while (!packet_read) { + while (!packet_read || partial_packet) { chunk_type = avio_rl32(pb); chunk_size = (ea->big_endian ? avio_rb32(pb) : avio_rl32(pb)) - 8; @@ -497,28 +516,35 @@ static int ea_read_packet(AVFormatContext *s, avio_skip(pb, 8); chunk_size -= 12; } + if (partial_packet) { + av_log_ask_for_sample(s, "video header followed by audio packet not supported.\n"); + av_free_packet(pkt); + partial_packet = 0; + } ret = av_get_packet(pb, pkt, chunk_size); if (ret < 0) return ret; pkt->stream_index = ea->audio_stream_index; - pkt->pts = 90000; - pkt->pts *= ea->audio_frame_counter; - pkt->pts /= ea->sample_rate; switch (ea->audio_codec) { case CODEC_ID_ADPCM_EA: - /* 2 samples/byte, 1 or 2 samples per frame depending - * on stereo; chunk also has 12-byte header */ - ea->audio_frame_counter += ((chunk_size - 12) * 2) / - ea->num_channels; + case CODEC_ID_ADPCM_EA_R1: + case CODEC_ID_ADPCM_EA_R2: + case CODEC_ID_ADPCM_IMA_EA_EACS: + pkt->duration = AV_RL32(pkt->data); + break; + case CODEC_ID_ADPCM_EA_R3: + pkt->duration = AV_RB32(pkt->data); + break; + case CODEC_ID_ADPCM_IMA_EA_SEAD: + pkt->duration = ret * 2 / ea->num_channels; break; case CODEC_ID_PCM_S16LE_PLANAR: case CODEC_ID_MP3: - ea->audio_frame_counter += num_samples; + pkt->duration = num_samples; break; default: - ea->audio_frame_counter += chunk_size / - (ea->bytes * ea->num_channels); + pkt->duration = chunk_size / (ea->bytes * ea->num_channels); } packet_read = 1; @@ -559,9 +585,15 @@ static int ea_read_packet(AVFormatContext *s, key = AV_PKT_FLAG_KEY; case MV0F_TAG: get_video_packet: - ret = av_get_packet(pb, pkt, chunk_size); - if (ret < 0) - return ret; + if (partial_packet) { + ret = av_append_packet(pb, pkt, chunk_size); + } else + ret = av_get_packet(pb, pkt, chunk_size); + if (ret < 0) { + packet_read = 1; + break; + } + partial_packet = chunk_type == MVIh_TAG; pkt->stream_index = ea->video_stream_index; pkt->flags |= key; packet_read = 1; @@ -573,6 +605,8 @@ get_video_packet: } } + if (ret < 0 && partial_packet) + av_free_packet(pkt); return ret; }