diff options
author | wm4 <wm4@nowhere> | 2012-10-29 00:06:51 +0100 |
---|---|---|
committer | wm4 <wm4@nowhere> | 2012-10-30 19:50:24 +0100 |
commit | 219e1ab1e7dd5a91e7e55adc90c0daf242783842 (patch) | |
tree | b7a6affc48c2dd4c176f5101a4c040b29ec82e30 | |
parent | 0c95e139a989ec3b18e97c3aab87adbe028d6185 (diff) | |
download | mpv-219e1ab1e7dd5a91e7e55adc90c0daf242783842.tar.bz2 mpv-219e1ab1e7dd5a91e7e55adc90c0daf242783842.tar.xz |
demux_lavf: add a hack to work around other hacks
mplayer (and all forks) use a single FourCC field to map codecs. This is
what sh_video->format and sh_audio->format is used for. Basically it's a
key into the codecs.conf table to find out what decoder to use. (There's
only one video codec and one major audio codec left - both libavcodec.
But we still have to deal with mapping coming from non-libavformat
demuxers.)
It seems this causes some video codecs to fail, such as WV1F in AVI [1].
demux_lavf generally throws away the codec_tag from libavformat if the
codec is MPEG-in-AVI. There are probably other cases like this. Add a
hack to enforce passing the correct codec tag when only ffmpeg demuxers
and decoders involved.
Note: the sample [1] needs to be flipped. With --demuxer=avi, this is
done correctly, because unlike demux_lavf, the demuxer uses the FourCC
directly for the sh_video->format tag, and finds the correct codecs.conf
entry (which contains the flip flag). We could just add a "whitelist" of
codec tags which can be passed through to sh_video->format, but I don't
want to do that just for such an obscure format as the sample at hand.
Note 2: when demux_lavf is used, the AVCodecContext could be passed
directly to vd_ffmpeg/ad_ffmpeg. The code to convert to/from the
internal mplayer stream headers is probably still needed, as there are
non-ffmpeg demuxers and audio decoders.
[1] http://samples.mplayerhq.hu/V-codecs/WV1F/AVI/title2.avi
-rw-r--r-- | libmpcodecs/ad_ffmpeg.c | 2 | ||||
-rw-r--r-- | libmpcodecs/vd_ffmpeg.c | 2 | ||||
-rw-r--r-- | libmpdemux/demux_lavf.c | 5 | ||||
-rw-r--r-- | libmpdemux/stheader.h | 3 |
4 files changed, 12 insertions, 0 deletions
diff --git a/libmpcodecs/ad_ffmpeg.c b/libmpcodecs/ad_ffmpeg.c index cca7725490..1d6683672b 100644 --- a/libmpcodecs/ad_ffmpeg.c +++ b/libmpcodecs/ad_ffmpeg.c @@ -159,6 +159,8 @@ static int init(sh_audio_t *sh_audio) } lavc_context->request_channels = opts->audio_output_channels; lavc_context->codec_tag = sh_audio->format; //FOURCC + if (sh_audio->gsh->lavf_codec_tag) + lavc_context->codec_tag = sh_audio->gsh->lavf_codec_tag; lavc_context->codec_type = AVMEDIA_TYPE_AUDIO; lavc_context->codec_id = lavc_codec->id; // not sure if required, imho not --A'rpi diff --git a/libmpcodecs/vd_ffmpeg.c b/libmpcodecs/vd_ffmpeg.c index 948fde2d00..10d494e48c 100644 --- a/libmpcodecs/vd_ffmpeg.c +++ b/libmpcodecs/vd_ffmpeg.c @@ -239,6 +239,8 @@ static int init(sh_video_t *sh) } else { avctx->pix_fmt = rawfmt; } + if (sh->gsh->lavf_codec_tag) + avctx->codec_tag = sh->gsh->lavf_codec_tag; avctx->stream_codec_tag = sh->video.fccHandler; avctx->idct_algo = lavc_param->idct_algo; avctx->error_concealment = lavc_param->error_concealment; diff --git a/libmpdemux/demux_lavf.c b/libmpdemux/demux_lavf.c index b1312a632f..c619d00b72 100644 --- a/libmpdemux/demux_lavf.c +++ b/libmpdemux/demux_lavf.c @@ -292,6 +292,8 @@ static void handle_stream(demuxer_t *demuxer, AVFormatContext *avfc, int i) int stream_id; AVDictionaryEntry *lang = av_dict_get(st->metadata, "language", NULL, 0); AVDictionaryEntry *title = av_dict_get(st->metadata, "title", NULL, 0); + // Work around collisions resulting from the hacks changing codec_tag. + int lavf_codec_tag = codec->codec_tag; // Don't use native MPEG codec tag values with our generic tag tables. // May contain for example value 3 for MP3, which we'd map to PCM audio. if (matches_avinputformat_name(priv, "mpeg") || @@ -320,6 +322,7 @@ static void handle_stream(demuxer_t *demuxer, AVFormatContext *avfc, int i) stream_type = "audio"; priv->astreams[priv->audio_streams] = i; sh_audio->libav_codec_id = codec->codec_id; + sh_audio->gsh->lavf_codec_tag = lavf_codec_tag; wf = calloc(sizeof(*wf) + codec->extradata_size, 1); // mp4a tag is used for all mp4 files no matter what they actually contain if (codec->codec_tag == MKTAG('m', 'p', '4', 'a')) @@ -403,6 +406,7 @@ static void handle_stream(demuxer_t *demuxer, AVFormatContext *avfc, int i) stream_type = "video"; priv->vstreams[priv->video_streams] = i; sh_video->libav_codec_id = codec->codec_id; + sh_video->gsh->lavf_codec_tag = lavf_codec_tag; bih = calloc(sizeof(*bih) + codec->extradata_size, 1); if (codec->codec_id == CODEC_ID_RAWVIDEO) { @@ -517,6 +521,7 @@ static void handle_stream(demuxer_t *demuxer, AVFormatContext *avfc, int i) stream_type = "subtitle"; priv->sstreams[priv->sub_streams] = i; sh_sub->libav_codec_id = codec->codec_id; + sh_sub->gsh->lavf_codec_tag = lavf_codec_tag; sh_sub->type = type; if (codec->extradata_size) { sh_sub->extradata = malloc(codec->extradata_size); diff --git a/libmpdemux/stheader.h b/libmpdemux/stheader.h index f55e8d2722..2d214966d2 100644 --- a/libmpdemux/stheader.h +++ b/libmpdemux/stheader.h @@ -54,6 +54,9 @@ struct sh_stream { struct sh_video *video; struct sh_sub *sub; + // Work around other hacks. + int lavf_codec_tag; + char *title; bool default_track; |