ducatividdec: remove another leftover -strided caps remnant
[glsdk/gst-plugin-ducati.git] / src / gstducatividenc.c
1 /* GStreamer
2  * Copyright (c) 2011, Texas Instruments Incorporated
3  * Copyright (c) 2011, Collabora Ltd.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  *
20  * Author: Alessandro Decina <alessandro.decina@collabora.com>
21  */
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
27 #include "gstducati.h"
28 #include "gstducatividenc.h"
29 #include "gstducatibufferpriv.h"
31 #include <string.h>
33 #include <math.h>
35 #define GST_CAT_DEFAULT gst_ducati_debug
37 #define DEFAULT_BITRATE 2048
38 #define DEFAULT_RATE_PRESET GST_DUCATI_VIDENC_RATE_PRESET_STORAGE
39 #define DEFAULT_INTRA_INTERVAL 16
41 #define GST_TYPE_DUCATI_VIDENC_RATE_PRESET (gst_ducati_videnc_rate_preset_get_type ())
44 enum
45 {
46   LAST_SIGNAL
47 };
49 enum
50 {
51   PROP_0,
52   PROP_BITRATE,
53   PROP_RATE_PRESET,
54   PROP_INTRA_INTERVAL
55 };
57 static void gst_ducati_videnc_set_property (GObject * object, guint prop_id,
58     const GValue * value, GParamSpec * pspec);
59 static void gst_ducati_videnc_get_property (GObject * object, guint prop_id,
60     GValue * value, GParamSpec * pspec);
61 static GstDucatiBufferPriv *get_buffer_priv (GstDucatiVidEnc * self,
62     GstBuffer * buf, gint stride, gint height);
64 static gboolean gst_ducati_videnc_set_format (GstBaseVideoEncoder *
65     base_video_encoder, GstVideoState * state);
66 static gboolean gst_ducati_videnc_start (GstBaseVideoEncoder *
67     base_video_encoder);
68 static gboolean gst_ducati_videnc_stop (GstBaseVideoEncoder *
69     base_video_encoder);
70 static GstFlowReturn gst_ducati_videnc_finish (GstBaseVideoEncoder *
71     base_video_encoder);
72 static GstFlowReturn gst_ducati_videnc_handle_frame (GstBaseVideoEncoder *
73     base_video_encoder, GstVideoFrame * frame);
74 static gboolean gst_ducati_videnc_allocate_params_default (GstDucatiVidEnc *
75     self, gint params_sz, gint dynparams_sz, gint status_sz, gint inargs_sz,
76     gint outargs_sz);
77 static gboolean gst_ducati_videnc_is_sync_point_default (GstDucatiVidEnc * enc,
78     int type);
79 static gboolean gst_ducati_videnc_configure_default (GstDucatiVidEnc * self);
80 static gboolean gst_ducati_videnc_event (GstBaseVideoEncoder * enc,
81     GstEvent * event);
84 GST_BOILERPLATE (GstDucatiVidEnc, gst_ducati_videnc, GstBaseVideoEncoder,
85     GST_TYPE_BASE_VIDEO_ENCODER);
88 /* the values for the following enums are taken from the codec */
90 enum
91 {
92   GST_DUCATI_VIDENC_RATE_PRESET_LOW_DELAY = IVIDEO_LOW_DELAY,   /**< CBR rate control for video conferencing. */
93   GST_DUCATI_VIDENC_RATE_PRESET_STORAGE = IVIDEO_STORAGE,  /**< VBR rate control for local storage (DVD)
94                            *   recording.
95                            */
96   GST_DUCATI_VIDENC_RATE_PRESET_TWOPASS = IVIDEO_TWOPASS,  /**< Two pass rate control for non real time
97                            *   applications.
98                            */
99   GST_DUCATI_VIDENC_RATE_PRESET_NONE = IVIDEO_NONE,        /**< No configurable video rate control
100                             *  mechanism.
101                             */
102   GST_DUCATI_VIDENC_RATE_PRESET_USER_DEFINED = IVIDEO_USER_DEFINED,/**< User defined configuration using extended
103                            *   parameters.
104                            */
105 };
107 static GType
108 gst_ducati_videnc_rate_preset_get_type (void)
110   static GType type = 0;
112   if (!type) {
113     static const GEnumValue vals[] = {
114       {GST_DUCATI_VIDENC_RATE_PRESET_LOW_DELAY, "Low Delay", "low-delay"},
115       {GST_DUCATI_VIDENC_RATE_PRESET_STORAGE, "Storage", "storage"},
116       {GST_DUCATI_VIDENC_RATE_PRESET_TWOPASS, "Two-Pass", "two-pass"},
117       {GST_DUCATI_VIDENC_RATE_PRESET_NONE, "None", "none"},
118       {GST_DUCATI_VIDENC_RATE_PRESET_USER_DEFINED, "User defined",
119           "user-defined"},
120       {0, NULL, NULL},
121     };
123     type = g_enum_register_static ("GstDucatiVidEncRatePreset", vals);
124   }
126   return type;
129 static void
130 gst_ducati_videnc_base_init (gpointer g_class)
134 static void
135 gst_ducati_videnc_class_init (GstDucatiVidEncClass * klass)
137   GObjectClass *gobject_class;
138   GstBaseVideoEncoderClass *basevideoencoder_class;
140   gobject_class = G_OBJECT_CLASS (klass);
141   basevideoencoder_class = GST_BASE_VIDEO_ENCODER_CLASS (klass);
143   gobject_class->set_property = gst_ducati_videnc_set_property;
144   gobject_class->get_property = gst_ducati_videnc_get_property;
146   basevideoencoder_class->set_format =
147       GST_DEBUG_FUNCPTR (gst_ducati_videnc_set_format);
148   basevideoencoder_class->start = GST_DEBUG_FUNCPTR (gst_ducati_videnc_start);
149   basevideoencoder_class->stop = GST_DEBUG_FUNCPTR (gst_ducati_videnc_stop);
150   basevideoencoder_class->finish = GST_DEBUG_FUNCPTR (gst_ducati_videnc_finish);
151   basevideoencoder_class->handle_frame =
152       GST_DEBUG_FUNCPTR (gst_ducati_videnc_handle_frame);
153   basevideoencoder_class->event = GST_DEBUG_FUNCPTR (gst_ducati_videnc_event);
155   klass->allocate_params = gst_ducati_videnc_allocate_params_default;
156   klass->configure = gst_ducati_videnc_configure_default;
157   klass->is_sync_point = gst_ducati_videnc_is_sync_point_default;
159   g_object_class_install_property (gobject_class, PROP_BITRATE,
160       g_param_spec_int ("bitrate", "Bitrate", "Bitrate in kbit/sec", -1,
161           100 * 1024, DEFAULT_BITRATE, G_PARAM_READWRITE));
163   g_object_class_install_property (gobject_class, PROP_RATE_PRESET,
164       g_param_spec_enum ("rate-preset", "H.264 Rate Control",
165           "H.264 Rate Control",
166           GST_TYPE_DUCATI_VIDENC_RATE_PRESET, DEFAULT_RATE_PRESET,
167           G_PARAM_READWRITE));
169   g_object_class_install_property (gobject_class, PROP_INTRA_INTERVAL,
170       g_param_spec_int ("intra-interval", "Intra-frame interval",
171           "Interval between intra frames (keyframes)", 0, INT_MAX,
172           DEFAULT_INTRA_INTERVAL, G_PARAM_READWRITE));
175 static void
176 gst_ducati_videnc_init (GstDucatiVidEnc * self, GstDucatiVidEncClass * klass)
178   GST_DEBUG ("gst_ducati_videnc_init");
180   self->device = NULL;
181   self->engine = NULL;
182   self->codec = NULL;
183   self->params = NULL;
184   self->status = NULL;
185   self->inBufs = NULL;
186   self->outBufs = NULL;
187   self->inArgs = NULL;
188   self->outArgs = NULL;
189   self->input_pool = NULL;
190   self->output_pool = NULL;
192   self->bitrate = DEFAULT_BITRATE * 1000;
193   self->rate_preset = DEFAULT_RATE_PRESET;
194   self->intra_interval = DEFAULT_INTRA_INTERVAL;
197 static gboolean
198 gst_ducati_videnc_set_format (GstBaseVideoEncoder * base_video_encoder,
199     GstVideoState * state)
201   GstDucatiVidEnc *self = GST_DUCATIVIDENC (base_video_encoder);
203   self->configure = TRUE;
205   return TRUE;
208 static void
209 gst_ducati_videnc_set_property (GObject * object, guint prop_id,
210     const GValue * value, GParamSpec * pspec)
212   GstDucatiVidEnc *self;
214   g_return_if_fail (GST_IS_DUCATIVIDENC (object));
215   self = GST_DUCATIVIDENC (object);
217   switch (prop_id) {
218     case PROP_BITRATE:
219       self->bitrate = g_value_get_int (value) * 1000;
220       break;
221     case PROP_RATE_PRESET:
222       self->rate_preset = g_value_get_enum (value);
223       break;
224     case PROP_INTRA_INTERVAL:
225       self->intra_interval = g_value_get_int (value);
226       break;
227     default:
228       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
229   }
232 static void
233 gst_ducati_videnc_get_property (GObject * object, guint prop_id,
234     GValue * value, GParamSpec * pspec)
236   GstDucatiVidEnc *self;
238   g_return_if_fail (GST_IS_DUCATIVIDENC (object));
239   self = GST_DUCATIVIDENC (object);
241   switch (prop_id) {
242     case PROP_BITRATE:
243       g_value_set_int (value, self->bitrate / 1000);
244       break;
245     case PROP_RATE_PRESET:
246       g_value_set_enum (value, self->rate_preset);
247       break;
248     case PROP_INTRA_INTERVAL:
249       g_value_set_int (value, self->intra_interval);
250       break;
251     default:
252       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
253   }
256 static gboolean
257 gst_ducati_videnc_configure (GstDucatiVidEnc * self)
259   int err;
260   int i;
261   int max_out_size = 0;
262   const GstVideoState *state;
264   state = gst_base_video_encoder_get_state (GST_BASE_VIDEO_ENCODER (self));
266   if (!GST_DUCATIVIDENC_GET_CLASS (self)->configure (self))
267     return FALSE;
269   if (self->codec == NULL) {
270     const gchar *codec_name;
272     codec_name = GST_DUCATIVIDENC_GET_CLASS (self)->codec_name;
273     self->codec = VIDENC2_create (self->engine,
274         (String) codec_name, self->params);
275     if (self->codec == NULL) {
276       GST_ERROR_OBJECT (self, "couldn't create codec");
277       return FALSE;
278     }
279   }
281   err = VIDENC2_control (self->codec,
282       XDM_SETPARAMS, self->dynParams, self->status);
283   if (err) {
284     GST_ERROR_OBJECT (self, "XDM_SETPARAMS err=%d, extendedError=%08x",
285         err, self->status->extendedError);
286     gst_ducati_log_extended_error_info (self->status->extendedError);
288     return FALSE;
289   }
291   err = VIDENC2_control (self->codec,
292       XDM_GETBUFINFO, self->dynParams, self->status);
293   if (err) {
294     GST_ERROR_OBJECT (self, "XDM_GETBUFINFO err=%d, extendedError=%08x",
295         err, self->status->extendedError);
297     return FALSE;
298   }
300   self->outBufs->numBufs = self->status->bufInfo.minNumOutBufs;
301   for (i = 0; i < self->outBufs->numBufs; i++) {
302     int size = self->status->bufInfo.minOutBufSize[i].bytes;
303     if (size > max_out_size)
304       max_out_size = size;
305   }
307   g_assert (self->input_pool == NULL);
308   self->input_pool = gst_drm_buffer_pool_new (GST_ELEMENT (self),
309       dce_get_fd (), NULL, state->bytes_per_picture);
311   g_assert (self->output_pool == NULL);
312   self->output_pool = gst_drm_buffer_pool_new (GST_ELEMENT (self),
313       dce_get_fd (), NULL, max_out_size);
315   GST_INFO_OBJECT (self, "configured");
317   self->configure = FALSE;
319   return TRUE;
322 static gboolean
323 gst_ducati_videnc_configure_default (GstDucatiVidEnc * self)
325   VIDENC2_DynamicParams *dynParams;
326   VIDENC2_Params *params;
327   const GstVideoState *state;
328   int i;
330   state = gst_base_video_encoder_get_state (GST_BASE_VIDEO_ENCODER (self));
332   if (self->rect.w == 0)
333     self->rect.w = state->width;
335   if (self->rect.h == 0)
336     self->rect.h = state->height;
338   params = (VIDENC2_Params *) self->params;
339   params->encodingPreset = 0x03;
340   params->rateControlPreset = self->rate_preset;
341   params->maxHeight = self->rect.h;
342   params->maxWidth = self->rect.w;
343   params->dataEndianness = XDM_BYTE;
344   params->maxInterFrameInterval = 1;
345   params->maxBitRate = -1;
346   params->minBitRate = 0;
347   params->inputChromaFormat = XDM_YUV_420SP;
348   params->inputContentType = IVIDEO_PROGRESSIVE;
349   params->operatingMode = IVIDEO_ENCODE_ONLY;
350   params->inputDataMode = IVIDEO_ENTIREFRAME;
351   params->outputDataMode = IVIDEO_ENTIREFRAME;
352   params->numInputDataUnits = 1;
353   params->numOutputDataUnits = 1;
354   for (i = 0; i < IVIDEO_MAX_NUM_METADATA_PLANES; i++) {
355     params->metadataType[i] = IVIDEO_METADATAPLANE_NONE;
356   }
358   dynParams = (VIDENC2_DynamicParams *) self->dynParams;
360   dynParams->refFrameRate =
361       gst_util_uint64_scale (1000, state->fps_n, state->fps_d);
362   dynParams->targetFrameRate = dynParams->refFrameRate;
363   dynParams->inputWidth = self->rect.w;
364   dynParams->inputHeight = self->rect.h;
365   dynParams->targetBitRate = self->bitrate;
366   dynParams->intraFrameInterval = self->intra_interval;
367   dynParams->captureWidth = dynParams->inputWidth;
369   dynParams->forceFrame = IVIDEO_NA_FRAME;
370   dynParams->interFrameInterval = 1;
371   dynParams->mvAccuracy = IVIDENC2_MOTIONVECTOR_QUARTERPEL;
372   dynParams->sampleAspectRatioHeight = 1;
373   dynParams->sampleAspectRatioWidth = 1;
374   dynParams->generateHeader = XDM_ENCODE_AU;
375   dynParams->ignoreOutbufSizeFlag = 1;
376   dynParams->lateAcquireArg = -1;
378   self->inBufs->chromaFormat = XDM_YUV_420SP;
379   self->inBufs->numPlanes = 2;
381   return TRUE;
384 static gboolean
385 gst_ducati_videnc_open_engine (GstDucatiVidEnc * self)
387   int error_code;
389   if (self->device == NULL) {
390     self->device = dce_init ();
391     if (self->device == NULL)
392       return FALSE;
393   }
395   self->engine = Engine_open ((String) "ivahd_vidsvr", NULL, &error_code);
396   if (self->engine == NULL) {
397     GST_ERROR_OBJECT (self, "couldn't open engine");
398     return FALSE;
399   }
401   return TRUE;
404 static gboolean
405 gst_ducati_videnc_allocate_params (GstDucatiVidEnc * self)
407   return GST_DUCATIVIDENC_GET_CLASS (self)->allocate_params (self,
408       sizeof (IVIDENC2_Params), sizeof (IVIDENC2_DynamicParams),
409       sizeof (IVIDENC2_Status), sizeof (IVIDENC2_InArgs),
410       sizeof (IVIDENC2_OutArgs));
413 static gboolean
414 gst_ducati_videnc_allocate_params_default (GstDucatiVidEnc * self,
415     gint params_sz, gint dynparams_sz, gint status_sz, gint inargs_sz,
416     gint outargs_sz)
418   self->params = dce_alloc (params_sz);
419   memset (self->params, 0, params_sz);
420   self->params->size = params_sz;
422   self->dynParams = dce_alloc (dynparams_sz);
423   memset (self->dynParams, 0, dynparams_sz);
424   self->dynParams->size = dynparams_sz;
426   self->status = dce_alloc (status_sz);
427   memset (self->status, 0, status_sz);
428   self->status->size = status_sz;
430   self->inBufs = dce_alloc (sizeof (IVIDEO2_BufDesc));
431   memset (self->inBufs, 0, sizeof (IVIDEO2_BufDesc));
433   self->outBufs = dce_alloc (sizeof (XDM2_BufDesc));
434   memset (self->outBufs, 0, sizeof (XDM2_BufDesc));
436   self->inArgs = dce_alloc (inargs_sz);
437   memset (self->inArgs, 0, inargs_sz);
438   self->inArgs->size = inargs_sz;
440   self->outArgs = dce_alloc (outargs_sz);
441   memset (self->outArgs, 0, outargs_sz);
442   self->outArgs->size = outargs_sz;
444   GST_INFO_OBJECT (self, "started");
446   return TRUE;
449 static gboolean
450 gst_ducati_videnc_free_params (GstDucatiVidEnc * self)
452   if (self->params) {
453     dce_free (self->params);
454     self->params = NULL;
455   }
457   if (self->dynParams) {
458     dce_free (self->dynParams);
459     self->dynParams = NULL;
460   }
462   if (self->inArgs) {
463     dce_free (self->inArgs);
464     self->inArgs = NULL;
465   }
467   if (self->outArgs) {
468     dce_free (self->outArgs);
469     self->outArgs = NULL;
470   }
472   if (self->status) {
473     dce_free (self->status);
474     self->status = NULL;
475   }
477   if (self->inBufs) {
478     dce_free (self->inBufs);
479     self->inBufs = NULL;
480   }
482   if (self->outBufs) {
483     dce_free (self->outBufs);
484     self->outBufs = NULL;
485   }
487   if (self->codec) {
488     VIDENC2_delete (self->codec);
489     self->codec = NULL;
490   }
492   return TRUE;
495 static void
496 gst_ducati_videnc_close_engine (GstDucatiVidEnc * self)
498   if (self->engine) {
499     Engine_close (self->engine);
500     self->engine = NULL;
501   }
503   if (self->device) {
504     dce_deinit (self->device);
505     self->device = NULL;
506   }
510 static gboolean
511 gst_ducati_videnc_start (GstBaseVideoEncoder * base_video_encoder)
513   GstDucatiVidEnc *self = GST_DUCATIVIDENC (base_video_encoder);
515   self->configure = TRUE;
516   memset (&self->rect, 0, sizeof (GstDucatiVideoRectangle));
518   if (!gst_ducati_videnc_open_engine (self))
519     goto fail;
521   if (!gst_ducati_videnc_allocate_params (self))
522     goto fail;
524   return TRUE;
526 fail:
527   gst_ducati_videnc_free_params (self);
528   gst_ducati_videnc_close_engine (self);
529   return FALSE;
532 static gboolean
533 gst_ducati_videnc_stop (GstBaseVideoEncoder * base_video_encoder)
535   GstDucatiVidEnc *self = GST_DUCATIVIDENC (base_video_encoder);
537   gst_ducati_videnc_free_params (self);
538   gst_ducati_videnc_close_engine (self);
540   if (self->input_pool) {
541     gst_drm_buffer_pool_destroy (self->input_pool);
542     self->input_pool = NULL;
543   }
545   if (self->output_pool) {
546     gst_drm_buffer_pool_destroy (self->output_pool);
547     self->output_pool = NULL;
548   }
550   /* reset cropping rect */
551   memset (&self->rect, 0, sizeof (GstDucatiVideoRectangle));
553   return TRUE;
556 static GstFlowReturn
557 gst_ducati_videnc_finish (GstBaseVideoEncoder * base_video_encoder)
559   GstDucatiVidEnc *self = GST_DUCATIVIDENC (base_video_encoder);
561   GST_DEBUG_OBJECT (self, "finish");
563   return GST_FLOW_OK;
566 static GstFlowReturn
567 gst_ducati_videnc_handle_frame (GstBaseVideoEncoder * base_video_encoder,
568     GstVideoFrame * frame)
570   GstDucatiVidEnc *self = GST_DUCATIVIDENC (base_video_encoder);
571   GstBuffer *inbuf, *outbuf;
572   GstDucatiBufferPriv *priv_in, *priv_out;
573   XDAS_Int32 err;
574   const GstVideoState *state;
575   int i;
576   GstClockTime ts;
577   GstClockTime t;
579   state = gst_base_video_encoder_get_state (base_video_encoder);
581   if (G_UNLIKELY (self->configure)) {
582     if (!gst_ducati_videnc_configure (self)) {
583       GST_DEBUG_OBJECT (self, "configure failed");
584       GST_ELEMENT_ERROR (self, STREAM, ENCODE, (NULL), (NULL));
586       return GST_FLOW_ERROR;
587     }
588   }
590   inbuf = gst_buffer_ref (frame->sink_buffer);
591   ts = GST_BUFFER_TIMESTAMP (inbuf);
592 have_inbuf:
593   priv_in = get_buffer_priv (self, inbuf, state->width, state->height);
594   if (priv_in == NULL) {
595     GST_DEBUG_OBJECT (self, "memcpying input");
596     gst_buffer_unref (inbuf);
597     inbuf = GST_BUFFER (gst_drm_buffer_pool_get (self->input_pool, FALSE));
598     memcpy (GST_BUFFER_DATA (inbuf), GST_BUFFER_DATA (frame->sink_buffer),
599         GST_BUFFER_SIZE (frame->sink_buffer));
600     GST_BUFFER_TIMESTAMP (inbuf) = ts;
601     goto have_inbuf;
602   }
604   outbuf = GST_BUFFER (gst_drm_buffer_pool_get (self->output_pool, FALSE));
605   priv_out = get_buffer_priv (self, outbuf, state->width, state->height);
607   self->inBufs->planeDesc[0].buf = (XDAS_Int8 *) omap_bo_handle (priv_in->bo);
608   self->inBufs->planeDesc[0].memType = XDM_MEMTYPE_BO;
609   self->inBufs->planeDesc[0].bufSize.tileMem.width = state->width;
610   self->inBufs->planeDesc[0].bufSize.tileMem.height = state->height;
611   self->inBufs->planeDesc[1].buf = (XDAS_Int8 *) priv_in->uv_offset;
612   self->inBufs->planeDesc[1].memType = XDM_MEMTYPE_BO_OFFSET;
613   self->inBufs->planeDesc[1].bufSize.tileMem.width = state->width;
614   self->inBufs->planeDesc[1].bufSize.tileMem.height = state->height / 2;
615   /* setting imageRegion doesn't seem to be strictly needed if activeFrameRegion
616    * is set but we set it anyway...
617    */
618   self->inBufs->imageRegion.topLeft.x = self->rect.x;
619   self->inBufs->imageRegion.topLeft.y = self->rect.y;
620   self->inBufs->imageRegion.bottomRight.x = self->rect.x + self->rect.w;
621   self->inBufs->imageRegion.bottomRight.y = self->rect.y + self->rect.h;
622   self->inBufs->activeFrameRegion.topLeft.x = self->rect.x;
623   self->inBufs->activeFrameRegion.topLeft.y = self->rect.y;
624   self->inBufs->activeFrameRegion.bottomRight.x = self->rect.x + self->rect.w;
625   self->inBufs->activeFrameRegion.bottomRight.y = self->rect.y + self->rect.h;
626   self->inBufs->imagePitch[0] = state->width;
627   self->inBufs->imagePitch[1] = state->width;
628   self->inBufs->topFieldFirstFlag = TRUE;
630   self->outBufs->numBufs = 1;
631   self->outBufs->descs[0].buf = (XDAS_Int8 *) omap_bo_handle (priv_out->bo);
632   self->outBufs->descs[0].bufSize.bytes = GST_BUFFER_SIZE (outbuf);
633   self->outBufs->descs[0].memType = XDM_MEMTYPE_BO;
635   self->inArgs->inputID = GPOINTER_TO_INT (inbuf);
637   GST_DEBUG ("Calling VIDENC2_process");
638   t = gst_util_get_timestamp ();
639   err = VIDENC2_process (self->codec, self->inBufs, self->outBufs,
640       self->inArgs, self->outArgs);
641   t = gst_util_get_timestamp () - t;
642   GST_DEBUG_OBJECT (self, "VIDENC2_process took %10dns (%d ms)", (gint) t,
643       (gint) (t / 1000000));
644   if (err) {
645     GST_WARNING_OBJECT (self, "process failed: err=%d, extendedError=%08x",
646         err, self->outArgs->extendedError);
647     gst_ducati_log_extended_error_info (self->outArgs->extendedError);
649     err = VIDENC2_control (self->codec,
650         XDM_GETSTATUS, (IVIDENC2_DynamicParams *) self->dynParams,
651         self->status);
653     GST_WARNING_OBJECT (self, "XDM_GETSTATUS: err=%d, extendedError=%08x",
654         err, self->status->extendedError);
656     return GST_FLOW_ERROR;
657   }
659   if (self->outArgs->bytesGenerated > 0) {
660     frame->is_sync_point =
661         GST_DUCATIVIDENC_GET_CLASS (self)->is_sync_point (self,
662         self->outArgs->encodedFrameType);
663     frame->src_buffer =
664         gst_buffer_new_and_alloc (self->outArgs->bytesGenerated);
665     memcpy (GST_BUFFER_DATA (frame->src_buffer), GST_BUFFER_DATA (outbuf),
666         self->outArgs->bytesGenerated);
667     GST_DEBUG_OBJECT (self, "Encoded frame in %u bytes",
668         self->outArgs->bytesGenerated);
670     /* As we can get frames in a different order we sent them (if the codec
671        supports B frames and we set it up for generating those), we need to
672        work out what input frame corresponds to the frame we just got, to
673        keep presentation times correct.
674        It seems that the codec will free buffers in the right order for this,
675        but I can not find anything saying this in the docs, so:
676        - it might be subject to change
677        - it might not be true in all setups
678        - it might not be true for all codecs
679        However, that's the only way I can see to do it. So there's a nice
680        assert below that will blow up if the codec does not free exactly one
681        input frame when it outputs a frame. That doesn't catch all cases,
682        such as when it frees them in the wrong order, but that seems less
683        likely to happen.
684        The timestamp and duration are given to the base class, which will
685        in turn set them onto the encoded buffer. */
686     g_assert (self->outArgs->freeBufID[0] && !self->outArgs->freeBufID[1]);
687     inbuf = GST_BUFFER (self->outArgs->freeBufID[0]);
688     frame->presentation_timestamp = GST_BUFFER_TIMESTAMP (inbuf);
689     frame->presentation_duration = GST_BUFFER_DURATION (inbuf);
690     GST_BUFFER_OFFSET_END (frame->src_buffer) = GST_BUFFER_TIMESTAMP (inbuf);
691   }
693   gst_buffer_unref (outbuf);
695   for (i = 0; self->outArgs->freeBufID[i]; i++) {
696     GstBuffer *buf = (GstBuffer *) self->outArgs->freeBufID[i];
698     GST_LOG_OBJECT (self, "free buffer: %p", buf);
699     gst_buffer_unref (buf);
700   }
702   return gst_base_video_encoder_finish_frame (base_video_encoder, frame);
705 static gboolean
706 gst_ducati_videnc_is_sync_point_default (GstDucatiVidEnc * enc, int type)
708   return type == IVIDEO_I_FRAME;
711 static gboolean
712 gst_ducati_videnc_event (GstBaseVideoEncoder * enc, GstEvent * event)
714   gboolean handled = FALSE;
715   GstDucatiVidEnc *self = GST_DUCATIVIDENC (enc);
717   switch (GST_EVENT_TYPE (event)) {
718     case GST_EVENT_CROP:
719       gst_event_parse_crop (event, &self->rect.y, &self->rect.x,
720           &self->rect.w, &self->rect.h);
721       GST_INFO_OBJECT (self, "got crop event top %d left %d %dx%d",
722           self->rect.x, self->rect.y, self->rect.w, self->rect.h);
723       handled = TRUE;
724       break;
725     default:
726       break;
727   }
729   return handled;
732 static GstDucatiBufferPriv *
733 get_buffer_priv (GstDucatiVidEnc * self, GstBuffer * buf,
734     gint stride, gint height)
736   GstDucatiBufferPriv *priv = gst_ducati_buffer_priv_get (buf);
737   if (!priv) {
738     GstVideoFormat format = GST_VIDEO_FORMAT_NV12;
739     GstDmaBuf *dmabuf = gst_buffer_get_dma_buf (buf);
741     /* if it isn't a dmabuf buffer that we can import, then there
742      * is nothing we can do with it:
743      */
744     if (!dmabuf) {
745       GST_DEBUG_OBJECT (self, "not importing non dmabuf buffer");
746       return NULL;
747     }
749     priv = gst_ducati_buffer_priv_new ();
750     priv->bo = omap_bo_from_dmabuf (self->device, gst_dma_buf_get_fd (dmabuf));
752     priv->uv_offset = gst_video_format_get_component_offset (format,
753         1, stride, height);
754     priv->size = gst_video_format_get_size (format, stride, height);
756     gst_ducati_buffer_priv_set (buf, priv);
757   }
758   return priv;