ducatividenc: use GST_PERFORMANCE category for traces related to profiling
[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
36 GST_DEBUG_CATEGORY_STATIC (GST_CAT_PERFORMANCE);
38 #define DEFAULT_BITRATE 2048
39 #define DEFAULT_RATE_PRESET GST_DUCATI_VIDENC_RATE_PRESET_STORAGE
40 #define DEFAULT_INTRA_INTERVAL 16
42 #define GST_TYPE_DUCATI_VIDENC_RATE_PRESET (gst_ducati_videnc_rate_preset_get_type ())
45 enum
46 {
47   LAST_SIGNAL
48 };
50 enum
51 {
52   PROP_0,
53   PROP_BITRATE,
54   PROP_RATE_PRESET,
55   PROP_INTRA_INTERVAL
56 };
58 static void gst_ducati_videnc_set_property (GObject * object, guint prop_id,
59     const GValue * value, GParamSpec * pspec);
60 static void gst_ducati_videnc_get_property (GObject * object, guint prop_id,
61     GValue * value, GParamSpec * pspec);
62 static GstDucatiBufferPriv *get_buffer_priv (GstDucatiVidEnc * self,
63     GstBuffer * buf, gint stride, gint height);
65 static gboolean gst_ducati_videnc_set_format (GstBaseVideoEncoder *
66     base_video_encoder, GstVideoState * state);
67 static gboolean gst_ducati_videnc_start (GstBaseVideoEncoder *
68     base_video_encoder);
69 static gboolean gst_ducati_videnc_stop (GstBaseVideoEncoder *
70     base_video_encoder);
71 static GstFlowReturn gst_ducati_videnc_finish (GstBaseVideoEncoder *
72     base_video_encoder);
73 static GstFlowReturn gst_ducati_videnc_handle_frame (GstBaseVideoEncoder *
74     base_video_encoder, GstVideoFrame * frame);
75 static gboolean gst_ducati_videnc_allocate_params_default (GstDucatiVidEnc *
76     self, gint params_sz, gint dynparams_sz, gint status_sz, gint inargs_sz,
77     gint outargs_sz);
78 static gboolean gst_ducati_videnc_is_sync_point_default (GstDucatiVidEnc * enc,
79     int type);
80 static gboolean gst_ducati_videnc_configure_default (GstDucatiVidEnc * self);
81 static gboolean gst_ducati_videnc_event (GstBaseVideoEncoder * enc,
82     GstEvent * event);
85 GST_BOILERPLATE (GstDucatiVidEnc, gst_ducati_videnc, GstBaseVideoEncoder,
86     GST_TYPE_BASE_VIDEO_ENCODER);
89 /* the values for the following enums are taken from the codec */
91 enum
92 {
93   GST_DUCATI_VIDENC_RATE_PRESET_LOW_DELAY = IVIDEO_LOW_DELAY,   /**< CBR rate control for video conferencing. */
94   GST_DUCATI_VIDENC_RATE_PRESET_STORAGE = IVIDEO_STORAGE,  /**< VBR rate control for local storage (DVD)
95                            *   recording.
96                            */
97   GST_DUCATI_VIDENC_RATE_PRESET_TWOPASS = IVIDEO_TWOPASS,  /**< Two pass rate control for non real time
98                            *   applications.
99                            */
100   GST_DUCATI_VIDENC_RATE_PRESET_NONE = IVIDEO_NONE,        /**< No configurable video rate control
101                             *  mechanism.
102                             */
103   GST_DUCATI_VIDENC_RATE_PRESET_USER_DEFINED = IVIDEO_USER_DEFINED,/**< User defined configuration using extended
104                            *   parameters.
105                            */
106 };
108 static GType
109 gst_ducati_videnc_rate_preset_get_type (void)
111   static GType type = 0;
113   if (!type) {
114     static const GEnumValue vals[] = {
115       {GST_DUCATI_VIDENC_RATE_PRESET_LOW_DELAY, "Low Delay", "low-delay"},
116       {GST_DUCATI_VIDENC_RATE_PRESET_STORAGE, "Storage", "storage"},
117       {GST_DUCATI_VIDENC_RATE_PRESET_TWOPASS, "Two-Pass", "two-pass"},
118       {GST_DUCATI_VIDENC_RATE_PRESET_NONE, "None", "none"},
119       {GST_DUCATI_VIDENC_RATE_PRESET_USER_DEFINED, "User defined",
120           "user-defined"},
121       {0, NULL, NULL},
122     };
124     type = g_enum_register_static ("GstDucatiVidEncRatePreset", vals);
125   }
127   return type;
130 static void
131 gst_ducati_videnc_base_init (gpointer g_class)
135 static void
136 gst_ducati_videnc_class_init (GstDucatiVidEncClass * klass)
138   GObjectClass *gobject_class;
139   GstBaseVideoEncoderClass *basevideoencoder_class;
141   gobject_class = G_OBJECT_CLASS (klass);
142   basevideoencoder_class = GST_BASE_VIDEO_ENCODER_CLASS (klass);
144   gobject_class->set_property = gst_ducati_videnc_set_property;
145   gobject_class->get_property = gst_ducati_videnc_get_property;
147   basevideoencoder_class->set_format =
148       GST_DEBUG_FUNCPTR (gst_ducati_videnc_set_format);
149   basevideoencoder_class->start = GST_DEBUG_FUNCPTR (gst_ducati_videnc_start);
150   basevideoencoder_class->stop = GST_DEBUG_FUNCPTR (gst_ducati_videnc_stop);
151   basevideoencoder_class->finish = GST_DEBUG_FUNCPTR (gst_ducati_videnc_finish);
152   basevideoencoder_class->handle_frame =
153       GST_DEBUG_FUNCPTR (gst_ducati_videnc_handle_frame);
154   basevideoencoder_class->event = GST_DEBUG_FUNCPTR (gst_ducati_videnc_event);
156   klass->allocate_params = gst_ducati_videnc_allocate_params_default;
157   klass->configure = gst_ducati_videnc_configure_default;
158   klass->is_sync_point = gst_ducati_videnc_is_sync_point_default;
160   g_object_class_install_property (gobject_class, PROP_BITRATE,
161       g_param_spec_int ("bitrate", "Bitrate", "Bitrate in kbit/sec", -1,
162           100 * 1024, DEFAULT_BITRATE, G_PARAM_READWRITE));
164   g_object_class_install_property (gobject_class, PROP_RATE_PRESET,
165       g_param_spec_enum ("rate-preset", "H.264 Rate Control",
166           "H.264 Rate Control",
167           GST_TYPE_DUCATI_VIDENC_RATE_PRESET, DEFAULT_RATE_PRESET,
168           G_PARAM_READWRITE));
170   g_object_class_install_property (gobject_class, PROP_INTRA_INTERVAL,
171       g_param_spec_int ("intra-interval", "Intra-frame interval",
172           "Interval between intra frames (keyframes)", 0, INT_MAX,
173           DEFAULT_INTRA_INTERVAL, G_PARAM_READWRITE));
176 static void
177 gst_ducati_videnc_init (GstDucatiVidEnc * self, GstDucatiVidEncClass * klass)
179   GST_DEBUG ("gst_ducati_videnc_init");
181   gst_ducati_set_generic_error_strings (self->error_strings);
183   self->device = NULL;
184   self->engine = NULL;
185   self->codec = NULL;
186   self->params = NULL;
187   self->status = NULL;
188   self->inBufs = NULL;
189   self->outBufs = NULL;
190   self->inArgs = NULL;
191   self->outArgs = NULL;
192   self->input_pool = NULL;
193   self->output_pool = NULL;
195   self->bitrate = DEFAULT_BITRATE * 1000;
196   self->rate_preset = DEFAULT_RATE_PRESET;
197   self->intra_interval = DEFAULT_INTRA_INTERVAL;
200 static gboolean
201 gst_ducati_videnc_set_format (GstBaseVideoEncoder * base_video_encoder,
202     GstVideoState * state)
204   GstDucatiVidEnc *self = GST_DUCATIVIDENC (base_video_encoder);
206   self->configure = TRUE;
208   return TRUE;
211 static void
212 gst_ducati_videnc_set_property (GObject * object, guint prop_id,
213     const GValue * value, GParamSpec * pspec)
215   GstDucatiVidEnc *self;
217   g_return_if_fail (GST_IS_DUCATIVIDENC (object));
218   self = GST_DUCATIVIDENC (object);
220   switch (prop_id) {
221     case PROP_BITRATE:
222       self->bitrate = g_value_get_int (value) * 1000;
223       break;
224     case PROP_RATE_PRESET:
225       self->rate_preset = g_value_get_enum (value);
226       break;
227     case PROP_INTRA_INTERVAL:
228       self->intra_interval = g_value_get_int (value);
229       break;
230     default:
231       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
232   }
235 static void
236 gst_ducati_videnc_get_property (GObject * object, guint prop_id,
237     GValue * value, GParamSpec * pspec)
239   GstDucatiVidEnc *self;
241   g_return_if_fail (GST_IS_DUCATIVIDENC (object));
242   self = GST_DUCATIVIDENC (object);
244   switch (prop_id) {
245     case PROP_BITRATE:
246       g_value_set_int (value, self->bitrate / 1000);
247       break;
248     case PROP_RATE_PRESET:
249       g_value_set_enum (value, self->rate_preset);
250       break;
251     case PROP_INTRA_INTERVAL:
252       g_value_set_int (value, self->intra_interval);
253       break;
254     default:
255       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
256   }
259 static gboolean
260 gst_ducati_videnc_configure (GstDucatiVidEnc * self)
262   int err;
263   int i;
264   int max_out_size = 0;
265   const GstVideoState *state;
267   state = gst_base_video_encoder_get_state (GST_BASE_VIDEO_ENCODER (self));
269   if (!GST_DUCATIVIDENC_GET_CLASS (self)->configure (self))
270     return FALSE;
272   if (self->codec == NULL) {
273     const gchar *codec_name;
275     codec_name = GST_DUCATIVIDENC_GET_CLASS (self)->codec_name;
276     self->codec = VIDENC2_create (self->engine,
277         (String) codec_name, self->params);
278     if (self->codec == NULL) {
279       GST_ERROR_OBJECT (self, "couldn't create codec");
280       return FALSE;
281     }
282   }
284   err = VIDENC2_control (self->codec,
285       XDM_SETPARAMS, self->dynParams, self->status);
286   if (err) {
287     GST_ERROR_OBJECT (self, "XDM_SETPARAMS err=%d, extendedError=%08x",
288         err, self->status->extendedError);
289     gst_ducati_log_extended_error_info (self->status->extendedError,
290         self->error_strings);
292     return FALSE;
293   }
295   err = VIDENC2_control (self->codec,
296       XDM_GETBUFINFO, self->dynParams, self->status);
297   if (err) {
298     GST_ERROR_OBJECT (self, "XDM_GETBUFINFO err=%d, extendedError=%08x",
299         err, self->status->extendedError);
301     return FALSE;
302   }
304   self->outBufs->numBufs = self->status->bufInfo.minNumOutBufs;
305   for (i = 0; i < self->outBufs->numBufs; i++) {
306     int size = self->status->bufInfo.minOutBufSize[i].bytes;
307     if (size > max_out_size)
308       max_out_size = size;
309   }
311   g_assert (self->input_pool == NULL);
312   self->input_pool = gst_drm_buffer_pool_new (GST_ELEMENT (self),
313       dce_get_fd (), NULL, state->bytes_per_picture);
315   g_assert (self->output_pool == NULL);
316   self->output_pool = gst_drm_buffer_pool_new (GST_ELEMENT (self),
317       dce_get_fd (), NULL, max_out_size);
319   GST_INFO_OBJECT (self, "configured");
321   self->configure = FALSE;
323   return TRUE;
326 static gboolean
327 gst_ducati_videnc_configure_default (GstDucatiVidEnc * self)
329   VIDENC2_DynamicParams *dynParams;
330   VIDENC2_Params *params;
331   const GstVideoState *state;
332   int i;
334   state = gst_base_video_encoder_get_state (GST_BASE_VIDEO_ENCODER (self));
336   if (self->rect.w == 0)
337     self->rect.w = state->width;
339   if (self->rect.h == 0)
340     self->rect.h = state->height;
342   params = (VIDENC2_Params *) self->params;
343   params->encodingPreset = 0x03;
344   params->rateControlPreset = self->rate_preset;
345   params->maxHeight = self->rect.h;
346   params->maxWidth = self->rect.w;
347   params->dataEndianness = XDM_BYTE;
348   params->maxInterFrameInterval = 1;
349   params->maxBitRate = -1;
350   params->minBitRate = 0;
351   params->inputChromaFormat = XDM_YUV_420SP;
352   params->inputContentType = IVIDEO_PROGRESSIVE;
353   params->operatingMode = IVIDEO_ENCODE_ONLY;
354   params->inputDataMode = IVIDEO_ENTIREFRAME;
355   params->outputDataMode = IVIDEO_ENTIREFRAME;
356   params->numInputDataUnits = 1;
357   params->numOutputDataUnits = 1;
358   for (i = 0; i < IVIDEO_MAX_NUM_METADATA_PLANES; i++) {
359     params->metadataType[i] = IVIDEO_METADATAPLANE_NONE;
360   }
362   dynParams = (VIDENC2_DynamicParams *) self->dynParams;
364   dynParams->refFrameRate =
365       gst_util_uint64_scale (1000, state->fps_n, state->fps_d);
366   dynParams->targetFrameRate = dynParams->refFrameRate;
367   dynParams->inputWidth = self->rect.w;
368   dynParams->inputHeight = self->rect.h;
369   dynParams->targetBitRate = self->bitrate;
370   dynParams->intraFrameInterval = self->intra_interval;
371   dynParams->captureWidth = dynParams->inputWidth;
373   dynParams->forceFrame = IVIDEO_NA_FRAME;
374   dynParams->interFrameInterval = 1;
375   dynParams->mvAccuracy = IVIDENC2_MOTIONVECTOR_QUARTERPEL;
376   dynParams->sampleAspectRatioHeight = 1;
377   dynParams->sampleAspectRatioWidth = 1;
378   dynParams->generateHeader = XDM_ENCODE_AU;
379   dynParams->ignoreOutbufSizeFlag = 1;
380   dynParams->lateAcquireArg = -1;
382   self->inBufs->chromaFormat = XDM_YUV_420SP;
383   self->inBufs->numPlanes = 2;
385   return TRUE;
388 static gboolean
389 gst_ducati_videnc_open_engine (GstDucatiVidEnc * self)
391   int error_code;
393   if (self->device == NULL) {
394     self->device = dce_init ();
395     if (self->device == NULL)
396       return FALSE;
397   }
399   self->engine = Engine_open ((String) "ivahd_vidsvr", NULL, &error_code);
400   if (self->engine == NULL) {
401     GST_ERROR_OBJECT (self, "couldn't open engine");
402     return FALSE;
403   }
405   return TRUE;
408 static gboolean
409 gst_ducati_videnc_allocate_params (GstDucatiVidEnc * self)
411   return GST_DUCATIVIDENC_GET_CLASS (self)->allocate_params (self,
412       sizeof (IVIDENC2_Params), sizeof (IVIDENC2_DynamicParams),
413       sizeof (IVIDENC2_Status), sizeof (IVIDENC2_InArgs),
414       sizeof (IVIDENC2_OutArgs));
417 static gboolean
418 gst_ducati_videnc_allocate_params_default (GstDucatiVidEnc * self,
419     gint params_sz, gint dynparams_sz, gint status_sz, gint inargs_sz,
420     gint outargs_sz)
422   self->params = dce_alloc (params_sz);
423   memset (self->params, 0, params_sz);
424   self->params->size = params_sz;
426   self->dynParams = dce_alloc (dynparams_sz);
427   memset (self->dynParams, 0, dynparams_sz);
428   self->dynParams->size = dynparams_sz;
430   self->status = dce_alloc (status_sz);
431   memset (self->status, 0, status_sz);
432   self->status->size = status_sz;
434   self->inBufs = dce_alloc (sizeof (IVIDEO2_BufDesc));
435   memset (self->inBufs, 0, sizeof (IVIDEO2_BufDesc));
437   self->outBufs = dce_alloc (sizeof (XDM2_BufDesc));
438   memset (self->outBufs, 0, sizeof (XDM2_BufDesc));
440   self->inArgs = dce_alloc (inargs_sz);
441   memset (self->inArgs, 0, inargs_sz);
442   self->inArgs->size = inargs_sz;
444   self->outArgs = dce_alloc (outargs_sz);
445   memset (self->outArgs, 0, outargs_sz);
446   self->outArgs->size = outargs_sz;
448   GST_INFO_OBJECT (self, "started");
450   return TRUE;
453 static gboolean
454 gst_ducati_videnc_free_params (GstDucatiVidEnc * self)
456   if (self->params) {
457     dce_free (self->params);
458     self->params = NULL;
459   }
461   if (self->dynParams) {
462     dce_free (self->dynParams);
463     self->dynParams = NULL;
464   }
466   if (self->inArgs) {
467     dce_free (self->inArgs);
468     self->inArgs = NULL;
469   }
471   if (self->outArgs) {
472     dce_free (self->outArgs);
473     self->outArgs = NULL;
474   }
476   if (self->status) {
477     dce_free (self->status);
478     self->status = NULL;
479   }
481   if (self->inBufs) {
482     dce_free (self->inBufs);
483     self->inBufs = NULL;
484   }
486   if (self->outBufs) {
487     dce_free (self->outBufs);
488     self->outBufs = NULL;
489   }
491   if (self->codec) {
492     VIDENC2_delete (self->codec);
493     self->codec = NULL;
494   }
496   return TRUE;
499 static void
500 gst_ducati_videnc_close_engine (GstDucatiVidEnc * self)
502   if (self->engine) {
503     Engine_close (self->engine);
504     self->engine = NULL;
505   }
507   if (self->device) {
508     dce_deinit (self->device);
509     self->device = NULL;
510   }
514 static gboolean
515 gst_ducati_videnc_start (GstBaseVideoEncoder * base_video_encoder)
517   GstDucatiVidEnc *self = GST_DUCATIVIDENC (base_video_encoder);
519   self->configure = TRUE;
520   memset (&self->rect, 0, sizeof (GstDucatiVideoRectangle));
522   if (!gst_ducati_videnc_open_engine (self))
523     goto fail;
525   if (!gst_ducati_videnc_allocate_params (self))
526     goto fail;
528   return TRUE;
530 fail:
531   gst_ducati_videnc_free_params (self);
532   gst_ducati_videnc_close_engine (self);
533   return FALSE;
536 static gboolean
537 gst_ducati_videnc_stop (GstBaseVideoEncoder * base_video_encoder)
539   GstDucatiVidEnc *self = GST_DUCATIVIDENC (base_video_encoder);
541   gst_ducati_videnc_free_params (self);
542   gst_ducati_videnc_close_engine (self);
544   if (self->input_pool) {
545     gst_drm_buffer_pool_destroy (self->input_pool);
546     self->input_pool = NULL;
547   }
549   if (self->output_pool) {
550     gst_drm_buffer_pool_destroy (self->output_pool);
551     self->output_pool = NULL;
552   }
554   /* reset cropping rect */
555   memset (&self->rect, 0, sizeof (GstDucatiVideoRectangle));
557   return TRUE;
560 static GstFlowReturn
561 gst_ducati_videnc_finish (GstBaseVideoEncoder * base_video_encoder)
563   GstDucatiVidEnc *self = GST_DUCATIVIDENC (base_video_encoder);
565   GST_DEBUG_OBJECT (self, "finish");
567   return GST_FLOW_OK;
570 static GstFlowReturn
571 gst_ducati_videnc_handle_frame (GstBaseVideoEncoder * base_video_encoder,
572     GstVideoFrame * frame)
574   GstDucatiVidEnc *self = GST_DUCATIVIDENC (base_video_encoder);
575   GstBuffer *inbuf, *outbuf;
576   GstDucatiBufferPriv *priv_in, *priv_out;
577   XDAS_Int32 err;
578   const GstVideoState *state;
579   int i;
580   GstClockTime ts;
581   GstClockTime t;
583   state = gst_base_video_encoder_get_state (base_video_encoder);
585   if (G_UNLIKELY (self->configure)) {
586     if (!gst_ducati_videnc_configure (self)) {
587       GST_DEBUG_OBJECT (self, "configure failed");
588       GST_ELEMENT_ERROR (self, STREAM, ENCODE, (NULL), (NULL));
590       return GST_FLOW_ERROR;
591     }
592   }
594   inbuf = gst_buffer_ref (frame->sink_buffer);
595   ts = GST_BUFFER_TIMESTAMP (inbuf);
596 have_inbuf:
597   priv_in = get_buffer_priv (self, inbuf, state->width, state->height);
598   if (priv_in == NULL) {
599     GST_DEBUG_OBJECT (self, "memcpying input");
600     gst_buffer_unref (inbuf);
601     inbuf = GST_BUFFER (gst_drm_buffer_pool_get (self->input_pool, FALSE));
602     memcpy (GST_BUFFER_DATA (inbuf), GST_BUFFER_DATA (frame->sink_buffer),
603         GST_BUFFER_SIZE (frame->sink_buffer));
604     GST_BUFFER_TIMESTAMP (inbuf) = ts;
605     goto have_inbuf;
606   }
608   outbuf = GST_BUFFER (gst_drm_buffer_pool_get (self->output_pool, FALSE));
609   priv_out = get_buffer_priv (self, outbuf, state->width, state->height);
611   self->inBufs->planeDesc[0].buf = (XDAS_Int8 *) omap_bo_handle (priv_in->bo);
612   self->inBufs->planeDesc[0].memType = XDM_MEMTYPE_BO;
613   self->inBufs->planeDesc[0].bufSize.tileMem.width = state->width;
614   self->inBufs->planeDesc[0].bufSize.tileMem.height = state->height;
615   self->inBufs->planeDesc[1].buf = (XDAS_Int8 *) priv_in->uv_offset;
616   self->inBufs->planeDesc[1].memType = XDM_MEMTYPE_BO_OFFSET;
617   self->inBufs->planeDesc[1].bufSize.tileMem.width = state->width;
618   self->inBufs->planeDesc[1].bufSize.tileMem.height = state->height / 2;
619   /* setting imageRegion doesn't seem to be strictly needed if activeFrameRegion
620    * is set but we set it anyway...
621    */
622   self->inBufs->imageRegion.topLeft.x = self->rect.x;
623   self->inBufs->imageRegion.topLeft.y = self->rect.y;
624   self->inBufs->imageRegion.bottomRight.x = self->rect.x + self->rect.w;
625   self->inBufs->imageRegion.bottomRight.y = self->rect.y + self->rect.h;
626   self->inBufs->activeFrameRegion.topLeft.x = self->rect.x;
627   self->inBufs->activeFrameRegion.topLeft.y = self->rect.y;
628   self->inBufs->activeFrameRegion.bottomRight.x = self->rect.x + self->rect.w;
629   self->inBufs->activeFrameRegion.bottomRight.y = self->rect.y + self->rect.h;
630   self->inBufs->imagePitch[0] = state->width;
631   self->inBufs->imagePitch[1] = state->width;
632   self->inBufs->topFieldFirstFlag = TRUE;
634   self->outBufs->numBufs = 1;
635   self->outBufs->descs[0].buf = (XDAS_Int8 *) omap_bo_handle (priv_out->bo);
636   self->outBufs->descs[0].bufSize.bytes = GST_BUFFER_SIZE (outbuf);
637   self->outBufs->descs[0].memType = XDM_MEMTYPE_BO;
639   self->inArgs->inputID = GPOINTER_TO_INT (inbuf);
641   GST_DEBUG ("Calling VIDENC2_process");
642   t = gst_util_get_timestamp ();
643   err = VIDENC2_process (self->codec, self->inBufs, self->outBufs,
644       self->inArgs, self->outArgs);
645   t = gst_util_get_timestamp () - t;
646   GST_DEBUG_OBJECT (self, "VIDENC2_process took %10dns (%d ms)", (gint) t,
647       (gint) (t / 1000000));
648   if (err) {
649     GST_WARNING_OBJECT (self, "process failed: err=%d, extendedError=%08x",
650         err, self->outArgs->extendedError);
651     gst_ducati_log_extended_error_info (self->outArgs->extendedError,
652         self->error_strings);
654     err = VIDENC2_control (self->codec,
655         XDM_GETSTATUS, (IVIDENC2_DynamicParams *) self->dynParams,
656         self->status);
658     GST_WARNING_OBJECT (self, "XDM_GETSTATUS: err=%d, extendedError=%08x",
659         err, self->status->extendedError);
661     return GST_FLOW_ERROR;
662   }
664   if (self->outArgs->bytesGenerated > 0) {
665     frame->is_sync_point =
666         GST_DUCATIVIDENC_GET_CLASS (self)->is_sync_point (self,
667         self->outArgs->encodedFrameType);
668     frame->src_buffer =
669         gst_buffer_new_and_alloc (self->outArgs->bytesGenerated);
670     memcpy (GST_BUFFER_DATA (frame->src_buffer), GST_BUFFER_DATA (outbuf),
671         self->outArgs->bytesGenerated);
672     GST_DEBUG_CATEGORY_GET (GST_CAT_PERFORMANCE, "GST_PERFORMANCE");
673     GST_CAT_DEBUG_OBJECT (GST_CAT_PERFORMANCE, self,
674             "Encoded frame in %u bytes", self->outArgs->bytesGenerated);
676     /* As we can get frames in a different order we sent them (if the codec
677        supports B frames and we set it up for generating those), we need to
678        work out what input frame corresponds to the frame we just got, to
679        keep presentation times correct.
680        It seems that the codec will free buffers in the right order for this,
681        but I can not find anything saying this in the docs, so:
682        - it might be subject to change
683        - it might not be true in all setups
684        - it might not be true for all codecs
685        However, that's the only way I can see to do it. So there's a nice
686        assert below that will blow up if the codec does not free exactly one
687        input frame when it outputs a frame. That doesn't catch all cases,
688        such as when it frees them in the wrong order, but that seems less
689        likely to happen.
690        The timestamp and duration are given to the base class, which will
691        in turn set them onto the encoded buffer. */
692     g_assert (self->outArgs->freeBufID[0] && !self->outArgs->freeBufID[1]);
693     inbuf = GST_BUFFER (self->outArgs->freeBufID[0]);
694     frame->presentation_timestamp = GST_BUFFER_TIMESTAMP (inbuf);
695     frame->presentation_duration = GST_BUFFER_DURATION (inbuf);
696     GST_BUFFER_OFFSET_END (frame->src_buffer) = GST_BUFFER_TIMESTAMP (inbuf);
697   }
699   gst_buffer_unref (outbuf);
701   for (i = 0; self->outArgs->freeBufID[i]; i++) {
702     GstBuffer *buf = (GstBuffer *) self->outArgs->freeBufID[i];
704     GST_LOG_OBJECT (self, "free buffer: %p", buf);
705     gst_buffer_unref (buf);
706   }
708   return gst_base_video_encoder_finish_frame (base_video_encoder, frame);
711 static gboolean
712 gst_ducati_videnc_is_sync_point_default (GstDucatiVidEnc * enc, int type)
714   return type == IVIDEO_I_FRAME;
717 static gboolean
718 gst_ducati_videnc_event (GstBaseVideoEncoder * enc, GstEvent * event)
720   gboolean handled = FALSE;
721   GstDucatiVidEnc *self = GST_DUCATIVIDENC (enc);
723   switch (GST_EVENT_TYPE (event)) {
724     case GST_EVENT_CROP:
725       gst_event_parse_crop (event, &self->rect.y, &self->rect.x,
726           &self->rect.w, &self->rect.h);
727       GST_INFO_OBJECT (self, "got crop event top %d left %d %dx%d",
728           self->rect.x, self->rect.y, self->rect.w, self->rect.h);
729       handled = TRUE;
730       break;
731     default:
732       break;
733   }
735   return handled;
738 static GstDucatiBufferPriv *
739 get_buffer_priv (GstDucatiVidEnc * self, GstBuffer * buf,
740     gint stride, gint height)
742   GstDucatiBufferPriv *priv = gst_ducati_buffer_priv_get (buf);
743   if (!priv) {
744     GstVideoFormat format = GST_VIDEO_FORMAT_NV12;
745     GstDmaBuf *dmabuf = gst_buffer_get_dma_buf (buf);
747     /* if it isn't a dmabuf buffer that we can import, then there
748      * is nothing we can do with it:
749      */
750     if (!dmabuf) {
751       GST_DEBUG_OBJECT (self, "not importing non dmabuf buffer");
752       return NULL;
753     }
755     priv = gst_ducati_buffer_priv_new ();
756     priv->bo = omap_bo_from_dmabuf (self->device, gst_dma_buf_get_fd (dmabuf));
758     priv->uv_offset = gst_video_format_get_component_offset (format,
759         1, stride, height);
760     priv->size = gst_video_format_get_size (format, stride, height);
762     gst_ducati_buffer_priv_set (buf, priv);
763   }
764   return priv;