diff --git a/src/gstducatividenc.c b/src/gstducatividenc.c
index a4abe4d1ba090b9fd28d89147bd138c808bbc77e..52a1b098da3c8f61e94fa1b02d708555791cdb87 100644 (file)
--- a/src/gstducatividenc.c
+++ b/src/gstducatividenc.c
#include "gstducati.h"
#include "gstducatividenc.h"
-#include <ti/sdo/codecs/mpeg4enc/impeg4enc.h>
+#include "gstducatibufferpriv.h"
#include <string.h>
#define DEFAULT_BITRATE 2048
#define DEFAULT_RATE_PRESET GST_DUCATI_VIDENC_RATE_PRESET_STORAGE
+#define DEFAULT_INTRA_INTERVAL 16
#define GST_TYPE_DUCATI_VIDENC_RATE_PRESET (gst_ducati_videnc_rate_preset_get_type ())
{
PROP_0,
PROP_BITRATE,
- PROP_RATE_PRESET
+ PROP_RATE_PRESET,
+ PROP_INTRA_INTERVAL
};
static void gst_ducati_videnc_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec);
static void gst_ducati_videnc_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec);
+static GstDucatiBufferPriv *get_buffer_priv (GstDucatiVidEnc * self,
+ GstBuffer * buf, gint stride, gint height);
static gboolean gst_ducati_videnc_set_format (GstBaseVideoEncoder *
base_video_encoder, GstVideoState * state);
static gboolean gst_ducati_videnc_allocate_params_default (GstDucatiVidEnc *
self, gint params_sz, gint dynparams_sz, gint status_sz, gint inargs_sz,
gint outargs_sz);
+static gboolean gst_ducati_videnc_is_sync_point_default (GstDucatiVidEnc * enc,
+ int type);
static gboolean gst_ducati_videnc_configure_default (GstDucatiVidEnc * self);
static gboolean gst_ducati_videnc_event (GstBaseVideoEncoder * enc,
GstEvent * event);
enum
{
- GST_DUCATI_VIDENC_RATE_PRESET_LOW_DELAY = 1, /**< CBR rate control for video conferencing. */
- GST_DUCATI_VIDENC_RATE_PRESET_STORAGE = 2, /**< VBR rate control for local storage (DVD)
+ GST_DUCATI_VIDENC_RATE_PRESET_LOW_DELAY = IVIDEO_LOW_DELAY, /**< CBR rate control for video conferencing. */
+ GST_DUCATI_VIDENC_RATE_PRESET_STORAGE = IVIDEO_STORAGE, /**< VBR rate control for local storage (DVD)
* recording.
*/
- GST_DUCATI_VIDENC_RATE_PRESET_TWOPASS = 3, /**< Two pass rate control for non real time
+ GST_DUCATI_VIDENC_RATE_PRESET_TWOPASS = IVIDEO_TWOPASS, /**< Two pass rate control for non real time
* applications.
*/
- GST_DUCATI_VIDENC_RATE_PRESET_NONE = 4, /**< No configurable video rate control
+ GST_DUCATI_VIDENC_RATE_PRESET_NONE = IVIDEO_NONE, /**< No configurable video rate control
* mechanism.
*/
- GST_DUCATI_VIDENC_RATE_PRESET_USER_DEFINED = 5,/**< User defined configuration using extended
+ GST_DUCATI_VIDENC_RATE_PRESET_USER_DEFINED = IVIDEO_USER_DEFINED,/**< User defined configuration using extended
* parameters.
*/
};
{GST_DUCATI_VIDENC_RATE_PRESET_LOW_DELAY, "Low Delay", "low-delay"},
{GST_DUCATI_VIDENC_RATE_PRESET_STORAGE, "Storage", "storage"},
{GST_DUCATI_VIDENC_RATE_PRESET_TWOPASS, "Two-Pass", "two-pass"},
+ {GST_DUCATI_VIDENC_RATE_PRESET_NONE, "None", "none"},
+ {GST_DUCATI_VIDENC_RATE_PRESET_USER_DEFINED, "User defined",
+ "user-defined"},
{0, NULL, NULL},
};
klass->allocate_params = gst_ducati_videnc_allocate_params_default;
klass->configure = gst_ducati_videnc_configure_default;
+ klass->is_sync_point = gst_ducati_videnc_is_sync_point_default;
g_object_class_install_property (gobject_class, PROP_BITRATE,
g_param_spec_int ("bitrate", "Bitrate", "Bitrate in kbit/sec", -1,
"H.264 Rate Control",
GST_TYPE_DUCATI_VIDENC_RATE_PRESET, DEFAULT_RATE_PRESET,
G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class, PROP_INTRA_INTERVAL,
+ g_param_spec_int ("intra-interval", "Intra-frame interval",
+ "Interval between intra frames (keyframes)", 0, INT_MAX,
+ DEFAULT_INTRA_INTERVAL, G_PARAM_READWRITE));
}
static void
{
GST_DEBUG ("gst_ducati_videnc_init");
+ self->device = NULL;
self->engine = NULL;
self->codec = NULL;
self->params = NULL;
self->bitrate = DEFAULT_BITRATE * 1000;
self->rate_preset = DEFAULT_RATE_PRESET;
+ self->intra_interval = DEFAULT_INTRA_INTERVAL;
}
static gboolean
gst_ducati_videnc_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec)
{
- GstDucatiVidEnc *self = GST_DUCATIVIDENC (object);
+ GstDucatiVidEnc *self;
g_return_if_fail (GST_IS_DUCATIVIDENC (object));
self = GST_DUCATIVIDENC (object);
case PROP_RATE_PRESET:
self->rate_preset = g_value_get_enum (value);
break;
+ case PROP_INTRA_INTERVAL:
+ self->intra_interval = g_value_get_int (value);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
gst_ducati_videnc_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec)
{
- GstDucatiVidEnc *self = GST_DUCATIVIDENC (object);
+ GstDucatiVidEnc *self;
g_return_if_fail (GST_IS_DUCATIVIDENC (object));
self = GST_DUCATIVIDENC (object);
case PROP_RATE_PRESET:
g_value_set_enum (value, self->rate_preset);
break;
+ case PROP_INTRA_INTERVAL:
+ g_value_set_int (value, self->intra_interval);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
if (err) {
GST_ERROR_OBJECT (self, "XDM_SETPARAMS err=%d, extendedError=%08x",
err, self->status->extendedError);
+ gst_ducati_log_extended_error_info (self->status->extendedError);
return FALSE;
}
}
g_assert (self->input_pool == NULL);
- self->input_pool =
- gst_ducati_bufferpool_new (GST_ELEMENT (self), NULL,
- state->bytes_per_picture);
+ self->input_pool = gst_drm_buffer_pool_new (GST_ELEMENT (self),
+ dce_get_fd (), 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);
+ self->output_pool = gst_drm_buffer_pool_new (GST_ELEMENT (self),
+ dce_get_fd (), NULL, max_out_size);
GST_INFO_OBJECT (self, "configured");
gst_ducati_videnc_configure_default (GstDucatiVidEnc * self)
{
VIDENC2_DynamicParams *dynParams;
+ VIDENC2_Params *params;
const GstVideoState *state;
int i;
if (self->rect.h == 0)
self->rect.h = state->height;
- self->params = (VIDENC2_Params *) self->params;
- self->params->encodingPreset = 0x03;
- self->params->rateControlPreset = self->rate_preset;
- self->params->maxHeight = self->rect.h;
- self->params->maxWidth = self->rect.w;
- self->params->dataEndianness = XDM_BYTE;
- self->params->maxInterFrameInterval = 1;
- self->params->maxBitRate = -1;
- self->params->minBitRate = 0;
- self->params->inputChromaFormat = XDM_YUV_420SP;
- self->params->inputContentType = IVIDEO_PROGRESSIVE;
- self->params->operatingMode = IVIDEO_ENCODE_ONLY;
- self->params->inputDataMode = IVIDEO_ENTIREFRAME;
- self->params->outputDataMode = IVIDEO_ENTIREFRAME;
- self->params->numInputDataUnits = 1;
- self->params->numOutputDataUnits = 1;
+ params = (VIDENC2_Params *) self->params;
+ params->encodingPreset = 0x03;
+ params->rateControlPreset = self->rate_preset;
+ params->maxHeight = self->rect.h;
+ params->maxWidth = self->rect.w;
+ params->dataEndianness = XDM_BYTE;
+ params->maxInterFrameInterval = 1;
+ params->maxBitRate = -1;
+ params->minBitRate = 0;
+ params->inputChromaFormat = XDM_YUV_420SP;
+ params->inputContentType = IVIDEO_PROGRESSIVE;
+ params->operatingMode = IVIDEO_ENCODE_ONLY;
+ params->inputDataMode = IVIDEO_ENTIREFRAME;
+ params->outputDataMode = IVIDEO_ENTIREFRAME;
+ params->numInputDataUnits = 1;
+ params->numOutputDataUnits = 1;
for (i = 0; i < IVIDEO_MAX_NUM_METADATA_PLANES; i++) {
- self->params->metadataType[i] = IVIDEO_METADATAPLANE_NONE;
+ params->metadataType[i] = IVIDEO_METADATAPLANE_NONE;
}
- dynParams = self->dynParams;
dynParams = (VIDENC2_DynamicParams *) self->dynParams;
dynParams->refFrameRate =
dynParams->inputWidth = self->rect.w;
dynParams->inputHeight = self->rect.h;
dynParams->targetBitRate = self->bitrate;
- dynParams->intraFrameInterval = 15;
+ dynParams->intraFrameInterval = self->intra_interval;
dynParams->captureWidth = dynParams->inputWidth;
- dynParams->captureWidth = dynParams->inputWidth = self->rect.w;
dynParams->forceFrame = IVIDEO_NA_FRAME;
dynParams->interFrameInterval = 1;
static gboolean
gst_ducati_videnc_open_engine (GstDucatiVidEnc * self)
{
- self->engine = Engine_open ((String) "ivahd_vidsvr", NULL, NULL);
+ int error_code;
+
+ if (self->device == NULL) {
+ self->device = dce_init ();
+ if (self->device == NULL)
+ return FALSE;
+ }
+
+ self->engine = Engine_open ((String) "ivahd_vidsvr", NULL, &error_code);
if (self->engine == NULL) {
GST_ERROR_OBJECT (self, "couldn't open engine");
return FALSE;
if (self->outBufs) {
dce_free (self->outBufs);
- self->inBufs = NULL;
+ self->outBufs = NULL;
}
if (self->codec) {
Engine_close (self->engine);
self->engine = NULL;
}
+
+ if (self->device) {
+ dce_deinit (self->device);
+ self->device = NULL;
+ }
}
gst_ducati_videnc_close_engine (self);
if (self->input_pool) {
- gst_ducati_bufferpool_destroy (self->input_pool);
+ gst_drm_buffer_pool_destroy (self->input_pool);
self->input_pool = NULL;
}
if (self->output_pool) {
- gst_ducati_bufferpool_destroy (self->output_pool);
+ gst_drm_buffer_pool_destroy (self->output_pool);
self->output_pool = NULL;
}
{
GstDucatiVidEnc *self = GST_DUCATIVIDENC (base_video_encoder);
GstBuffer *inbuf, *outbuf;
- guint8 *y_vaddr, *uv_vaddr;
- SSPtr y_paddr, uv_paddr, outbuf_paddr;
+ GstDucatiBufferPriv *priv_in, *priv_out;
XDAS_Int32 err;
- XDAS_Int16 y_type, uv_type;
const GstVideoState *state;
int i;
+ GstClockTime ts;
+ GstClockTime t;
state = gst_base_video_encoder_get_state (base_video_encoder);
}
inbuf = gst_buffer_ref (frame->sink_buffer);
+ ts = GST_BUFFER_TIMESTAMP (inbuf);
have_inbuf:
- 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);
- y_type = gst_ducati_get_mem_type (y_paddr);
- uv_type = gst_ducati_get_mem_type (uv_paddr);
- if (y_type < 0 || uv_type < 0) {
- GST_DEBUG_OBJECT (self, "memcpying input %d %d", y_type, uv_type);
+ priv_in = get_buffer_priv (self, inbuf, state->width, state->height);
+ if (priv_in == NULL) {
+ GST_DEBUG_OBJECT (self, "memcpying input");
gst_buffer_unref (inbuf);
- inbuf = GST_BUFFER (gst_ducati_bufferpool_get (self->input_pool, NULL));
+ inbuf = GST_BUFFER (gst_drm_buffer_pool_get (self->input_pool, FALSE));
memcpy (GST_BUFFER_DATA (inbuf), GST_BUFFER_DATA (frame->sink_buffer),
GST_BUFFER_SIZE (frame->sink_buffer));
+ GST_BUFFER_TIMESTAMP (inbuf) = ts;
goto have_inbuf;
}
- 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);
+ outbuf = GST_BUFFER (gst_drm_buffer_pool_get (self->output_pool, FALSE));
+ priv_out = get_buffer_priv (self, outbuf, 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].buf = (XDAS_Int8 *) omap_bo_handle (priv_in->bo);
+ self->inBufs->planeDesc[0].memType = XDM_MEMTYPE_BO;
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].buf = (XDAS_Int8 *) priv_in->uv_offset;
+ self->inBufs->planeDesc[1].memType = XDM_MEMTYPE_BO_OFFSET;
self->inBufs->planeDesc[1].bufSize.tileMem.width = state->width;
self->inBufs->planeDesc[1].bufSize.tileMem.height = state->height / 2;
/* setting imageRegion doesn't seem to be strictly needed if activeFrameRegion
self->inBufs->topFieldFirstFlag = TRUE;
self->outBufs->numBufs = 1;
- self->outBufs->descs[0].buf = (XDAS_Int8 *) outbuf_paddr;
+ self->outBufs->descs[0].buf = (XDAS_Int8 *) omap_bo_handle (priv_out->bo);
self->outBufs->descs[0].bufSize.bytes = GST_BUFFER_SIZE (outbuf);
+ self->outBufs->descs[0].memType = XDM_MEMTYPE_BO;
self->inArgs->inputID = GPOINTER_TO_INT (inbuf);
+ GST_DEBUG ("Calling VIDENC2_process");
+ t = gst_util_get_timestamp ();
err = VIDENC2_process (self->codec, self->inBufs, self->outBufs,
self->inArgs, self->outArgs);
+ t = gst_util_get_timestamp () - t;
+ GST_DEBUG_OBJECT (self, "VIDENC2_process took %10dns (%d ms)", (gint) t,
+ (gint) (t / 1000000));
if (err) {
GST_WARNING_OBJECT (self, "process failed: err=%d, extendedError=%08x",
- err, self->status->extendedError);
+ err, self->outArgs->extendedError);
+ gst_ducati_log_extended_error_info (self->outArgs->extendedError);
err = VIDENC2_control (self->codec,
XDM_GETSTATUS, (IVIDENC2_DynamicParams *) self->dynParams,
return GST_FLOW_ERROR;
}
- if (self->outArgs->encodedFrameType == IVIDEO_IDR_FRAME)
- frame->is_sync_point = TRUE;
- 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);
+ if (self->outArgs->bytesGenerated > 0) {
+ frame->is_sync_point =
+ GST_DUCATIVIDENC_GET_CLASS (self)->is_sync_point (self,
+ self->outArgs->encodedFrameType);
+ 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_DEBUG_OBJECT (self, "Encoded frame in %u bytes",
+ self->outArgs->bytesGenerated);
+
+ /* As we can get frames in a different order we sent them (if the codec
+ supports B frames and we set it up for generating those), we need to
+ work out what input frame corresponds to the frame we just got, to
+ keep presentation times correct.
+ It seems that the codec will free buffers in the right order for this,
+ but I can not find anything saying this in the docs, so:
+ - it might be subject to change
+ - it might not be true in all setups
+ - it might not be true for all codecs
+ However, that's the only way I can see to do it. So there's a nice
+ assert below that will blow up if the codec does not free exactly one
+ input frame when it outputs a frame. That doesn't catch all cases,
+ such as when it frees them in the wrong order, but that seems less
+ likely to happen.
+ The timestamp and duration are given to the base class, which will
+ in turn set them onto the encoded buffer. */
+ g_assert (self->outArgs->freeBufID[0] && !self->outArgs->freeBufID[1]);
+ inbuf = GST_BUFFER (self->outArgs->freeBufID[0]);
+ frame->presentation_timestamp = GST_BUFFER_TIMESTAMP (inbuf);
+ frame->presentation_duration = GST_BUFFER_DURATION (inbuf);
+ GST_BUFFER_OFFSET_END (frame->src_buffer) = GST_BUFFER_TIMESTAMP (inbuf);
+ }
gst_buffer_unref (outbuf);
return gst_base_video_encoder_finish_frame (base_video_encoder, frame);
}
+static gboolean
+gst_ducati_videnc_is_sync_point_default (GstDucatiVidEnc * enc, int type)
+{
+ return type == IVIDEO_I_FRAME;
+}
+
static gboolean
gst_ducati_videnc_event (GstBaseVideoEncoder * enc, GstEvent * event)
{
return handled;
}
+
+static GstDucatiBufferPriv *
+get_buffer_priv (GstDucatiVidEnc * self, GstBuffer * buf,
+ gint stride, gint height)
+{
+ GstDucatiBufferPriv *priv = gst_ducati_buffer_priv_get (buf);
+ if (!priv) {
+ GstVideoFormat format = GST_VIDEO_FORMAT_NV12;
+ GstDmaBuf *dmabuf = gst_buffer_get_dma_buf (buf);
+
+ /* if it isn't a dmabuf buffer that we can import, then there
+ * is nothing we can do with it:
+ */
+ if (!dmabuf) {
+ GST_DEBUG_OBJECT (self, "not importing non dmabuf buffer");
+ return NULL;
+ }
+
+ priv = gst_ducati_buffer_priv_new ();
+ priv->bo = omap_bo_from_dmabuf (self->device, gst_dma_buf_get_fd (dmabuf));
+
+ priv->uv_offset = gst_video_format_get_component_offset (format,
+ 1, stride, height);
+ priv->size = gst_video_format_get_size (format, stride, height);
+
+ gst_ducati_buffer_priv_set (buf, priv);
+ }
+ return priv;
+}