From 327a5d0ecf33dd44e5542f9128a26d7659864a79 Mon Sep 17 00:00:00 2001 From: Rudolf Polzer Date: Sat, 29 Sep 2012 15:04:40 +0200 Subject: [PATCH] encode: add options --ovfirst and --oafirst This allows to define which stream is to be used as first output stream. This is useful because dvdauthor refuses VOB files where the audio stream is the first stream. --- DOCS/man/en/encode.rst | 42 ++++++++++++++++++------------ cfg-mplayer.h | 2 ++ encode_lavc.c | 39 ++++++++++++++++++++++----- encode_lavc.h | 3 +++ etc/encoding-example-profiles.conf | 8 +++--- libao2/ao_lavc.c | 2 ++ mplayer.c | 14 +++++----- options.h | 2 ++ 8 files changed, 77 insertions(+), 35 deletions(-) diff --git a/DOCS/man/en/encode.rst b/DOCS/man/en/encode.rst index 7ebd8e6c01..20b4d35487 100644 --- a/DOCS/man/en/encode.rst +++ b/DOCS/man/en/encode.rst @@ -56,8 +56,8 @@ You can encode files from one format/codec to another using this facility. avoid --oautofps. --oac= - Specifies the output audio codec. - See --oac=help for a full list of supported codecs. + Specifies the output audio codec. This can be a comma separated list of + possible codecs to try. See --oac=help for a full list of supported codecs. --oaoffset= Shifts audio data by the given time (in seconds) by adding/removing @@ -86,27 +86,18 @@ You can encode files from one format/codec to another using this facility. --oacopts-clr Completely empties the options list. +--oafirst + Force the audio stream to become the first stream in the output. By default + the order is unspecified. + --ovc= - Specifies the output video codec. - See --ovc=help for a full list of supported codecs. + Specifies the output video codec. This can be a comma separated list of + possible codecs to try. See --ovc=help for a full list of supported codecs. --ovoffset= Shifts video data by the given time (in seconds) by shifting the pts values. ---ocopyts - Copies input pts to the output video (not supported by some output - container formats, e.g. avi). Discontinuities are still fixed. - By default, audio pts are set to playback time and video pts are - synchronized to match audio pts, as some output formats do not support - anything else. - ---orawts - Copies input pts to the output video (not supported by some output - container formats, e.g. avi). In this modem discontinuities are not fixed - and all pts are passed through as-is. Never seek backwards or use multiple - input files in this mode! - --ovcopts Specifies the output video codec options for libavcodec. See --ovcopts=help for a full list of supported options. @@ -132,3 +123,20 @@ You can encode files from one format/codec to another using this facility. --ovcopts-clr Completely empties the options list. + +--ovfirst + Force the video stream to become the first stream in the output. By default + the order is unspecified. + +--ocopyts + Copies input pts to the output video (not supported by some output + container formats, e.g. avi). Discontinuities are still fixed. + By default, audio pts are set to playback time and video pts are + synchronized to match audio pts, as some output formats do not support + anything else. + +--orawts + Copies input pts to the output video (not supported by some output + container formats, e.g. avi). In this modem discontinuities are not fixed + and all pts are passed through as-is. Never seek backwards or use multiple + input files in this mode! diff --git a/cfg-mplayer.h b/cfg-mplayer.h index 775963a879..870dec4649 100644 --- a/cfg-mplayer.h +++ b/cfg-mplayer.h @@ -760,6 +760,8 @@ const m_option_t mplayer_opts[]={ OPT_MAKE_FLAGS("orawts", encode_output.rawts, CONF_GLOBAL), OPT_MAKE_FLAGS("oautofps", encode_output.autofps, CONF_GLOBAL), OPT_MAKE_FLAGS("oneverdrop", encode_output.neverdrop, CONF_GLOBAL), + OPT_MAKE_FLAGS("ovfirst", encode_output.video_first, CONF_GLOBAL), + OPT_MAKE_FLAGS("oafirst", encode_output.audio_first, CONF_GLOBAL), {NULL, NULL, 0, 0, 0, 0, NULL} }; diff --git a/encode_lavc.c b/encode_lavc.c index bcde17f6c5..d3f8f9761c 100644 --- a/encode_lavc.c +++ b/encode_lavc.c @@ -208,6 +208,13 @@ struct encode_lavc_context *encode_lavc_init(struct encode_output_conf *options) ctx->vbytes = 0; ctx->frames = 0; + if (options->video_first) { + ctx->video_first = true; + } + if (options->audio_first) { + ctx->audio_first = true; + } + return ctx; } @@ -408,6 +415,26 @@ AVStream *encode_lavc_alloc_stream(struct encode_lavc_context *ctx, // already have a stream of that type, this cannot really happen return NULL; + if (ctx->avc->nb_streams == 0) { + // if this stream isn't stream #0, allocate a dummy stream first for + // the next loop to use + if (mt == AVMEDIA_TYPE_VIDEO && ctx->audio_first) { + mp_msg(MSGT_ENCODE, MSGL_INFO, "vo-lavc: preallocated audio stream for later use\n"); + avformat_new_stream(ctx->avc, NULL); // this one is AVMEDIA_TYPE_UNKNOWN for now + } + if (mt == AVMEDIA_TYPE_AUDIO && ctx->video_first) { + mp_msg(MSGT_ENCODE, MSGL_INFO, "ao-lavc: preallocated video stream for later use\n"); + avformat_new_stream(ctx->avc, NULL); // this one is AVMEDIA_TYPE_UNKNOWN for now + } + } else { + // find possibly preallocated stream + for (i = 0; i < ctx->avc->nb_streams; ++i) + if (ctx->avc->streams[i]->codec->codec_type == AVMEDIA_TYPE_UNKNOWN) // preallocated stream + stream = ctx->avc->streams[i]; + } + if (!stream) + stream = avformat_new_stream(ctx->avc, NULL); + if (ctx->timebase.den == 0) { AVRational r; @@ -447,7 +474,6 @@ AVStream *encode_lavc_alloc_stream(struct encode_lavc_context *ctx, encode_lavc_fail(ctx, "vo-lavc: encoder not found\n"); return NULL; } - stream = avformat_new_stream(ctx->avc, NULL); avcodec_get_context_defaults3(stream->codec, ctx->vc); // stream->time_base = ctx->timebase; @@ -455,9 +481,7 @@ AVStream *encode_lavc_alloc_stream(struct encode_lavc_context *ctx, // which doesn't properly force the time base to be 90000 // furthermore, ffmpeg.c doesn't do this either and works - stream->codec->codec_id = ctx->vc->id; stream->codec->time_base = ctx->timebase; - stream->codec->codec_type = AVMEDIA_TYPE_VIDEO; dummy = avcodec_alloc_context3(ctx->vc); dummy->codec = ctx->vc; // FIXME remove this once we can, caused by a bug in libav, elenril is aware of this @@ -498,12 +522,9 @@ AVStream *encode_lavc_alloc_stream(struct encode_lavc_context *ctx, encode_lavc_fail(ctx, "ao-lavc: encoder not found\n"); return NULL; } - stream = avformat_new_stream(ctx->avc, NULL); avcodec_get_context_defaults3(stream->codec, ctx->ac); - stream->codec->codec_id = ctx->ac->id; stream->codec->time_base = ctx->timebase; - stream->codec->codec_type = AVMEDIA_TYPE_AUDIO; dummy = avcodec_alloc_context3(ctx->ac); dummy->codec = ctx->ac; // FIXME remove this once we can, caused by a bug in libav, elenril is aware of this @@ -676,12 +697,16 @@ int encode_lavc_write_frame(struct encode_lavc_context *ctx, AVPacket *packet) return -1; mp_msg(MSGT_ENCODE, MSGL_DBG2, - "encode-lavc: write frame: stream %d ptsi %d (%f) size %d\n", + "encode-lavc: write frame: stream %d ptsi %d (%f) dtsi %d (%f) size %d\n", (int)packet->stream_index, (int)packet->pts, packet->pts * (double)ctx->avc->streams[packet->stream_index]-> time_base.num / (double)ctx->avc->streams[packet-> stream_index]->time_base.den, + (int)packet->dts, + packet->dts * (double)ctx->avc->streams[packet->stream_index]-> + time_base.num / (double)ctx->avc->streams[packet-> + stream_index]->time_base.den, (int)packet->size); switch (ctx->avc->streams[packet->stream_index]->codec->codec_type) { diff --git a/encode_lavc.h b/encode_lavc.h index 7c1ca07545..29b35c6335 100644 --- a/encode_lavc.h +++ b/encode_lavc.h @@ -59,8 +59,11 @@ struct encode_lavc_context { struct stream *twopass_bytebuffer_v; unsigned int t0; unsigned int frames; + bool expect_video; bool expect_audio; + bool video_first; + bool audio_first; // has encoding failed? bool failed; diff --git a/etc/encoding-example-profiles.conf b/etc/encoding-example-profiles.conf index 41f9dc4e66..2484382622 100644 --- a/etc/encoding-example-profiles.conf +++ b/etc/encoding-example-profiles.conf @@ -124,26 +124,26 @@ ofopts-clr = yes # target devices # ################## [enc-to-dvdpal] -profile-desc = "DVD-Video PAL, use dvdauthor -v pal+4:3 -a ac3+en" +profile-desc = "DVD-Video PAL, use dvdauthor -v pal -a ac3+en (MUST be used with 4:3 or 16:9 aspect, and 720x576, 704x576, 352x576 or 352x288 resolution)" profile = enc-v-mpeg2 profile = enc-a-ac3 of = dvd ofopts-add = packetsize=2048,muxrate=10080000 ofps = 25 oharddup = yes -vf-add = expand=aspect=4/3,scale=w=720:h=576 +ovfirst = yes # dvdauthor needs this srate = 48000 ovcopts-add = g=15,b=6000000,maxrate=9000000,minrate=0,bufsize=1835008 [enc-to-dvdntsc] -profile-desc = "DVD-Video NTSC, use dvdauthor -v ntsc+4:3 -a ac3+en" +profile-desc = "DVD-Video NTSC, use dvdauthor -v ntsc -a ac3+en (MUST be used with 4:3 or 16:9 aspect, and 720x480, 704x480, 352x480 or 352x240 resolution)" profile = enc-v-mpeg2 profile = enc-a-ac3 of = dvd ofopts-add = packetsize=2048,muxrate=10080000 ofps = 24000/1001 oharddup = yes -vf-add = expand=aspect=4/3,scale=w=720:h=480 +ovfirst = yes # dvdauthor needs this srate = 48000 ovcopts-add = g=18,b=6000000,maxrate=9000000,minrate=0,bufsize=1835008 diff --git a/libao2/ao_lavc.c b/libao2/ao_lavc.c index f23f14d59e..d4523f0d54 100644 --- a/libao2/ao_lavc.c +++ b/libao2/ao_lavc.c @@ -405,6 +405,8 @@ static int encode(struct ao *ao, double apts, void *data) encode_lavc_write_stats(ao->encode_lavc_ctx, ac->stream); + packet.stream_index = ac->stream->index; + // Do we need this at all? Better be safe than sorry... if (packet.pts == AV_NOPTS_VALUE) { mp_msg(MSGT_ENCODE, MSGL_WARN, "ao-lavc: encoder lost pts, why?\n"); diff --git a/mplayer.c b/mplayer.c index d17be7c357..b62cb524ee 100644 --- a/mplayer.c +++ b/mplayer.c @@ -3961,6 +3961,13 @@ goto_enable_cache: preselect_demux_streams(mpctx); +#ifdef CONFIG_ENCODING + if (mpctx->encode_lavc_ctx && mpctx->current_track[STREAM_VIDEO]) + encode_lavc_expect_stream(mpctx->encode_lavc_ctx, AVMEDIA_TYPE_VIDEO); + if (mpctx->encode_lavc_ctx && mpctx->current_track[STREAM_AUDIO]) + encode_lavc_expect_stream(mpctx->encode_lavc_ctx, AVMEDIA_TYPE_AUDIO); +#endif + reinit_video_chain(mpctx); reinit_audio_chain(mpctx); reinit_subs(mpctx); @@ -3988,13 +3995,6 @@ goto_enable_cache: goto terminate_playback; } -#ifdef CONFIG_ENCODING - if (mpctx->encode_lavc_ctx && mpctx->sh_video) - encode_lavc_expect_stream(mpctx->encode_lavc_ctx, AVMEDIA_TYPE_VIDEO); - if (mpctx->encode_lavc_ctx && mpctx->sh_audio) - encode_lavc_expect_stream(mpctx->encode_lavc_ctx, AVMEDIA_TYPE_AUDIO); -#endif - if (opts->playing_msg) { char *msg = property_expand_string(mpctx, opts->playing_msg); mp_msg(MSGT_CPLAYER, MSGL_INFO, "%s", msg); diff --git a/options.h b/options.h index 6438f0e97b..b8bf0b4963 100644 --- a/options.h +++ b/options.h @@ -176,6 +176,8 @@ typedef struct MPOpts { int rawts; int autofps; int neverdrop; + int video_first; + int audio_first; } encode_output; } MPOpts;