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 15
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_configure_default (GstDucatiVidEnc * self);
78 static gboolean gst_ducati_videnc_event (GstBaseVideoEncoder * enc,
79 GstEvent * event);
82 GST_BOILERPLATE (GstDucatiVidEnc, gst_ducati_videnc, GstBaseVideoEncoder,
83 GST_TYPE_BASE_VIDEO_ENCODER);
86 /* the values for the following enums are taken from the codec */
88 enum
89 {
90 GST_DUCATI_VIDENC_RATE_PRESET_LOW_DELAY = IVIDEO_LOW_DELAY, /**< CBR rate control for video conferencing. */
91 GST_DUCATI_VIDENC_RATE_PRESET_STORAGE = IVIDEO_STORAGE, /**< VBR rate control for local storage (DVD)
92 * recording.
93 */
94 GST_DUCATI_VIDENC_RATE_PRESET_TWOPASS = IVIDEO_TWOPASS, /**< Two pass rate control for non real time
95 * applications.
96 */
97 GST_DUCATI_VIDENC_RATE_PRESET_NONE = IVIDEO_NONE, /**< No configurable video rate control
98 * mechanism.
99 */
100 GST_DUCATI_VIDENC_RATE_PRESET_USER_DEFINED = IVIDEO_USER_DEFINED,/**< User defined configuration using extended
101 * parameters.
102 */
103 };
105 static GType
106 gst_ducati_videnc_rate_preset_get_type (void)
107 {
108 static GType type = 0;
110 if (!type) {
111 static const GEnumValue vals[] = {
112 {GST_DUCATI_VIDENC_RATE_PRESET_LOW_DELAY, "Low Delay", "low-delay"},
113 {GST_DUCATI_VIDENC_RATE_PRESET_STORAGE, "Storage", "storage"},
114 {GST_DUCATI_VIDENC_RATE_PRESET_TWOPASS, "Two-Pass", "two-pass"},
115 {GST_DUCATI_VIDENC_RATE_PRESET_NONE, "None", "None"},
116 {GST_DUCATI_VIDENC_RATE_PRESET_USER_DEFINED, "User defined",
117 "user-defined"},
118 {0, NULL, NULL},
119 };
121 type = g_enum_register_static ("GstDucatiVidEncRatePreset", vals);
122 }
124 return type;
125 }
127 static void
128 gst_ducati_videnc_base_init (gpointer g_class)
129 {
130 }
132 static void
133 gst_ducati_videnc_class_init (GstDucatiVidEncClass * klass)
134 {
135 GObjectClass *gobject_class;
136 GstBaseVideoEncoderClass *basevideoencoder_class;
138 gobject_class = G_OBJECT_CLASS (klass);
139 basevideoencoder_class = GST_BASE_VIDEO_ENCODER_CLASS (klass);
141 gobject_class->set_property = gst_ducati_videnc_set_property;
142 gobject_class->get_property = gst_ducati_videnc_get_property;
144 basevideoencoder_class->set_format =
145 GST_DEBUG_FUNCPTR (gst_ducati_videnc_set_format);
146 basevideoencoder_class->start = GST_DEBUG_FUNCPTR (gst_ducati_videnc_start);
147 basevideoencoder_class->stop = GST_DEBUG_FUNCPTR (gst_ducati_videnc_stop);
148 basevideoencoder_class->finish = GST_DEBUG_FUNCPTR (gst_ducati_videnc_finish);
149 basevideoencoder_class->handle_frame =
150 GST_DEBUG_FUNCPTR (gst_ducati_videnc_handle_frame);
151 basevideoencoder_class->event = GST_DEBUG_FUNCPTR (gst_ducati_videnc_event);
153 klass->allocate_params = gst_ducati_videnc_allocate_params_default;
154 klass->configure = gst_ducati_videnc_configure_default;
156 g_object_class_install_property (gobject_class, PROP_BITRATE,
157 g_param_spec_int ("bitrate", "Bitrate", "Bitrate in kbit/sec", -1,
158 100 * 1024, DEFAULT_BITRATE, G_PARAM_READWRITE));
160 g_object_class_install_property (gobject_class, PROP_RATE_PRESET,
161 g_param_spec_enum ("rate-preset", "H.264 Rate Control",
162 "H.264 Rate Control",
163 GST_TYPE_DUCATI_VIDENC_RATE_PRESET, DEFAULT_RATE_PRESET,
164 G_PARAM_READWRITE));
166 g_object_class_install_property (gobject_class, PROP_INTRA_INTERVAL,
167 g_param_spec_int ("intra-interval", "Intra-frame interval",
168 "Interval between intra frames (keyframes)", 0, INT_MAX,
169 DEFAULT_INTRA_INTERVAL, G_PARAM_READWRITE));
170 }
172 static void
173 gst_ducati_videnc_init (GstDucatiVidEnc * self, GstDucatiVidEncClass * klass)
174 {
175 GST_DEBUG ("gst_ducati_videnc_init");
177 self->device = NULL;
178 self->engine = NULL;
179 self->codec = NULL;
180 self->params = NULL;
181 self->status = NULL;
182 self->inBufs = NULL;
183 self->outBufs = NULL;
184 self->inArgs = NULL;
185 self->outArgs = NULL;
186 self->input_pool = NULL;
187 self->output_pool = NULL;
189 self->bitrate = DEFAULT_BITRATE * 1000;
190 self->rate_preset = DEFAULT_RATE_PRESET;
191 self->intra_interval = DEFAULT_INTRA_INTERVAL;
192 }
194 static gboolean
195 gst_ducati_videnc_set_format (GstBaseVideoEncoder * base_video_encoder,
196 GstVideoState * state)
197 {
198 GstDucatiVidEnc *self = GST_DUCATIVIDENC (base_video_encoder);
200 self->configure = TRUE;
202 return TRUE;
203 }
205 static void
206 gst_ducati_videnc_set_property (GObject * object, guint prop_id,
207 const GValue * value, GParamSpec * pspec)
208 {
209 GstDucatiVidEnc *self = GST_DUCATIVIDENC (object);
211 g_return_if_fail (GST_IS_DUCATIVIDENC (object));
212 self = GST_DUCATIVIDENC (object);
214 switch (prop_id) {
215 case PROP_BITRATE:
216 self->bitrate = g_value_get_int (value) * 1000;
217 break;
218 case PROP_RATE_PRESET:
219 self->rate_preset = g_value_get_enum (value);
220 break;
221 case PROP_INTRA_INTERVAL:
222 self->intra_interval = g_value_get_int (value);
223 break;
224 default:
225 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
226 }
227 }
229 static void
230 gst_ducati_videnc_get_property (GObject * object, guint prop_id,
231 GValue * value, GParamSpec * pspec)
232 {
233 GstDucatiVidEnc *self = GST_DUCATIVIDENC (object);
235 g_return_if_fail (GST_IS_DUCATIVIDENC (object));
236 self = GST_DUCATIVIDENC (object);
238 switch (prop_id) {
239 case PROP_BITRATE:
240 g_value_set_int (value, self->bitrate / 1000);
241 break;
242 case PROP_RATE_PRESET:
243 g_value_set_enum (value, self->rate_preset);
244 break;
245 case PROP_INTRA_INTERVAL:
246 g_value_set_int (value, self->intra_interval);
247 break;
248 default:
249 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
250 }
251 }
253 static gboolean
254 gst_ducati_videnc_configure (GstDucatiVidEnc * self)
255 {
256 int err;
257 int i;
258 int max_out_size = 0;
259 const GstVideoState *state;
261 state = gst_base_video_encoder_get_state (GST_BASE_VIDEO_ENCODER (self));
263 if (!GST_DUCATIVIDENC_GET_CLASS (self)->configure (self))
264 return FALSE;
266 if (self->codec == NULL) {
267 const gchar *codec_name;
269 codec_name = GST_DUCATIVIDENC_GET_CLASS (self)->codec_name;
270 self->codec = VIDENC2_create (self->engine,
271 (String) codec_name, self->params);
272 if (self->codec == NULL) {
273 GST_ERROR_OBJECT (self, "couldn't create codec");
274 return FALSE;
275 }
276 }
278 err = VIDENC2_control (self->codec,
279 XDM_SETPARAMS, self->dynParams, self->status);
280 if (err) {
281 GST_ERROR_OBJECT (self, "XDM_SETPARAMS err=%d, extendedError=%08x",
282 err, self->status->extendedError);
283 gst_ducati_log_extended_error_info (self->status->extendedError);
285 return FALSE;
286 }
288 err = VIDENC2_control (self->codec,
289 XDM_GETBUFINFO, self->dynParams, self->status);
290 if (err) {
291 GST_ERROR_OBJECT (self, "XDM_GETBUFINFO err=%d, extendedError=%08x",
292 err, self->status->extendedError);
294 return FALSE;
295 }
297 self->outBufs->numBufs = self->status->bufInfo.minNumOutBufs;
298 for (i = 0; i < self->outBufs->numBufs; i++) {
299 int size = self->status->bufInfo.minOutBufSize[i].bytes;
300 if (size > max_out_size)
301 max_out_size = size;
302 }
304 g_assert (self->input_pool == NULL);
305 self->input_pool = gst_drm_buffer_pool_new (GST_ELEMENT (self),
306 dce_get_fd (), NULL, state->bytes_per_picture);
308 g_assert (self->output_pool == NULL);
309 self->output_pool = gst_drm_buffer_pool_new (GST_ELEMENT (self),
310 dce_get_fd (), NULL, max_out_size);
312 GST_INFO_OBJECT (self, "configured");
314 self->configure = FALSE;
316 return TRUE;
317 }
319 static gboolean
320 gst_ducati_videnc_configure_default (GstDucatiVidEnc * self)
321 {
322 VIDENC2_DynamicParams *dynParams;
323 VIDENC2_Params *params;
324 const GstVideoState *state;
325 int i;
327 state = gst_base_video_encoder_get_state (GST_BASE_VIDEO_ENCODER (self));
329 if (self->rect.w == 0)
330 self->rect.w = state->width;
332 if (self->rect.h == 0)
333 self->rect.h = state->height;
335 params = (VIDENC2_Params *) self->params;
336 params->encodingPreset = 0x03;
337 params->rateControlPreset = self->rate_preset;
338 params->maxHeight = self->rect.h;
339 params->maxWidth = self->rect.w;
340 params->dataEndianness = XDM_BYTE;
341 params->maxInterFrameInterval = 1;
342 params->maxBitRate = -1;
343 params->minBitRate = 0;
344 params->inputChromaFormat = XDM_YUV_420SP;
345 params->inputContentType = IVIDEO_PROGRESSIVE;
346 params->operatingMode = IVIDEO_ENCODE_ONLY;
347 params->inputDataMode = IVIDEO_ENTIREFRAME;
348 params->outputDataMode = IVIDEO_ENTIREFRAME;
349 params->numInputDataUnits = 1;
350 params->numOutputDataUnits = 1;
351 for (i = 0; i < IVIDEO_MAX_NUM_METADATA_PLANES; i++) {
352 params->metadataType[i] = IVIDEO_METADATAPLANE_NONE;
353 }
355 dynParams = (VIDENC2_DynamicParams *) self->dynParams;
357 dynParams->refFrameRate =
358 gst_util_uint64_scale (1000, state->fps_n, state->fps_d);
359 dynParams->targetFrameRate = dynParams->refFrameRate;
360 dynParams->inputWidth = self->rect.w;
361 dynParams->inputHeight = self->rect.h;
362 dynParams->targetBitRate = self->bitrate;
363 dynParams->intraFrameInterval = self->intra_interval;
364 dynParams->captureWidth = dynParams->inputWidth;
366 dynParams->forceFrame = IVIDEO_NA_FRAME;
367 dynParams->interFrameInterval = 1;
368 dynParams->mvAccuracy = IVIDENC2_MOTIONVECTOR_QUARTERPEL;
369 dynParams->sampleAspectRatioHeight = 1;
370 dynParams->sampleAspectRatioWidth = 1;
371 dynParams->generateHeader = XDM_ENCODE_AU;
372 dynParams->ignoreOutbufSizeFlag = 1;
373 dynParams->lateAcquireArg = -1;
375 self->inBufs->chromaFormat = XDM_YUV_420SP;
376 self->inBufs->numPlanes = 2;
378 return TRUE;
379 }
381 static gboolean
382 gst_ducati_videnc_open_engine (GstDucatiVidEnc * self)
383 {
384 int error_code;
386 if (self->device == NULL) {
387 self->device = dce_init ();
388 if (self->device == NULL)
389 return FALSE;
390 }
392 self->engine = Engine_open ((String) "ivahd_vidsvr", NULL, &error_code);
393 if (self->engine == NULL) {
394 GST_ERROR_OBJECT (self, "couldn't open engine");
395 return FALSE;
396 }
398 return TRUE;
399 }
401 static gboolean
402 gst_ducati_videnc_allocate_params (GstDucatiVidEnc * self)
403 {
404 return GST_DUCATIVIDENC_GET_CLASS (self)->allocate_params (self,
405 sizeof (IVIDENC2_Params), sizeof (IVIDENC2_DynamicParams),
406 sizeof (IVIDENC2_Status), sizeof (IVIDENC2_InArgs),
407 sizeof (IVIDENC2_OutArgs));
408 }
410 static gboolean
411 gst_ducati_videnc_allocate_params_default (GstDucatiVidEnc * self,
412 gint params_sz, gint dynparams_sz, gint status_sz, gint inargs_sz,
413 gint outargs_sz)
414 {
415 self->params = dce_alloc (params_sz);
416 memset (self->params, 0, params_sz);
417 self->params->size = params_sz;
419 self->dynParams = dce_alloc (dynparams_sz);
420 memset (self->dynParams, 0, dynparams_sz);
421 self->dynParams->size = dynparams_sz;
423 self->status = dce_alloc (status_sz);
424 memset (self->status, 0, status_sz);
425 self->status->size = status_sz;
427 self->inBufs = dce_alloc (sizeof (IVIDEO2_BufDesc));
428 memset (self->inBufs, 0, sizeof (IVIDEO2_BufDesc));
430 self->outBufs = dce_alloc (sizeof (XDM2_BufDesc));
431 memset (self->outBufs, 0, sizeof (XDM2_BufDesc));
433 self->inArgs = dce_alloc (inargs_sz);
434 memset (self->inArgs, 0, inargs_sz);
435 self->inArgs->size = inargs_sz;
437 self->outArgs = dce_alloc (outargs_sz);
438 memset (self->outArgs, 0, outargs_sz);
439 self->outArgs->size = outargs_sz;
441 GST_INFO_OBJECT (self, "started");
443 return TRUE;
444 }
446 static gboolean
447 gst_ducati_videnc_free_params (GstDucatiVidEnc * self)
448 {
449 if (self->params) {
450 dce_free (self->params);
451 self->params = NULL;
452 }
454 if (self->dynParams) {
455 dce_free (self->dynParams);
456 self->dynParams = NULL;
457 }
459 if (self->inArgs) {
460 dce_free (self->inArgs);
461 self->inArgs = NULL;
462 }
464 if (self->outArgs) {
465 dce_free (self->outArgs);
466 self->outArgs = NULL;
467 }
469 if (self->status) {
470 dce_free (self->status);
471 self->status = NULL;
472 }
474 if (self->inBufs) {
475 dce_free (self->inBufs);
476 self->inBufs = NULL;
477 }
479 if (self->outBufs) {
480 dce_free (self->outBufs);
481 self->outBufs = NULL;
482 }
484 if (self->codec) {
485 VIDENC2_delete (self->codec);
486 self->codec = NULL;
487 }
489 return TRUE;
490 }
492 static void
493 gst_ducati_videnc_close_engine (GstDucatiVidEnc * self)
494 {
495 if (self->engine) {
496 Engine_close (self->engine);
497 self->engine = NULL;
498 }
500 if (self->device) {
501 dce_deinit (self->device);
502 self->device = NULL;
503 }
504 }
507 static gboolean
508 gst_ducati_videnc_start (GstBaseVideoEncoder * base_video_encoder)
509 {
510 GstDucatiVidEnc *self = GST_DUCATIVIDENC (base_video_encoder);
512 self->configure = TRUE;
513 memset (&self->rect, 0, sizeof (GstDucatiVideoRectangle));
515 if (!gst_ducati_videnc_open_engine (self))
516 goto fail;
518 if (!gst_ducati_videnc_allocate_params (self))
519 goto fail;
521 return TRUE;
523 fail:
524 gst_ducati_videnc_free_params (self);
525 gst_ducati_videnc_close_engine (self);
526 return FALSE;
527 }
529 static gboolean
530 gst_ducati_videnc_stop (GstBaseVideoEncoder * base_video_encoder)
531 {
532 GstDucatiVidEnc *self = GST_DUCATIVIDENC (base_video_encoder);
534 gst_ducati_videnc_free_params (self);
535 gst_ducati_videnc_close_engine (self);
537 if (self->input_pool) {
538 gst_drm_buffer_pool_destroy (self->input_pool);
539 self->input_pool = NULL;
540 }
542 if (self->output_pool) {
543 gst_drm_buffer_pool_destroy (self->output_pool);
544 self->output_pool = NULL;
545 }
547 /* reset cropping rect */
548 memset (&self->rect, 0, sizeof (GstDucatiVideoRectangle));
550 return TRUE;
551 }
553 static GstFlowReturn
554 gst_ducati_videnc_finish (GstBaseVideoEncoder * base_video_encoder)
555 {
556 GstDucatiVidEnc *self = GST_DUCATIVIDENC (base_video_encoder);
558 GST_DEBUG_OBJECT (self, "finish");
560 return GST_FLOW_OK;
561 }
563 static GstFlowReturn
564 gst_ducati_videnc_handle_frame (GstBaseVideoEncoder * base_video_encoder,
565 GstVideoFrame * frame)
566 {
567 GstDucatiVidEnc *self = GST_DUCATIVIDENC (base_video_encoder);
568 GstBuffer *inbuf, *outbuf;
569 GstDucatiBufferPriv *priv_in, *priv_out;
570 XDAS_Int32 err;
571 const GstVideoState *state;
572 int i;
574 state = gst_base_video_encoder_get_state (base_video_encoder);
576 if (G_UNLIKELY (self->configure)) {
577 if (!gst_ducati_videnc_configure (self)) {
578 GST_DEBUG_OBJECT (self, "configure failed");
579 GST_ELEMENT_ERROR (self, STREAM, ENCODE, (NULL), (NULL));
581 return GST_FLOW_ERROR;
582 }
583 }
585 inbuf = gst_buffer_ref (frame->sink_buffer);
586 have_inbuf:
587 priv_in = get_buffer_priv (self, inbuf, state->width, state->height);
588 if (priv_in == NULL) {
589 GST_DEBUG_OBJECT (self, "memcpying input");
590 gst_buffer_unref (inbuf);
591 inbuf = GST_BUFFER (gst_drm_buffer_pool_get (self->input_pool, FALSE));
592 memcpy (GST_BUFFER_DATA (inbuf), GST_BUFFER_DATA (frame->sink_buffer),
593 GST_BUFFER_SIZE (frame->sink_buffer));
594 goto have_inbuf;
595 }
597 outbuf = GST_BUFFER (gst_drm_buffer_pool_get (self->output_pool, FALSE));
598 priv_out = get_buffer_priv (self, outbuf, state->width, state->height);
600 self->inBufs->planeDesc[0].buf = (XDAS_Int8 *) omap_bo_handle (priv_in->bo);
601 self->inBufs->planeDesc[0].memType = XDM_MEMTYPE_BO;
602 self->inBufs->planeDesc[0].bufSize.tileMem.width = state->width;
603 self->inBufs->planeDesc[0].bufSize.tileMem.height = state->height;
604 self->inBufs->planeDesc[1].buf = (XDAS_Int8 *) priv_in->uv_offset;
605 self->inBufs->planeDesc[1].memType = XDM_MEMTYPE_BO_OFFSET;
606 self->inBufs->planeDesc[1].bufSize.tileMem.width = state->width;
607 self->inBufs->planeDesc[1].bufSize.tileMem.height = state->height / 2;
608 /* setting imageRegion doesn't seem to be strictly needed if activeFrameRegion
609 * is set but we set it anyway...
610 */
611 self->inBufs->imageRegion.topLeft.x = self->rect.x;
612 self->inBufs->imageRegion.topLeft.y = self->rect.y;
613 self->inBufs->imageRegion.bottomRight.x = self->rect.x + self->rect.w;
614 self->inBufs->imageRegion.bottomRight.y = self->rect.y + self->rect.h;
615 self->inBufs->activeFrameRegion.topLeft.x = self->rect.x;
616 self->inBufs->activeFrameRegion.topLeft.y = self->rect.y;
617 self->inBufs->activeFrameRegion.bottomRight.x = self->rect.x + self->rect.w;
618 self->inBufs->activeFrameRegion.bottomRight.y = self->rect.y + self->rect.h;
619 self->inBufs->imagePitch[0] = state->width;
620 self->inBufs->imagePitch[1] = state->width;
621 self->inBufs->topFieldFirstFlag = TRUE;
623 self->outBufs->numBufs = 1;
624 self->outBufs->descs[0].buf = (XDAS_Int8 *) omap_bo_handle (priv_out->bo);
625 self->outBufs->descs[0].bufSize.bytes = GST_BUFFER_SIZE (outbuf);
626 self->outBufs->descs[0].memType = XDM_MEMTYPE_BO;
629 self->inArgs->inputID = GPOINTER_TO_INT (inbuf);
631 err = VIDENC2_process (self->codec, self->inBufs, self->outBufs,
632 self->inArgs, self->outArgs);
633 if (err) {
634 GST_WARNING_OBJECT (self, "process failed: err=%d, extendedError=%08x",
635 err, self->outArgs->extendedError);
636 gst_ducati_log_extended_error_info (self->outArgs->extendedError);
638 err = VIDENC2_control (self->codec,
639 XDM_GETSTATUS, (IVIDENC2_DynamicParams *) self->dynParams,
640 self->status);
642 GST_WARNING_OBJECT (self, "XDM_GETSTATUS: err=%d, extendedError=%08x",
643 err, self->status->extendedError);
645 return GST_FLOW_ERROR;
646 }
648 if (!strcmp (GST_DUCATIVIDENC_GET_CLASS (self)->codec_name, "ivahd_h264enc")) {
649 if (self->outArgs->encodedFrameType == IVIDEO_IDR_FRAME)
650 frame->is_sync_point = TRUE;
651 } else {
652 if (self->outArgs->encodedFrameType == IVIDEO_I_FRAME)
653 frame->is_sync_point = TRUE;
654 }
655 frame->src_buffer = gst_buffer_new_and_alloc (self->outArgs->bytesGenerated);
656 memcpy (GST_BUFFER_DATA (frame->src_buffer),
657 GST_BUFFER_DATA (outbuf), self->outArgs->bytesGenerated);
659 gst_buffer_unref (outbuf);
661 for (i = 0; self->outArgs->freeBufID[i]; i++) {
662 GstBuffer *buf = (GstBuffer *) self->outArgs->freeBufID[i];
664 GST_LOG_OBJECT (self, "free buffer: %p", buf);
665 gst_buffer_unref (buf);
666 }
668 return gst_base_video_encoder_finish_frame (base_video_encoder, frame);
669 }
671 static gboolean
672 gst_ducati_videnc_event (GstBaseVideoEncoder * enc, GstEvent * event)
673 {
674 gboolean handled = FALSE;
675 GstDucatiVidEnc *self = GST_DUCATIVIDENC (enc);
677 switch (GST_EVENT_TYPE (event)) {
678 case GST_EVENT_CROP:
679 gst_event_parse_crop (event, &self->rect.y, &self->rect.x,
680 &self->rect.w, &self->rect.h);
681 GST_INFO_OBJECT (self, "got crop event top %d left %d %dx%d",
682 self->rect.x, self->rect.y, self->rect.w, self->rect.h);
683 handled = TRUE;
684 break;
685 default:
686 break;
687 }
689 return handled;
690 }
692 static GstDucatiBufferPriv *
693 get_buffer_priv (GstDucatiVidEnc * self, GstBuffer * buf,
694 gint stride, gint height)
695 {
696 GstDucatiBufferPriv *priv = gst_ducati_buffer_priv_get (buf);
697 if (!priv) {
698 GstVideoFormat format = GST_VIDEO_FORMAT_NV12;
699 GstDmaBuf *dmabuf = gst_buffer_get_dma_buf (buf);
701 /* if it isn't a dmabuf buffer that we can import, then there
702 * is nothing we can do with it:
703 */
704 if (!dmabuf) {
705 GST_DEBUG_OBJECT (self, "not importing non dmabuf buffer");
706 return NULL;
707 }
709 priv = gst_ducati_buffer_priv_new ();
710 priv->bo = omap_bo_from_dmabuf (self->device, gst_dma_buf_get_fd (dmabuf));
712 priv->uv_offset = gst_video_format_get_component_offset (format,
713 1, stride, height);
714 priv->size = gst_video_format_get_size (format, stride, height);
716 gst_ducati_buffer_priv_set (buf, priv);
717 }
718 return priv;
719 }