diff options
author | Alessandro Decina <alessandro.decina@collabora.co.uk> | 2011-10-14 18:14:00 +0200 |
---|---|---|
committer | Alessandro Decina <alessandro.decina@collabora.co.uk> | 2011-10-16 23:53:40 +0200 |
commit | dfef372881283ab0106668e7a912100b975bbbe2 (patch) | |
tree | 91ae9aa55a380ccc575114435e10216c11e91480 | |
parent | 85e8a453644b1e46edf8e52ff8722af9de13760f (diff) |
ducatih264enc: add h264 encoder
-rw-r--r-- | configure.ac | 1 | ||||
-rw-r--r-- | src/Makefile.am | 5 | ||||
-rw-r--r-- | src/gstducati.c | 4 | ||||
-rw-r--r-- | src/gstducatibufferpool.c | 18 | ||||
-rw-r--r-- | src/gstducatih264enc.c | 708 | ||||
-rw-r--r-- | src/gstducatih264enc.h | 81 |
6 files changed, 809 insertions, 8 deletions
diff --git a/configure.ac b/configure.ac index 54ccf5d..09f78eb 100644 --- a/configure.ac +++ b/configure.ac @@ -85,6 +85,7 @@ PKG_CHECK_MODULES(GST, [ gstreamer-0.10 >= $GST_REQUIRED gstreamer-base-0.10 >= $GST_REQUIRED gstreamer-plugins-base-0.10 >= $GST_REQUIRED + gstreamer-plugins-bad-0.10 ], [ AC_SUBST(GST_CFLAGS) AC_SUBST(GST_LIBS) diff --git a/src/Makefile.am b/src/Makefile.am index 14de718..ba39759 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -24,11 +24,12 @@ libgstducati_la_SOURCES = \ gstducatih264dec.c \ gstducatividdec.c \ gstducatibufferpool.c \ + gstducatih264enc.c \ gstducati.c \ $(noinst_HEADERS) # compiler and linker flags used to compile this plugin, set in configure.ac -libgstducati_la_CFLAGS = $(GST_CFLAGS) $(MEMMGR_CFLAGS) $(LIBDCE_CFLAGS) -libgstducati_la_LIBADD = $(GST_LIBS) $(MEMMGR_LIBS) $(LIBDCE_LIBS) -lgstvideo-0.10 +libgstducati_la_CFLAGS = $(GST_CFLAGS) $(MEMMGR_CFLAGS) $(LIBDCE_CFLAGS) -DGST_USE_UNSTABLE_API +libgstducati_la_LIBADD = $(GST_LIBS) $(MEMMGR_LIBS) $(LIBDCE_LIBS) -lgstvideo-0.10 -lgstbasevideo-0.10 libgstducati_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) $(GST_ALL_LDFLAGS) --no-undefined libgstducati_la_LIBTOOLFLAGS = --tag=disable-static diff --git a/src/gstducati.c b/src/gstducati.c index 244fb59..b6e19fb 100644 --- a/src/gstducati.c +++ b/src/gstducati.c @@ -29,6 +29,7 @@ #include "gstducativp6dec.h" #include "gstducativp7dec.h" #include "gstducatirvdec.h" +#include "gstducatih264enc.h" GST_DEBUG_CATEGORY (gst_ducati_debug); @@ -46,7 +47,8 @@ plugin_init (GstPlugin * plugin) gst_element_register (plugin, "ducativc1dec", GST_RANK_PRIMARY, GST_TYPE_DUCATIVC1DEC) && gst_element_register (plugin, "ducativp6dec", GST_RANK_PRIMARY, GST_TYPE_DUCATIVP6DEC) && gst_element_register (plugin, "ducativp7dec", GST_RANK_PRIMARY, GST_TYPE_DUCATIVP7DEC) && - gst_element_register (plugin, "ducatirvdec", GST_RANK_PRIMARY, GST_TYPE_DUCATIRVDEC); + gst_element_register (plugin, "ducatirvdec", GST_RANK_PRIMARY, GST_TYPE_DUCATIRVDEC) && + gst_element_register (plugin, "ducatih264enc", GST_RANK_PRIMARY, GST_TYPE_DUCATIH264ENC); } void * diff --git a/src/gstducatibufferpool.c b/src/gstducatibufferpool.c index 88480c1..3f91c8c 100644 --- a/src/gstducatibufferpool.c +++ b/src/gstducatibufferpool.c @@ -133,13 +133,20 @@ gst_ducati_bufferpool_new (GstElement * element, GstCaps * caps, guint size) { GstDucatiBufferPool *self = (GstDucatiBufferPool *) gst_mini_object_new (GST_TYPE_DUCATIBUFFERPOOL); - GstStructure *s = gst_caps_get_structure (caps, 0); self->element = gst_object_ref (element); - gst_structure_get_int (s, "width", &self->padded_width); - gst_structure_get_int (s, "height", &self->padded_height); + if (caps) { + GstStructure *s = gst_caps_get_structure (caps, 0); + + self->caps = gst_caps_ref (caps); + gst_structure_get_int (s, "width", &self->padded_width); + gst_structure_get_int (s, "height", &self->padded_height); + } else { + self->padded_width = 0; + self->padded_height = 0; + self->caps = NULL; + } self->size = size; - self->caps = gst_caps_ref (caps); self->freelist = NULL; self->lock = g_mutex_new (); self->running = TRUE; @@ -203,7 +210,8 @@ static void gst_ducati_bufferpool_finalize (GstDucatiBufferPool * self) { g_mutex_free (self->lock); - gst_caps_unref (self->caps); + if (self->caps) + gst_caps_unref (self->caps); gst_object_unref (self->element); GST_MINI_OBJECT_CLASS (bufferpool_parent_class)-> finalize (GST_MINI_OBJECT (self)); diff --git a/src/gstducatih264enc.c b/src/gstducatih264enc.c new file mode 100644 index 0000000..d1f226d --- /dev/null +++ b/src/gstducatih264enc.c @@ -0,0 +1,708 @@ +/* GStreamer + * Copyright (c) 2011, Texas Instruments Incorporated + * Copyright (c) 2011, Collabora Ltd. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: Alessandro Decina <alessandro.decina@collabora.com> + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstducati.h" +#include "gstducatih264enc.h" + +#include <string.h> + +#include <math.h> + +#define GST_CAT_DEFAULT gst_ducati_debug + +#define DEFAULT_PROFILE GST_DUCATI_H264ENC_PROFILE_HIGH +#define DEFAULT_LEVEL GST_DUCATI_H264ENC_LEVEL_40 +#define DEFAULT_BITRATE 2048 +#define DEFAULT_RATE_PRESET GST_DUCATI_H264ENC_RATE_PRESET_LOW_DELAY + +#define GST_TYPE_DUCATI_H264ENC_PROFILE (gst_ducati_h264enc_profile_get_type ()) +#define GST_TYPE_DUCATI_H264ENC_LEVEL (gst_ducati_h264enc_level_get_type ()) +#define GST_TYPE_DUCATI_H264ENC_RATE_PRESET (gst_ducati_h264enc_rate_preset_get_type ()) + + +enum +{ + LAST_SIGNAL +}; + +enum +{ + PROP_0, + PROP_PROFILE, + PROP_LEVEL, + PROP_BITRATE, + PROP_RATE_PRESET +}; + +static void gst_ducati_h264enc_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_ducati_h264enc_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + +static gboolean gst_ducati_h264enc_set_format (GstBaseVideoEncoder * + base_video_encoder, GstVideoState * state); +static gboolean gst_ducati_h264enc_start (GstBaseVideoEncoder * + base_video_encoder); +static gboolean gst_ducati_h264enc_stop (GstBaseVideoEncoder * + base_video_encoder); +static GstFlowReturn gst_ducati_h264enc_finish (GstBaseVideoEncoder * + base_video_encoder); +static GstFlowReturn gst_ducati_h264enc_handle_frame (GstBaseVideoEncoder * + base_video_encoder, GstVideoFrame * frame); + +static GstStaticPadTemplate gst_ducati_h264enc_sink_template = +GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("NV12")) + ); + +static GstStaticPadTemplate gst_ducati_h264enc_src_template = +GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("video/x-h264") + ); + +GST_BOILERPLATE (GstDucatiH264Enc, gst_ducati_h264enc, GstBaseVideoEncoder, + GST_TYPE_BASE_VIDEO_ENCODER); + + +/* the values for the following enums are taken from the codec */ + +enum +{ + GST_DUCATI_H264ENC_PROFILE_BASELINE = 66, /**< BaseLine Profile */ + GST_DUCATI_H264ENC_PROFILE_MAIN = 77, /**< Main Profile */ + GST_DUCATI_H264ENC_PROFILE_EXTENDED = 88, /**< Extended Profile */ + GST_DUCATI_H264ENC_PROFILE_HIGH = 100, /**< High Profile */ + GST_DUCATI_H264ENC_PROFILE_HIGH_10 = 110, /**< High 10 Profile */ + GST_DUCATI_H264ENC_PROFILE_HIGH_422 = 122 /**< High 4:2:2 Profile */ +}; + +enum +{ + GST_DUCATI_H264ENC_LEVEL_10 = 10, /**< Level 1.0 */ + GST_DUCATI_H264ENC_LEVEL_1b = 9, /**< Level 1.b */ + GST_DUCATI_H264ENC_LEVEL_11 = 11, /**< Level 1.1 */ + GST_DUCATI_H264ENC_LEVEL_12 = 12, /**< Level 1.2 */ + GST_DUCATI_H264ENC_LEVEL_13 = 13, /**< Level 1.3 */ + GST_DUCATI_H264ENC_LEVEL_20 = 20, /**< Level 2.0 */ + GST_DUCATI_H264ENC_LEVEL_21 = 21, /**< Level 2.1 */ + GST_DUCATI_H264ENC_LEVEL_22 = 22, /**< Level 2.2 */ + GST_DUCATI_H264ENC_LEVEL_30 = 30, /**< Level 3.0 */ + GST_DUCATI_H264ENC_LEVEL_31 = 31, /**< Level 3.1 */ + GST_DUCATI_H264ENC_LEVEL_32 = 32, /**< Level 3.2 */ + GST_DUCATI_H264ENC_LEVEL_40 = 40, /**< Level 4.0 */ + GST_DUCATI_H264ENC_LEVEL_41 = 41, /**< Level 4.1 */ + GST_DUCATI_H264ENC_LEVEL_42 = 42, /**< Level 4.2 */ + GST_DUCATI_H264ENC_LEVEL_50 = 50, /**< Level 5.0 */ + GST_DUCATI_H264ENC_LEVEL_51 = 51 /**< Level 5.1 */ +}; + +enum +{ + GST_DUCATI_H264ENC_RATE_PRESET_LOW_DELAY = 1, /**< CBR rate control for video conferencing. */ + GST_DUCATI_H264ENC_RATE_PRESET_STORAGE = 2, /**< VBR rate control for local storage (DVD) + * recording. + */ + GST_DUCATI_H264ENC_RATE_PRESET_TWOPASS = 3, /**< Two pass rate control for non real time + * applications. + */ + GST_DUCATI_H264ENC_RATE_PRESET_NONE = 4, /**< No configurable video rate control + * mechanism. + */ + GST_DUCATI_H264ENC_RATE_PRESET_USER_DEFINED = 5,/**< User defined configuration using extended + * parameters. + */ +}; + +static GType +gst_ducati_h264enc_profile_get_type (void) +{ + static GType type = 0; + + if (!type) { + static const GEnumValue vals[] = { + {GST_DUCATI_H264ENC_PROFILE_BASELINE, "Base Profile", "baseline"}, + {GST_DUCATI_H264ENC_PROFILE_MAIN, "Main Profile", "main"}, + {GST_DUCATI_H264ENC_PROFILE_EXTENDED, "Extended Profile", "extended"}, + {GST_DUCATI_H264ENC_PROFILE_HIGH, "High Profile", "high"}, + {GST_DUCATI_H264ENC_PROFILE_HIGH_10, "High 10 Profile", "high-10"}, + {GST_DUCATI_H264ENC_PROFILE_HIGH_422, "High 4:2:2 Profile", "high-422"}, + {0, NULL, NULL}, + }; + + type = g_enum_register_static ("GstDucatiH264EncProfile", vals); + } + + return type; +} + +static GType +gst_ducati_h264enc_level_get_type (void) +{ + static GType type = 0; + + if (!type) { + static const GEnumValue vals[] = { + {GST_DUCATI_H264ENC_LEVEL_10, "Level 1", "level-1"}, + {GST_DUCATI_H264ENC_LEVEL_1b, "Level 1b", "level-1b"}, + {GST_DUCATI_H264ENC_LEVEL_11, "Level 11", "level-11"}, + {GST_DUCATI_H264ENC_LEVEL_12, "Level 12", "level-12"}, + {GST_DUCATI_H264ENC_LEVEL_13, "Level 13", "level-13"}, + {GST_DUCATI_H264ENC_LEVEL_20, "Level 2", "level-2"}, + {GST_DUCATI_H264ENC_LEVEL_21, "Level 21", "level-21"}, + {GST_DUCATI_H264ENC_LEVEL_22, "Level 22", "level-22"}, + {GST_DUCATI_H264ENC_LEVEL_30, "Level 3", "level-3"}, + {GST_DUCATI_H264ENC_LEVEL_31, "Level 31", "level-31"}, + {GST_DUCATI_H264ENC_LEVEL_32, "Level 32", "level-32"}, + {GST_DUCATI_H264ENC_LEVEL_40, "Level 4", "level-4"}, + {GST_DUCATI_H264ENC_LEVEL_41, "Level 41", "level-41"}, + {GST_DUCATI_H264ENC_LEVEL_42, "Level 42", "level-42"}, + {GST_DUCATI_H264ENC_LEVEL_50, "Level 5", "level-5"}, + {GST_DUCATI_H264ENC_LEVEL_51, "Level 51", "level-51"}, + {0, NULL, NULL}, + }; + + type = g_enum_register_static ("GstDucatiH264EncLevel", vals); + } + + return type; +} + +static GType +gst_ducati_h264enc_rate_preset_get_type (void) +{ + static GType type = 0; + + if (!type) { + static const GEnumValue vals[] = { + {GST_DUCATI_H264ENC_RATE_PRESET_LOW_DELAY, "Low Delay", "low-delay"}, + {GST_DUCATI_H264ENC_RATE_PRESET_STORAGE, "Storage", "storage"}, + {GST_DUCATI_H264ENC_RATE_PRESET_TWOPASS, "Two-Pass", "two-pass"}, + {0, NULL, NULL}, + }; + + type = g_enum_register_static ("GstDucatiH264EncRatePreset", vals); + } + + return type; +} + +static void +gst_ducati_h264enc_base_init (gpointer g_class) +{ + + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_ducati_h264enc_src_template)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_ducati_h264enc_sink_template)); + + gst_element_class_set_details_simple (element_class, "H264 Encoder", + "Codec/Encoder/Video", + "Encode raw video into H264 stream", + "Alessandro Decina <alessandro.decina@collabora.com>"); +} + +static void +gst_ducati_h264enc_class_init (GstDucatiH264EncClass * klass) +{ + GObjectClass *gobject_class; + GstBaseVideoEncoderClass *basevideocoder_class; + + gobject_class = G_OBJECT_CLASS (klass); + basevideocoder_class = GST_BASE_VIDEO_ENCODER_CLASS (klass); + + gobject_class->set_property = gst_ducati_h264enc_set_property; + gobject_class->get_property = gst_ducati_h264enc_get_property; + + basevideocoder_class->set_format = + GST_DEBUG_FUNCPTR (gst_ducati_h264enc_set_format); + basevideocoder_class->start = GST_DEBUG_FUNCPTR (gst_ducati_h264enc_start); + basevideocoder_class->stop = GST_DEBUG_FUNCPTR (gst_ducati_h264enc_stop); + basevideocoder_class->finish = GST_DEBUG_FUNCPTR (gst_ducati_h264enc_finish); + basevideocoder_class->handle_frame = + GST_DEBUG_FUNCPTR (gst_ducati_h264enc_handle_frame); + + g_object_class_install_property (gobject_class, PROP_PROFILE, + g_param_spec_enum ("profile", "H.264 Profile", "H.264 Profile", + GST_TYPE_DUCATI_H264ENC_PROFILE, DEFAULT_PROFILE, G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, PROP_LEVEL, + g_param_spec_enum ("level", "H.264 Level", "H.264 Level", + GST_TYPE_DUCATI_H264ENC_LEVEL, DEFAULT_LEVEL, G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, PROP_BITRATE, + g_param_spec_int ("bitrate", "Bitrate", "Bitrate in kbit/sec", -1, + 100 * 1024, DEFAULT_BITRATE, G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, PROP_RATE_PRESET, + g_param_spec_enum ("rate-preset", "H.264 Rate Control", + "H.264 Rate Control", + GST_TYPE_DUCATI_H264ENC_RATE_PRESET, DEFAULT_RATE_PRESET, + G_PARAM_READWRITE)); +} + +static void +gst_ducati_h264enc_init (GstDucatiH264Enc * self, GstDucatiH264EncClass * klass) +{ + GST_DEBUG ("gst_ducati_h264enc_init"); + + self->engine = NULL; + self->codec = NULL; + self->params = NULL; + self->status = NULL; + self->inBufs = NULL; + self->outBufs = NULL; + self->inArgs = NULL; + self->outArgs = NULL; + self->configure = FALSE; + self->input_pool = NULL; + self->output_pool = NULL; + + self->profile = DEFAULT_PROFILE; + self->level = DEFAULT_LEVEL; + self->bitrate = DEFAULT_BITRATE * 1000; + self->rate_preset = DEFAULT_RATE_PRESET; +} + +static gboolean +gst_ducati_h264enc_set_format (GstBaseVideoEncoder * base_video_encoder, + GstVideoState * state) +{ + GstDucatiH264Enc *self = GST_DUCATIH264ENC (base_video_encoder); + + self->configure = TRUE; + + return TRUE; +} + +static void +gst_ducati_h264enc_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstDucatiH264Enc *self = GST_DUCATIH264ENC (object); + + g_return_if_fail (GST_IS_DUCATIH264ENC (object)); + self = GST_DUCATIH264ENC (object); + + switch (prop_id) { + case PROP_PROFILE: + self->profile = g_value_get_enum (value); + break; + case PROP_LEVEL: + self->level = g_value_get_enum (value); + break; + case PROP_BITRATE: + self->bitrate = g_value_get_int (value) * 1000; + break; + case PROP_RATE_PRESET: + self->rate_preset = g_value_get_enum (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +gst_ducati_h264enc_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstDucatiH264Enc *self = GST_DUCATIH264ENC (object); + + g_return_if_fail (GST_IS_DUCATIH264ENC (object)); + self = GST_DUCATIH264ENC (object); + + switch (prop_id) { + case PROP_PROFILE: + g_value_set_enum (value, self->profile); + break; + case PROP_LEVEL: + g_value_set_enum (value, self->level); + break; + case PROP_BITRATE: + g_value_set_int (value, self->bitrate / 1000); + break; + case PROP_RATE_PRESET: + g_value_set_enum (value, self->rate_preset); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static gboolean +gst_ducati_h264enc_configure (GstDucatiH264Enc * self) +{ + int err, i, max_out_size = 0; + VIDENC2_DynamicParams *baseDynParams; + VIDENC2_Params *baseParams; + IH264ENC_Params *params; + IH264ENC_DynamicParams *dynParams; + const GstVideoState *state; + + state = gst_base_video_encoder_get_state (GST_BASE_VIDEO_ENCODER (self)); + + params = self->params; + baseParams = (VIDENC2_Params *) self->params; + baseParams->encodingPreset = 0x03; /* ??? */ + baseParams->rateControlPreset = self->rate_preset; + baseParams->maxHeight = state->height; + baseParams->maxWidth = state->width; + baseParams->dataEndianness = XDM_BYTE; + baseParams->maxInterFrameInterval = 1; + baseParams->maxBitRate = self->bitrate; + baseParams->minBitRate = 0; + baseParams->inputChromaFormat = XDM_YUV_420SP; + baseParams->inputContentType = IVIDEO_PROGRESSIVE; + baseParams->operatingMode = IVIDEO_ENCODE_ONLY; + baseParams->profile = self->profile; + baseParams->level = self->level; + baseParams->inputDataMode = IVIDEO_ENTIREFRAME; + baseParams->outputDataMode = IVIDEO_ENTIREFRAME; + baseParams->numInputDataUnits = 1; + baseParams->numOutputDataUnits = 1; + for (i = 0; i < IVIDEO_MAX_NUM_METADATA_PLANES; i++) { + baseParams->metadataType[i] = IVIDEO_METADATAPLANE_NONE; + } + + params->rateControlParams.rateControlParamsPreset = + IH264_RATECONTROLPARAMS_DEFAULT; + params->interCodingParams.interCodingPreset = IH264_INTERCODING_DEFAULT; + params->intraCodingParams.intraCodingPreset = IH264_INTRACODING_DEFAULT; + params->nalUnitControlParams.naluControlPreset = IH264_NALU_CONTROL_DEFAULT; + params->fmoCodingParams.fmoCodingPreset = IH264_FMOCODING_DEFAULT; + params->maxIntraFrameInterval = 0x7fffffff; + + if (self->codec == NULL) { + self->codec = VIDENC2_create (self->engine, + (String) "ivahd_h264enc", baseParams); + if (self->codec == NULL) { + GST_ERROR_OBJECT (self, "couldn't create codec"); + return FALSE; + } + } + + dynParams = self->dynParams; + baseDynParams = (VIDENC2_DynamicParams *) self->dynParams; + baseDynParams->size = sizeof (IH264ENC_DynamicParams); + baseDynParams = &dynParams->videnc2DynamicParams; + + baseDynParams->refFrameRate = + gst_util_uint64_scale (1000, state->fps_n, state->fps_d); + baseDynParams->targetFrameRate = baseDynParams->refFrameRate; + baseDynParams->inputWidth = state->width; + baseDynParams->inputHeight = state->height; + baseDynParams->targetBitRate = self->bitrate; + baseDynParams->intraFrameInterval = 15; + baseDynParams->captureWidth = baseDynParams->inputWidth; + baseDynParams->forceFrame = IVIDEO_NA_FRAME; + baseDynParams->interFrameInterval = 1; + baseDynParams->mvAccuracy = IVIDENC2_MOTIONVECTOR_QUARTERPEL; + baseDynParams->sampleAspectRatioHeight = 1; + baseDynParams->sampleAspectRatioWidth = 1; + baseDynParams->generateHeader = XDM_ENCODE_AU; + baseDynParams->ignoreOutbufSizeFlag = 1; + baseDynParams->lateAcquireArg = -1; + + dynParams->rateControlParams.rateControlParamsPreset = 2; + dynParams->interCodingParams.interCodingPreset = 2; + + err = VIDENC2_control (self->codec, + XDM_SETPARAMS, baseDynParams, (IVIDENC2_Status *) self->status); + if (err) { + GST_ERROR_OBJECT (self, "XDM_SETPARAMS err=%d, extendedError=%08x", + err, self->status->videnc2Status.extendedError); + + return FALSE; + } + + err = VIDENC2_control (self->codec, + XDM_GETBUFINFO, baseDynParams, (IVIDENC2_Status *) self->status); + if (err) { + GST_ERROR_OBJECT (self, "XDM_GETBUFINFO err=%d, extendedError=%08x", + err, self->status->videnc2Status.extendedError); + + return FALSE; + } + + self->inBufs->chromaFormat = XDM_YUV_420SP; + self->inBufs->numPlanes = 2; + + self->outBufs->numBufs = self->status->videnc2Status.bufInfo.minNumOutBufs; + for (i = 0; i < self->outBufs->numBufs; i++) { + int size = self->status->videnc2Status.bufInfo.minOutBufSize[i].bytes; + if (size > max_out_size) + max_out_size = size; + } + + g_assert (self->input_pool == NULL); + self->input_pool = + gst_ducati_bufferpool_new (GST_ELEMENT (self), NULL, + state->bytes_per_picture); + + g_assert (self->output_pool == NULL); + self->output_pool = + gst_ducati_bufferpool_new (GST_ELEMENT (self), NULL, max_out_size); + + GST_INFO_OBJECT (self, "configured"); + + self->configure = FALSE; + + return TRUE; +} + +static gboolean +gst_ducati_h264enc_alloc_dce (GstDucatiH264Enc * self) +{ + self->engine = Engine_open ((String) "ivahd_vidsvr", NULL, NULL); + if (self->engine == NULL) { + GST_ERROR_OBJECT (self, "couldn't open engine"); + return FALSE; + } + + self->params = dce_alloc (sizeof (IH264ENC_Params)); + memset (self->params, 0, sizeof (IH264ENC_Params)); + self->params->videnc2Params.size = sizeof (IH264ENC_Params); + + self->codec = NULL; + + self->dynParams = dce_alloc (sizeof (IH264ENC_DynamicParams)); + memset (self->dynParams, 0, sizeof (IH264ENC_DynamicParams)); + self->dynParams->videnc2DynamicParams.size = sizeof (IH264ENC_DynamicParams); + + self->status = dce_alloc (sizeof (IH264ENC_Status)); + memset (self->status, 0, sizeof (IH264ENC_Status)); + self->status->videnc2Status.size = sizeof (IH264ENC_Status); + + self->inBufs = dce_alloc (sizeof (IVIDEO2_BufDesc)); + memset (self->inBufs, 0, sizeof (IVIDEO2_BufDesc)); + + self->outBufs = dce_alloc (sizeof (XDM2_BufDesc)); + memset (self->outBufs, 0, sizeof (XDM2_BufDesc)); + + self->inArgs = dce_alloc (sizeof (IVIDENC2_InArgs)); + memset (self->inArgs, 0, sizeof (IVIDENC2_InArgs)); + self->inArgs->size = sizeof (IVIDENC2_InArgs); + + self->outArgs = dce_alloc (sizeof (IVIDENC2_OutArgs)); + memset (self->outArgs, 0, sizeof (IVIDENC2_OutArgs)); + self->outArgs->size = sizeof (IVIDENC2_OutArgs); + + GST_INFO_OBJECT (self, "started"); + + return TRUE; +} + +static gboolean +gst_ducati_h264enc_free_dce (GstDucatiH264Enc * self) +{ + if (self->params) { + dce_free (self->params); + self->params = NULL; + } + + if (self->dynParams) { + dce_free (self->dynParams); + self->dynParams = NULL; + } + + if (self->inArgs) { + dce_free (self->inArgs); + self->inArgs = NULL; + } + + if (self->outArgs) { + dce_free (self->outArgs); + self->outArgs = NULL; + } + + if (self->status) { + dce_free (self->status); + self->status = NULL; + } + + if (self->inBufs) { + dce_free (self->inBufs); + self->inBufs = NULL; + } + + if (self->outBufs) { + dce_free (self->outBufs); + self->inBufs = NULL; + } + + if (self->codec) { + VIDENC2_delete (self->codec); + self->codec = NULL; + } + + if (self->engine) { + Engine_close (self->engine); + self->engine = NULL; + } + + return TRUE; +} + +static gboolean +gst_ducati_h264enc_start (GstBaseVideoEncoder * base_video_encoder) +{ + GstDucatiH264Enc *self = GST_DUCATIH264ENC (base_video_encoder); + + if (!gst_ducati_h264enc_alloc_dce (self)) + goto fail; + + return TRUE; + +fail: + gst_ducati_h264enc_free_dce (self); + return FALSE; +} + +static gboolean +gst_ducati_h264enc_stop (GstBaseVideoEncoder * base_video_encoder) +{ + GstDucatiH264Enc *self = GST_DUCATIH264ENC (base_video_encoder); + + gst_ducati_h264enc_free_dce (self); + + if (self->input_pool) { + gst_ducati_bufferpool_destroy (self->input_pool); + self->input_pool = NULL; + } + + if (self->output_pool) { + gst_ducati_bufferpool_destroy (self->output_pool); + self->output_pool = NULL; + } + + return TRUE; +} + +static GstFlowReturn +gst_ducati_h264enc_finish (GstBaseVideoEncoder * base_video_encoder) +{ + GstDucatiH264Enc *self = GST_DUCATIH264ENC (base_video_encoder); + + GST_DEBUG_OBJECT (self, "finish"); + + return GST_FLOW_OK; +} + +static GstFlowReturn +gst_ducati_h264enc_handle_frame (GstBaseVideoEncoder * base_video_encoder, + GstVideoFrame * frame) +{ + GstDucatiH264Enc *self = GST_DUCATIH264ENC (base_video_encoder); + GstBuffer *inbuf, *outbuf; + guint8 *y_vaddr, *uv_vaddr; + SSPtr y_paddr, uv_paddr, outbuf_paddr; + XDAS_Int32 err; + const GstVideoState *state; + int i; + + state = gst_base_video_encoder_get_state (base_video_encoder); + + if (G_UNLIKELY (self->configure)) { + if (!gst_ducati_h264enc_configure (self)) { + GST_DEBUG_OBJECT (self, "configure failed"); + GST_ELEMENT_ERROR (self, STREAM, ENCODE, (NULL), (NULL)); + + return GST_FLOW_ERROR; + } + } + + inbuf = GST_BUFFER (gst_ducati_bufferpool_get (self->input_pool, NULL)); + memcpy (GST_BUFFER_DATA (inbuf), GST_BUFFER_DATA (frame->sink_buffer), + GST_BUFFER_SIZE (frame->sink_buffer)); + outbuf = GST_BUFFER (gst_ducati_bufferpool_get (self->output_pool, NULL)); + + y_vaddr = GST_BUFFER_DATA (inbuf); + uv_vaddr = y_vaddr + gst_video_format_get_component_offset (state->format, + 1, state->width, state->height); + + y_paddr = TilerMem_VirtToPhys (y_vaddr); + uv_paddr = TilerMem_VirtToPhys (uv_vaddr); + + outbuf_paddr = TilerMem_VirtToPhys (GST_BUFFER_DATA (outbuf)); + + self->inBufs->planeDesc[0].buf = (XDAS_Int8 *) y_paddr; + self->inBufs->planeDesc[0].memType = XDM_MEMTYPE_TILEDPAGE; + self->inBufs->planeDesc[0].bufSize.tileMem.width = state->width; + self->inBufs->planeDesc[0].bufSize.tileMem.height = state->height; + self->inBufs->planeDesc[1].buf = (XDAS_Int8 *) uv_paddr; + self->inBufs->planeDesc[1].memType = XDM_MEMTYPE_TILEDPAGE; + self->inBufs->planeDesc[1].bufSize.tileMem.width = state->width; + self->inBufs->planeDesc[1].bufSize.tileMem.height = state->height / 2; + self->inBufs->imagePitch[0] = state->width; + self->inBufs->imagePitch[1] = state->width; + self->inBufs->imageRegion.bottomRight.x = state->width; + self->inBufs->activeFrameRegion.bottomRight.x = state->width; + self->inBufs->imageRegion.bottomRight.y = state->height; + self->inBufs->activeFrameRegion.bottomRight.y = state->height; + self->inBufs->topFieldFirstFlag = TRUE; + + self->outBufs->numBufs = 1; + self->outBufs->descs[0].buf = (XDAS_Int8 *) outbuf_paddr; + self->outBufs->descs[0].bufSize.bytes = GST_BUFFER_SIZE (outbuf); + + self->inArgs->inputID = GPOINTER_TO_INT (inbuf); + + err = VIDENC2_process (self->codec, self->inBufs, self->outBufs, + self->inArgs, self->outArgs); + if (err) { + GST_WARNING_OBJECT (self, "process failed: err=%d, extendedError=%08x", + err, self->status->videnc2Status.extendedError); + + err = VIDENC2_control (self->codec, + XDM_GETSTATUS, (IVIDENC2_DynamicParams *) self->dynParams, + (IVIDENC2_Status *) self->status); + + GST_WARNING_OBJECT (self, "XDM_GETSTATUS: err=%d, extendedError=%08x", + err, self->status->videnc2Status.extendedError); + + return GST_FLOW_ERROR; + } + + frame->src_buffer = gst_buffer_new_and_alloc (self->outArgs->bytesGenerated); + memcpy (GST_BUFFER_DATA (frame->src_buffer), + GST_BUFFER_DATA (outbuf), self->outArgs->bytesGenerated); + + gst_buffer_unref (outbuf); + + for (i = 0; self->outArgs->freeBufID[i]; i++) { + GstBuffer *buf = (GstBuffer *) self->outArgs->freeBufID[i]; + + GST_LOG_OBJECT (self, "free buffer: %p", buf); + gst_buffer_unref (buf); + } + + return gst_base_video_encoder_finish_frame (base_video_encoder, frame); +} diff --git a/src/gstducatih264enc.h b/src/gstducatih264enc.h new file mode 100644 index 0000000..0e03f71 --- /dev/null +++ b/src/gstducatih264enc.h @@ -0,0 +1,81 @@ +/* + * GStreamer + * Copyright (c) 2010, Texas Instruments Incorporated + * + * 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 + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __GST_DUCATIH264ENC_H__ +#define __GST_DUCATIH264ENC_H__ + +#include <gst/gst.h> +#include <gst/video/video.h> +#include <gst/video/gstbasevideoencoder.h> +#include <gst/video/gstbasevideoutils.h> + +#include <ti/sdo/ce/video2/videnc2.h> +#include <ti/sdo/codecs/h264enc/ih264enc.h> + +#include "gstducatibufferpool.h" + +#define GST_TYPE_DUCATIH264ENC \ + (gst_ducati_h264enc_get_type()) +#define GST_DUCATIH264ENC(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_DUCATIH264ENC,GstDucatiH264Enc)) +#define GST_DUCATIH264ENC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_DUCATIH264ENC,GstDucatiH264EncClass)) +#define GST_IS_DUCATIH264ENC(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_DUCATIH264ENC)) +#define GST_IS_DUCATIH264ENC_CLASS(obj) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_DUCATIH264ENC)) + +typedef struct _GstDucatiH264Enc GstDucatiH264Enc; +typedef struct _GstDucatiH264EncClass GstDucatiH264EncClass; + +struct _GstDucatiH264Enc +{ + GstBaseVideoEncoder base_encoder; + + GstPad *sinkpad; + GstPad *srcpad; + + Engine_Handle engine; + VIDENC2_Handle codec; + IH264ENC_Params *params; + IH264ENC_DynamicParams *dynParams; + IH264ENC_Status *status; + IVIDEO2_BufDesc *inBufs; + XDM2_BufDesc *outBufs; + IVIDENC2_InArgs *inArgs; + IVIDENC2_OutArgs *outArgs; + + GstDucatiBufferPool *input_pool; + GstDucatiBufferPool *output_pool; + gboolean configure; + + guint profile; + guint level; + gint bitrate; + guint rate_preset; +}; + +struct _GstDucatiH264EncClass +{ + GstBaseVideoEncoderClass parent_class; +}; + +GType gst_ducati_h264enc_get_type (void); + +#endif |