From 9196c7cf54c3d8672b0342e68ad66f4d8b86acae Mon Sep 17 00:00:00 2001 From: Michal Adamczak Date: Fri, 22 Jul 2022 20:01:50 +0200 Subject: [PATCH] Demuxer reopening fixes This is quite deep and important change. Thing is, old code had "demuxer reuse" attempt. And unfortunately it neither made sense (next to nothing performance improvement, complex code, limited to MPEGTS streams), nor was working fine. During Low Latency work I tried to eliminate demuxer reusing because I wanted single demuxer logic to make input I/O plug-in easier. It turned out that so modified code failed certain tests such as Nvidia_AudioOnly. It took me a great deal of debugging, but I found out that there is bug in demuxer reuse procedure: namely only first muxer open attempt _really_ checks what is in the segment provided, the rest just assumes that same streams are there. So basically, in the series of "audio/video"/"audio without video" /"audio/video" segments all will be perceived as containing video! This "patched over" *AudioOnly tests, and let them run, but only because Transcoder "though" that it has video all the time. And this simply wasn't true. When I removed "muxer reusing" code, the Nvidia-dedicated "preserve video decoder" tactics was falling over the fact that pixel format changed (because it changed from AV_PIX_FMT_SOMETHING into AV_PIX_FMT_NONE) and tried to create hardware video decoder for AV_PIX_FMT_NONE, and failed. Fixing all that finally allowed me to get rid of recursive call to open_input when HW decoder needs to be reset. All is well that ends well, I guess... --- ffmpeg/decoder.c | 193 +++++++++++++++++++++----------------------- ffmpeg/encoder.c | 35 ++++---- ffmpeg/ffmpeg.go | 29 ------- ffmpeg/filter.h | 3 +- ffmpeg/transcoder.c | 16 ++-- ffmpeg/transcoder.h | 1 - 6 files changed, 119 insertions(+), 158 deletions(-) diff --git a/ffmpeg/decoder.c b/ffmpeg/decoder.c index 9f830d99e0..3290e5b6cc 100755 --- a/ffmpeg/decoder.c +++ b/ffmpeg/decoder.c @@ -128,21 +128,22 @@ static enum AVPixelFormat get_hw_pixfmt(AVCodecContext *vc, const enum AVPixelFo } -int open_audio_decoder(struct input_ctx *ctx, AVCodec *codec) +static int open_audio_decoder(struct input_ctx *ctx, AVCodec *codec) { int ret = 0; AVFormatContext *ic = ctx->ic; // open audio decoder - AVCodecContext * ac = avcodec_alloc_context3(codec); - if (!ac) LPMS_ERR(open_audio_err, "Unable to alloc audio codec"); - if (ctx->ac) LPMS_WARN("An audio context was already open!"); - ctx->ac = ac; - ret = avcodec_parameters_to_context(ac, ic->streams[ctx->ai]->codecpar); - if (ret < 0) LPMS_ERR(open_audio_err, "Unable to assign audio params"); - ret = avcodec_open2(ac, codec, NULL); - if (ret < 0) LPMS_ERR(open_audio_err, "Unable to open audio decoder"); - + AVCodecContext * ac = avcodec_alloc_context3(codec); + if (!ac) LPMS_ERR(open_audio_err, "Unable to alloc audio codec"); + if (ctx->ac) LPMS_WARN("An audio context was already open!"); + ctx->ac = ac; + ret = avcodec_parameters_to_context(ac, ic->streams[ctx->ai]->codecpar); + if (ret < 0) LPMS_ERR(open_audio_err, "Unable to assign audio params"); + ret = avcodec_open2(ac, codec, NULL); + if (ret < 0) LPMS_ERR(open_audio_err, "Unable to open audio decoder"); + ctx->last_frame_a = av_frame_alloc(); + if (!ctx->last_frame_a) LPMS_ERR(open_audio_err, "Unable to alloc last_frame_a"); return 0; open_audio_err: @@ -150,7 +151,13 @@ int open_audio_decoder(struct input_ctx *ctx, AVCodec *codec) return ret; } -char* get_hw_decoder(int ff_codec_id, int hw_type) +static void close_audio_decoder(struct input_ctx *ictx) +{ + if (ictx->ac) avcodec_free_context(&ictx->ac); + if (ictx->last_frame_a) av_frame_free(&ictx->last_frame_a); +} + +static char* get_hw_decoder(int ff_codec_id, int hw_type) { switch (hw_type) { case AV_HWDEVICE_TYPE_CUDA: @@ -184,47 +191,49 @@ char* get_hw_decoder(int ff_codec_id, int hw_type) } } -int open_video_decoder(struct input_ctx *ctx, AVCodec *codec) +static int open_video_decoder(struct input_ctx *ctx, AVCodec *codec) { int ret = 0; AVDictionary **opts = NULL; AVFormatContext *ic = ctx->ic; // open video decoder - if (ctx->hw_type > AV_HWDEVICE_TYPE_NONE) { - char* decoder_name = get_hw_decoder(codec->id, ctx->hw_type); - if (!*decoder_name) { - ret = lpms_ERR_INPUT_CODEC; - LPMS_ERR(open_decoder_err, "Input codec does not support hardware acceleration"); - } - AVCodec *c = avcodec_find_decoder_by_name(decoder_name); - if (c) codec = c; - else LPMS_WARN("Nvidia decoder not found; defaulting to software"); - if (AV_PIX_FMT_YUV420P != ic->streams[ctx->vi]->codecpar->format && - AV_PIX_FMT_YUVJ420P != ic->streams[ctx->vi]->codecpar->format) { - // TODO check whether the color range is truncated if yuvj420p is used - ret = lpms_ERR_INPUT_PIXFMT; - LPMS_ERR(open_decoder_err, "Non 4:2:0 pixel format detected in input"); - } + if (ctx->hw_type > AV_HWDEVICE_TYPE_NONE) { + char* decoder_name = get_hw_decoder(codec->id, ctx->hw_type); + if (!*decoder_name) { + ret = lpms_ERR_INPUT_CODEC; + LPMS_ERR(open_decoder_err, "Input codec does not support hardware acceleration"); } - AVCodecContext *vc = avcodec_alloc_context3(codec); - if (!vc) LPMS_ERR(open_decoder_err, "Unable to alloc video codec"); - ctx->vc = vc; - ret = avcodec_parameters_to_context(vc, ic->streams[ctx->vi]->codecpar); - if (ret < 0) LPMS_ERR(open_decoder_err, "Unable to assign video params"); - vc->opaque = (void*)ctx; - // XXX Could this break if the original device falls out of scope in golang? - if (ctx->hw_type == AV_HWDEVICE_TYPE_CUDA) { - // First set the hw device then set the hw frame - ret = av_hwdevice_ctx_create(&ctx->hw_device_ctx, ctx->hw_type, ctx->device, NULL, 0); - if (ret < 0) LPMS_ERR(open_decoder_err, "Unable to open hardware context for decoding") - vc->hw_device_ctx = av_buffer_ref(ctx->hw_device_ctx); - vc->get_format = get_hw_pixfmt; + AVCodec *c = avcodec_find_decoder_by_name(decoder_name); + if (c) codec = c; + else LPMS_WARN("Nvidia decoder not found; defaulting to software"); + if (AV_PIX_FMT_YUV420P != ic->streams[ctx->vi]->codecpar->format && + AV_PIX_FMT_YUVJ420P != ic->streams[ctx->vi]->codecpar->format) { + // TODO check whether the color range is truncated if yuvj420p is used + ret = lpms_ERR_INPUT_PIXFMT; + LPMS_ERR(open_decoder_err, "Non 4:2:0 pixel format detected in input"); } - vc->pkt_timebase = ic->streams[ctx->vi]->time_base; - av_opt_set(vc->priv_data, "xcoder-params", ctx->xcoderParams, 0); - ret = avcodec_open2(vc, codec, opts); - if (ret < 0) LPMS_ERR(open_decoder_err, "Unable to open video decoder"); + } + AVCodecContext *vc = avcodec_alloc_context3(codec); + if (!vc) LPMS_ERR(open_decoder_err, "Unable to alloc video codec"); + ctx->vc = vc; + ret = avcodec_parameters_to_context(vc, ic->streams[ctx->vi]->codecpar); + if (ret < 0) LPMS_ERR(open_decoder_err, "Unable to assign video params"); + vc->opaque = (void*)ctx; + // XXX Could this break if the original device falls out of scope in golang? + if (ctx->hw_type == AV_HWDEVICE_TYPE_CUDA) { + // First set the hw device then set the hw frame + ret = av_hwdevice_ctx_create(&ctx->hw_device_ctx, ctx->hw_type, ctx->device, NULL, 0); + if (ret < 0) LPMS_ERR(open_decoder_err, "Unable to open hardware context for decoding") + vc->hw_device_ctx = av_buffer_ref(ctx->hw_device_ctx); + vc->get_format = get_hw_pixfmt; + } + vc->pkt_timebase = ic->streams[ctx->vi]->time_base; + av_opt_set(vc->priv_data, "xcoder-params", ctx->xcoderParams, 0); + ret = avcodec_open2(vc, codec, opts); + if (ret < 0) LPMS_ERR(open_decoder_err, "Unable to open video decoder"); + ctx->last_frame_v = av_frame_alloc(); + if (!ctx->last_frame_v) LPMS_ERR(open_decoder_err, "Unable to alloc last_frame_v"); return 0; open_decoder_err: @@ -233,6 +242,16 @@ int open_video_decoder(struct input_ctx *ctx, AVCodec *codec) return ret; } +static void close_video_decoder(struct input_ctx *ictx) +{ + if (ictx->vc) { + if (ictx->vc->hw_device_ctx) av_buffer_unref(&ictx->vc->hw_device_ctx); + avcodec_free_context(&ictx->vc); + } + if (ictx->hw_device_ctx) av_buffer_unref(&ictx->hw_device_ctx); + if (ictx->last_frame_v) av_frame_free(&ictx->last_frame_v); +} + int open_input(input_params *params, struct input_ctx *ctx) { char *inp = params->fname; @@ -247,52 +266,47 @@ int open_input(input_params *params, struct input_ctx *ctx) ctx->device = params->device; // open demuxer - if (!ctx->ic) { - ret = avformat_open_input(&ctx->ic, inp, NULL, NULL); - if (ret < 0) LPMS_ERR(open_input_err, "demuxer: Unable to open input"); - ret = avformat_find_stream_info(ctx->ic, NULL); - if (ret < 0) LPMS_ERR(open_input_err, "Unable to find input info"); - } else if (!ctx->ic->pb) { - // reopen input segment file IO context if needed - ret = avio_open(&ctx->ic->pb, inp, AVIO_FLAG_READ); - if (ret < 0) LPMS_ERR(open_input_err, "Unable to reopen file"); - } else reopen_decoders = 0; + ret = avformat_open_input(&ctx->ic, inp, NULL, NULL); + if (ret < 0) LPMS_ERR(open_input_err, "demuxer: Unable to open input"); + ret = avformat_find_stream_info(ctx->ic, NULL); + if (ret < 0) LPMS_ERR(open_input_err, "Unable to find input info"); AVCodec *video_codec = NULL; AVCodec *audio_codec = NULL; ctx->vi = av_find_best_stream(ctx->ic, AVMEDIA_TYPE_VIDEO, -1, -1, &video_codec, 0); ctx->ai = av_find_best_stream(ctx->ic, AVMEDIA_TYPE_AUDIO, -1, -1, &audio_codec, 0); - if (AV_HWDEVICE_TYPE_CUDA == ctx->hw_type && ctx->vi >= 0) { - if (ctx->last_format == AV_PIX_FMT_NONE) ctx->last_format = ctx->ic->streams[ctx->vi]->codecpar->format; - else if (ctx->ic->streams[ctx->vi]->codecpar->format != ctx->last_format) { + // Now be careful here. It appears that in certain situation (such as .ts + // stream without video stream) ctx->vi will be set to 0, but the format will + // be set to AV_PIX_FMT_NONE and both width and height will be zero, etc + // This is normally fine, but when re-using video decoder we have to be + // extra careful + enum AVPixelFormat format = ctx->ic->streams[ctx->vi]->codecpar->format; + if ((AV_HWDEVICE_TYPE_CUDA == ctx->hw_type) && (ctx->vi >= 0) + && (AV_PIX_FMT_NONE != format)) { + if (ctx->last_format == AV_PIX_FMT_NONE) ctx->last_format = format; + else if (format != ctx->last_format) { LPMS_WARN("Input pixel format has been changed in the middle."); - ctx->last_format = ctx->ic->streams[ctx->vi]->codecpar->format; + ctx->last_format = format; // if the decoder is not re-opened when the video pixel format is changed, // the decoder tries HW decoding with the video context initialized to a pixel format different from the input one. // to handle a change in the input pixel format, - // we close the demuxer and re-open the decoder by calling open_input(). - free_input(ctx, FORCE_CLOSE_HW_DECODER); - ret = open_input(params, ctx); - if (ret < 0) LPMS_ERR(open_input_err, "Unable to reopen video demuxer for HW decoding"); - reopen_decoders = 0; + // we close the decoder so it will get reopened later + close_video_decoder(ctx); } } if (reopen_decoders) { - if (!ctx->dv && (ctx->vi >= 0) && - (!ctx->vc || (ctx->hw_type == AV_HWDEVICE_TYPE_NONE))) { - ret = open_video_decoder(ctx, video_codec); - if (ret < 0) LPMS_ERR(open_input_err, "Unable to open video decoder") - ctx->last_frame_v = av_frame_alloc(); - if (!ctx->last_frame_v) LPMS_ERR(open_input_err, "Unable to alloc last_frame_v"); + if (!ctx->dv && (ctx->vi >= 0) && (AV_PIX_FMT_NONE != format)) { + if (!ctx->vc || (ctx->hw_type == AV_HWDEVICE_TYPE_NONE)) { + ret = open_video_decoder(ctx, video_codec); + if (ret < 0) LPMS_ERR(open_input_err, "Unable to open video decoder") + } } else LPMS_WARN("No video stream found in input"); if (!ctx->da && (ctx->ai >= 0)) { ret = open_audio_decoder(ctx, audio_codec); if (ret < 0) LPMS_ERR(open_input_err, "Unable to open audio decoder") - ctx->last_frame_a = av_frame_alloc(); - if (!ctx->last_frame_a) LPMS_ERR(open_input_err, "Unable to alloc last_frame_a"); } else LPMS_WARN("No audio stream found in input"); } @@ -306,44 +320,19 @@ int open_input(input_params *params, struct input_ctx *ctx) void free_input(struct input_ctx *ictx, enum FreeInputPolicy policy) { - if (FORCE_CLOSE_HW_DECODER == policy) { - // This means we are closing everything, so we also want to - // remove demuxer - if (ictx->ic) avformat_close_input(&ictx->ic); - } else { - // Otherwise we may want to retain demuxer in certain cases. Note that - // this is a lot of effort for very little gain, because demuxer is very - // cheap to create and destroy (being software component) - if (ictx->ic) { - // Only mpegts reuse the demuxer for subsequent segments. - // Close the demuxer for everything else. - // TODO might be reusable with fmp4 ; check! - if (!is_mpegts(ictx->ic)) avformat_close_input(&ictx->ic); - else if (ictx->ic->pb) { - // Reset leftovers from demuxer internals to prepare for next segment - avio_flush(ictx->ic->pb); - avformat_flush(ictx->ic); - avio_closep(&ictx->ic->pb); - } - } - } + if (ictx->ic) avformat_close_input(&ictx->ic); ictx->flushed = 0; ictx->flushing = 0; ictx->pkt_diff = 0; ictx->sentinel_count = 0; + // this is allocated elsewhere on first video packet if (ictx->first_pkt) av_packet_free(&ictx->first_pkt); - if (ictx->ac) avcodec_free_context(&ictx->ac); // video decoder is always closed when it is a SW decoder // otherwise only when forced - int close_vc = ictx->vc && - ((AV_HWDEVICE_TYPE_NONE == ictx->hw_type) || (FORCE_CLOSE_HW_DECODER == policy)); - if (close_vc) { - if (ictx->vc->hw_device_ctx) av_buffer_unref(&ictx->vc->hw_device_ctx); - avcodec_free_context(&ictx->vc); - if (ictx->hw_device_ctx) av_buffer_unref(&ictx->hw_device_ctx); - if (ictx->last_frame_v) av_frame_free(&ictx->last_frame_v); + if ((AV_HWDEVICE_TYPE_NONE == ictx->hw_type) || (FORCE_CLOSE_HW_DECODER == policy)) { + close_video_decoder(ictx); } - if (ictx->last_frame_a) av_frame_free(&ictx->last_frame_a); - + // audio decoder is always closed + close_audio_decoder(ictx); } diff --git a/ffmpeg/encoder.c b/ffmpeg/encoder.c index ecd6441293..86471dbb74 100755 --- a/ffmpeg/encoder.c +++ b/ffmpeg/encoder.c @@ -11,7 +11,7 @@ static AVStream *add_stream_copy(struct output_ctx *octx, AVStream *ist) if (!ist) LPMS_ERR(add_copy_err, "Input stream for copy not available"); AVStream *st = avformat_new_stream(octx->oc, NULL); if (!st) LPMS_ERR(add_copy_err, "Unable to alloc copy stream"); - octx->vi = st->index; + // octx->vi = st->index; if (octx->fps.den) st->avg_frame_rate = octx->fps; else st->avg_frame_rate = ist->r_frame_rate; st->time_base = ist->time_base; @@ -45,16 +45,15 @@ static int add_video_stream(struct output_ctx *octx, struct input_ctx *ictx) { // video stream to muxer int ret = 0; - AVStream *st = NULL; if (is_copy(octx->video->name)) { // create stream as a copy of existing one if (ictx->vi < 0) LPMS_ERR(add_video_err, "Input video stream does not exist"); - st = add_stream_copy(octx, ictx->ic->streams[ictx->vi]); - if (!st) LPMS_ERR(add_video_err, "Error adding video copy stream"); + octx->video_stream = add_stream_copy(octx, ictx->ic->streams[ictx->vi]); + if (!octx->video_stream) LPMS_ERR(add_video_err, "Error adding video copy stream"); } else if (octx->vc) { // create stream from encoder - st = add_stream_for_encoder(octx, octx->vc); - if (!st) LPMS_ERR(add_video_err, "Error adding video encoder stream"); + octx->video_stream = add_stream_for_encoder(octx, octx->vc); + if (!octx->video_stream) LPMS_ERR(add_video_err, "Error adding video encoder stream"); // Video has rescale here. Audio is slightly different // Rescale the gop/clip time to the expected timebase after filtering. // The FPS filter outputs pts incrementing by 1 at a rate of 1/framerate @@ -74,8 +73,14 @@ static int add_video_stream(struct output_ctx *octx, struct input_ctx *ictx) octx->clip_to_pts = av_rescale_q(octx->clip_to, ms_tb, dest_tb); } } else if (is_drop(octx->video->name)) { + octx->video_stream = NULL; LPMS_ERR(add_video_err, "add_video_stream called for dropped video!"); - } else LPMS_ERR(add_video_err, "No video encoder, not a copy; what is this?"); + } else { + // this can actually happen if the transcoder configured for video + // gets segment without actual video stream + octx->video_stream = NULL; + LPMS_WARN("No video encoder, not a copy; missing video input perhaps?"); + } octx->last_video_dts = AV_NOPTS_VALUE; return 0; @@ -96,24 +101,26 @@ static int add_audio_stream(struct input_ctx *ictx, struct output_ctx *octx) // audio stream to muxer int ret = 0; - AVStream *st = NULL; if (is_copy(octx->audio->name)) { // create stream as a copy of existing one if (ictx->ai < 0) LPMS_ERR(add_audio_err, "Input audio stream does not exist"); - st = add_stream_copy(octx, ictx->ic->streams[ictx->ai]); + octx->audio_stream = add_stream_copy(octx, ictx->ic->streams[ictx->ai]); } else if (octx->ac) { // create stream from encoder - st = add_stream_for_encoder(octx, octx->ac); + octx->audio_stream = add_stream_for_encoder(octx, octx->ac); // Video has rescale here } else if (is_drop(octx->audio->name)) { // Supposed to exit this function early if there's a drop + octx->audio_stream = NULL; LPMS_ERR(add_audio_err, "add_audio_stream called for dropped audio!"); } else { - LPMS_ERR(add_audio_err, "No audio encoder; not a copy; what is this?"); + // see comment in add_video_stream above + octx->audio_stream = NULL; + LPMS_WARN("No audio encoder; not a copy; missing audio input perhaps?"); + return 0; } - if (!st) LPMS_ERR(add_audio_err, "Error adding video copy stream"); - octx->ai = st->index; + if (!octx->audio_stream) LPMS_ERR(add_audio_err, "Error adding audio stream");; // Audio has rescale here. Video version is slightly different AVRational ms_tb = {1, 1000}; @@ -126,7 +133,7 @@ static int add_audio_stream(struct input_ctx *ictx, struct output_ctx *octx) } // signal whether to drop preroll audio - if (st->codecpar->initial_padding) octx->drop_ts = AV_NOPTS_VALUE; + if (octx->audio_stream->codecpar->initial_padding) octx->drop_ts = AV_NOPTS_VALUE; octx->last_audio_dts = AV_NOPTS_VALUE; diff --git a/ffmpeg/ffmpeg.go b/ffmpeg/ffmpeg.go index b22a3239da..c73ff78fcd 100755 --- a/ffmpeg/ffmpeg.go +++ b/ffmpeg/ffmpeg.go @@ -88,7 +88,6 @@ type Transcoder struct { handle *C.struct_transcode_thread stopped bool started bool - lastacodec string mu *sync.Mutex } @@ -857,8 +856,6 @@ func (t *Transcoder) Transcode(input *TranscodeOptionsIn, ps []TranscodeOptions) if input == nil { return nil, ErrTranscoderInp } - var reopendemux bool - reopendemux = false // don't read metadata for pipe input, because it can't seek back and av_find_input_format in the decoder will fail if !strings.HasPrefix(strings.ToLower(input.Fname), "pipe:") { status, format, err := GetCodecInfo(input.Fname) @@ -881,24 +878,8 @@ func (t *Transcoder) Transcode(input *TranscodeOptionsIn, ps []TranscodeOptions) // Audio-only segment, fail fast right here as we cannot handle them nicely return nil, ErrTranscoderVid } - // keep last audio codec - t.lastacodec = format.Acodec // Stream is either OK or completely broken, let the transcoder handle it t.started = true - } else { - // check if we need to reopen demuxer because added audio in video - // TODO: fixes like that are needed because handling of cfg change in - // LPMS is a joke. We need to decide whether LPMS should support full - // dynamic config one day and either implement it there, or implement - // some generic workaround for the problem in Go code, such as marking - // config changes as significant/insignificant and re-creating the instance - // if the former type change happens - if format.Acodec != "" && !isAudioAllDrop(ps) { - if (t.lastacodec == "") || (t.lastacodec != "" && t.lastacodec != format.Acodec) { - reopendemux = true - t.lastacodec = format.Acodec - } - } } } hw_type, err := accelDeviceType(input.Accel) @@ -954,16 +935,6 @@ func (t *Transcoder) Transcode(input *TranscodeOptionsIn, ps []TranscodeOptions) paramsPointer = (*C.output_params)(¶ms[0]) resultsPointer = (*C.output_results)(&results[0]) } - if reopendemux { - // forcefully close and open demuxer - ret := int(C.lpms_transcode_reopen_demux(inp)) - if ret != 0 { - if LogTranscodeErrors { - glog.Error("Reopen demux returned : ", ErrorMap[ret]) - } - return nil, ErrorMap[ret] - } - } ret := int(C.lpms_transcode(inp, paramsPointer, resultsPointer, C.int(len(params)), decoded)) if ret != 0 { if LogTranscodeErrors { diff --git a/ffmpeg/filter.h b/ffmpeg/filter.h index 2e556b63cd..5e6995c493 100755 --- a/ffmpeg/filter.h +++ b/ffmpeg/filter.h @@ -45,7 +45,8 @@ struct output_ctx { AVFormatContext *oc; // muxer required AVCodecContext *vc; // video decoder optional AVCodecContext *ac; // audo decoder optional - int vi, ai; // video and audio stream indices + AVStream *audio_stream; + AVStream *video_stream; int dv, da; // flags whether to drop video or audio struct filter_ctx vf, af, sf; diff --git a/ffmpeg/transcoder.c b/ffmpeg/transcoder.c index 59b60b83ec..c2b4869823 100755 --- a/ffmpeg/transcoder.c +++ b/ffmpeg/transcoder.c @@ -133,13 +133,13 @@ static int flush_output(struct input_ctx *ictx, struct output_ctx *octx) int ret = 0; if (octx->vc) { // flush video while (!ret || ret == AVERROR(EAGAIN)) { - ret = process_out(ictx, octx, octx->vc, octx->oc->streams[0], &octx->vf, NULL); + ret = process_out(ictx, octx, octx->vc, octx->video_stream, &octx->vf, NULL); } } ret = 0; if (octx->ac) { // flush audio while (!ret || ret == AVERROR(EAGAIN)) { - ret = process_out(ictx, octx, octx->ac, octx->oc->streams[octx->dv ? 0 : 1], &octx->af, NULL); + ret = process_out(ictx, octx, octx->ac, octx->audio_stream, &octx->af, NULL); } } // send EOF signal to signature filter @@ -237,7 +237,7 @@ static int handle_audio_frame(struct transcode_thread *h, AVStream *ist, if (octx->ac) { int ret = process_out(ictx, octx, octx->ac, - octx->oc->streams[octx->dv ? 0 : 1], &octx->af, dframe); + octx->audio_stream, &octx->af, dframe); if (AVERROR(EAGAIN) == ret || AVERROR_EOF == ret) continue; // this is ok if (ret < 0) LPMS_ERR_RETURN("Error encoding audio"); } @@ -320,7 +320,7 @@ static int handle_audio_packet(struct transcode_thread *h, output_results *decod if (octx->da) continue; // drop audio // If there is no encoder, then we are copying. Also the index of // audio stream is 0 when we are dropping video and 1 otherwise - if (!octx->ac) ost = octx->oc->streams[octx->dv ? 0 : 1]; + if (!octx->ac) ost = octx->audio_stream; } if (ost) { @@ -418,7 +418,7 @@ static int handle_video_packet(struct transcode_thread *h, output_results *decod // This is video stream for this output, but do we need packet? if (octx->dv) continue; // drop video // If there is no encoder, then we are copying - if (!octx->vc) ost = octx->oc->streams[0]; + if (!octx->vc) ost = octx->video_stream; } if (ost) { @@ -714,12 +714,6 @@ int lpms_transcode(input_params *inp, output_params *params, return ret; } -int lpms_transcode_reopen_demux(input_params *inp) -{ - free_input(&inp->handle->ictx, FORCE_CLOSE_HW_DECODER); - return open_input(inp, &inp->handle->ictx); -} - // TODO: name - this is called _stop, but it is more like stop & destroy void lpms_transcode_stop(struct transcode_thread *handle) { diff --git a/ffmpeg/transcoder.h b/ffmpeg/transcoder.h index 8047550bc7..e53a7635c0 100755 --- a/ffmpeg/transcoder.h +++ b/ffmpeg/transcoder.h @@ -98,7 +98,6 @@ enum LPMSLogLevel { void lpms_init(enum LPMSLogLevel max_level); int lpms_transcode(input_params *inp, output_params *params, output_results *results, int nb_outputs, output_results *decoded_results); -int lpms_transcode_reopen_demux(input_params *inp); struct transcode_thread* lpms_transcode_new(lvpdnn_opts *dnn_opts); void lpms_transcode_stop(struct transcode_thread* handle); void lpms_transcode_discontinuity(struct transcode_thread *handle);