diff --git a/src/gstducatividenc.c b/src/gstducatividenc.c
index 745dc9d9128163d5946e3c2ee9883076354765bf..9e58cb343cce26a6f924f648bbb80b521980db96 100644 (file)
--- a/src/gstducatividenc.c
+++ b/src/gstducatividenc.c
#include <math.h>
#define GST_CAT_DEFAULT gst_ducati_debug
+GST_DEBUG_CATEGORY_STATIC (GST_CAT_PERFORMANCE);
#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_start (GstBaseVideoEncoder *
+static gboolean gst_ducati_videnc_set_format (GstVideoEncoder *
+ base_video_encoder, GstVideoCodecState * state);
+static gboolean gst_ducati_videnc_start (GstVideoEncoder * base_video_encoder);
+static gboolean gst_ducati_videnc_stop (GstVideoEncoder * base_video_encoder);
+static GstFlowReturn gst_ducati_videnc_finish (GstVideoEncoder *
base_video_encoder);
-static gboolean gst_ducati_videnc_stop (GstBaseVideoEncoder *
- base_video_encoder);
-static GstFlowReturn gst_ducati_videnc_finish (GstBaseVideoEncoder *
- base_video_encoder);
-static GstFlowReturn gst_ducati_videnc_handle_frame (GstBaseVideoEncoder *
- base_video_encoder, GstVideoFrame * frame);
+static GstFlowReturn gst_ducati_videnc_handle_frame (GstVideoEncoder *
+ base_video_encoder, GstVideoCodecFrame * frame);
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,
+static gboolean gst_ducati_videnc_event (GstVideoEncoder * enc,
GstEvent * event);
+static gboolean
+gst_ducati_videnc_propose_allocation (GstVideoEncoder * encoder,
+ GstQuery * query);
+static GstBufferPool *gst_drm_buffer_pool_new (GstCaps * caps, guint size);
-
-GST_BOILERPLATE (GstDucatiVidEnc, gst_ducati_videnc, GstBaseVideoEncoder,
- GST_TYPE_BASE_VIDEO_ENCODER);
-
+#define gst_ducati_videnc_parent_class parent_class
+G_DEFINE_TYPE (GstDucatiVidEnc, gst_ducati_videnc, GST_TYPE_VIDEO_ENCODER);
/* the values for the following enums are taken from the codec */
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},
};
return type;
}
-static void
-gst_ducati_videnc_base_init (gpointer g_class)
+static GstBufferPool *
+gst_drm_buffer_pool_new (GstCaps * caps, guint size)
+{
+ GstAllocator *allocator;
+ GstStructure *conf;
+ GstBufferPool *ret_pool;
+
+ allocator = gst_drm_allocator_get ();
+ if (!allocator) {
+ GST_DEBUG
+ ("Failed to get a DRM bufferpool. Proceeding with default allocator");
+ }
+ ret_pool = gst_buffer_pool_new ();
+ conf = gst_buffer_pool_get_config (GST_BUFFER_POOL (ret_pool));
+ if (conf) {
+ gst_buffer_pool_config_set_params (conf, caps, size, 0, 0);
+ gst_buffer_pool_config_set_allocator (conf, allocator, NULL);
+ gst_buffer_pool_set_config (GST_BUFFER_POOL (ret_pool), conf);
+ }
+
+ if (allocator)
+ gst_object_unref (allocator);
+
+ return ret_pool;
+}
+
+static gboolean
+gst_ducati_videnc_propose_allocation (GstVideoEncoder * encoder,
+ GstQuery * query)
{
+ GstDucatiVidEnc *self = GST_DUCATIVIDENC (encoder);
+ GstStructure *config;
+ guint size, min_bufs, max_bufs;
+ GstCaps *allowed_sink_caps;
+ GstVideoInfo info;
+
+ if (!self->input_pool) {
+ allowed_sink_caps =
+ gst_pad_get_allowed_caps (GST_VIDEO_ENCODER_SINK_PAD (self));
+ if (!allowed_sink_caps) {
+ GST_DEBUG_OBJECT (self, "... but no peer, using template caps");
+ allowed_sink_caps =
+ gst_pad_get_pad_template_caps (GST_VIDEO_ENCODER_SINK_PAD (self));
+ }
+ GST_DEBUG_OBJECT (self, "chose caps %" GST_PTR_FORMAT, allowed_sink_caps);
+ allowed_sink_caps = gst_caps_truncate (allowed_sink_caps);
+ gst_video_info_from_caps (&info, gst_caps_fixate (allowed_sink_caps));
+ self->input_pool =
+ gst_drm_buffer_pool_new (gst_caps_fixate (allowed_sink_caps),
+ info.size);
+ }
+
+ config = gst_buffer_pool_get_config (self->input_pool);
+ gst_buffer_pool_config_get_params (config, NULL, &size, &min_bufs, &max_bufs);
+
+ gst_query_add_allocation_pool (query, self->input_pool, size, min_bufs,
+ max_bufs);
+ gst_query_add_allocation_param (query, gst_drm_allocator_get (), NULL);
+ gst_structure_free (config);
+
+ return TRUE;
}
+
static void
gst_ducati_videnc_class_init (GstDucatiVidEncClass * klass)
{
GObjectClass *gobject_class;
- GstBaseVideoEncoderClass *basevideoencoder_class;
+ GstVideoEncoderClass *basevideoencoder_class;
gobject_class = G_OBJECT_CLASS (klass);
- basevideoencoder_class = GST_BASE_VIDEO_ENCODER_CLASS (klass);
+ basevideoencoder_class = GST_VIDEO_ENCODER_CLASS (klass);
+ parent_class = g_type_class_peek_parent (klass);
gobject_class->set_property = gst_ducati_videnc_set_property;
gobject_class->get_property = gst_ducati_videnc_get_property;
basevideoencoder_class->finish = GST_DEBUG_FUNCPTR (gst_ducati_videnc_finish);
basevideoencoder_class->handle_frame =
GST_DEBUG_FUNCPTR (gst_ducati_videnc_handle_frame);
- basevideoencoder_class->event = GST_DEBUG_FUNCPTR (gst_ducati_videnc_event);
+
+ basevideoencoder_class->src_event =
+ GST_DEBUG_FUNCPTR (gst_ducati_videnc_event);
+
+ basevideoencoder_class->propose_allocation =
+ GST_DEBUG_FUNCPTR (gst_ducati_videnc_propose_allocation);
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));
+
+ GST_DEBUG_CATEGORY_GET (GST_CAT_PERFORMANCE, "GST_PERFORMANCE");
+
}
static void
-gst_ducati_videnc_init (GstDucatiVidEnc * self, GstDucatiVidEncClass * klass)
+gst_ducati_videnc_init (GstDucatiVidEnc * self)
{
GST_DEBUG ("gst_ducati_videnc_init");
+ gst_ducati_set_generic_error_strings (self->error_strings);
+
self->device = NULL;
self->engine = NULL;
self->codec = NULL;
self->bitrate = DEFAULT_BITRATE * 1000;
self->rate_preset = DEFAULT_RATE_PRESET;
+ self->intra_interval = DEFAULT_INTRA_INTERVAL;
}
static gboolean
-gst_ducati_videnc_set_format (GstBaseVideoEncoder * base_video_encoder,
- GstVideoState * state)
+gst_ducati_videnc_set_format (GstVideoEncoder * base_video_encoder,
+ GstVideoCodecState * state)
{
GstDucatiVidEnc *self = GST_DUCATIVIDENC (base_video_encoder);
+ GstVideoCodecState *output_state;
+ GstCaps *allowed_caps = NULL;
+
+ GST_DEBUG_OBJECT (self, "picking an output format ...");
+ allowed_caps =
+ gst_pad_get_allowed_caps (GST_VIDEO_ENCODER_SRC_PAD (base_video_encoder));
+ if (!allowed_caps) {
+ GST_DEBUG_OBJECT (self, "... but no peer, using template caps");
+ allowed_caps =
+ gst_pad_get_pad_template_caps (GST_VIDEO_ENCODER_SRC_PAD
+ (base_video_encoder));
+ }
+ GST_DEBUG_OBJECT (self, "chose caps %" GST_PTR_FORMAT, allowed_caps);
+ allowed_caps = gst_caps_truncate (allowed_caps);
+ GST_DEBUG_OBJECT (self, "allowed caps %" GST_PTR_FORMAT, allowed_caps);
+ output_state = gst_video_encoder_set_output_state (GST_VIDEO_ENCODER (self),
+ allowed_caps, state);
+ gst_video_codec_state_unref (output_state);
+
+
+ if (!gst_video_encoder_negotiate (GST_VIDEO_ENCODER (self))) {
+ GST_DEBUG_OBJECT (self, "negotiate failed");
+ return FALSE;
+ }
+
+ if (self->input_state)
+ gst_video_codec_state_unref (self->input_state);
+ self->input_state = gst_video_codec_state_ref (state);
self->configure = TRUE;
return TRUE;
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);
}
int err;
int i;
int max_out_size = 0;
- const GstVideoState *state;
-
- state = gst_base_video_encoder_get_state (GST_BASE_VIDEO_ENCODER (self));
+ const GstVideoCodecState *state;
+ GstCaps *allowed_sink_caps = NULL;
+ GstCaps *allowed_src_caps = NULL;
+ state = self->input_state;
if (!GST_DUCATIVIDENC_GET_CLASS (self)->configure (self))
return FALSE;
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,
+ self->error_strings);
return FALSE;
}
max_out_size = size;
}
- g_assert (self->input_pool == NULL);
- self->input_pool = gst_drm_buffer_pool_new (GST_ELEMENT (self),
- dce_get_fd (), NULL, state->bytes_per_picture);
+ if (!self->input_pool) {
+ GstVideoInfo info;
+ allowed_sink_caps =
+ gst_pad_get_allowed_caps (GST_VIDEO_ENCODER_SINK_PAD (self));
+ if (!allowed_sink_caps) {
+ GST_DEBUG_OBJECT (self, "... but no peer, using template caps");
+ allowed_sink_caps =
+ gst_pad_get_pad_template_caps (GST_VIDEO_ENCODER_SINK_PAD (self));
+ }
+ GST_DEBUG_OBJECT (self, "chose caps %" GST_PTR_FORMAT, allowed_sink_caps);
+ allowed_sink_caps = gst_caps_truncate (allowed_sink_caps);
+ gst_video_info_from_caps (&info, gst_caps_fixate (allowed_sink_caps));
+ self->input_pool =
+ gst_drm_buffer_pool_new (gst_caps_fixate (allowed_sink_caps),
+ info.size);
+ }
+
+
+ gst_buffer_pool_set_active (GST_BUFFER_POOL (self->input_pool), TRUE);
g_assert (self->output_pool == NULL);
- self->output_pool = gst_drm_buffer_pool_new (GST_ELEMENT (self),
- dce_get_fd (), NULL, max_out_size);
+ allowed_src_caps =
+ gst_pad_get_allowed_caps (GST_VIDEO_ENCODER_SRC_PAD (self));
+ if (!allowed_src_caps) {
+ GST_DEBUG_OBJECT (self, "... but no peer, using template caps");
+ allowed_src_caps =
+ gst_pad_get_pad_template_caps (GST_VIDEO_ENCODER_SRC_PAD (self));
+ }
+ GST_DEBUG_OBJECT (self, "chose caps %" GST_PTR_FORMAT, allowed_src_caps);
+ allowed_src_caps = gst_caps_truncate (allowed_src_caps);
+ self->output_pool =
+ gst_drm_buffer_pool_new (gst_caps_fixate (allowed_src_caps),
+ max_out_size);
+
+ gst_buffer_pool_set_active (GST_BUFFER_POOL (self->output_pool), TRUE);
GST_INFO_OBJECT (self, "configured");
gst_ducati_videnc_configure_default (GstDucatiVidEnc * self)
{
VIDENC2_DynamicParams *dynParams;
- const GstVideoState *state;
+ VIDENC2_Params *params;
+ const GstVideoCodecState *state;
int i;
- state = gst_base_video_encoder_get_state (GST_BASE_VIDEO_ENCODER (self));
+ state = self->input_state;
if (self->rect.w == 0)
- self->rect.w = state->width;
+ self->rect.w = GST_VIDEO_INFO_WIDTH (&state->info);
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;
+ self->rect.h = GST_VIDEO_INFO_HEIGHT (&state->info);
+
+ 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 =
- gst_util_uint64_scale (1000, state->fps_n, state->fps_d);
+ gst_util_uint64_scale (1000, GST_VIDEO_INFO_FPS_N (&state->info),
+ GST_VIDEO_INFO_FPS_D (&state->info));
dynParams->targetFrameRate = 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_start (GstBaseVideoEncoder * base_video_encoder)
+gst_ducati_videnc_start (GstVideoEncoder * base_video_encoder)
{
GstDucatiVidEnc *self = GST_DUCATIVIDENC (base_video_encoder);
}
static gboolean
-gst_ducati_videnc_stop (GstBaseVideoEncoder * base_video_encoder)
+gst_ducati_videnc_stop (GstVideoEncoder * base_video_encoder)
{
GstDucatiVidEnc *self = GST_DUCATIVIDENC (base_video_encoder);
gst_ducati_videnc_close_engine (self);
if (self->input_pool) {
- gst_drm_buffer_pool_destroy (self->input_pool);
+ gst_object_unref (self->input_pool);
self->input_pool = NULL;
}
if (self->output_pool) {
- gst_drm_buffer_pool_destroy (self->output_pool);
+ gst_object_unref (self->output_pool);
self->output_pool = NULL;
}
}
static GstFlowReturn
-gst_ducati_videnc_finish (GstBaseVideoEncoder * base_video_encoder)
+gst_ducati_videnc_finish (GstVideoEncoder * base_video_encoder)
{
GstDucatiVidEnc *self = GST_DUCATIVIDENC (base_video_encoder);
return GST_FLOW_OK;
}
+static int
+gst_ducati_videnc_buffer_lock (GstDucatiVidEnc * self, GstBuffer * buf)
+{
+ int fd;
+ GstMemory *mem;
+ mem = gst_buffer_peek_memory (buf, 0);
+ if (!gst_is_drm_memory (mem)) {
+ GST_LOG_OBJECT (self, "Not a dmabuf memory");
+ return -1;
+ }
+
+ fd = gst_fd_memory_get_fd (mem);
+ if (fd < 0) {
+ GST_ERROR_OBJECT (self, "Invalid dma buf fd %d", fd);
+ return -1;
+ }
+ dce_buf_lock (1, (size_t *) & fd);
+ return fd;
+}
+
+static void
+gst_ducati_videnc_buffer_unlock (GstDucatiVidEnc * self, GstBuffer * buf)
+{
+ int fd;
+ GstMemory *mem;
+ mem = gst_buffer_peek_memory (buf, 0);
+ if (!gst_is_drm_memory (mem)) {
+ GST_LOG_OBJECT (self, "Not a dmabuf memory");
+ return;
+ }
+ fd = gst_fd_memory_get_fd (mem);
+ if (fd < 0) {
+ GST_ERROR_OBJECT (self, "Invalid dma buf fd %d", fd);
+ return;
+ }
+ dce_buf_unlock (1, (size_t *) & fd);
+}
+
static GstFlowReturn
-gst_ducati_videnc_handle_frame (GstBaseVideoEncoder * base_video_encoder,
- GstVideoFrame * frame)
+gst_ducati_videnc_handle_frame (GstVideoEncoder * base_video_encoder,
+ GstVideoCodecFrame * frame)
{
GstDucatiVidEnc *self = GST_DUCATIVIDENC (base_video_encoder);
GstBuffer *inbuf, *outbuf;
- GstDucatiBufferPriv *priv_in, *priv_out;
+ GstBuffer *output_buffer;
+ int dmabuf_fd_in, dmabuf_fd_out;
XDAS_Int32 err;
- const GstVideoState *state;
+ const GstVideoCodecState *state;
int i;
+ GstClockTime ts;
+ GstClockTime t;
+ GstVideoCropMeta *crop;
- state = gst_base_video_encoder_get_state (base_video_encoder);
+ state = self->input_state;
if (G_UNLIKELY (self->configure)) {
if (!gst_ducati_videnc_configure (self)) {
}
}
- inbuf = gst_buffer_ref (frame->sink_buffer);
+ inbuf = gst_buffer_ref (frame->input_buffer);
+ ts = GST_BUFFER_PTS (inbuf);
have_inbuf:
- priv_in = get_buffer_priv (self, inbuf, state->width, state->height);
- if (priv_in == NULL) {
+ dmabuf_fd_in = gst_ducati_videnc_buffer_lock (self, inbuf);
+ if (dmabuf_fd_in < 0) {
+ GstMapInfo info;
+ gboolean mapped;
+
GST_DEBUG_OBJECT (self, "memcpying input");
gst_buffer_unref (inbuf);
- 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_pool_acquire_buffer (self->input_pool, &inbuf, NULL);
+ mapped = gst_buffer_map (frame->input_buffer, &info, GST_MAP_READ);
+ if (mapped) {
+ gst_buffer_fill (inbuf, 0, info.data, info.size);
+ gst_buffer_unmap (frame->input_buffer, &info);
+ }
+
+ GST_BUFFER_PTS (inbuf) = ts;
goto have_inbuf;
}
- outbuf = GST_BUFFER (gst_drm_buffer_pool_get (self->output_pool, FALSE));
- priv_out = get_buffer_priv (self, outbuf, state->width, state->height);
+ gst_buffer_pool_acquire_buffer (self->output_pool, &outbuf, NULL);
- 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 *) 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;
+ crop = gst_buffer_add_video_crop_meta (outbuf);
+ if (crop) {
+ crop->x = 0;
+ crop->y = 0;
+ crop->width = GST_VIDEO_INFO_WIDTH (&state->info);
+ crop->height = GST_VIDEO_INFO_HEIGHT (&state->info);
+ }
+ dmabuf_fd_out = gst_ducati_videnc_buffer_lock (self, outbuf);
+
+ self->inBufs->planeDesc[0].buf = (XDAS_Int8 *) dmabuf_fd_in;
+ self->inBufs->planeDesc[0].memType = XDM_MEMTYPE_RAW;
+ self->inBufs->planeDesc[0].bufSize.tileMem.width =
+ GST_VIDEO_INFO_WIDTH (&state->info);
+ self->inBufs->planeDesc[0].bufSize.tileMem.height =
+ GST_VIDEO_INFO_HEIGHT (&state->info);
+ self->inBufs->planeDesc[0].bufSize.bytes =
+ GST_VIDEO_INFO_WIDTH (&state->info) *
+ GST_VIDEO_INFO_HEIGHT (&state->info);
+ self->inBufs->planeDesc[1].buf = (XDAS_Int8 *) dmabuf_fd_in;
+ self->inBufs->planeDesc[1].memType = XDM_MEMTYPE_RAW;
+ self->inBufs->planeDesc[1].bufSize.tileMem.width =
+ GST_VIDEO_INFO_WIDTH (&state->info);
+ self->inBufs->planeDesc[1].bufSize.tileMem.height =
+ GST_VIDEO_INFO_HEIGHT (&state->info) / 2;
+ self->inBufs->planeDesc[1].bufSize.bytes =
+ GST_VIDEO_INFO_WIDTH (&state->info) *
+ GST_VIDEO_INFO_HEIGHT (&state->info) / 2;
/* setting imageRegion doesn't seem to be strictly needed if activeFrameRegion
* is set but we set it anyway...
*/
self->inBufs->activeFrameRegion.topLeft.y = self->rect.y;
self->inBufs->activeFrameRegion.bottomRight.x = self->rect.x + self->rect.w;
self->inBufs->activeFrameRegion.bottomRight.y = self->rect.y + self->rect.h;
- self->inBufs->imagePitch[0] = state->width;
- self->inBufs->imagePitch[1] = state->width;
+ self->inBufs->imagePitch[0] = GST_VIDEO_INFO_WIDTH (&state->info);
+ self->inBufs->imagePitch[1] = GST_VIDEO_INFO_WIDTH (&state->info);
self->inBufs->topFieldFirstFlag = TRUE;
self->outBufs->numBufs = 1;
- 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->outBufs->descs[0].buf = (XDAS_Int8 *) dmabuf_fd_out;
+
+ GstStructure *conf;
+ guint size;
+ conf = gst_buffer_pool_get_config (self->output_pool);
+ gst_buffer_pool_config_get_params (conf, NULL, &size, NULL, NULL);
+ self->outBufs->descs[0].bufSize.bytes = size;
+ self->outBufs->descs[0].memType = XDM_MEMTYPE_RAW;
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));
+ gst_ducati_videnc_buffer_unlock (self, outbuf);
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,
+ self->error_strings);
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) {
+ GstMapInfo info;
+ gboolean mapped;
+ if (GST_DUCATIVIDENC_GET_CLASS (self)->is_sync_point (self,
+ self->outArgs->encodedFrameType)) {
+ GST_VIDEO_CODEC_FRAME_SET_SYNC_POINT (frame);
+ }
+ if (frame->output_buffer) {
+ gst_buffer_unref (frame->output_buffer);
+ }
+
+ frame->output_buffer =
+ gst_video_encoder_allocate_output_buffer (GST_VIDEO_ENCODER (self),
+ self->outArgs->bytesGenerated);
+ mapped = gst_buffer_map (outbuf, &info, GST_MAP_READ);
+ if (mapped) {
+ gst_buffer_fill (frame->output_buffer, 0, info.data, info.size);
+ gst_buffer_unmap (outbuf, &info);
+ }
+
+ GST_CAT_DEBUG_OBJECT (GST_CAT_PERFORMANCE, 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->pts = GST_BUFFER_PTS (inbuf);
+ frame->duration = GST_BUFFER_DURATION (inbuf);
+ GST_BUFFER_OFFSET_END (frame->output_buffer) = GST_BUFFER_PTS (inbuf);
+ }
gst_buffer_unref (outbuf);
GstBuffer *buf = (GstBuffer *) self->outArgs->freeBufID[i];
GST_LOG_OBJECT (self, "free buffer: %p", buf);
+ gst_ducati_videnc_buffer_unlock (self, buf);
gst_buffer_unref (buf);
}
- return gst_base_video_encoder_finish_frame (base_video_encoder, frame);
+ return gst_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)
+gst_ducati_videnc_event (GstVideoEncoder * enc, GstEvent * event)
{
gboolean handled = FALSE;
GstDucatiVidEnc *self = GST_DUCATIVIDENC (enc);
switch (GST_EVENT_TYPE (event)) {
- case GST_EVENT_CROP:
- gst_event_parse_crop (event, &self->rect.y, &self->rect.x,
- &self->rect.w, &self->rect.h);
- GST_INFO_OBJECT (self, "got crop event top %d left %d %dx%d",
- self->rect.x, self->rect.y, self->rect.w, self->rect.h);
- handled = TRUE;
- break;
default:
break;
}
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;
-}