0292976967f556e27947a8a50164630faeba87bc
[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   gst_ducati_set_generic_error_strings (self->error_strings);
182   self->device = NULL;
183   self->engine = NULL;
184   self->codec = NULL;
185   self->params = NULL;
186   self->status = NULL;
187   self->inBufs = NULL;
188   self->outBufs = NULL;
189   self->inArgs = NULL;
190   self->outArgs = NULL;
191   self->input_pool = NULL;
192   self->output_pool = NULL;
194   self->bitrate = DEFAULT_BITRATE * 1000;
195   self->rate_preset = DEFAULT_RATE_PRESET;
196   self->intra_interval = DEFAULT_INTRA_INTERVAL;
199 static gboolean
200 gst_ducati_videnc_set_format (GstBaseVideoEncoder * base_video_encoder,
201     GstVideoState * state)
203   GstDucatiVidEnc *self = GST_DUCATIVIDENC (base_video_encoder);
205   self->configure = TRUE;
207   return TRUE;
210 static void
211 gst_ducati_videnc_set_property (GObject * object, guint prop_id,
212     const GValue * value, GParamSpec * pspec)
214   GstDucatiVidEnc *self;
216   g_return_if_fail (GST_IS_DUCATIVIDENC (object));
217   self = GST_DUCATIVIDENC (object);
219   switch (prop_id) {
220     case PROP_BITRATE:
221       self->bitrate = g_value_get_int (value) * 1000;
222       break;
223     case PROP_RATE_PRESET:
224       self->rate_preset = g_value_get_enum (value);
225       break;
226     case PROP_INTRA_INTERVAL:
227       self->intra_interval = g_value_get_int (value);
228       break;
229     default:
230       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
231   }
234 static void
235 gst_ducati_videnc_get_property (GObject * object, guint prop_id,
236     GValue * value, GParamSpec * pspec)
238   GstDucatiVidEnc *self;
240   g_return_if_fail (GST_IS_DUCATIVIDENC (object));
241   self = GST_DUCATIVIDENC (object);
243   switch (prop_id) {
244     case PROP_BITRATE:
245       g_value_set_int (value, self->bitrate / 1000);
246       break;
247     case PROP_RATE_PRESET:
248       g_value_set_enum (value, self->rate_preset);
249       break;
250     case PROP_INTRA_INTERVAL:
251       g_value_set_int (value, self->intra_interval);
252       break;
253     default:
254       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
255   }
258 static gboolean
259 gst_ducati_videnc_configure (GstDucatiVidEnc * self)
261   int err;
262   int i;
263   int max_out_size = 0;
264   const GstVideoState *state;
266   state = gst_base_video_encoder_get_state (GST_BASE_VIDEO_ENCODER (self));
268   if (!GST_DUCATIVIDENC_GET_CLASS (self)->configure (self))
269     return FALSE;
271   if (self->codec == NULL) {
272     const gchar *codec_name;
274     codec_name = GST_DUCATIVIDENC_GET_CLASS (self)->codec_name;
275     self->codec = VIDENC2_create (self->engine,
276         (String) codec_name, self->params);
277     if (self->codec == NULL) {
278       GST_ERROR_OBJECT (self, "couldn't create codec");
279       return FALSE;
280     }
281   }
283   err = VIDENC2_control (self->codec,
284       XDM_SETPARAMS, self->dynParams, self->status);
285   if (err) {
286     GST_ERROR_OBJECT (self, "XDM_SETPARAMS err=%d, extendedError=%08x",
287         err, self->status->extendedError);
288     gst_ducati_log_extended_error_info (self->status->extendedError,
289         self->error_strings);
291     return FALSE;
292   }
294   err = VIDENC2_control (self->codec,
295       XDM_GETBUFINFO, self->dynParams, self->status);
296   if (err) {
297     GST_ERROR_OBJECT (self, "XDM_GETBUFINFO err=%d, extendedError=%08x",
298         err, self->status->extendedError);
300     return FALSE;
301   }
303   self->outBufs->numBufs = self->status->bufInfo.minNumOutBufs;
304   for (i = 0; i < self->outBufs->numBufs; i++) {
305     int size = self->status->bufInfo.minOutBufSize[i].bytes;
306     if (size > max_out_size)
307       max_out_size = size;
308   }
310   g_assert (self->input_pool == NULL);
311   self->input_pool = gst_drm_buffer_pool_new (GST_ELEMENT (self),
312       dce_get_fd (), NULL, state->bytes_per_picture);
314   g_assert (self->output_pool == NULL);
315   self->output_pool = gst_drm_buffer_pool_new (GST_ELEMENT (self),
316       dce_get_fd (), NULL, max_out_size);
318   GST_INFO_OBJECT (self, "configured");
320   self->configure = FALSE;
322   return TRUE;
325 static gboolean
326 gst_ducati_videnc_configure_default (GstDucatiVidEnc * self)
328   VIDENC2_DynamicParams *dynParams;
329   VIDENC2_Params *params;
330   const GstVideoState *state;
331   int i;
333   state = gst_base_video_encoder_get_state (GST_BASE_VIDEO_ENCODER (self));
335   if (self->rect.w == 0)
336     self->rect.w = state->width;
338   if (self->rect.h == 0)
339     self->rect.h = state->height;
341   params = (VIDENC2_Params *) self->params;
342   params->encodingPreset = 0x03;
343   params->rateControlPreset = self->rate_preset;
344   params->maxHeight = self->rect.h;
345   params->maxWidth = self->rect.w;
346   params->dataEndianness = XDM_BYTE;
347   params->maxInterFrameInterval = 1;
348   params->maxBitRate = -1;
349   params->minBitRate = 0;
350   params->inputChromaFormat = XDM_YUV_420SP;
351   params->inputContentType = IVIDEO_PROGRESSIVE;
352   params->operatingMode = IVIDEO_ENCODE_ONLY;
353   params->inputDataMode = IVIDEO_ENTIREFRAME;
354   params->outputDataMode = IVIDEO_ENTIREFRAME;
355   params->numInputDataUnits = 1;
356   params->numOutputDataUnits = 1;
357   for (i = 0; i < IVIDEO_MAX_NUM_METADATA_PLANES; i++) {
358     params->metadataType[i] = IVIDEO_METADATAPLANE_NONE;
359   }
361   dynParams = (VIDENC2_DynamicParams *) self->dynParams;
363   dynParams->refFrameRate =
364       gst_util_uint64_scale (1000, state->fps_n, state->fps_d);
365   dynParams->targetFrameRate = dynParams->refFrameRate;
366   dynParams->inputWidth = self->rect.w;
367   dynParams->inputHeight = self->rect.h;
368   dynParams->targetBitRate = self->bitrate;
369   dynParams->intraFrameInterval = self->intra_interval;
370   dynParams->captureWidth = dynParams->inputWidth;
372   dynParams->forceFrame = IVIDEO_NA_FRAME;
373   dynParams->interFrameInterval = 1;
374   dynParams->mvAccuracy = IVIDENC2_MOTIONVECTOR_QUARTERPEL;
375   dynParams->sampleAspectRatioHeight = 1;
376   dynParams->sampleAspectRatioWidth = 1;
377   dynParams->generateHeader = XDM_ENCODE_AU;
378   dynParams->ignoreOutbufSizeFlag = 1;
379   dynParams->lateAcquireArg = -1;
381   self->inBufs->chromaFormat = XDM_YUV_420SP;
382   self->inBufs->numPlanes = 2;
384   return TRUE;
387 static gboolean
388 gst_ducati_videnc_open_engine (GstDucatiVidEnc * self)
390   int error_code;
392   if (self->device == NULL) {
393     self->device = dce_init ();
394     if (self->device == NULL)
395       return FALSE;
396   }
398   self->engine = Engine_open ((String) "ivahd_vidsvr", NULL, &error_code);
399   if (self->engine == NULL) {
400     GST_ERROR_OBJECT (self, "couldn't open engine");
401     return FALSE;
402   }
404   return TRUE;
407 static gboolean
408 gst_ducati_videnc_allocate_params (GstDucatiVidEnc * self)
410   return GST_DUCATIVIDENC_GET_CLASS (self)->allocate_params (self,
411       sizeof (IVIDENC2_Params), sizeof (IVIDENC2_DynamicParams),
412       sizeof (IVIDENC2_Status), sizeof (IVIDENC2_InArgs),
413       sizeof (IVIDENC2_OutArgs));
416 static gboolean
417 gst_ducati_videnc_allocate_params_default (GstDucatiVidEnc * self,
418     gint params_sz, gint dynparams_sz, gint status_sz, gint inargs_sz,
419     gint outargs_sz)
421   self->params = dce_alloc (params_sz);
422   memset (self->params, 0, params_sz);
423   self->params->size = params_sz;
425   self->dynParams = dce_alloc (dynparams_sz);
426   memset (self->dynParams, 0, dynparams_sz);
427   self->dynParams->size = dynparams_sz;
429   self->status = dce_alloc (status_sz);
430   memset (self->status, 0, status_sz);
431   self->status->size = status_sz;
433   self->inBufs = dce_alloc (sizeof (IVIDEO2_BufDesc));
434   memset (self->inBufs, 0, sizeof (IVIDEO2_BufDesc));
436   self->outBufs = dce_alloc (sizeof (XDM2_BufDesc));
437   memset (self->outBufs, 0, sizeof (XDM2_BufDesc));
439   self->inArgs = dce_alloc (inargs_sz);
440   memset (self->inArgs, 0, inargs_sz);
441   self->inArgs->size = inargs_sz;
443   self->outArgs = dce_alloc (outargs_sz);
444   memset (self->outArgs, 0, outargs_sz);
445   self->outArgs->size = outargs_sz;
447   GST_INFO_OBJECT (self, "started");
449   return TRUE;
452 static gboolean
453 gst_ducati_videnc_free_params (GstDucatiVidEnc * self)
455   if (self->params) {
456     dce_free (self->params);
457     self->params = NULL;
458   }
460   if (self->dynParams) {
461     dce_free (self->dynParams);
462     self->dynParams = NULL;
463   }
465   if (self->inArgs) {
466     dce_free (self->inArgs);
467     self->inArgs = NULL;
468   }
470   if (self->outArgs) {
471     dce_free (self->outArgs);
472     self->outArgs = NULL;
473   }
475   if (self->status) {
476     dce_free (self->status);
477     self->status = NULL;
478   }
480   if (self->inBufs) {
481     dce_free (self->inBufs);
482     self->inBufs = NULL;
483   }
485   if (self->outBufs) {
486     dce_free (self->outBufs);
487     self->outBufs = NULL;
488   }
490   if (self->codec) {
491     VIDENC2_delete (self->codec);
492     self->codec = NULL;
493   }
495   return TRUE;
498 static void
499 gst_ducati_videnc_close_engine (GstDucatiVidEnc * self)
501   if (self->engine) {
502     Engine_close (self->engine);
503     self->engine = NULL;
504   }
506   if (self->device) {
507     dce_deinit (self->device);
508     self->device = NULL;
509   }
513 static gboolean
514 gst_ducati_videnc_start (GstBaseVideoEncoder * base_video_encoder)
516   GstDucatiVidEnc *self = GST_DUCATIVIDENC (base_video_encoder);
518   self->configure = TRUE;
519   memset (&self->rect, 0, sizeof (GstDucatiVideoRectangle));
521   if (!gst_ducati_videnc_open_engine (self))
522     goto fail;
524   if (!gst_ducati_videnc_allocate_params (self))
525     goto fail;
527   return TRUE;
529 fail:
530   gst_ducati_videnc_free_params (self);
531   gst_ducati_videnc_close_engine (self);
532   return FALSE;
535 static gboolean
536 gst_ducati_videnc_stop (GstBaseVideoEncoder * base_video_encoder)
538   GstDucatiVidEnc *self = GST_DUCATIVIDENC (base_video_encoder);
540   gst_ducati_videnc_free_params (self);
541   gst_ducati_videnc_close_engine (self);
543   if (self->input_pool) {
544     gst_drm_buffer_pool_destroy (self->input_pool);
545     self->input_pool = NULL;
546   }
548   if (self->output_pool) {
549     gst_drm_buffer_pool_destroy (self->output_pool);
550     self->output_pool = NULL;
551   }
553   /* reset cropping rect */
554   memset (&self->rect, 0, sizeof (GstDucatiVideoRectangle));
556   return TRUE;
559 static GstFlowReturn
560 gst_ducati_videnc_finish (GstBaseVideoEncoder * base_video_encoder)
562   GstDucatiVidEnc *self = GST_DUCATIVIDENC (base_video_encoder);
564   GST_DEBUG_OBJECT (self, "finish");
566   return GST_FLOW_OK;
569 static GstFlowReturn
570 gst_ducati_videnc_handle_frame (GstBaseVideoEncoder * base_video_encoder,
571     GstVideoFrame * frame)
573   GstDucatiVidEnc *self = GST_DUCATIVIDENC (base_video_encoder);
574   GstBuffer *inbuf, *outbuf;
575   GstDucatiBufferPriv *priv_in, *priv_out;
576   XDAS_Int32 err;
577   const GstVideoState *state;
578   int i;
579   GstClockTime ts;
580   GstClockTime t;
582   state = gst_base_video_encoder_get_state (base_video_encoder);
584   if (G_UNLIKELY (self->configure)) {
585     if (!gst_ducati_videnc_configure (self)) {
586       GST_DEBUG_OBJECT (self, "configure failed");
587       GST_ELEMENT_ERROR (self, STREAM, ENCODE, (NULL), (NULL));
589       return GST_FLOW_ERROR;
590     }
591   }
593   inbuf = gst_buffer_ref (frame->sink_buffer);
594   ts = GST_BUFFER_TIMESTAMP (inbuf);
595 have_inbuf:
596   priv_in = get_buffer_priv (self, inbuf, state->width, state->height);
597   if (priv_in == NULL) {
598     GST_DEBUG_OBJECT (self, "memcpying input");
599     gst_buffer_unref (inbuf);
600     inbuf = GST_BUFFER (gst_drm_buffer_pool_get (self->input_pool, FALSE));
601     memcpy (GST_BUFFER_DATA (inbuf), GST_BUFFER_DATA (frame->sink_buffer),
602         GST_BUFFER_SIZE (frame->sink_buffer));
603     GST_BUFFER_TIMESTAMP (inbuf) = ts;
604     goto have_inbuf;
605   }
607   outbuf = GST_BUFFER (gst_drm_buffer_pool_get (self->output_pool, FALSE));
608   priv_out = get_buffer_priv (self, outbuf, state->width, state->height);
610   self->inBufs->planeDesc[0].buf = (XDAS_Int8 *) omap_bo_handle (priv_in->bo);
611   self->inBufs->planeDesc[0].memType = XDM_MEMTYPE_BO;
612   self->inBufs->planeDesc[0].bufSize.tileMem.width = state->width;
613   self->inBufs->planeDesc[0].bufSize.tileMem.height = state->height;
614   self->inBufs->planeDesc[1].buf = (XDAS_Int8 *) priv_in->uv_offset;
615   self->inBufs->planeDesc[1].memType = XDM_MEMTYPE_BO_OFFSET;
616   self->inBufs->planeDesc[1].bufSize.tileMem.width = state->width;
617   self->inBufs->planeDesc[1].bufSize.tileMem.height = state->height / 2;
618   /* setting imageRegion doesn't seem to be strictly needed if activeFrameRegion
619    * is set but we set it anyway...
620    */
621   self->inBufs->imageRegion.topLeft.x = self->rect.x;
622   self->inBufs->imageRegion.topLeft.y = self->rect.y;
623   self->inBufs->imageRegion.bottomRight.x = self->rect.x + self->rect.w;
624   self->inBufs->imageRegion.bottomRight.y = self->rect.y + self->rect.h;
625   self->inBufs->activeFrameRegion.topLeft.x = self->rect.x;
626   self->inBufs->activeFrameRegion.topLeft.y = self->rect.y;
627   self->inBufs->activeFrameRegion.bottomRight.x = self->rect.x + self->rect.w;
628   self->inBufs->activeFrameRegion.bottomRight.y = self->rect.y + self->rect.h;
629   self->inBufs->imagePitch[0] = state->width;
630   self->inBufs->imagePitch[1] = state->width;
631   self->inBufs->topFieldFirstFlag = TRUE;
633   self->outBufs->numBufs = 1;
634   self->outBufs->descs[0].buf = (XDAS_Int8 *) omap_bo_handle (priv_out->bo);
635   self->outBufs->descs[0].bufSize.bytes = GST_BUFFER_SIZE (outbuf);
636   self->outBufs->descs[0].memType = XDM_MEMTYPE_BO;
638   self->inArgs->inputID = GPOINTER_TO_INT (inbuf);
640   GST_DEBUG ("Calling VIDENC2_process");
641   t = gst_util_get_timestamp ();
642   err = VIDENC2_process (self->codec, self->inBufs, self->outBufs,
643       self->inArgs, self->outArgs);
644   t = gst_util_get_timestamp () - t;
645   GST_DEBUG_OBJECT (self, "VIDENC2_process took %10dns (%d ms)", (gint) t,
646       (gint) (t / 1000000));
647   if (err) {
648     GST_WARNING_OBJECT (self, "process failed: err=%d, extendedError=%08x",
649         err, self->outArgs->extendedError);
650     gst_ducati_log_extended_error_info (self->outArgs->extendedError,
651         self->error_strings);
653     err = VIDENC2_control (self->codec,
654         XDM_GETSTATUS, (IVIDENC2_DynamicParams *) self->dynParams,
655         self->status);
657     GST_WARNING_OBJECT (self, "XDM_GETSTATUS: err=%d, extendedError=%08x",
658         err, self->status->extendedError);
660     return GST_FLOW_ERROR;
661   }
663   if (self->outArgs->bytesGenerated > 0) {
664     frame->is_sync_point =
665         GST_DUCATIVIDENC_GET_CLASS (self)->is_sync_point (self,
666         self->outArgs->encodedFrameType);
667     frame->src_buffer =
668         gst_buffer_new_and_alloc (self->outArgs->bytesGenerated);
669     memcpy (GST_BUFFER_DATA (frame->src_buffer), GST_BUFFER_DATA (outbuf),
670         self->outArgs->bytesGenerated);
671     GST_DEBUG_OBJECT (self, "Encoded frame in %u bytes",
672         self->outArgs->bytesGenerated);
674     /* As we can get frames in a different order we sent them (if the codec
675        supports B frames and we set it up for generating those), we need to
676        work out what input frame corresponds to the frame we just got, to
677        keep presentation times correct.
678        It seems that the codec will free buffers in the right order for this,
679        but I can not find anything saying this in the docs, so:
680        - it might be subject to change
681        - it might not be true in all setups
682        - it might not be true for all codecs
683        However, that's the only way I can see to do it. So there's a nice
684        assert below that will blow up if the codec does not free exactly one
685        input frame when it outputs a frame. That doesn't catch all cases,
686        such as when it frees them in the wrong order, but that seems less
687        likely to happen.
688        The timestamp and duration are given to the base class, which will
689        in turn set them onto the encoded buffer. */
690     g_assert (self->outArgs->freeBufID[0] && !self->outArgs->freeBufID[1]);
691     inbuf = GST_BUFFER (self->outArgs->freeBufID[0]);
692     frame->presentation_timestamp = GST_BUFFER_TIMESTAMP (inbuf);
693     frame->presentation_duration = GST_BUFFER_DURATION (inbuf);
694     GST_BUFFER_OFFSET_END (frame->src_buffer) = GST_BUFFER_TIMESTAMP (inbuf);
695   }
697   gst_buffer_unref (outbuf);
699   for (i = 0; self->outArgs->freeBufID[i]; i++) {
700     GstBuffer *buf = (GstBuffer *) self->outArgs->freeBufID[i];
702     GST_LOG_OBJECT (self, "free buffer: %p", buf);
703     gst_buffer_unref (buf);
704   }
706   return gst_base_video_encoder_finish_frame (base_video_encoder, frame);
709 static gboolean
710 gst_ducati_videnc_is_sync_point_default (GstDucatiVidEnc * enc, int type)
712   return type == IVIDEO_I_FRAME;
715 static gboolean
716 gst_ducati_videnc_event (GstBaseVideoEncoder * enc, GstEvent * event)
718   gboolean handled = FALSE;
719   GstDucatiVidEnc *self = GST_DUCATIVIDENC (enc);
721   switch (GST_EVENT_TYPE (event)) {
722     case GST_EVENT_CROP:
723       gst_event_parse_crop (event, &self->rect.y, &self->rect.x,
724           &self->rect.w, &self->rect.h);
725       GST_INFO_OBJECT (self, "got crop event top %d left %d %dx%d",
726           self->rect.x, self->rect.y, self->rect.w, self->rect.h);
727       handled = TRUE;
728       break;
729     default:
730       break;
731   }
733   return handled;
736 static GstDucatiBufferPriv *
737 get_buffer_priv (GstDucatiVidEnc * self, GstBuffer * buf,
738     gint stride, gint height)
740   GstDucatiBufferPriv *priv = gst_ducati_buffer_priv_get (buf);
741   if (!priv) {
742     GstVideoFormat format = GST_VIDEO_FORMAT_NV12;
743     GstDmaBuf *dmabuf = gst_buffer_get_dma_buf (buf);
745     /* if it isn't a dmabuf buffer that we can import, then there
746      * is nothing we can do with it:
747      */
748     if (!dmabuf) {
749       GST_DEBUG_OBJECT (self, "not importing non dmabuf buffer");
750       return NULL;
751     }
753     priv = gst_ducati_buffer_priv_new ();
754     priv->bo = omap_bo_from_dmabuf (self->device, gst_dma_buf_get_fd (dmabuf));
756     priv->uv_offset = gst_video_format_get_component_offset (format,
757         1, stride, height);
758     priv->size = gst_video_format_get_size (format, stride, height);
760     gst_ducati_buffer_priv_set (buf, priv);
761   }
762   return priv;