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;