Message ID | 20240328111132.34419-1-gnattuoc@me.com |
---|---|
State | New |
Headers | show |
Series | [FFmpeg-devel] lavc/videotoolboxenc: add MJPEG support | expand |
Context | Check | Description |
---|---|---|
yinshiyou/make_loongarch64 | success | Make finished |
yinshiyou/make_fate_loongarch64 | success | Make fate finished |
andriy/make_x86 | success | Make finished |
andriy/make_fate_x86 | success | Make fate finished |
gnattu via ffmpeg-devel: > For example: > ./ffmpeg -hwaccel videotoolbox\ > -i INPUT -c:v mjpeg_videotoolbox\ > out.mp4 > > This encoder does not have many options and can only use ``-q:v` to control quality. > > Signed-off-by: Gnattu OC <gnattuoc@me.com> > --- > Changelog | 1 + > configure | 2 ++ > libavcodec/Makefile | 1 + > libavcodec/allcodecs.c | 1 + > libavcodec/videotoolboxenc.c | 39 +++++++++++++++++++++++++++++++++--- > 5 files changed, 41 insertions(+), 3 deletions(-) > > diff --git a/Changelog b/Changelog > index e83a00e35c..b73a44f9ad 100644 > --- a/Changelog > +++ b/Changelog > @@ -38,6 +38,7 @@ version 7.0: > - ffplay with hwaccel decoding support (depends on vulkan renderer via libplacebo) > - dnn filter libtorch backend > - Android content URIs protocol > +- VideoToolbox MJPEG encoder > > > version 6.1: > diff --git a/configure b/configure > index 2a1d22310b..52a0ee762f 100755 > --- a/configure > +++ b/configure > @@ -3474,6 +3474,8 @@ hevc_videotoolbox_encoder_deps="pthreads" > hevc_videotoolbox_encoder_select="atsc_a53 videotoolbox_encoder" > prores_videotoolbox_encoder_deps="pthreads" > prores_videotoolbox_encoder_select="videotoolbox_encoder" > +mjpeg_videotoolbox_encoder_deps="pthreads" > +mjpeg_videotoolbox_encoder_select="videotoolbox_encoder" > libaom_av1_decoder_deps="libaom" > libaom_av1_encoder_deps="libaom" > libaom_av1_encoder_select="extract_extradata_bsf" > diff --git a/libavcodec/Makefile b/libavcodec/Makefile > index 9ce6d445c1..f59b2ae691 100644 > --- a/libavcodec/Makefile > +++ b/libavcodec/Makefile > @@ -503,6 +503,7 @@ OBJS-$(CONFIG_MJPEGB_DECODER) += mjpegbdec.o > OBJS-$(CONFIG_MJPEG_CUVID_DECODER) += cuviddec.o > OBJS-$(CONFIG_MJPEG_QSV_ENCODER) += qsvenc_jpeg.o > OBJS-$(CONFIG_MJPEG_VAAPI_ENCODER) += vaapi_encode_mjpeg.o > +OBJS-$(CONFIG_MJPEG_VIDEOTOOLBOX_ENCODER) += videotoolboxenc.o > OBJS-$(CONFIG_MLP_DECODER) += mlpdec.o mlpdsp.o > OBJS-$(CONFIG_MLP_ENCODER) += mlpenc.o mlp.o > OBJS-$(CONFIG_MMVIDEO_DECODER) += mmvideo.o > diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c > index 2386b450a6..f8a90fdca2 100644 > --- a/libavcodec/allcodecs.c > +++ b/libavcodec/allcodecs.c > @@ -879,6 +879,7 @@ extern const FFCodec ff_mpeg4_mediacodec_encoder; > extern const FFCodec ff_mpeg4_omx_encoder; > extern const FFCodec ff_mpeg4_v4l2m2m_encoder; > extern const FFCodec ff_prores_videotoolbox_encoder; > +extern const FFCodec ff_mjpeg_videotoolbox_encoder; > extern const FFCodec ff_vc1_cuvid_decoder; > extern const FFCodec ff_vp8_cuvid_decoder; > extern const FFCodec ff_vp8_mediacodec_decoder; > diff --git a/libavcodec/videotoolboxenc.c b/libavcodec/videotoolboxenc.c > index 15c34d59c3..0574edab56 100644 > --- a/libavcodec/videotoolboxenc.c > +++ b/libavcodec/videotoolboxenc.c > @@ -547,6 +547,7 @@ static CMVideoCodecType get_cm_codec_type(AVCodecContext *avctx, > else > return MKBETAG('a','p','c','n'); // kCMVideoCodecType_AppleProRes422 > } > + case AV_CODEC_ID_MJPEG: return kCMVideoCodecType_JPEG; > default: return 0; > } > } > @@ -1233,7 +1234,7 @@ static int vtenc_create_encoder(AVCodecContext *avctx, > kVTCompressionPropertyKey_Quality, > quality_num); > CFRelease(quality_num); > - } else if (avctx->codec_id != AV_CODEC_ID_PRORES) { > + } else if (avctx->codec_id != AV_CODEC_ID_PRORES && avctx->codec_id != AV_CODEC_ID_MJPEG) { > bit_rate_num = CFNumberCreate(kCFAllocatorDefault, > kCFNumberSInt32Type, > &bit_rate); > @@ -1347,7 +1348,7 @@ static int vtenc_create_encoder(AVCodecContext *avctx, > } > } > > - if (avctx->gop_size > 0 && avctx->codec_id != AV_CODEC_ID_PRORES) { > + if (avctx->gop_size > 0 && avctx->codec_id != AV_CODEC_ID_PRORES && avctx->codec_id != AV_CODEC_ID_MJPEG) { > CFNumberRef interval = CFNumberCreate(kCFAllocatorDefault, > kCFNumberIntType, > &avctx->gop_size); > @@ -1496,7 +1497,7 @@ static int vtenc_create_encoder(AVCodecContext *avctx, > } > } > > - if (!vtctx->has_b_frames && avctx->codec_id != AV_CODEC_ID_PRORES) { > + if (!vtctx->has_b_frames && avctx->codec_id != AV_CODEC_ID_PRORES && avctx->codec_id != AV_CODEC_ID_MJPEG) { > status = VTSessionSetProperty(vtctx->session, > kVTCompressionPropertyKey_AllowFrameReordering, > kCFBooleanFalse); > @@ -2844,6 +2845,13 @@ static const enum AVPixelFormat prores_pix_fmts[] = { > AV_PIX_FMT_NONE > }; > > +static const enum AVPixelFormat mjpeg_pix_fmts[] = { > + AV_PIX_FMT_VIDEOTOOLBOX, > + AV_PIX_FMT_NV12, > + AV_PIX_FMT_YUV420P, > + AV_PIX_FMT_NONE > +}; > + > #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM > #define COMMON_OPTIONS \ > { "allow_sw", "Allow software encoding", OFFSET(allow_sw), AV_OPT_TYPE_BOOL, \ > @@ -3004,3 +3012,28 @@ const FFCodec ff_prores_videotoolbox_encoder = { > .p.wrapper_name = "videotoolbox", > .hw_configs = vt_encode_hw_configs, > }; > + > +static const AVClass mjpeg_videotoolbox_class = { > + .class_name = "mjpeg_videotoolbox", > + .item_name = av_default_item_name, > + .option = NULL, > + .version = LIBAVUTIL_VERSION_INT, > +}; If you have no options, it makes no sense to use an AVClass. > + > +const FFCodec ff_mjpeg_videotoolbox_encoder = { > + .p.name = "mjpeg_videotoolbox", > + CODEC_LONG_NAME("VideoToolbox MJPEG Encoder"), > + .p.type = AVMEDIA_TYPE_VIDEO, > + .p.id = AV_CODEC_ID_MJPEG, > + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | > + AV_CODEC_CAP_HARDWARE, > + .priv_data_size = sizeof(VTEncContext), > + .p.pix_fmts = prores_pix_fmts, > + .init = vtenc_init, > + FF_CODEC_ENCODE_CB(vtenc_frame), > + .close = vtenc_close, > + .p.priv_class = &mjpeg_videotoolbox_class, > + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, > + .p.wrapper_name = "videotoolbox", > + .hw_configs = vt_encode_hw_configs, > +};
diff --git a/Changelog b/Changelog index e83a00e35c..b73a44f9ad 100644 --- a/Changelog +++ b/Changelog @@ -38,6 +38,7 @@ version 7.0: - ffplay with hwaccel decoding support (depends on vulkan renderer via libplacebo) - dnn filter libtorch backend - Android content URIs protocol +- VideoToolbox MJPEG encoder version 6.1: diff --git a/configure b/configure index 2a1d22310b..52a0ee762f 100755 --- a/configure +++ b/configure @@ -3474,6 +3474,8 @@ hevc_videotoolbox_encoder_deps="pthreads" hevc_videotoolbox_encoder_select="atsc_a53 videotoolbox_encoder" prores_videotoolbox_encoder_deps="pthreads" prores_videotoolbox_encoder_select="videotoolbox_encoder" +mjpeg_videotoolbox_encoder_deps="pthreads" +mjpeg_videotoolbox_encoder_select="videotoolbox_encoder" libaom_av1_decoder_deps="libaom" libaom_av1_encoder_deps="libaom" libaom_av1_encoder_select="extract_extradata_bsf" diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 9ce6d445c1..f59b2ae691 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -503,6 +503,7 @@ OBJS-$(CONFIG_MJPEGB_DECODER) += mjpegbdec.o OBJS-$(CONFIG_MJPEG_CUVID_DECODER) += cuviddec.o OBJS-$(CONFIG_MJPEG_QSV_ENCODER) += qsvenc_jpeg.o OBJS-$(CONFIG_MJPEG_VAAPI_ENCODER) += vaapi_encode_mjpeg.o +OBJS-$(CONFIG_MJPEG_VIDEOTOOLBOX_ENCODER) += videotoolboxenc.o OBJS-$(CONFIG_MLP_DECODER) += mlpdec.o mlpdsp.o OBJS-$(CONFIG_MLP_ENCODER) += mlpenc.o mlp.o OBJS-$(CONFIG_MMVIDEO_DECODER) += mmvideo.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 2386b450a6..f8a90fdca2 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -879,6 +879,7 @@ extern const FFCodec ff_mpeg4_mediacodec_encoder; extern const FFCodec ff_mpeg4_omx_encoder; extern const FFCodec ff_mpeg4_v4l2m2m_encoder; extern const FFCodec ff_prores_videotoolbox_encoder; +extern const FFCodec ff_mjpeg_videotoolbox_encoder; extern const FFCodec ff_vc1_cuvid_decoder; extern const FFCodec ff_vp8_cuvid_decoder; extern const FFCodec ff_vp8_mediacodec_decoder; diff --git a/libavcodec/videotoolboxenc.c b/libavcodec/videotoolboxenc.c index 15c34d59c3..0574edab56 100644 --- a/libavcodec/videotoolboxenc.c +++ b/libavcodec/videotoolboxenc.c @@ -547,6 +547,7 @@ static CMVideoCodecType get_cm_codec_type(AVCodecContext *avctx, else return MKBETAG('a','p','c','n'); // kCMVideoCodecType_AppleProRes422 } + case AV_CODEC_ID_MJPEG: return kCMVideoCodecType_JPEG; default: return 0; } } @@ -1233,7 +1234,7 @@ static int vtenc_create_encoder(AVCodecContext *avctx, kVTCompressionPropertyKey_Quality, quality_num); CFRelease(quality_num); - } else if (avctx->codec_id != AV_CODEC_ID_PRORES) { + } else if (avctx->codec_id != AV_CODEC_ID_PRORES && avctx->codec_id != AV_CODEC_ID_MJPEG) { bit_rate_num = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &bit_rate); @@ -1347,7 +1348,7 @@ static int vtenc_create_encoder(AVCodecContext *avctx, } } - if (avctx->gop_size > 0 && avctx->codec_id != AV_CODEC_ID_PRORES) { + if (avctx->gop_size > 0 && avctx->codec_id != AV_CODEC_ID_PRORES && avctx->codec_id != AV_CODEC_ID_MJPEG) { CFNumberRef interval = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &avctx->gop_size); @@ -1496,7 +1497,7 @@ static int vtenc_create_encoder(AVCodecContext *avctx, } } - if (!vtctx->has_b_frames && avctx->codec_id != AV_CODEC_ID_PRORES) { + if (!vtctx->has_b_frames && avctx->codec_id != AV_CODEC_ID_PRORES && avctx->codec_id != AV_CODEC_ID_MJPEG) { status = VTSessionSetProperty(vtctx->session, kVTCompressionPropertyKey_AllowFrameReordering, kCFBooleanFalse); @@ -2844,6 +2845,13 @@ static const enum AVPixelFormat prores_pix_fmts[] = { AV_PIX_FMT_NONE }; +static const enum AVPixelFormat mjpeg_pix_fmts[] = { + AV_PIX_FMT_VIDEOTOOLBOX, + AV_PIX_FMT_NV12, + AV_PIX_FMT_YUV420P, + AV_PIX_FMT_NONE +}; + #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM #define COMMON_OPTIONS \ { "allow_sw", "Allow software encoding", OFFSET(allow_sw), AV_OPT_TYPE_BOOL, \ @@ -3004,3 +3012,28 @@ const FFCodec ff_prores_videotoolbox_encoder = { .p.wrapper_name = "videotoolbox", .hw_configs = vt_encode_hw_configs, }; + +static const AVClass mjpeg_videotoolbox_class = { + .class_name = "mjpeg_videotoolbox", + .item_name = av_default_item_name, + .option = NULL, + .version = LIBAVUTIL_VERSION_INT, +}; + +const FFCodec ff_mjpeg_videotoolbox_encoder = { + .p.name = "mjpeg_videotoolbox", + CODEC_LONG_NAME("VideoToolbox MJPEG Encoder"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_MJPEG, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | + AV_CODEC_CAP_HARDWARE, + .priv_data_size = sizeof(VTEncContext), + .p.pix_fmts = prores_pix_fmts, + .init = vtenc_init, + FF_CODEC_ENCODE_CB(vtenc_frame), + .close = vtenc_close, + .p.priv_class = &mjpeg_videotoolbox_class, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, + .p.wrapper_name = "videotoolbox", + .hw_configs = vt_encode_hw_configs, +};
For example: ./ffmpeg -hwaccel videotoolbox\ -i INPUT -c:v mjpeg_videotoolbox\ out.mp4 This encoder does not have many options and can only use ``-q:v` to control quality. Signed-off-by: Gnattu OC <gnattuoc@me.com> --- Changelog | 1 + configure | 2 ++ libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 1 + libavcodec/videotoolboxenc.c | 39 +++++++++++++++++++++++++++++++++--- 5 files changed, 41 insertions(+), 3 deletions(-)