msdkenc: add need_conversion method

In future, a sub class of GstMsdkEncClass may decide a native format by
using this method, e.g. JPEG encoder may accept YUY2 input, however the
current implemation needs a conversion from YUY2 to NV12 before encoding.

In addtion, a sub class may choose a format for encoding if the input
format is not supported by MSDK, e.g. the current implemation does
UYVY->NV12 if the input format is UYVY. We may do UYVY->YUY2 for JPEG
encoder in future
This commit is contained in:
Haihao Xiang 2019-10-11 12:50:02 +08:00 committed by Víctor Manuel Jáquez Leal
parent afce02b392
commit fbeaa37b79
2 changed files with 67 additions and 37 deletions

View file

@ -247,6 +247,7 @@ gst_msdkenc_init_encoder (GstMsdkEnc * thiz)
mfxFrameAllocRequest request[2]; mfxFrameAllocRequest request[2];
guint i; guint i;
gboolean need_vpp = TRUE; gboolean need_vpp = TRUE;
GstVideoFormat encoder_input_fmt;
if (thiz->initialized) { if (thiz->initialized) {
GST_DEBUG_OBJECT (thiz, "Already initialized"); GST_DEBUG_OBJECT (thiz, "Already initialized");
@ -271,15 +272,11 @@ gst_msdkenc_init_encoder (GstMsdkEnc * thiz)
if (thiz->use_video_memory) if (thiz->use_video_memory)
gst_msdk_set_frame_allocator (thiz->context); gst_msdk_set_frame_allocator (thiz->context);
encoder_input_fmt = GST_VIDEO_INFO_FORMAT (info);
need_vpp = klass->need_conversion (thiz, info, &encoder_input_fmt);
if (need_vpp) {
switch (GST_VIDEO_INFO_FORMAT (info)) { switch (GST_VIDEO_INFO_FORMAT (info)) {
case GST_VIDEO_FORMAT_NV12:
case GST_VIDEO_FORMAT_P010_10LE:
case GST_VIDEO_FORMAT_VUYA:
#if (MFX_VERSION >= 1027)
case GST_VIDEO_FORMAT_Y410:
#endif
need_vpp = FALSE;
break;
case GST_VIDEO_FORMAT_YV12: case GST_VIDEO_FORMAT_YV12:
case GST_VIDEO_FORMAT_I420: case GST_VIDEO_FORMAT_I420:
thiz->vpp_param.vpp.In.FourCC = MFX_FOURCC_YV12; thiz->vpp_param.vpp.In.FourCC = MFX_FOURCC_YV12;
@ -302,7 +299,6 @@ gst_msdkenc_init_encoder (GstMsdkEnc * thiz)
break; break;
} }
if (need_vpp) {
if (thiz->use_video_memory) if (thiz->use_video_memory)
thiz->vpp_param.IOPattern = thiz->vpp_param.IOPattern =
MFX_IOPATTERN_IN_VIDEO_MEMORY | MFX_IOPATTERN_OUT_VIDEO_MEMORY; MFX_IOPATTERN_IN_VIDEO_MEMORY | MFX_IOPATTERN_OUT_VIDEO_MEMORY;
@ -326,7 +322,7 @@ gst_msdkenc_init_encoder (GstMsdkEnc * thiz)
thiz->vpp_param.vpp.Out = thiz->vpp_param.vpp.In; thiz->vpp_param.vpp.Out = thiz->vpp_param.vpp.In;
if ((GST_VIDEO_INFO_COMP_DEPTH (info, 0)) == 10) { if (encoder_input_fmt == GST_VIDEO_FORMAT_P010_10LE) {
thiz->vpp_param.vpp.Out.FourCC = MFX_FOURCC_P010; thiz->vpp_param.vpp.Out.FourCC = MFX_FOURCC_P010;
thiz->vpp_param.vpp.Out.ChromaFormat = MFX_CHROMAFORMAT_YUV420; thiz->vpp_param.vpp.Out.ChromaFormat = MFX_CHROMAFORMAT_YUV420;
} else { } else {
@ -418,7 +414,7 @@ gst_msdkenc_init_encoder (GstMsdkEnc * thiz)
thiz->param.mfx.FrameInfo.PicStruct = MFX_PICSTRUCT_PROGRESSIVE; thiz->param.mfx.FrameInfo.PicStruct = MFX_PICSTRUCT_PROGRESSIVE;
thiz->param.mfx.FrameInfo.ChromaFormat = MFX_CHROMAFORMAT_YUV420; thiz->param.mfx.FrameInfo.ChromaFormat = MFX_CHROMAFORMAT_YUV420;
switch (GST_VIDEO_INFO_FORMAT (info)) { switch (encoder_input_fmt) {
case GST_VIDEO_FORMAT_P010_10LE: case GST_VIDEO_FORMAT_P010_10LE:
thiz->param.mfx.FrameInfo.FourCC = MFX_FOURCC_P010; thiz->param.mfx.FrameInfo.FourCC = MFX_FOURCC_P010;
thiz->param.mfx.FrameInfo.BitDepthLuma = 10; thiz->param.mfx.FrameInfo.BitDepthLuma = 10;
@ -1133,14 +1129,17 @@ gst_msdkenc_set_format (GstVideoEncoder * encoder, GstVideoCodecState * state)
/* Create another bufferpool if VPP requires */ /* Create another bufferpool if VPP requires */
if (thiz->has_vpp) { if (thiz->has_vpp) {
GstVideoInfo *info = &thiz->input_state->info; GstVideoInfo *info = &thiz->input_state->info;
GstVideoInfo nv12_info; GstVideoInfo out_info;
GstVideoFormat out_fmt;
GstCaps *caps; GstCaps *caps;
GstBufferPool *pool = NULL; GstBufferPool *pool = NULL;
gst_video_info_init (&nv12_info); gst_video_info_init (&out_info);
gst_video_info_set_format (&nv12_info, GST_VIDEO_FORMAT_NV12, info->width, out_fmt =
info->height); gst_msdk_get_video_format_from_mfx_fourcc (thiz->vpp_param.vpp.
caps = gst_video_info_to_caps (&nv12_info); Out.FourCC);
gst_video_info_set_format (&out_info, out_fmt, info->width, info->height);
caps = gst_video_info_to_caps (&out_info);
/* If there's an existing pool try to reuse it when is compatible */ /* If there's an existing pool try to reuse it when is compatible */
if (thiz->msdk_converted_pool) { if (thiz->msdk_converted_pool) {
@ -1634,6 +1633,28 @@ gst_msdkenc_finalize (GObject * object)
G_OBJECT_CLASS (parent_class)->finalize (object); G_OBJECT_CLASS (parent_class)->finalize (object);
} }
static gboolean
gst_msdkenc_need_conversion (GstMsdkEnc * encoder, GstVideoInfo * info,
GstVideoFormat * out_format)
{
switch (GST_VIDEO_INFO_FORMAT (info)) {
case GST_VIDEO_FORMAT_NV12:
case GST_VIDEO_FORMAT_P010_10LE:
case GST_VIDEO_FORMAT_VUYA:
#if (MFX_VERSION >= 1027)
case GST_VIDEO_FORMAT_Y410:
#endif
return FALSE;
default:
if (GST_VIDEO_INFO_COMP_DEPTH (info, 0) == 10)
*out_format = GST_VIDEO_FORMAT_P010_10LE;
else
*out_format = GST_VIDEO_FORMAT_NV12;
return TRUE;
}
}
static void static void
gst_msdkenc_class_init (GstMsdkEncClass * klass) gst_msdkenc_class_init (GstMsdkEncClass * klass)
{ {
@ -1645,6 +1666,8 @@ gst_msdkenc_class_init (GstMsdkEncClass * klass)
element_class = GST_ELEMENT_CLASS (klass); element_class = GST_ELEMENT_CLASS (klass);
gstencoder_class = GST_VIDEO_ENCODER_CLASS (klass); gstencoder_class = GST_VIDEO_ENCODER_CLASS (klass);
klass->need_conversion = gst_msdkenc_need_conversion;
gobject_class->finalize = gst_msdkenc_finalize; gobject_class->finalize = gst_msdkenc_finalize;
element_class->set_context = gst_msdkenc_set_context; element_class->set_context = gst_msdkenc_set_context;

View file

@ -167,6 +167,13 @@ struct _GstMsdkEncClass
gboolean (*set_format) (GstMsdkEnc * encoder); gboolean (*set_format) (GstMsdkEnc * encoder);
gboolean (*configure) (GstMsdkEnc * encoder); gboolean (*configure) (GstMsdkEnc * encoder);
GstCaps *(*set_src_caps) (GstMsdkEnc * encoder); GstCaps *(*set_src_caps) (GstMsdkEnc * encoder);
/* Return TRUE if vpp is required before encoding
* @info (in), input video info
* @out_format (out), a pointer to the output format of vpp, which is set
* when return TRUE
*/
gboolean (*need_conversion) (GstMsdkEnc * encoder, GstVideoInfo * info,
GstVideoFormat * out_format);
}; };
struct _MsdkEncTask struct _MsdkEncTask