X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavformat%2Felectronicarts.c;h=6e53ae7b35f86d5e850a26f98a566fbdf670bd8f;hb=a2517fca1e7dc5e0ff63c8490b5c92a9298f5837;hp=d6a396b1ef5ffcfc9e8bbe17d97b6ccbf5a8ee78;hpb=6ed8341cb163e4c253449458aa21a0b3aab1e2b6;p=ffmpeg diff --git a/libavformat/electronicarts.c b/libavformat/electronicarts.c index d6a396b1ef5..6e53ae7b35f 100644 --- a/libavformat/electronicarts.c +++ b/libavformat/electronicarts.c @@ -61,15 +61,20 @@ #define MV0F_TAG MKTAG('M', 'V', '0', 'F') #define MVIh_TAG MKTAG('M', 'V', 'I', 'h') /* CMV header */ #define MVIf_TAG MKTAG('M', 'V', 'I', 'f') /* CMV I-frame */ +#define AVP6_TAG MKTAG('A', 'V', 'P', '6') -typedef struct EaDemuxContext { - int big_endian; - - enum AVCodecID video_codec; +typedef struct VideoProperties { + enum AVCodecID codec; AVRational time_base; int width, height; int nb_frames; - int video_stream_index; + int stream_index; +} VideoProperties; + +typedef struct EaDemuxContext { + int big_endian; + + VideoProperties video; enum AVCodecID audio_codec; int audio_stream_index; @@ -301,46 +306,43 @@ static void process_audio_header_sead(AVFormatContext *s) ea->audio_codec = AV_CODEC_ID_ADPCM_IMA_EA_SEAD; } -static void process_video_header_mdec(AVFormatContext *s) +static void process_video_header_mdec(AVFormatContext *s, VideoProperties *video) { - EaDemuxContext *ea = s->priv_data; AVIOContext *pb = s->pb; avio_skip(pb, 4); - ea->width = avio_rl16(pb); - ea->height = avio_rl16(pb); - ea->time_base = (AVRational) { 1, 15 }; - ea->video_codec = AV_CODEC_ID_MDEC; + video->width = avio_rl16(pb); + video->height = avio_rl16(pb); + video->time_base = (AVRational) { 1, 15 }; + video->codec = AV_CODEC_ID_MDEC; } -static int process_video_header_vp6(AVFormatContext *s) +static int process_video_header_vp6(AVFormatContext *s, VideoProperties *video) { - EaDemuxContext *ea = s->priv_data; - AVIOContext *pb = s->pb; + AVIOContext *pb = s->pb; avio_skip(pb, 8); - ea->nb_frames = avio_rl32(pb); + video->nb_frames = avio_rl32(pb); avio_skip(pb, 4); - ea->time_base.den = avio_rl32(pb); - ea->time_base.num = avio_rl32(pb); - if (ea->time_base.den <= 0 || ea->time_base.num <= 0) { + video->time_base.den = avio_rl32(pb); + video->time_base.num = avio_rl32(pb); + if (video->time_base.den <= 0 || video->time_base.num <= 0) { av_log(s, AV_LOG_ERROR, "Timebase is invalid\n"); return AVERROR_INVALIDDATA; } - ea->video_codec = AV_CODEC_ID_VP6; + video->codec = AV_CODEC_ID_VP6; return 1; } -static void process_video_header_cmv(AVFormatContext *s) +static void process_video_header_cmv(AVFormatContext *s, VideoProperties *video) { - 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 = AV_CODEC_ID_CMV; + video->time_base = (AVRational) { 1, fps }; + video->codec = AV_CODEC_ID_CMV; } /* Process EA file header. @@ -352,7 +354,7 @@ static int process_ea_header(AVFormatContext *s) AVIOContext *pb = s->pb; int i; - for (i = 0; i < 5 && (!ea->audio_codec || !ea->video_codec); i++) { + for (i = 0; i < 5 && (!ea->audio_codec || !ea->video.codec); i++) { uint64_t startpos = avio_tell(pb); int err = 0; @@ -394,40 +396,40 @@ static int process_ea_header(AVFormatContext *s) break; case MVIh_TAG: - process_video_header_cmv(s); + process_video_header_cmv(s, &ea->video); break; case kVGT_TAG: - ea->video_codec = AV_CODEC_ID_TGV; + ea->video.codec = AV_CODEC_ID_TGV; break; case mTCD_TAG: - process_video_header_mdec(s); + process_video_header_mdec(s, &ea->video); break; case MPCh_TAG: - ea->video_codec = AV_CODEC_ID_MPEG2VIDEO; + ea->video.codec = AV_CODEC_ID_MPEG2VIDEO; break; case pQGT_TAG: case TGQs_TAG: - ea->video_codec = AV_CODEC_ID_TGQ; - ea->time_base = (AVRational) { 1, 15 }; + ea->video.codec = AV_CODEC_ID_TGQ; + ea->video.time_base = (AVRational) { 1, 15 }; break; case pIQT_TAG: - ea->video_codec = AV_CODEC_ID_TQI; - ea->time_base = (AVRational) { 1, 15 }; + ea->video.codec = AV_CODEC_ID_TQI; + ea->video.time_base = (AVRational) { 1, 15 }; break; case MADk_TAG: - ea->video_codec = AV_CODEC_ID_MAD; + ea->video.codec = AV_CODEC_ID_MAD; avio_skip(pb, 6); - ea->time_base = (AVRational) { avio_rl16(pb), 1000 }; + ea->video.time_base = (AVRational) { avio_rl16(pb), 1000 }; break; case MVhd_TAG: - err = process_video_header_vp6(s); + err = process_video_header_vp6(s, &ea->video); break; } @@ -458,6 +460,7 @@ static int ea_probe(AVProbeData *p) case MPCh_TAG: case MVhd_TAG: case MVIh_TAG: + case AVP6_TAG: break; default: return 0; @@ -472,6 +475,34 @@ static int ea_probe(AVProbeData *p) return AVPROBE_SCORE_MAX; } +static int init_video_stream(AVFormatContext *s, VideoProperties *video) +{ + AVStream *st; + + if (!video->codec) + return 0; + + /* initialize the video decoder stream */ + st = avformat_new_stream(s, NULL); + if (!st) + return AVERROR(ENOMEM); + video->stream_index = st->index; + st->codec->codec_type = AVMEDIA_TYPE_VIDEO; + st->codec->codec_id = video->codec; + // parsing is necessary to make FFmpeg generate correct timestamps + if (st->codec->codec_id == AV_CODEC_ID_MPEG2VIDEO) + st->need_parsing = AVSTREAM_PARSE_HEADERS; + st->codec->codec_tag = 0; /* no fourcc */ + st->codec->width = video->width; + st->codec->height = video->height; + st->duration = st->nb_frames = video->nb_frames; + if (video->time_base.num) + avpriv_set_pts_info(st, 64, video->time_base.num, video->time_base.den); + st->r_frame_rate = + st->avg_frame_rate = av_inv_q(video->time_base); + return 0; +} + static int ea_read_header(AVFormatContext *s) { EaDemuxContext *ea = s->priv_data; @@ -480,26 +511,8 @@ static int ea_read_header(AVFormatContext *s) if (process_ea_header(s)<=0) return AVERROR(EIO); - if (ea->video_codec) { - /* initialize the video decoder stream */ - st = avformat_new_stream(s, NULL); - if (!st) - return AVERROR(ENOMEM); - ea->video_stream_index = st->index; - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - st->codec->codec_id = ea->video_codec; - // parsing is necessary to make FFmpeg generate correct timestamps - if (st->codec->codec_id == AV_CODEC_ID_MPEG2VIDEO) - st->need_parsing = AVSTREAM_PARSE_HEADERS; - st->codec->codec_tag = 0; /* no fourcc */ - 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 = av_inv_q(ea->time_base); - } + if (init_video_stream(s, &ea->video)) + return AVERROR(ENOMEM); if (ea->audio_codec) { if (ea->num_channels <= 0 || ea->num_channels > 2) { @@ -676,7 +689,7 @@ get_video_packet: break; } partial_packet = chunk_type == MVIh_TAG; - pkt->stream_index = ea->video_stream_index; + pkt->stream_index = ea->video.stream_index; pkt->flags |= key; packet_read = 1; break;