ソースを参照

ffmpeg:add mjpeg support and fix encoder default big fps issue

Signed-off-by: sw.multimedia <sw.multimedia@starfivetech.com>
sw.multimedia 2 年 前
コミット
aa319c228e

+ 324 - 0
package/ffmpeg/0007-add-mjpeg-decoder-support-and-fix-default-big-fps.patch

@@ -0,0 +1,324 @@
+From 5102c406a361cba201b9d5eb1301937a39308c11 Mon Sep 17 00:00:00 2001
+From: sw.multimedia <sw.multimedia@starfivetech.com>
+Date: Fri, 4 Mar 2022 15:32:52 +0800
+Subject: [PATCH] add mjpeg decoder support and fix default big framerate issue
+
+---
+ configure              |  1 +
+ libavcodec/allcodecs.c |  1 +
+ libavcodec/omx.c       |  4 ++--
+ libavcodec/omxdec.c    | 54 ++++++++++++++++++++++++++++++++----------
+ libavformat/utils.c    | 21 +++++++++++-----
+ 5 files changed, 61 insertions(+), 20 deletions(-)
+
+diff --git a/configure b/configure
+index 5523c59..0e91768 100755
+--- a/configure
++++ b/configure
+@@ -3065,6 +3065,7 @@ h264_v4l2m2m_decoder_select="h264_mp4toannexb_bsf"
+ h264_v4l2m2m_encoder_deps="v4l2_m2m h264_v4l2_m2m"
+ hevc_omx_encoder_deps="omx"
+ hevc_omx_decoder_deps="omx"
++mjpeg_omx_decoder_deps="omx"
+ hevc_amf_encoder_deps="amf"
+ hevc_cuvid_decoder_deps="cuvid"
+ hevc_cuvid_decoder_select="hevc_mp4toannexb_bsf"
+diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
+index b9db275..73f86fa 100644
+--- a/libavcodec/allcodecs.c
++++ b/libavcodec/allcodecs.c
+@@ -791,6 +791,7 @@ extern AVCodec ff_libkvazaar_encoder;
+ extern AVCodec ff_mjpeg_cuvid_decoder;
+ extern AVCodec ff_mjpeg_qsv_encoder;
+ extern AVCodec ff_mjpeg_qsv_decoder;
++extern AVCodec ff_mjpeg_omx_decoder;
+ extern AVCodec ff_mjpeg_vaapi_encoder;
+ extern AVCodec ff_mpeg1_cuvid_decoder;
+ extern AVCodec ff_mpeg2_cuvid_decoder;
+diff --git a/libavcodec/omx.c b/libavcodec/omx.c
+index e3140f1..a05183a 100644
+--- a/libavcodec/omx.c
++++ b/libavcodec/omx.c
+@@ -475,9 +475,9 @@ static av_cold int omx_component_init(AVCodecContext *avctx, const char *role)
+     in_port_params.format.video.nFrameWidth  = avctx->width;
+     in_port_params.format.video.nFrameHeight = avctx->height;
+     if (avctx->framerate.den > 0 && avctx->framerate.num > 0)
+-        in_port_params.format.video.xFramerate = (1LL << 16) * avctx->framerate.num / avctx->framerate.den;
++        in_port_params.format.video.xFramerate = avctx->framerate.num / avctx->framerate.den;
+     else
+-        in_port_params.format.video.xFramerate = (1LL << 16) * avctx->time_base.den / avctx->time_base.num;
++        in_port_params.format.video.xFramerate = avctx->time_base.den / avctx->time_base.num;
+ 
+     err = OMX_SetParameter(s->handle, OMX_IndexParamPortDefinition, &in_port_params);
+     CHECK(err);
+diff --git a/libavcodec/omxdec.c b/libavcodec/omxdec.c
+index f5da60d..d055d19 100755
+--- a/libavcodec/omxdec.c
++++ b/libavcodec/omxdec.c
+@@ -107,6 +107,7 @@ static const struct {
+     { OMX_COLOR_FormatYUV420Planar,                           AV_PIX_FMT_YUV420P },
+     { OMX_COLOR_FormatYUV420SemiPlanar,                       AV_PIX_FMT_NV12    },
+     { OMX_COLOR_FormatYUV420PackedSemiPlanar,                 AV_PIX_FMT_NV21    },
++    { OMX_COLOR_FormatYUV444Interleaved,                      AV_PIX_FMT_YUV444P },
+     { 0 }
+ };
+ 
+@@ -366,7 +367,7 @@ static OMX_ERRORTYPE event_handler(OMX_HANDLETYPE component, OMX_PTR app_data, O
+ 				dec_out_width = out_port_params.format.video.nFrameWidth;
+ 				dec_out_height = out_port_params.format.video.nFrameHeight;
+ 				dec_pix_fmt = out_port_params.format.video.eColorFormat;
+-	            
++	            av_log(s->avctx, AV_LOG_VERBOSE, "w:%d, h:%d, fmt:%d\n", dec_out_width, dec_out_height, dec_pix_fmt); 
+ 	        } 
+ 	    }		
+         break;
+@@ -384,7 +385,6 @@ static OMX_ERRORTYPE event_handler(OMX_HANDLETYPE component, OMX_PTR app_data, O
+ static OMX_ERRORTYPE empty_buffer_done(OMX_HANDLETYPE component, OMX_PTR app_data,
+                                        OMX_BUFFERHEADERTYPE *buffer)
+ {
+-
+     OMXCodecContext *s = app_data;
+     if (s->input_zerocopy) {
+         if (buffer->pAppPrivate) {
+@@ -536,9 +536,9 @@ static av_cold int omx_component_init(AVCodecContext *avctx, const char *role)
+     in_port_params.format.video.nFrameHeight = avctx->height;
+ 
+     if (avctx->framerate.den > 0 && avctx->framerate.num > 0)
+-        in_port_params.format.video.xFramerate = (1LL << 16) * avctx->framerate.num / avctx->framerate.den;
++        in_port_params.format.video.xFramerate = avctx->framerate.num / avctx->framerate.den;
+     else
+-        in_port_params.format.video.xFramerate = (1LL << 16) * avctx->time_base.den / avctx->time_base.num;
++        in_port_params.format.video.xFramerate = avctx->time_base.den / avctx->time_base.num;
+ 
+     err = OMX_SetParameter(s->handle, OMX_IndexParamPortDefinition, &in_port_params);
+     CHECK(err);
+@@ -567,6 +567,8 @@ static av_cold int omx_component_init(AVCodecContext *avctx, const char *role)
+         out_port_params.format.video.eCompressionFormat = OMX_VIDEO_CodingAVC;	
+     else if (avctx->codec->id == AV_CODEC_ID_HEVC)
+         out_port_params.format.video.eCompressionFormat = OMX_VIDEO_CodingHEVC;
++	else if (avctx->codec->id == AV_CODEC_ID_MJPEG)
++        out_port_params.format.video.eCompressionFormat = OMX_VIDEO_CodingMJPEG;
+ 	
+     err = OMX_SetParameter(s->handle, OMX_IndexParamPortDefinition, &out_port_params);
+     CHECK(err);
+@@ -702,11 +704,13 @@ static av_cold int omx_decode_init(AVCodecContext *avctx)
+ 	case AV_CODEC_ID_HEVC:
+ 		role = "video_decoder.hevc";
+ 		break;
++	case AV_CODEC_ID_MJPEG:
++		role = "video_decoder.mjpeg";
++		break;
+ 
+     default:
+         return AVERROR(ENOSYS);
+     }
+-
+     if ((ret = find_component(s->omx_context, avctx, role, s->component_name, sizeof(s->component_name))) < 0)
+         goto fail;
+ 
+@@ -764,14 +768,15 @@ static int omx_decode_frame(AVCodecContext *avctx, void *data,
+ 		buffer->pAppPrivate = avctx->priv_data;
+ 		buffer->nFlags = OMX_BUFFERFLAG_ENDOFFRAME;
+ 
+-
+ 	    err = OMX_EmptyThisBuffer(s->handle, buffer);
+ 	    if (err != OMX_ErrorNone) {
+ 	        append_buffer(&s->input_mutex, &s->input_cond, &s->num_free_in_buffers, s->free_in_buffers, buffer);
+ 	        av_log(avctx, AV_LOG_ERROR, "OMX_EmptyThisBuffer failed: %x\n", err);
+ 	        return AVERROR_UNKNOWN;
+ 	    }
++
+     } else if (!s->eos_sent) {
++
+ 		
+         buffer = get_buffer(&s->input_mutex, &s->input_cond,
+                             &s->num_free_in_buffers, s->free_in_buffers, 1);
+@@ -784,7 +789,6 @@ static int omx_decode_frame(AVCodecContext *avctx, void *data,
+         buffer->nFilledLen = 0;
+         buffer->nFlags = OMX_BUFFERFLAG_EOS;
+         buffer->pAppPrivate = buffer->pOutputPortPrivate = NULL;
+-
+         err = OMX_EmptyThisBuffer(s->handle, buffer);
+         if (err != OMX_ErrorNone) {
+             append_buffer(&s->input_mutex, &s->input_cond, &s->num_free_in_buffers, s->free_in_buffers, buffer);
+@@ -793,7 +797,7 @@ static int omx_decode_frame(AVCodecContext *avctx, void *data,
+         }
+         s->eos_sent = 1;
+     }
+-
++	
+     while (!*got_packet && ret == 0 && !s->got_eos) {
+         // If not flushing, just poll the queue if there's finished packets.
+         // If flushing, do a blocking wait until we either get a completed
+@@ -804,11 +808,13 @@ static int omx_decode_frame(AVCodecContext *avctx, void *data,
+                             !pkt || had_partial);
+ 
+         if (!buffer) {
+-            /*eos is sent wait for vpu evnet_bufferflag to get all frames*/
+-            if(s->eos_sent && !evnet_bufferflag){
++
++            /*eos is sent wait for vpu evnet_bufferflag to get all frames
++			  mjpeg: sent a frame, then wait for a decoder frame 
++			*/
++            if((s->eos_sent && !evnet_bufferflag) || (avctx->codec_id == AV_CODEC_ID_MJPEG )) {
+ 				continue; 
+-       		}	
+-			break;
++       		}
+         } 
+ 
+ 		if(!buffer->nFilledLen){
+@@ -818,6 +824,7 @@ static int omx_decode_frame(AVCodecContext *avctx, void *data,
+ 		avctx->width = dec_out_width;
+ 		avctx->height = dec_out_height;
+ 		avctx->pix_fmt = omx_map_color_format(avctx, dec_pix_fmt);
++		
+ 		s->stride     = avctx->width;
+     	s->plane_size = avctx->height;
+ 
+@@ -863,6 +870,8 @@ static av_cold int omx_decode_end(AVCodecContext *avctx)
+ #define OFFSET(x) offsetof(OMXCodecContext, x)
+ #define VDE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_ENCODING_PARAM
+ #define VE  AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
++#define VD  AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM
++
+ static const AVOption options[] = {
+     { "omx_libname", "OpenMAX library name", OFFSET(libname), AV_OPT_TYPE_STRING, { 0 }, 0, 0, VDE },
+     { "omx_libprefix", "OpenMAX library prefix", OFFSET(libprefix), AV_OPT_TYPE_STRING, { 0 }, 0, 0, VDE },
+@@ -944,4 +953,25 @@ AVCodec ff_hevc_omx_decoder = {
+     .priv_class       = &omx_hevcdec_class,
+ };
+ 
++static const AVClass omx_mjpegdec_class = {
++    .class_name = "mjpeg_omx",
++    .item_name  = av_default_item_name,
++    .version    = LIBAVUTIL_VERSION_INT,
++};
++AVCodec ff_mjpeg_omx_decoder = {
++    .name             = "mjpeg_omx",
++    .long_name        = NULL_IF_CONFIG_SMALL("OpenMAX IL mjpeg video decoder"),
++    .type             = AVMEDIA_TYPE_VIDEO,
++    .id               = AV_CODEC_ID_MJPEG,
++    .priv_data_size   = sizeof(OMXCodecContext),
++    .init             = omx_decode_init,
++    .decode           = omx_decode_frame,
++    .close            = omx_decode_end,
++	.capabilities	  = AV_CODEC_CAP_DR1,
++	.max_lowres 	  = 3,
++	.caps_internal	  = FF_CODEC_CAP_INIT_THREADSAFE,
++    .priv_class       = &omx_mjpegdec_class,
++};
++
++
+ 
+diff --git a/libavformat/utils.c b/libavformat/utils.c
+index 11fdc44..1aaf3aa 100644
+--- a/libavformat/utils.c
++++ b/libavformat/utils.c
+@@ -218,6 +218,14 @@ static const AVCodec *find_probe_decoder(AVFormatContext *s, const AVStream *st,
+ 		return avcodec_find_decoder_by_name("hevc");
+ #endif
+ 
++#if CONFIG_MJPEG_DECODER
++		/* Other parts of the code assume this decoder to be used for mjpeg,
++		 * so force it if possible. */
++		if (codec_id == AV_CODEC_ID_MJPEG)
++			return avcodec_find_decoder_by_name("mjpeg");
++#endif
++
++
+     codec = find_decoder(s, st, codec_id);
+     if (!codec)
+         return NULL;
+@@ -3047,7 +3055,6 @@ static int has_codec_parameters(AVStream *st, const char **errmsg_ptr)
+     case AVMEDIA_TYPE_DATA:
+         if (avctx->codec_id == AV_CODEC_ID_NONE) return 1;
+     }
+-
+     return 1;
+ }
+ 
+@@ -3085,6 +3092,7 @@ static int try_decode_frame(AVFormatContext *s, AVStream *st,
+         av_dict_set(options ? options : &thread_opt, "threads", "1", 0);
+         if (s->codec_whitelist)
+             av_dict_set(options ? options : &thread_opt, "codec_whitelist", s->codec_whitelist, 0);
++				
+         ret = avcodec_open2(avctx, codec, options ? options : &thread_opt);
+         if (!options)
+             av_dict_free(&thread_opt);
+@@ -3095,7 +3103,7 @@ static int try_decode_frame(AVFormatContext *s, AVStream *st,
+         st->info->found_decoder = 1;
+     } else if (!st->info->found_decoder)
+         st->info->found_decoder = 1;
+-
++	
+     if (st->info->found_decoder < 0) {
+         ret = -1;
+         goto fail;
+@@ -3106,7 +3114,7 @@ static int try_decode_frame(AVFormatContext *s, AVStream *st,
+         skip_frame = avctx->skip_frame;
+         avctx->skip_frame = AVDISCARD_ALL;
+     }
+-
++		
+     while ((pkt.size > 0 || (!pkt.data && got_picture)) &&
+            ret >= 0 &&
+            (!has_codec_parameters(st, NULL) || !has_decode_delay_been_guessed(st) ||
+@@ -3751,7 +3759,6 @@ FF_ENABLE_DEPRECATION_WARNINGS
+             av_log(ic, AV_LOG_DEBUG, "interrupted\n");
+             break;
+         }
+-
+         /* check if one codec still needs to be handled */
+         for (i = 0; i < ic->nb_streams; i++) {
+             int fps_analyze_framecount = 20;
+@@ -3850,6 +3857,7 @@ FF_ENABLE_DEPRECATION_WARNINGS
+             pkt = &pkt1;
+         }
+ 
++		
+         st = ic->streams[pkt->stream_index];
+         if (!(st->disposition & AV_DISPOSITION_ATTACHED_PIC))
+             read_size += pkt->size;
+@@ -3861,7 +3869,6 @@ FF_ENABLE_DEPRECATION_WARNINGS
+                 goto unref_then_goto_end;
+             st->internal->avctx_inited = 1;
+         }
+-
+         if (pkt->dts != AV_NOPTS_VALUE && st->codec_info_nb_frames > 1) {
+             /* check for non-increasing dts */
+             if (st->info->fps_last_dts != AV_NOPTS_VALUE &&
+@@ -3901,6 +3908,7 @@ FF_ENABLE_DEPRECATION_WARNINGS
+             st->info->fps_last_dts     = pkt->dts;
+             st->info->fps_last_dts_idx = st->codec_info_nb_frames;
+         }
++
+         if (st->codec_info_nb_frames>1) {
+             int64_t t = 0;
+             int64_t limit;
+@@ -3949,6 +3957,7 @@ FF_ENABLE_DEPRECATION_WARNINGS
+                 goto unref_then_goto_end;
+         }
+ 
++
+         /* If still no information, we try to open the codec and to
+          * decompress the frame. We try to avoid that in most cases as
+          * it takes longer and uses more memory. For MPEG-4, we need to
+@@ -3961,13 +3970,13 @@ FF_ENABLE_DEPRECATION_WARNINGS
+         try_decode_frame(ic, st, pkt,
+                          (options && i < orig_nb_streams) ? &options[i] : NULL);
+ 
++
+         if (ic->flags & AVFMT_FLAG_NOBUFFER)
+             av_packet_unref(&pkt1);
+ 
+         st->codec_info_nb_frames++;
+         count++;
+     }
+-
+     if (eof_reached) {
+         int stream_index;
+         for (stream_index = 0; stream_index < ic->nb_streams; stream_index++) {
+-- 
+2.17.1
+