Mark I frames as keyframes for encoders other than H264
[gstreamer-omap:mstorsjos-gst-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  */
22
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include "gstducati.h"
28 #include "gstducatividenc.h"
29 #include <ti/sdo/codecs/mpeg4enc/impeg4enc.h>
30
31 #include <string.h>
32
33 #include <math.h>
34
35 #define GST_CAT_DEFAULT gst_ducati_debug
36
37 #define DEFAULT_BITRATE 2048
38 #define DEFAULT_RATE_PRESET GST_DUCATI_VIDENC_RATE_PRESET_STORAGE
39
40 #define GST_TYPE_DUCATI_VIDENC_RATE_PRESET (gst_ducati_videnc_rate_preset_get_type ())
41
42
43 enum
44 {
45   LAST_SIGNAL
46 };
47
48 enum
49 {
50   PROP_0,
51   PROP_BITRATE,
52   PROP_RATE_PRESET
53 };
54
55 static void gst_ducati_videnc_set_property (GObject * object, guint prop_id,
56     const GValue * value, GParamSpec * pspec);
57 static void gst_ducati_videnc_get_property (GObject * object, guint prop_id,
58     GValue * value, GParamSpec * pspec);
59
60 static gboolean gst_ducati_videnc_set_format (GstBaseVideoEncoder *
61     base_video_encoder, GstVideoState * state);
62 static gboolean gst_ducati_videnc_start (GstBaseVideoEncoder *
63     base_video_encoder);
64 static gboolean gst_ducati_videnc_stop (GstBaseVideoEncoder *
65     base_video_encoder);
66 static GstFlowReturn gst_ducati_videnc_finish (GstBaseVideoEncoder *
67     base_video_encoder);
68 static GstFlowReturn gst_ducati_videnc_handle_frame (GstBaseVideoEncoder *
69     base_video_encoder, GstVideoFrame * frame);
70 static gboolean gst_ducati_videnc_allocate_params_default (GstDucatiVidEnc *
71     self, gint params_sz, gint dynparams_sz, gint status_sz, gint inargs_sz,
72     gint outargs_sz);
73 static gboolean gst_ducati_videnc_configure_default (GstDucatiVidEnc * self);
74 static gboolean gst_ducati_videnc_event (GstBaseVideoEncoder * enc,
75     GstEvent * event);
76
77
78 GST_BOILERPLATE (GstDucatiVidEnc, gst_ducati_videnc, GstBaseVideoEncoder,
79     GST_TYPE_BASE_VIDEO_ENCODER);
80
81
82 /* the values for the following enums are taken from the codec */
83
84 enum
85 {
86   GST_DUCATI_VIDENC_RATE_PRESET_LOW_DELAY = 1,   /**< CBR rate control for video conferencing. */
87   GST_DUCATI_VIDENC_RATE_PRESET_STORAGE = 2,     /**< VBR rate control for local storage (DVD)
88                            *   recording.
89                            */
90   GST_DUCATI_VIDENC_RATE_PRESET_TWOPASS = 3,     /**< Two pass rate control for non real time
91                            *   applications.
92                            */
93   GST_DUCATI_VIDENC_RATE_PRESET_NONE = 4,        /**< No configurable video rate control
94                             *  mechanism.
95                             */
96   GST_DUCATI_VIDENC_RATE_PRESET_USER_DEFINED = 5,/**< User defined configuration using extended
97                            *   parameters.
98                            */
99 };
100
101 static GType
102 gst_ducati_videnc_rate_preset_get_type (void)
103 {
104   static GType type = 0;
105
106   if (!type) {
107     static const GEnumValue vals[] = {
108       {GST_DUCATI_VIDENC_RATE_PRESET_LOW_DELAY, "Low Delay", "low-delay"},
109       {GST_DUCATI_VIDENC_RATE_PRESET_STORAGE, "Storage", "storage"},
110       {GST_DUCATI_VIDENC_RATE_PRESET_TWOPASS, "Two-Pass", "two-pass"},
111       {0, NULL, NULL},
112     };
113
114     type = g_enum_register_static ("GstDucatiVidEncRatePreset", vals);
115   }
116
117   return type;
118 }
119
120 static void
121 gst_ducati_videnc_base_init (gpointer g_class)
122 {
123 }
124
125 static void
126 gst_ducati_videnc_class_init (GstDucatiVidEncClass * klass)
127 {
128   GObjectClass *gobject_class;
129   GstBaseVideoEncoderClass *basevideoencoder_class;
130
131   gobject_class = G_OBJECT_CLASS (klass);
132   basevideoencoder_class = GST_BASE_VIDEO_ENCODER_CLASS (klass);
133
134   gobject_class->set_property = gst_ducati_videnc_set_property;
135   gobject_class->get_property = gst_ducati_videnc_get_property;
136
137   basevideoencoder_class->set_format =
138       GST_DEBUG_FUNCPTR (gst_ducati_videnc_set_format);
139   basevideoencoder_class->start = GST_DEBUG_FUNCPTR (gst_ducati_videnc_start);
140   basevideoencoder_class->stop = GST_DEBUG_FUNCPTR (gst_ducati_videnc_stop);
141   basevideoencoder_class->finish = GST_DEBUG_FUNCPTR (gst_ducati_videnc_finish);
142   basevideoencoder_class->handle_frame =
143       GST_DEBUG_FUNCPTR (gst_ducati_videnc_handle_frame);
144   basevideoencoder_class->event = GST_DEBUG_FUNCPTR (gst_ducati_videnc_event);
145
146   klass->allocate_params = gst_ducati_videnc_allocate_params_default;
147   klass->configure = gst_ducati_videnc_configure_default;
148
149   g_object_class_install_property (gobject_class, PROP_BITRATE,
150       g_param_spec_int ("bitrate", "Bitrate", "Bitrate in kbit/sec", -1,
151           100 * 1024, DEFAULT_BITRATE, G_PARAM_READWRITE));
152
153   g_object_class_install_property (gobject_class, PROP_RATE_PRESET,
154       g_param_spec_enum ("rate-preset", "H.264 Rate Control",
155           "H.264 Rate Control",
156           GST_TYPE_DUCATI_VIDENC_RATE_PRESET, DEFAULT_RATE_PRESET,
157           G_PARAM_READWRITE));
158 }
159
160 static void
161 gst_ducati_videnc_init (GstDucatiVidEnc * self, GstDucatiVidEncClass * klass)
162 {
163   GST_DEBUG ("gst_ducati_videnc_init");
164
165   self->engine = NULL;
166   self->codec = NULL;
167   self->params = NULL;
168   self->status = NULL;
169   self->inBufs = NULL;
170   self->outBufs = NULL;
171   self->inArgs = NULL;
172   self->outArgs = NULL;
173   self->input_pool = NULL;
174   self->output_pool = NULL;
175
176   self->bitrate = DEFAULT_BITRATE * 1000;
177   self->rate_preset = DEFAULT_RATE_PRESET;
178 }
179
180 static gboolean
181 gst_ducati_videnc_set_format (GstBaseVideoEncoder * base_video_encoder,
182     GstVideoState * state)
183 {
184   GstDucatiVidEnc *self = GST_DUCATIVIDENC (base_video_encoder);
185
186   self->configure = TRUE;
187
188   return TRUE;
189 }
190
191 static void
192 gst_ducati_videnc_set_property (GObject * object, guint prop_id,
193     const GValue * value, GParamSpec * pspec)
194 {
195   GstDucatiVidEnc *self = GST_DUCATIVIDENC (object);
196
197   g_return_if_fail (GST_IS_DUCATIVIDENC (object));
198   self = GST_DUCATIVIDENC (object);
199
200   switch (prop_id) {
201     case PROP_BITRATE:
202       self->bitrate = g_value_get_int (value) * 1000;
203       break;
204     case PROP_RATE_PRESET:
205       self->rate_preset = g_value_get_enum (value);
206       break;
207     default:
208       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
209   }
210 }
211
212 static void
213 gst_ducati_videnc_get_property (GObject * object, guint prop_id,
214     GValue * value, GParamSpec * pspec)
215 {
216   GstDucatiVidEnc *self = GST_DUCATIVIDENC (object);
217
218   g_return_if_fail (GST_IS_DUCATIVIDENC (object));
219   self = GST_DUCATIVIDENC (object);
220
221   switch (prop_id) {
222     case PROP_BITRATE:
223       g_value_set_int (value, self->bitrate / 1000);
224       break;
225     case PROP_RATE_PRESET:
226       g_value_set_enum (value, self->rate_preset);
227       break;
228     default:
229       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
230   }
231 }
232
233 static gboolean
234 gst_ducati_videnc_configure (GstDucatiVidEnc * self)
235 {
236   int err;
237   int i;
238   int max_out_size = 0;
239   const GstVideoState *state;
240
241   state = gst_base_video_encoder_get_state (GST_BASE_VIDEO_ENCODER (self));
242
243   if (!GST_DUCATIVIDENC_GET_CLASS (self)->configure (self))
244     return FALSE;
245
246   if (self->codec == NULL) {
247     const gchar *codec_name;
248
249     codec_name = GST_DUCATIVIDENC_GET_CLASS (self)->codec_name;
250     self->codec = VIDENC2_create (self->engine,
251         (String) codec_name, self->params);
252     if (self->codec == NULL) {
253       GST_ERROR_OBJECT (self, "couldn't create codec");
254       return FALSE;
255     }
256   }
257
258   err = VIDENC2_control (self->codec,
259       XDM_SETPARAMS, self->dynParams, self->status);
260   if (err) {
261     GST_ERROR_OBJECT (self, "XDM_SETPARAMS err=%d, extendedError=%08x",
262         err, self->status->extendedError);
263
264     return FALSE;
265   }
266
267   err = VIDENC2_control (self->codec,
268       XDM_GETBUFINFO, self->dynParams, self->status);
269   if (err) {
270     GST_ERROR_OBJECT (self, "XDM_GETBUFINFO err=%d, extendedError=%08x",
271         err, self->status->extendedError);
272
273     return FALSE;
274   }
275
276   self->outBufs->numBufs = self->status->bufInfo.minNumOutBufs;
277   for (i = 0; i < self->outBufs->numBufs; i++) {
278     int size = self->status->bufInfo.minOutBufSize[i].bytes;
279     if (size > max_out_size)
280       max_out_size = size;
281   }
282
283   g_assert (self->input_pool == NULL);
284   self->input_pool =
285       gst_ducati_bufferpool_new (GST_ELEMENT (self), NULL,
286       state->bytes_per_picture);
287
288   g_assert (self->output_pool == NULL);
289   self->output_pool =
290       gst_ducati_bufferpool_new (GST_ELEMENT (self), NULL, max_out_size);
291
292   GST_INFO_OBJECT (self, "configured");
293
294   self->configure = FALSE;
295
296   return TRUE;
297 }
298
299 static gboolean
300 gst_ducati_videnc_configure_default (GstDucatiVidEnc * self)
301 {
302   VIDENC2_DynamicParams *dynParams;
303   const GstVideoState *state;
304   int i;
305
306   state = gst_base_video_encoder_get_state (GST_BASE_VIDEO_ENCODER (self));
307
308   if (self->rect.w == 0)
309     self->rect.w = state->width;
310
311   if (self->rect.h == 0)
312     self->rect.h = state->height;
313
314   self->params = (VIDENC2_Params *) self->params;
315   self->params->encodingPreset = 0x03;
316   self->params->rateControlPreset = self->rate_preset;
317   self->params->maxHeight = self->rect.h;
318   self->params->maxWidth = self->rect.w;
319   self->params->dataEndianness = XDM_BYTE;
320   self->params->maxInterFrameInterval = 1;
321   self->params->maxBitRate = -1;
322   self->params->minBitRate = 0;
323   self->params->inputChromaFormat = XDM_YUV_420SP;
324   self->params->inputContentType = IVIDEO_PROGRESSIVE;
325   self->params->operatingMode = IVIDEO_ENCODE_ONLY;
326   self->params->inputDataMode = IVIDEO_ENTIREFRAME;
327   self->params->outputDataMode = IVIDEO_ENTIREFRAME;
328   self->params->numInputDataUnits = 1;
329   self->params->numOutputDataUnits = 1;
330   for (i = 0; i < IVIDEO_MAX_NUM_METADATA_PLANES; i++) {
331     self->params->metadataType[i] = IVIDEO_METADATAPLANE_NONE;
332   }
333
334   dynParams = self->dynParams;
335   dynParams = (VIDENC2_DynamicParams *) self->dynParams;
336
337   dynParams->refFrameRate =
338       gst_util_uint64_scale (1000, state->fps_n, state->fps_d);
339   dynParams->targetFrameRate = dynParams->refFrameRate;
340   dynParams->inputWidth = self->rect.w;
341   dynParams->inputHeight = self->rect.h;
342   dynParams->targetBitRate = self->bitrate;
343   dynParams->intraFrameInterval = 15;
344   dynParams->captureWidth = dynParams->inputWidth;
345   dynParams->captureWidth = dynParams->inputWidth = self->rect.w;
346
347   dynParams->forceFrame = IVIDEO_NA_FRAME;
348   dynParams->interFrameInterval = 1;
349   dynParams->mvAccuracy = IVIDENC2_MOTIONVECTOR_QUARTERPEL;
350   dynParams->sampleAspectRatioHeight = 1;
351   dynParams->sampleAspectRatioWidth = 1;
352   dynParams->generateHeader = XDM_ENCODE_AU;
353   dynParams->ignoreOutbufSizeFlag = 1;
354   dynParams->lateAcquireArg = -1;
355
356   self->inBufs->chromaFormat = XDM_YUV_420SP;
357   self->inBufs->numPlanes = 2;
358
359   return TRUE;
360 }
361
362 static gboolean
363 gst_ducati_videnc_open_engine (GstDucatiVidEnc * self)
364 {
365   self->engine = Engine_open ((String) "ivahd_vidsvr", NULL, NULL);
366   if (self->engine == NULL) {
367     GST_ERROR_OBJECT (self, "couldn't open engine");
368     return FALSE;
369   }
370
371   return TRUE;
372 }
373
374 static gboolean
375 gst_ducati_videnc_allocate_params (GstDucatiVidEnc * self)
376 {
377   return GST_DUCATIVIDENC_GET_CLASS (self)->allocate_params (self,
378       sizeof (IVIDENC2_Params), sizeof (IVIDENC2_DynamicParams),
379       sizeof (IVIDENC2_Status), sizeof (IVIDENC2_InArgs),
380       sizeof (IVIDENC2_OutArgs));
381 }
382
383 static gboolean
384 gst_ducati_videnc_allocate_params_default (GstDucatiVidEnc * self,
385     gint params_sz, gint dynparams_sz, gint status_sz, gint inargs_sz,
386     gint outargs_sz)
387 {
388   self->params = dce_alloc (params_sz);
389   memset (self->params, 0, params_sz);
390   self->params->size = params_sz;
391
392   self->dynParams = dce_alloc (dynparams_sz);
393   memset (self->dynParams, 0, dynparams_sz);
394   self->dynParams->size = dynparams_sz;
395
396   self->status = dce_alloc (status_sz);
397   memset (self->status, 0, status_sz);
398   self->status->size = status_sz;
399
400   self->inBufs = dce_alloc (sizeof (IVIDEO2_BufDesc));
401   memset (self->inBufs, 0, sizeof (IVIDEO2_BufDesc));
402
403   self->outBufs = dce_alloc (sizeof (XDM2_BufDesc));
404   memset (self->outBufs, 0, sizeof (XDM2_BufDesc));
405
406   self->inArgs = dce_alloc (inargs_sz);
407   memset (self->inArgs, 0, inargs_sz);
408   self->inArgs->size = inargs_sz;
409
410   self->outArgs = dce_alloc (outargs_sz);
411   memset (self->outArgs, 0, outargs_sz);
412   self->outArgs->size = outargs_sz;
413
414   GST_INFO_OBJECT (self, "started");
415
416   return TRUE;
417 }
418
419 static gboolean
420 gst_ducati_videnc_free_params (GstDucatiVidEnc * self)
421 {
422   if (self->params) {
423     dce_free (self->params);
424     self->params = NULL;
425   }
426
427   if (self->dynParams) {
428     dce_free (self->dynParams);
429     self->dynParams = NULL;
430   }
431
432   if (self->inArgs) {
433     dce_free (self->inArgs);
434     self->inArgs = NULL;
435   }
436
437   if (self->outArgs) {
438     dce_free (self->outArgs);
439     self->outArgs = NULL;
440   }
441
442   if (self->status) {
443     dce_free (self->status);
444     self->status = NULL;
445   }
446
447   if (self->inBufs) {
448     dce_free (self->inBufs);
449     self->inBufs = NULL;
450   }
451
452   if (self->outBufs) {
453     dce_free (self->outBufs);
454     self->inBufs = NULL;
455   }
456
457   if (self->codec) {
458     VIDENC2_delete (self->codec);
459     self->codec = NULL;
460   }
461
462   return TRUE;
463 }
464
465 static void
466 gst_ducati_videnc_close_engine (GstDucatiVidEnc * self)
467 {
468   if (self->engine) {
469     Engine_close (self->engine);
470     self->engine = NULL;
471   }
472 }
473
474
475 static gboolean
476 gst_ducati_videnc_start (GstBaseVideoEncoder * base_video_encoder)
477 {
478   GstDucatiVidEnc *self = GST_DUCATIVIDENC (base_video_encoder);
479
480   self->configure = TRUE;
481   memset (&self->rect, 0, sizeof (GstDucatiVideoRectangle));
482
483   if (!gst_ducati_videnc_open_engine (self))
484     goto fail;
485
486   if (!gst_ducati_videnc_allocate_params (self))
487     goto fail;
488
489   return TRUE;
490
491 fail:
492   gst_ducati_videnc_free_params (self);
493   gst_ducati_videnc_close_engine (self);
494   return FALSE;
495 }
496
497 static gboolean
498 gst_ducati_videnc_stop (GstBaseVideoEncoder * base_video_encoder)
499 {
500   GstDucatiVidEnc *self = GST_DUCATIVIDENC (base_video_encoder);
501
502   gst_ducati_videnc_free_params (self);
503   gst_ducati_videnc_close_engine (self);
504
505   if (self->input_pool) {
506     gst_ducati_bufferpool_destroy (self->input_pool);
507     self->input_pool = NULL;
508   }
509
510   if (self->output_pool) {
511     gst_ducati_bufferpool_destroy (self->output_pool);
512     self->output_pool = NULL;
513   }
514
515   /* reset cropping rect */
516   memset (&self->rect, 0, sizeof (GstDucatiVideoRectangle));
517
518   return TRUE;
519 }
520
521 static GstFlowReturn
522 gst_ducati_videnc_finish (GstBaseVideoEncoder * base_video_encoder)
523 {
524   GstDucatiVidEnc *self = GST_DUCATIVIDENC (base_video_encoder);
525
526   GST_DEBUG_OBJECT (self, "finish");
527
528   return GST_FLOW_OK;
529 }
530
531 static GstFlowReturn
532 gst_ducati_videnc_handle_frame (GstBaseVideoEncoder * base_video_encoder,
533     GstVideoFrame * frame)
534 {
535   GstDucatiVidEnc *self = GST_DUCATIVIDENC (base_video_encoder);
536   GstBuffer *inbuf, *outbuf;
537   guint8 *y_vaddr, *uv_vaddr;
538   SSPtr y_paddr, uv_paddr, outbuf_paddr;
539   XDAS_Int32 err;
540   XDAS_Int16 y_type, uv_type;
541   const GstVideoState *state;
542   int i;
543
544   state = gst_base_video_encoder_get_state (base_video_encoder);
545
546   if (G_UNLIKELY (self->configure)) {
547     if (!gst_ducati_videnc_configure (self)) {
548       GST_DEBUG_OBJECT (self, "configure failed");
549       GST_ELEMENT_ERROR (self, STREAM, ENCODE, (NULL), (NULL));
550
551       return GST_FLOW_ERROR;
552     }
553   }
554
555   inbuf = gst_buffer_ref (frame->sink_buffer);
556 have_inbuf:
557   y_vaddr = GST_BUFFER_DATA (inbuf);
558   uv_vaddr = y_vaddr + gst_video_format_get_component_offset (state->format,
559       1, state->width, state->height);
560   y_paddr = TilerMem_VirtToPhys (y_vaddr);
561   uv_paddr = TilerMem_VirtToPhys (uv_vaddr);
562   y_type = gst_ducati_get_mem_type (y_paddr);
563   uv_type = gst_ducati_get_mem_type (uv_paddr);
564   if (y_type < 0 || uv_type < 0) {
565     GST_DEBUG_OBJECT (self, "memcpying input %d %d", y_type, uv_type);
566     gst_buffer_unref (inbuf);
567     inbuf = GST_BUFFER (gst_ducati_bufferpool_get (self->input_pool, NULL));
568     memcpy (GST_BUFFER_DATA (inbuf), GST_BUFFER_DATA (frame->sink_buffer),
569         GST_BUFFER_SIZE (frame->sink_buffer));
570     goto have_inbuf;
571   }
572
573   outbuf = GST_BUFFER (gst_ducati_bufferpool_get (self->output_pool, NULL));
574
575   y_vaddr = GST_BUFFER_DATA (inbuf);
576   uv_vaddr = y_vaddr + gst_video_format_get_component_offset (state->format,
577       1, state->width, state->height);
578
579   y_paddr = TilerMem_VirtToPhys (y_vaddr);
580   uv_paddr = TilerMem_VirtToPhys (uv_vaddr);
581
582   outbuf_paddr = TilerMem_VirtToPhys (GST_BUFFER_DATA (outbuf));
583
584   self->inBufs->planeDesc[0].buf = (XDAS_Int8 *) y_paddr;
585   self->inBufs->planeDesc[0].memType = XDM_MEMTYPE_TILEDPAGE;
586   self->inBufs->planeDesc[0].bufSize.tileMem.width = state->width;
587   self->inBufs->planeDesc[0].bufSize.tileMem.height = state->height;
588   self->inBufs->planeDesc[1].buf = (XDAS_Int8 *) uv_paddr;
589   self->inBufs->planeDesc[1].memType = XDM_MEMTYPE_TILEDPAGE;
590   self->inBufs->planeDesc[1].bufSize.tileMem.width = state->width;
591   self->inBufs->planeDesc[1].bufSize.tileMem.height = state->height / 2;
592   /* setting imageRegion doesn't seem to be strictly needed if activeFrameRegion
593    * is set but we set it anyway...
594    */
595   self->inBufs->imageRegion.topLeft.x = self->rect.x;
596   self->inBufs->imageRegion.topLeft.y = self->rect.y;
597   self->inBufs->imageRegion.bottomRight.x = self->rect.x + self->rect.w;
598   self->inBufs->imageRegion.bottomRight.y = self->rect.y + self->rect.h;
599   self->inBufs->activeFrameRegion.topLeft.x = self->rect.x;
600   self->inBufs->activeFrameRegion.topLeft.y = self->rect.y;
601   self->inBufs->activeFrameRegion.bottomRight.x = self->rect.x + self->rect.w;
602   self->inBufs->activeFrameRegion.bottomRight.y = self->rect.y + self->rect.h;
603   self->inBufs->imagePitch[0] = state->width;
604   self->inBufs->imagePitch[1] = state->width;
605   self->inBufs->topFieldFirstFlag = TRUE;
606
607   self->outBufs->numBufs = 1;
608   self->outBufs->descs[0].buf = (XDAS_Int8 *) outbuf_paddr;
609   self->outBufs->descs[0].bufSize.bytes = GST_BUFFER_SIZE (outbuf);
610
611   self->inArgs->inputID = GPOINTER_TO_INT (inbuf);
612
613   err = VIDENC2_process (self->codec, self->inBufs, self->outBufs,
614       self->inArgs, self->outArgs);
615   if (err) {
616     GST_WARNING_OBJECT (self, "process failed: err=%d, extendedError=%08x",
617         err, self->status->extendedError);
618
619     err = VIDENC2_control (self->codec,
620         XDM_GETSTATUS, (IVIDENC2_DynamicParams *) self->dynParams,
621         self->status);
622
623     GST_WARNING_OBJECT (self, "XDM_GETSTATUS: err=%d, extendedError=%08x",
624         err, self->status->extendedError);
625
626     return GST_FLOW_ERROR;
627   }
628
629   if (!strcmp (GST_DUCATIVIDENC_GET_CLASS (self)->codec_name, "ivahd_h264enc")) {
630     if (self->outArgs->encodedFrameType == IVIDEO_IDR_FRAME)
631       frame->is_sync_point = TRUE;
632   } else {
633     if (self->outArgs->encodedFrameType == IVIDEO_I_FRAME)
634       frame->is_sync_point = TRUE;
635   }
636   frame->src_buffer = gst_buffer_new_and_alloc (self->outArgs->bytesGenerated);
637   memcpy (GST_BUFFER_DATA (frame->src_buffer),
638       GST_BUFFER_DATA (outbuf), self->outArgs->bytesGenerated);
639
640   gst_buffer_unref (outbuf);
641
642   for (i = 0; self->outArgs->freeBufID[i]; i++) {
643     GstBuffer *buf = (GstBuffer *) self->outArgs->freeBufID[i];
644
645     GST_LOG_OBJECT (self, "free buffer: %p", buf);
646     gst_buffer_unref (buf);
647   }
648
649   return gst_base_video_encoder_finish_frame (base_video_encoder, frame);
650 }
651
652 static gboolean
653 gst_ducati_videnc_event (GstBaseVideoEncoder * enc, GstEvent * event)
654 {
655   gboolean handled = FALSE;
656   GstDucatiVidEnc *self = GST_DUCATIVIDENC (enc);
657
658   switch (GST_EVENT_TYPE (event)) {
659     case GST_EVENT_CROP:
660       gst_event_parse_crop (event, &self->rect.y, &self->rect.x,
661           &self->rect.w, &self->rect.h);
662       GST_INFO_OBJECT (self, "got crop event top %d left %d %dx%d",
663           self->rect.x, self->rect.y, self->rect.w, self->rect.h);
664       handled = TRUE;
665       break;
666     default:
667       break;
668   }
669
670   return handled;
671 }