diff options
Diffstat (limited to 'gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_h264enc.c')
-rw-r--r-- | gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_h264enc.c | 374 |
1 files changed, 360 insertions, 14 deletions
diff --git a/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_h264enc.c b/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_h264enc.c index 82a2d65..6d4e9c5 100644 --- a/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_h264enc.c +++ b/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_h264enc.c @@ -3,6 +3,9 @@ * * Author: Felipe Contreras <felipe.contreras@nokia.com> * + * Modified by: David Soto <david.soto@ridgerun.com> + * Copyright (C) 2011 RidgeRun + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation @@ -21,6 +24,8 @@ #include "gstomx_h264enc.h" #include "gstomx.h" +#include <OMX_TI_Index.h> +#include <OMX_TI_Video.h> #include <string.h> /* for memset */ @@ -32,11 +37,18 @@ enum ARG_BYTESTREAM, ARG_PROFILE, ARG_LEVEL, + ARG_I_PERIOD, + ARG_IDR_PERIOD, + ARG_FORCE_IDR, + ARG_ENCODING_PRESET, + ARG_RATECONTROL_PRESET, }; #define DEFAULT_BYTESTREAM FALSE -#define DEFAULT_PROFILE OMX_VIDEO_AVCProfileHigh -#define DEFAULT_LEVEL OMX_VIDEO_AVCLevel4 +#define DEFAULT_PROFILE OMX_VIDEO_AVCProfileBaseline +#define DEFAULT_LEVEL OMX_VIDEO_AVCLevel42 +#define DEFAULT_ENCODE_PRESET OMX_Video_Enc_High_Speed_Med_Quality +#define DEFAULT_RATECONTROL_PRESET OMX_Video_RC_Low_Delay #define GST_TYPE_OMX_VIDEO_AVCPROFILETYPE (gst_omx_video_avcprofiletype_get_type ()) static GType @@ -99,6 +111,54 @@ gst_omx_video_avcleveltype_get_type () return type; } +#define GST_TYPE_OMX_VIDEO_ENCODE_PRESETTYPE (gst_omx_video_enocdepreset_get_type ()) +static GType +gst_omx_video_enocdepreset_get_type () +{ + static GType type = 0; + + if (!type) + { + static const GEnumValue vals[] = + { + {OMX_Video_Enc_High_Quality, "High Quality", "hq"}, + {OMX_Video_Enc_User_Defined, "User Defined", "user"}, + {OMX_Video_Enc_High_Speed_Med_Quality, "High Speed Med Qual", "hsmq"}, + {OMX_Video_Enc_Med_Speed_Med_Quality, "Med Speed Med Qaul", "msmq"}, + {OMX_Video_Enc_Med_Speed_High_Quality, "Med Speed High Qaul", "mshq"}, + {OMX_Video_Enc_High_Speed, "High Speed", "hs"}, + {0, NULL, NULL }, + }; + + type = g_enum_register_static ("GstOmxVideoEncoderPreset", vals); + } + + return type; +} + +#define GST_TYPE_OMX_VIDEO_RATECONTROL_PRESETTYPE (gst_omx_video_ratecontrolpreset_get_type ()) +static GType +gst_omx_video_ratecontrolpreset_get_type () +{ + static GType type = 0; + + if (!type) + { + static const GEnumValue vals[] = + { + {OMX_Video_RC_Low_Delay, "Low Delay", "low-delay"}, + {OMX_Video_RC_Storage, "Storage", "storage"}, + {OMX_Video_RC_Twopass, "Two Pass", "two-pass"}, + {OMX_Video_RC_None, "none", "none"}, + {0, NULL, NULL }, + }; + + type = g_enum_register_static ("GstOmxVideoRateControlPreset", vals); + } + + return type; +} + static GstCaps * generate_src_template (void) { @@ -108,6 +168,8 @@ generate_src_template (void) "width", GST_TYPE_INT_RANGE, 16, 4096, "height", GST_TYPE_INT_RANGE, 16, 4096, "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, + "stream-format", G_TYPE_STRING, "byte-stream", + "alignment", G_TYPE_STRING, "au", NULL); return caps; @@ -150,11 +212,9 @@ set_property (GObject *obj, { GstOmxBaseFilter *omx_base; GstOmxH264Enc *self; - GOmxCore *gomx; omx_base = GST_OMX_BASE_FILTER (obj); self = GST_OMX_H264ENC (obj); - gomx = (GOmxCore*) omx_base->gomx; switch (prop_id) { @@ -162,15 +222,14 @@ set_property (GObject *obj, self->bytestream = g_value_get_boolean (value); break; case ARG_PROFILE: + #if 0 { OMX_VIDEO_PARAM_PROFILELEVELTYPE tProfileLevel; - GOmxCore *gomx; OMX_ERRORTYPE error_val = OMX_ErrorNone; - gomx = (GOmxCore *) omx_base->gomx; _G_OMX_INIT_PARAM (&tProfileLevel); tProfileLevel.nPortIndex = omx_base->out_port->port_index; - error_val = OMX_GetParameter (gomx->omx_handle, + error_val = OMX_GetParameter (g_omx_core_get_handle (omx_base->gomx), OMX_IndexParamVideoProfileLevelCurrent, &tProfileLevel); g_assert (error_val == OMX_ErrorNone); @@ -178,22 +237,25 @@ set_property (GObject *obj, GST_DEBUG_OBJECT (self, "Profile: param=%d", (gint)tProfileLevel.eProfile); - error_val = OMX_SetParameter (gomx->omx_handle, + error_val = OMX_SetParameter (g_omx_core_get_handle (omx_base->gomx), OMX_IndexParamVideoProfileLevelCurrent, &tProfileLevel); g_assert (error_val == OMX_ErrorNone); break; } + #else + self->profile = g_value_get_enum(value); + break; + #endif case ARG_LEVEL: + #if 0 { OMX_VIDEO_PARAM_PROFILELEVELTYPE tProfileLevel; - GOmxCore *gomx; OMX_ERRORTYPE error_val = OMX_ErrorNone; - gomx = (GOmxCore *) omx_base->gomx; _G_OMX_INIT_PARAM (&tProfileLevel); tProfileLevel.nPortIndex = omx_base->out_port->port_index; - error_val = OMX_GetParameter (gomx->omx_handle, + error_val = OMX_GetParameter (g_omx_core_get_handle (omx_base->gomx), OMX_IndexParamVideoProfileLevelCurrent, &tProfileLevel); g_assert (error_val == OMX_ErrorNone); @@ -201,12 +263,101 @@ set_property (GObject *obj, GST_DEBUG_OBJECT (self, "Level: param=%d", (gint)tProfileLevel.eLevel); - error_val = OMX_SetParameter (gomx->omx_handle, + error_val = OMX_SetParameter (g_omx_core_get_handle (omx_base->gomx), OMX_IndexParamVideoProfileLevelCurrent, &tProfileLevel); g_assert (error_val == OMX_ErrorNone); break; } + #else + self->level = g_value_get_enum(value); + break; + #endif + case ARG_I_PERIOD: + #if 0 + { + OMX_VIDEO_CONFIG_AVCINTRAPERIOD avcIntraPeriod; + OMX_ERRORTYPE error_val = OMX_ErrorNone; + + _G_OMX_INIT_PARAM (&avcIntraPeriod); + avcIntraPeriod.nPortIndex = omx_base->out_port->port_index; + error_val = OMX_GetConfig (g_omx_core_get_handle (omx_base->gomx), + OMX_IndexConfigVideoAVCIntraPeriod, + (OMX_PTR)&avcIntraPeriod); + g_assert (error_val == OMX_ErrorNone); + avcIntraPeriod.nPFrames = g_value_get_uint (value); + + if(value>0) + { + error_val = OMX_SetConfig (g_omx_core_get_handle (omx_base->gomx), + OMX_IndexConfigVideoAVCIntraPeriod, + &avcIntraPeriod); + } + g_assert (error_val == OMX_ErrorNone); + break; + } + #else + self->i_period = g_value_get_uint (value); + break; + #endif + case ARG_IDR_PERIOD: + { + self->idr_period = g_value_get_uint (value); + break; + } + case ARG_FORCE_IDR: + { + self->force_idr = g_value_get_boolean (value); + break; + } + case ARG_ENCODING_PRESET: + { + #if 0 + OMX_ERRORTYPE error_val = OMX_ErrorNone; + OMX_VIDEO_PARAM_ENCODER_PRESETTYPE tEncoderPreset; + _G_OMX_INIT_PARAM(&tEncoderPreset); + tEncoderPreset.nPortIndex = omx_base->out_port->port_index; + + error_val = + OMX_GetParameter(g_omx_core_get_handle (omx_base->gomx), + OMX_TI_IndexParamVideoEncoderPreset, + &tEncoderPreset); + g_assert (error_val == OMX_ErrorNone); + + tEncoderPreset.eEncodingModePreset = g_value_get_enum (value); + error_val = OMX_SetParameter(g_omx_core_get_handle (omx_base->gomx), + OMX_TI_IndexParamVideoEncoderPreset, + &tEncoderPreset); + g_assert (error_val == OMX_ErrorNone); + #else + self->encodingPreset = g_value_get_enum(value); + #endif + break; + } + case ARG_RATECONTROL_PRESET: + { + #if 0 + OMX_ERRORTYPE error_val = OMX_ErrorNone; + OMX_VIDEO_PARAM_ENCODER_PRESETTYPE tEncoderPreset; + _G_OMX_INIT_PARAM(&tEncoderPreset); + tEncoderPreset.nPortIndex = omx_base->out_port->port_index; + + error_val = + OMX_GetParameter(g_omx_core_get_handle (omx_base->gomx), + OMX_TI_IndexParamVideoEncoderPreset, + &tEncoderPreset); + g_assert (error_val == OMX_ErrorNone); + + tEncoderPreset.eRateControlPreset = g_value_get_enum (value); + error_val = OMX_SetParameter(g_omx_core_get_handle (omx_base->gomx), + OMX_TI_IndexParamVideoEncoderPreset, + &tEncoderPreset); + g_assert (error_val == OMX_ErrorNone); + #else + self->ratecontrolPreset = g_value_get_enum(value); + #endif + break; + } default: G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec); break; @@ -231,6 +382,7 @@ get_property (GObject *obj, g_value_set_boolean (value, self->bytestream); break; case ARG_PROFILE: + #if 0 { OMX_VIDEO_PARAM_PROFILELEVELTYPE tProfileLevel; GOmxCore *gomx; @@ -250,7 +402,12 @@ get_property (GObject *obj, break; } + #else + g_value_set_enum(value, self->profile); + break; + #endif case ARG_LEVEL: + #if 0 { OMX_VIDEO_PARAM_PROFILELEVELTYPE tProfileLevel; GOmxCore *gomx; @@ -270,6 +427,82 @@ get_property (GObject *obj, break; } + #else + g_value_set_enum(value, self->level); + break; + #endif + case ARG_I_PERIOD: + #if 0 + { + OMX_VIDEO_CONFIG_AVCINTRAPERIOD avcIntraPeriod; + GOmxCore *gomx; + + gomx = (GOmxCore *) omx_base->gomx; + _G_OMX_INIT_PARAM (&avcIntraPeriod); + avcIntraPeriod.nPortIndex = omx_base->out_port->port_index; + OMX_GetConfig (gomx->omx_handle, + OMX_IndexConfigVideoAVCIntraPeriod, + &avcIntraPeriod); + g_value_set_uint (value, (gint)avcIntraPeriod.nPFrames); + + break; + } + #else + g_value_set_uint(value, self->i_period); + break; + #endif + case ARG_IDR_PERIOD: + { + g_value_set_uint (value, self->idr_period); + + break; + } + case ARG_FORCE_IDR: + { + g_value_set_boolean (value, self->force_idr); + + break; + } + case ARG_ENCODING_PRESET: + { + #if 0 + OMX_VIDEO_PARAM_ENCODER_PRESETTYPE tEncoderPreset; + GOmxCore *gomx; + OMX_ERRORTYPE error_val = OMX_ErrorNone; + + gomx = (GOmxCore *) omx_base->gomx; + error_val = OMX_GetParameter(gomx->omx_handle, OMX_TI_IndexParamVideoEncoderPreset, + &tEncoderPreset); + + g_value_set_enum (value, tEncoderPreset.eEncodingModePreset); + + GST_DEBUG_OBJECT (self, "Encoding Preset: param=%d", + (gint)tEncoderPreset.eEncodingModePreset); + #else + g_value_set_enum(value, self->encodingPreset); + #endif + break; + } + case ARG_RATECONTROL_PRESET: + { + #if 0 + OMX_VIDEO_PARAM_ENCODER_PRESETTYPE tEncoderPreset; + GOmxCore *gomx; + OMX_ERRORTYPE error_val = OMX_ErrorNone; + + gomx = (GOmxCore *) omx_base->gomx; + error_val = OMX_GetParameter(gomx->omx_handle, OMX_TI_IndexParamVideoEncoderPreset, + &tEncoderPreset); + + g_value_set_enum (value, tEncoderPreset.eRateControlPreset); + + GST_DEBUG_OBJECT (self, "RateControl Preset: param=%d", + (gint)tEncoderPreset.eRateControlPreset); + #else + g_value_set_enum(value, self->ratecontrolPreset); + #endif + break; + } default: G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec); break; @@ -304,8 +537,73 @@ type_class_init (gpointer g_class, GST_TYPE_OMX_VIDEO_AVCLEVELTYPE, DEFAULT_LEVEL, G_PARAM_READWRITE)); + g_object_class_install_property (gobject_class, ARG_I_PERIOD, + g_param_spec_uint ("i-period", "Specifies periodicity of I frames", + "Specifies periodicity of I frames (0:Disable)", + 0, G_MAXINT32, 90, G_PARAM_READWRITE)); + g_object_class_install_property (gobject_class, ARG_IDR_PERIOD, + g_param_spec_uint ("force-idr-period", "Specifies periodicity of IDR frames", + "Specifies periodicity of IDR frames (0:Disable)", + 0, G_MAXINT32, 0, G_PARAM_READWRITE)); + g_object_class_install_property (gobject_class, ARG_FORCE_IDR, + g_param_spec_boolean ("force-idr", "force-idr", "force next frame to be IDR", + FALSE, G_PARAM_WRITABLE)); + g_object_class_install_property (gobject_class, ARG_ENCODING_PRESET, + g_param_spec_enum ("encodingPreset", "Specifies which encoding preset to use", + "Specifies which encoding preset to use", + GST_TYPE_OMX_VIDEO_ENCODE_PRESETTYPE, + DEFAULT_ENCODE_PRESET, + G_PARAM_READWRITE)); + g_object_class_install_property (gobject_class, ARG_RATECONTROL_PRESET, + g_param_spec_enum ("rateControlPreset", "Specifies what rate control preset to use", + "Specifies what rate control preset to use", + GST_TYPE_OMX_VIDEO_RATECONTROL_PRESETTYPE, + DEFAULT_RATECONTROL_PRESET, + G_PARAM_READWRITE)); + + } +} + +static void +omx_h264_push_cb (GstOmxBaseFilter *omx_base, GstBuffer *buf) +{ + GstOmxH264Enc *self; + self = GST_OMX_H264ENC (omx_base); + /* Currently we use this logic to handle IDR period since the latest + * EZSDK version doesn't have support for OMX_IndexConfigVideoAVCIntraPeriod + */ + if ((self->idr_period > 0) || (self->force_idr)) + { + if ((self->cont == self->idr_period) || (self->force_idr)) + { + OMX_CONFIG_INTRAREFRESHVOPTYPE confIntraRefreshVOP; + + _G_OMX_INIT_PARAM (&confIntraRefreshVOP); + confIntraRefreshVOP.nPortIndex = omx_base->out_port->port_index; + + OMX_GetConfig (g_omx_core_get_handle (omx_base->gomx), + OMX_IndexConfigVideoIntraVOPRefresh, + &confIntraRefreshVOP); + confIntraRefreshVOP.IntraRefreshVOP = TRUE; + + OMX_SetConfig (g_omx_core_get_handle (omx_base->gomx), + OMX_IndexConfigVideoIntraVOPRefresh, + &confIntraRefreshVOP); + + if (self->cont == self->idr_period) + self->cont = 0; + + if (self->force_idr) + { + self->force_idr = FALSE; + self->cont++; + } + } else { + self->cont++; + } } + GST_BUFFER_CAPS(buf) = gst_caps_ref(GST_PAD_CAPS(omx_base->srcpad)); } static void @@ -313,7 +611,9 @@ omx_setup (GstOmxBaseFilter *omx_base) { GstOmxBaseVideoEnc *self; GOmxCore *gomx; + GstOmxH264Enc *h264enc; + h264enc = GST_OMX_H264ENC (omx_base); self = GST_OMX_BASE_VIDEOENC (omx_base); gomx = (GOmxCore *) omx_base->gomx; @@ -325,9 +625,7 @@ omx_setup (GstOmxBaseFilter *omx_base) if (OMX_GetExtensionIndex (gomx->omx_handle, "OMX.TI.VideoEncode.Config.NALFormat", &index) == OMX_ErrorNone) { OMX_U32 nal_format; - GstOmxH264Enc *h264enc; - h264enc = GST_OMX_H264ENC (omx_base); nal_format = h264enc->bytestream ? 0 : 1; GST_DEBUG_OBJECT (omx_base, "setting 'OMX.TI.VideoEncode.Config.NALFormat' to %ld", nal_format); @@ -339,6 +637,36 @@ omx_setup (GstOmxBaseFilter *omx_base) } } + { + OMX_VIDEO_PARAM_AVCTYPE tAVCParams; + + _G_OMX_INIT_PARAM (&tAVCParams); + + tAVCParams.nPortIndex = OMX_DirOutput; + OMX_GetParameter(gomx->omx_handle, OMX_IndexParamVideoAvc, &tAVCParams); + + tAVCParams.eLevel = h264enc->level; + tAVCParams.eProfile = h264enc->profile; + tAVCParams.nPFrames = h264enc->i_period - 1; + tAVCParams.nBFrames = 0; + + OMX_SetParameter(gomx->omx_handle, OMX_IndexParamVideoAvc, &tAVCParams); + } + + { + OMX_VIDEO_PARAM_ENCODER_PRESETTYPE tEncoderPreset; + + _G_OMX_INIT_PARAM(&tEncoderPreset); + tEncoderPreset.nPortIndex = omx_base->out_port->port_index; + + OMX_GetParameter(gomx->omx_handle, OMX_TI_IndexParamVideoEncoderPreset, &tEncoderPreset); + + tEncoderPreset.eEncodingModePreset = h264enc->encodingPreset; + tEncoderPreset.eRateControlPreset = h264enc->ratecontrolPreset; + + OMX_SetParameter(gomx->omx_handle, OMX_TI_IndexParamVideoEncoderPreset, &tEncoderPreset); + } + GST_INFO_OBJECT (omx_base, "end"); } @@ -371,6 +699,8 @@ settings_changed_cb (GOmxCore *core) "height", G_TYPE_INT, height, "framerate", GST_TYPE_FRACTION, omx_base->framerate_num, omx_base->framerate_denom, + "stream-format", G_TYPE_STRING, "byte-stream", + "alignment", G_TYPE_STRING, "au", NULL); GST_INFO_OBJECT (omx_base, "caps are: %" GST_PTR_FORMAT, new_caps); @@ -384,13 +714,29 @@ type_instance_init (GTypeInstance *instance, { GstOmxBaseFilter *omx_base_filter; GstOmxBaseVideoEnc *omx_base; + GstOmxBaseFilterClass *bclass; + GstOmxH264Enc *self; omx_base_filter = GST_OMX_BASE_FILTER (instance); omx_base = GST_OMX_BASE_VIDEOENC (instance); + self = GST_OMX_H264ENC (instance); + bclass = GST_OMX_BASE_FILTER_CLASS (g_class); omx_base->omx_setup = omx_setup; + omx_base_filter->push_cb = omx_h264_push_cb; + omx_base->compression_format = OMX_VIDEO_CodingAVC; omx_base_filter->gomx->settings_changed_cb = settings_changed_cb; + + self->idr_period = 0; + self->cont = 0; + self->force_idr = FALSE; + + self->i_period = 90; + self->profile = DEFAULT_PROFILE; + self->level = DEFAULT_LEVEL; + self->encodingPreset = OMX_Video_Enc_High_Speed_Med_Quality; + self->ratecontrolPreset = OMX_Video_RC_Low_Delay; } |