From de94555cdc69ea566f9f8770c5e3f26af10a67ca Mon Sep 17 00:00:00 2001 From: Yondon Fu Date: Sat, 20 Jan 2024 15:04:05 +0000 Subject: [PATCH] ffmpeg: Support image2 demuxer --- ffmpeg/decoder.c | 6 +++++- ffmpeg/ffmpeg.go | 34 +++++++++++++++++++++++++++++++++- ffmpeg/transcoder.c | 10 ++++++++-- ffmpeg/transcoder.h | 2 ++ 4 files changed, 48 insertions(+), 4 deletions(-) diff --git a/ffmpeg/decoder.c b/ffmpeg/decoder.c index 2c344ee17a..652c6f5120 100755 --- a/ffmpeg/decoder.c +++ b/ffmpeg/decoder.c @@ -338,8 +338,12 @@ int open_input(input_params *params, struct input_ctx *ctx) ctx->transmuxing = params->transmuxe; // open demuxer - ret = avformat_open_input(&ic, inp, NULL, NULL); + AVDictionary **demuxer_opts = NULL; + if (params->demuxer.opts) demuxer_opts = ¶ms->demuxer.opts; + ret = avformat_open_input(&ic, inp, NULL, demuxer_opts); if (ret < 0) LPMS_ERR(open_input_err, "demuxer: Unable to open input"); + // If avformat_open_input replaced the options AVDictionary with options that were not found free it + if (demuxer_opts) av_dict_free(demuxer_opts); ctx->ic = ic; ret = avformat_find_stream_info(ic, NULL); if (ret < 0) LPMS_ERR(open_input_err, "Unable to find input info"); diff --git a/ffmpeg/ffmpeg.go b/ffmpeg/ffmpeg.go index de1c441b2b..407764d13d 100755 --- a/ffmpeg/ffmpeg.go +++ b/ffmpeg/ffmpeg.go @@ -97,6 +97,7 @@ type TranscodeOptionsIn struct { Accel Acceleration Device string Transmuxing bool + Profile VideoProfile } type TranscodeOptions struct { @@ -649,6 +650,11 @@ func createCOutputParams(input *TranscodeOptionsIn, ps []TranscodeOptions) ([]C. // needed for hw dec -> hw rescale -> sw enc filters = filters + ",hwdownload,format=nv12" } + if p.Accel == Nvidia && filepath.Ext(input.Fname) == ".png" { + // If the input is PNG image(s) and we are scaling on a Nvidia device + // we need to first convert to a pixel format that the scale_npp filter supports + filters = "format=nv12," + filters + } // set FPS denominator to 1 if unset by user if param.FramerateDen == 0 { param.FramerateDen = 1 @@ -955,8 +961,34 @@ func (t *Transcoder) Transcode(input *TranscodeOptionsIn, ps []TranscodeOptions) defer C.free(unsafe.Pointer(fname)) xcoderParams := C.CString("") defer C.free(unsafe.Pointer(xcoderParams)) + + var demuxerOpts C.component_opts + + ext := filepath.Ext(input.Fname) + // If the input has an image file extension setup the image2 demuxer + if ext == ".png" { + image2 := C.CString("image2") + defer C.free(unsafe.Pointer(image2)) + + demuxerOpts = C.component_opts{ + name: image2, + } + + if input.Profile.Framerate > 0 { + if input.Profile.FramerateDen == 0 { + input.Profile.FramerateDen = 1 + } + + // Do not try tofree in this function because in the C code avformat_open_input() + // will destroy this + demuxerOpts.opts = newAVOpts(map[string]string{ + "framerate": fmt.Sprintf("%d/%d", input.Profile.Framerate, input.Profile.FramerateDen), + }) + } + } + inp := &C.input_params{fname: fname, hw_type: hw_type, device: device, xcoderParams: xcoderParams, - handle: t.handle} + handle: t.handle, demuxer: demuxerOpts} if input.Transmuxing { inp.transmuxe = 1 } diff --git a/ffmpeg/transcoder.c b/ffmpeg/transcoder.c index 0247f5657e..00a1845bd1 100755 --- a/ffmpeg/transcoder.c +++ b/ffmpeg/transcoder.c @@ -160,17 +160,23 @@ int transcode_init(struct transcode_thread *h, input_params *inp, if (!inp) LPMS_ERR(transcode_cleanup, "Missing input params") + AVDictionary **demuxer_opts; + if (inp->demuxer.opts) demuxer_opts = &inp->demuxer.opts; + // by default we re-use decoder between segments of same stream // unless we are using SW deocder and had to re-open IO or demuxer if (!ictx->ic) { // reopen demuxer for the input segment if needed // XXX could open_input() be re-used here? - ret = avformat_open_input(&ictx->ic, inp->fname, NULL, NULL); + ret = avformat_open_input(&ictx->ic, inp->fname, NULL, demuxer_opts); if (ret < 0) LPMS_ERR(transcode_cleanup, "Unable to reopen demuxer"); + // If avformat_open_input replaced the options AVDictionary with options that were not found free it + if (demuxer_opts) av_dict_free(demuxer_opts); ret = avformat_find_stream_info(ictx->ic, NULL); if (ret < 0) LPMS_ERR(transcode_cleanup, "Unable to find info for reopened stream") - } else if (!ictx->ic->pb) { + } else if (is_mpegts(ictx->ic) && !ictx->ic->pb) { // reopen input segment file IO context if needed + // only necessary for mpegts ret = avio_open(&ictx->ic->pb, inp->fname, AVIO_FLAG_READ); if (ret < 0) LPMS_ERR(transcode_cleanup, "Unable to reopen file"); } else reopen_decoders = 0; diff --git a/ffmpeg/transcoder.h b/ffmpeg/transcoder.h index 53ded33f35..3d9ff73ff2 100755 --- a/ffmpeg/transcoder.h +++ b/ffmpeg/transcoder.h @@ -51,6 +51,8 @@ typedef struct { char *device; char *xcoderParams; + // Optional demuxer opts + component_opts demuxer; // Optional video decoder + opts component_opts video;