summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlessandro Decina <alessandro.decina@collabora.co.uk>2011-10-14 18:14:00 +0200
committerAlessandro Decina <alessandro.decina@collabora.co.uk>2011-10-16 23:53:40 +0200
commitdfef372881283ab0106668e7a912100b975bbbe2 (patch)
tree91ae9aa55a380ccc575114435e10216c11e91480
parent85e8a453644b1e46edf8e52ff8722af9de13760f (diff)
ducatih264enc: add h264 encoder
-rw-r--r--configure.ac1
-rw-r--r--src/Makefile.am5
-rw-r--r--src/gstducati.c4
-rw-r--r--src/gstducatibufferpool.c18
-rw-r--r--src/gstducatih264enc.c708
-rw-r--r--src/gstducatih264enc.h81
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