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);
63 static gboolean gst_ducati_videnc_set_format (GstVideoEncoder *
64 base_video_encoder, GstVideoCodecState * state);
65 static gboolean gst_ducati_videnc_start (GstVideoEncoder * base_video_encoder);
66 static gboolean gst_ducati_videnc_stop (GstVideoEncoder * base_video_encoder);
67 static GstFlowReturn gst_ducati_videnc_finish (GstVideoEncoder *
68 base_video_encoder);
69 static GstFlowReturn gst_ducati_videnc_handle_frame (GstVideoEncoder *
70 base_video_encoder, GstVideoCodecFrame * frame);
71 static gboolean gst_ducati_videnc_allocate_params_default (GstDucatiVidEnc *
72 self, gint params_sz, gint dynparams_sz, gint status_sz, gint inargs_sz,
73 gint outargs_sz);
74 static gboolean gst_ducati_videnc_is_sync_point_default (GstDucatiVidEnc * enc,
75 int type);
76 static gboolean gst_ducati_videnc_configure_default (GstDucatiVidEnc * self);
77 static gboolean gst_ducati_videnc_event (GstVideoEncoder * enc,
78 GstEvent * event);
81 #define gst_ducati_videnc_parent_class parent_class
82 G_DEFINE_TYPE (GstDucatiVidEnc, gst_ducati_videnc, GST_TYPE_VIDEO_ENCODER);
85 /* the values for the following enums are taken from the codec */
87 enum
88 {
89 GST_DUCATI_VIDENC_RATE_PRESET_LOW_DELAY = IVIDEO_LOW_DELAY, /**< CBR rate control for video conferencing. */
90 GST_DUCATI_VIDENC_RATE_PRESET_STORAGE = IVIDEO_STORAGE, /**< VBR rate control for local storage (DVD)
91 * recording.
92 */
93 GST_DUCATI_VIDENC_RATE_PRESET_TWOPASS = IVIDEO_TWOPASS, /**< Two pass rate control for non real time
94 * applications.
95 */
96 GST_DUCATI_VIDENC_RATE_PRESET_NONE = IVIDEO_NONE, /**< No configurable video rate control
97 * mechanism.
98 */
99 GST_DUCATI_VIDENC_RATE_PRESET_USER_DEFINED = IVIDEO_USER_DEFINED,/**< User defined configuration using extended
100 * parameters.
101 */
102 };
104 static GType
105 gst_ducati_videnc_rate_preset_get_type (void)
106 {
107 static GType type = 0;
109 if (!type) {
110 static const GEnumValue vals[] = {
111 {GST_DUCATI_VIDENC_RATE_PRESET_LOW_DELAY, "Low Delay", "low-delay"},
112 {GST_DUCATI_VIDENC_RATE_PRESET_STORAGE, "Storage", "storage"},
113 {GST_DUCATI_VIDENC_RATE_PRESET_TWOPASS, "Two-Pass", "two-pass"},
114 {GST_DUCATI_VIDENC_RATE_PRESET_NONE, "None", "none"},
115 {GST_DUCATI_VIDENC_RATE_PRESET_USER_DEFINED, "User defined",
116 "user-defined"},
117 {0, NULL, NULL},
118 };
120 type = g_enum_register_static ("GstDucatiVidEncRatePreset", vals);
121 }
123 return type;
124 }
127 static void
128 gst_ducati_videnc_class_init (GstDucatiVidEncClass * klass)
129 {
130 GObjectClass *gobject_class;
131 GstVideoEncoderClass *basevideoencoder_class;
133 gobject_class = G_OBJECT_CLASS (klass);
134 basevideoencoder_class = GST_VIDEO_ENCODER_CLASS (klass);
135 parent_class = g_type_class_peek_parent (klass);
137 gobject_class->set_property = gst_ducati_videnc_set_property;
138 gobject_class->get_property = gst_ducati_videnc_get_property;
140 basevideoencoder_class->set_format =
141 GST_DEBUG_FUNCPTR (gst_ducati_videnc_set_format);
142 basevideoencoder_class->start = GST_DEBUG_FUNCPTR (gst_ducati_videnc_start);
143 basevideoencoder_class->stop = GST_DEBUG_FUNCPTR (gst_ducati_videnc_stop);
144 basevideoencoder_class->finish = GST_DEBUG_FUNCPTR (gst_ducati_videnc_finish);
145 basevideoencoder_class->handle_frame =
146 GST_DEBUG_FUNCPTR (gst_ducati_videnc_handle_frame);
148 basevideoencoder_class->src_event =
149 GST_DEBUG_FUNCPTR (gst_ducati_videnc_event);
151 klass->allocate_params = gst_ducati_videnc_allocate_params_default;
152 klass->configure = gst_ducati_videnc_configure_default;
153 klass->is_sync_point = gst_ducati_videnc_is_sync_point_default;
155 g_object_class_install_property (gobject_class, PROP_BITRATE,
156 g_param_spec_int ("bitrate", "Bitrate", "Bitrate in kbit/sec", -1,
157 100 * 1024, DEFAULT_BITRATE, G_PARAM_READWRITE));
159 g_object_class_install_property (gobject_class, PROP_RATE_PRESET,
160 g_param_spec_enum ("rate-preset", "H.264 Rate Control",
161 "H.264 Rate Control",
162 GST_TYPE_DUCATI_VIDENC_RATE_PRESET, DEFAULT_RATE_PRESET,
163 G_PARAM_READWRITE));
165 g_object_class_install_property (gobject_class, PROP_INTRA_INTERVAL,
166 g_param_spec_int ("intra-interval", "Intra-frame interval",
167 "Interval between intra frames (keyframes)", 0, INT_MAX,
168 DEFAULT_INTRA_INTERVAL, G_PARAM_READWRITE));
170 GST_DEBUG_CATEGORY_GET (GST_CAT_PERFORMANCE, "GST_PERFORMANCE");
172 }
174 static void
175 gst_ducati_videnc_init (GstDucatiVidEnc * self)
176 {
177 GST_DEBUG ("gst_ducati_videnc_init");
179 gst_ducati_set_generic_error_strings (self->error_strings);
181 self->device = NULL;
182 self->engine = NULL;
183 self->codec = NULL;
184 self->params = NULL;
185 self->status = NULL;
186 self->inBufs = NULL;
187 self->outBufs = NULL;
188 self->inArgs = NULL;
189 self->outArgs = NULL;
190 self->input_pool = NULL;
191 self->output_pool = NULL;
193 self->bitrate = DEFAULT_BITRATE * 1000;
194 self->rate_preset = DEFAULT_RATE_PRESET;
195 self->intra_interval = DEFAULT_INTRA_INTERVAL;
196 }
198 static gboolean
199 gst_ducati_videnc_set_format (GstVideoEncoder * base_video_encoder,
200 GstVideoCodecState * state)
201 {
202 GstDucatiVidEnc *self = GST_DUCATIVIDENC (base_video_encoder);
203 GstVideoCodecState *output_state;
204 GstCaps *allowed_caps = NULL;
207 GST_DEBUG_OBJECT (self, "picking an output format ...");
208 allowed_caps =
209 gst_pad_get_allowed_caps (GST_VIDEO_ENCODER_SRC_PAD (base_video_encoder));
210 if (!allowed_caps) {
211 GST_DEBUG_OBJECT (self, "... but no peer, using template caps");
212 allowed_caps =
213 gst_pad_get_pad_template_caps (GST_VIDEO_ENCODER_SRC_PAD
214 (base_video_encoder));
215 }
216 GST_DEBUG_OBJECT (self, "chose caps %" GST_PTR_FORMAT, allowed_caps);
217 allowed_caps = gst_caps_truncate (allowed_caps);
218 GST_DEBUG_OBJECT (self, "allowed caps %" GST_PTR_FORMAT, allowed_caps);
219 output_state = gst_video_encoder_set_output_state (GST_VIDEO_ENCODER (self),
220 allowed_caps, state);
221 gst_video_codec_state_unref (output_state);
224 if (!gst_video_encoder_negotiate (GST_VIDEO_ENCODER (self))) {
225 GST_DEBUG_OBJECT (self, "negotiate failed");
226 return FALSE;
227 }
230 if (self->input_state)
231 gst_video_codec_state_unref (self->input_state);
232 self->input_state = gst_video_codec_state_ref (state);
233 self->configure = TRUE;
235 return TRUE;
236 }
238 static void
239 gst_ducati_videnc_set_property (GObject * object, guint prop_id,
240 const GValue * value, GParamSpec * pspec)
241 {
242 GstDucatiVidEnc *self;
244 g_return_if_fail (GST_IS_DUCATIVIDENC (object));
245 self = GST_DUCATIVIDENC (object);
247 switch (prop_id) {
248 case PROP_BITRATE:
249 self->bitrate = g_value_get_int (value) * 1000;
250 break;
251 case PROP_RATE_PRESET:
252 self->rate_preset = g_value_get_enum (value);
253 break;
254 case PROP_INTRA_INTERVAL:
255 self->intra_interval = g_value_get_int (value);
256 break;
257 default:
258 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
259 }
260 }
262 static void
263 gst_ducati_videnc_get_property (GObject * object, guint prop_id,
264 GValue * value, GParamSpec * pspec)
265 {
266 GstDucatiVidEnc *self;
268 g_return_if_fail (GST_IS_DUCATIVIDENC (object));
269 self = GST_DUCATIVIDENC (object);
271 switch (prop_id) {
272 case PROP_BITRATE:
273 g_value_set_int (value, self->bitrate / 1000);
274 break;
275 case PROP_RATE_PRESET:
276 g_value_set_enum (value, self->rate_preset);
277 break;
278 case PROP_INTRA_INTERVAL:
279 g_value_set_int (value, self->intra_interval);
280 break;
281 default:
282 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
283 }
284 }
286 static gboolean
287 gst_ducati_videnc_configure (GstDucatiVidEnc * self)
288 {
289 int err;
290 int i;
291 int max_out_size = 0;
292 const GstVideoCodecState *state;
293 GstCaps *allowed_sink_caps = NULL;
294 GstCaps *allowed_src_caps = NULL;
295 state = self->input_state;
297 if (!GST_DUCATIVIDENC_GET_CLASS (self)->configure (self))
298 return FALSE;
300 if (self->codec == NULL) {
301 const gchar *codec_name;
303 codec_name = GST_DUCATIVIDENC_GET_CLASS (self)->codec_name;
304 self->codec = VIDENC2_create (self->engine,
305 (String) codec_name, self->params);
306 if (self->codec == NULL) {
307 GST_ERROR_OBJECT (self, "couldn't create codec");
308 return FALSE;
309 }
310 }
312 err = VIDENC2_control (self->codec,
313 XDM_SETPARAMS, self->dynParams, self->status);
314 if (err) {
315 GST_ERROR_OBJECT (self, "XDM_SETPARAMS err=%d, extendedError=%08x",
316 err, self->status->extendedError);
317 gst_ducati_log_extended_error_info (self->status->extendedError,
318 self->error_strings);
320 return FALSE;
321 }
323 err = VIDENC2_control (self->codec,
324 XDM_GETBUFINFO, self->dynParams, self->status);
325 if (err) {
326 GST_ERROR_OBJECT (self, "XDM_GETBUFINFO err=%d, extendedError=%08x",
327 err, self->status->extendedError);
329 return FALSE;
330 }
332 self->outBufs->numBufs = self->status->bufInfo.minNumOutBufs;
333 for (i = 0; i < self->outBufs->numBufs; i++) {
334 int size = self->status->bufInfo.minOutBufSize[i].bytes;
335 if (size > max_out_size)
336 max_out_size = size;
337 }
339 g_assert (self->input_pool == NULL);
341 allowed_sink_caps =
342 gst_pad_get_allowed_caps (GST_VIDEO_ENCODER_SINK_PAD (self));
343 if (!allowed_sink_caps) {
344 GST_DEBUG_OBJECT (self, "... but no peer, using template caps");
345 allowed_sink_caps =
346 gst_pad_get_pad_template_caps (GST_VIDEO_ENCODER_SINK_PAD (self));
347 }
348 GST_DEBUG_OBJECT (self, "chose caps %" GST_PTR_FORMAT, allowed_sink_caps);
349 allowed_sink_caps = gst_caps_truncate (allowed_sink_caps);
350 self->input_pool = gst_drm_buffer_pool_new (GST_ELEMENT (self),
351 dce_get_fd (), gst_caps_fixate (allowed_sink_caps),
352 GST_VIDEO_INFO_SIZE (&state->info));
354 g_assert (self->output_pool == NULL);
355 allowed_src_caps =
356 gst_pad_get_allowed_caps (GST_VIDEO_ENCODER_SRC_PAD (self));
357 if (!allowed_src_caps) {
358 GST_DEBUG_OBJECT (self, "... but no peer, using template caps");
359 allowed_src_caps =
360 gst_pad_get_pad_template_caps (GST_VIDEO_ENCODER_SRC_PAD (self));
361 }
362 GST_DEBUG_OBJECT (self, "chose caps %" GST_PTR_FORMAT, allowed_src_caps);
363 allowed_src_caps = gst_caps_truncate (allowed_src_caps);
364 self->output_pool = gst_drm_buffer_pool_new (GST_ELEMENT (self),
365 dce_get_fd (), gst_caps_fixate (allowed_src_caps), max_out_size);
367 GST_INFO_OBJECT (self, "configured");
369 self->configure = FALSE;
371 return TRUE;
372 }
374 static gboolean
375 gst_ducati_videnc_configure_default (GstDucatiVidEnc * self)
376 {
377 VIDENC2_DynamicParams *dynParams;
378 VIDENC2_Params *params;
379 const GstVideoCodecState *state;
380 int i;
382 state = self->input_state;
384 if (self->rect.w == 0)
385 self->rect.w = GST_VIDEO_INFO_WIDTH (&state->info);
387 if (self->rect.h == 0)
388 self->rect.h = GST_VIDEO_INFO_HEIGHT (&state->info);
390 params = (VIDENC2_Params *) self->params;
391 params->encodingPreset = 0x03;
392 params->rateControlPreset = self->rate_preset;
393 params->maxHeight = self->rect.h;
394 params->maxWidth = self->rect.w;
395 params->dataEndianness = XDM_BYTE;
396 params->maxInterFrameInterval = 1;
397 params->maxBitRate = -1;
398 params->minBitRate = 0;
399 params->inputChromaFormat = XDM_YUV_420SP;
400 params->inputContentType = IVIDEO_PROGRESSIVE;
401 params->operatingMode = IVIDEO_ENCODE_ONLY;
402 params->inputDataMode = IVIDEO_ENTIREFRAME;
403 params->outputDataMode = IVIDEO_ENTIREFRAME;
404 params->numInputDataUnits = 1;
405 params->numOutputDataUnits = 1;
406 for (i = 0; i < IVIDEO_MAX_NUM_METADATA_PLANES; i++) {
407 params->metadataType[i] = IVIDEO_METADATAPLANE_NONE;
408 }
410 dynParams = (VIDENC2_DynamicParams *) self->dynParams;
412 dynParams->refFrameRate =
413 gst_util_uint64_scale (1000, GST_VIDEO_INFO_FPS_N (&state->info),
414 GST_VIDEO_INFO_FPS_D (&state->info));
415 dynParams->targetFrameRate = dynParams->refFrameRate;
416 dynParams->inputWidth = self->rect.w;
417 dynParams->inputHeight = self->rect.h;
418 dynParams->targetBitRate = self->bitrate;
419 dynParams->intraFrameInterval = self->intra_interval;
420 dynParams->captureWidth = dynParams->inputWidth;
422 dynParams->forceFrame = IVIDEO_NA_FRAME;
423 dynParams->interFrameInterval = 1;
424 dynParams->mvAccuracy = IVIDENC2_MOTIONVECTOR_QUARTERPEL;
425 dynParams->sampleAspectRatioHeight = 1;
426 dynParams->sampleAspectRatioWidth = 1;
427 dynParams->generateHeader = XDM_ENCODE_AU;
428 dynParams->ignoreOutbufSizeFlag = 1;
429 dynParams->lateAcquireArg = -1;
431 self->inBufs->chromaFormat = XDM_YUV_420SP;
432 self->inBufs->numPlanes = 2;
434 return TRUE;
435 }
437 static gboolean
438 gst_ducati_videnc_open_engine (GstDucatiVidEnc * self)
439 {
440 int error_code;
442 if (self->device == NULL) {
443 self->device = dce_init ();
444 if (self->device == NULL)
445 return FALSE;
446 }
448 self->engine = Engine_open ((String) "ivahd_vidsvr", NULL, &error_code);
449 if (self->engine == NULL) {
450 GST_ERROR_OBJECT (self, "couldn't open engine");
451 return FALSE;
452 }
454 return TRUE;
455 }
457 static gboolean
458 gst_ducati_videnc_allocate_params (GstDucatiVidEnc * self)
459 {
460 return GST_DUCATIVIDENC_GET_CLASS (self)->allocate_params (self,
461 sizeof (IVIDENC2_Params), sizeof (IVIDENC2_DynamicParams),
462 sizeof (IVIDENC2_Status), sizeof (IVIDENC2_InArgs),
463 sizeof (IVIDENC2_OutArgs));
464 }
466 static gboolean
467 gst_ducati_videnc_allocate_params_default (GstDucatiVidEnc * self,
468 gint params_sz, gint dynparams_sz, gint status_sz, gint inargs_sz,
469 gint outargs_sz)
470 {
471 self->params = dce_alloc (params_sz);
472 memset (self->params, 0, params_sz);
473 self->params->size = params_sz;
475 self->dynParams = dce_alloc (dynparams_sz);
476 memset (self->dynParams, 0, dynparams_sz);
477 self->dynParams->size = dynparams_sz;
479 self->status = dce_alloc (status_sz);
480 memset (self->status, 0, status_sz);
481 self->status->size = status_sz;
483 self->inBufs = dce_alloc (sizeof (IVIDEO2_BufDesc));
484 memset (self->inBufs, 0, sizeof (IVIDEO2_BufDesc));
486 self->outBufs = dce_alloc (sizeof (XDM2_BufDesc));
487 memset (self->outBufs, 0, sizeof (XDM2_BufDesc));
489 self->inArgs = dce_alloc (inargs_sz);
490 memset (self->inArgs, 0, inargs_sz);
491 self->inArgs->size = inargs_sz;
493 self->outArgs = dce_alloc (outargs_sz);
494 memset (self->outArgs, 0, outargs_sz);
495 self->outArgs->size = outargs_sz;
497 GST_INFO_OBJECT (self, "started");
499 return TRUE;
500 }
502 static gboolean
503 gst_ducati_videnc_free_params (GstDucatiVidEnc * self)
504 {
505 if (self->params) {
506 dce_free (self->params);
507 self->params = NULL;
508 }
510 if (self->dynParams) {
511 dce_free (self->dynParams);
512 self->dynParams = NULL;
513 }
515 if (self->inArgs) {
516 dce_free (self->inArgs);
517 self->inArgs = NULL;
518 }
520 if (self->outArgs) {
521 dce_free (self->outArgs);
522 self->outArgs = NULL;
523 }
525 if (self->status) {
526 dce_free (self->status);
527 self->status = NULL;
528 }
530 if (self->inBufs) {
531 dce_free (self->inBufs);
532 self->inBufs = NULL;
533 }
535 if (self->outBufs) {
536 dce_free (self->outBufs);
537 self->outBufs = NULL;
538 }
540 if (self->codec) {
541 VIDENC2_delete (self->codec);
542 self->codec = NULL;
543 }
545 return TRUE;
546 }
548 static void
549 gst_ducati_videnc_close_engine (GstDucatiVidEnc * self)
550 {
551 if (self->engine) {
552 Engine_close (self->engine);
553 self->engine = NULL;
554 }
556 if (self->device) {
557 dce_deinit (self->device);
558 self->device = NULL;
559 }
560 }
563 static gboolean
564 gst_ducati_videnc_start (GstVideoEncoder * base_video_encoder)
565 {
566 GstDucatiVidEnc *self = GST_DUCATIVIDENC (base_video_encoder);
568 self->configure = TRUE;
569 memset (&self->rect, 0, sizeof (GstDucatiVideoRectangle));
571 if (!gst_ducati_videnc_open_engine (self))
572 goto fail;
574 if (!gst_ducati_videnc_allocate_params (self))
575 goto fail;
577 return TRUE;
579 fail:
580 gst_ducati_videnc_free_params (self);
581 gst_ducati_videnc_close_engine (self);
582 return FALSE;
583 }
585 static gboolean
586 gst_ducati_videnc_stop (GstVideoEncoder * base_video_encoder)
587 {
588 GstDucatiVidEnc *self = GST_DUCATIVIDENC (base_video_encoder);
590 gst_ducati_videnc_free_params (self);
591 gst_ducati_videnc_close_engine (self);
593 if (self->input_pool) {
594 gst_drm_buffer_pool_destroy (self->input_pool);
595 self->input_pool = NULL;
596 }
598 if (self->output_pool) {
599 gst_drm_buffer_pool_destroy (self->output_pool);
600 self->output_pool = NULL;
601 }
603 /* reset cropping rect */
604 memset (&self->rect, 0, sizeof (GstDucatiVideoRectangle));
606 return TRUE;
607 }
609 static GstFlowReturn
610 gst_ducati_videnc_finish (GstVideoEncoder * base_video_encoder)
611 {
612 GstDucatiVidEnc *self = GST_DUCATIVIDENC (base_video_encoder);
614 GST_DEBUG_OBJECT (self, "finish");
616 return GST_FLOW_OK;
617 }
619 static int
620 gst_ducati_videnc_buffer_lock (GstDucatiVidEnc * self, GstBuffer * buf)
621 {
622 int fd;
623 GstMetaDmaBuf *dmabuf = gst_buffer_get_dma_buf_meta (buf);
624 if (!dmabuf) {
625 GST_ERROR_OBJECT (self, "invalid dmabuf for buf = %p", buf);
626 return -1;
627 }
628 fd = gst_dma_buf_meta_get_fd (dmabuf);
629 if (fd < 0) {
630 GST_ERROR_OBJECT (self, "Invalid dma buf fd %d", fd);
631 return -1;
632 }
633 dce_buf_lock (1, (size_t *) & fd);
634 return fd;
635 }
637 static void
638 gst_ducati_videnc_buffer_unlock (GstDucatiVidEnc * self, GstBuffer * buf)
639 {
640 int fd;
641 GstMetaDmaBuf *dmabuf = gst_buffer_get_dma_buf_meta (buf);
642 if (!dmabuf) {
643 GST_ERROR_OBJECT (self, "invalid dmabuf for buf = %p", buf);
644 return;
645 }
646 fd = gst_dma_buf_meta_get_fd (dmabuf);
647 if (fd < 0) {
648 GST_ERROR_OBJECT (self, "Invalid dma buf fd %d", fd);
649 return;
650 }
651 dce_buf_unlock (1, (size_t *) & fd);
652 }
654 static GstFlowReturn
655 gst_ducati_videnc_handle_frame (GstVideoEncoder * base_video_encoder,
656 GstVideoCodecFrame * frame)
657 {
658 GstDucatiVidEnc *self = GST_DUCATIVIDENC (base_video_encoder);
659 GstBuffer *inbuf, *outbuf;
660 GstBuffer *output_buffer;
661 int dmabuf_fd_in, dmabuf_fd_out;
662 XDAS_Int32 err;
663 const GstVideoCodecState *state;
664 int i;
665 GstClockTime ts;
666 GstClockTime t;
667 GstVideoCropMeta *crop;
669 state = self->input_state;
671 if (G_UNLIKELY (self->configure)) {
672 if (!gst_ducati_videnc_configure (self)) {
673 GST_DEBUG_OBJECT (self, "configure failed");
674 GST_ELEMENT_ERROR (self, STREAM, ENCODE, (NULL), (NULL));
676 return GST_FLOW_ERROR;
677 }
678 }
680 inbuf = gst_buffer_ref (frame->input_buffer);
681 ts = GST_BUFFER_PTS (inbuf);
682 have_inbuf:
683 dmabuf_fd_in = gst_ducati_videnc_buffer_lock (self, inbuf);
684 if (dmabuf_fd_in < 0) {
685 gsize offset, maxsize, totalsize;
686 guint8 *codecdata = NULL;
687 gsize codecdatasize;
689 GST_DEBUG_OBJECT (self, "memcpying input");
690 gst_buffer_unref (inbuf);
691 inbuf = GST_BUFFER (gst_drm_buffer_pool_get (self->input_pool, FALSE));
692 gst_buffer_pool_set_active (GST_BUFFER_POOL (self->input_pool), TRUE);
694 totalsize = gst_buffer_get_sizes (frame->input_buffer, &offset, &maxsize);
695 codecdata = g_slice_alloc (totalsize);
696 codecdatasize =
697 gst_buffer_extract (frame->input_buffer, offset, codecdata, totalsize);
698 gst_buffer_fill (inbuf, offset, codecdata, codecdatasize);
699 g_free (codecdata);
700 GST_BUFFER_PTS (inbuf) = ts;
701 goto have_inbuf;
702 }
704 outbuf = GST_BUFFER (gst_drm_buffer_pool_get (self->output_pool, FALSE));
705 gst_buffer_pool_set_active (GST_BUFFER_POOL (self->output_pool), TRUE);
706 crop = gst_buffer_get_video_crop_meta (outbuf);
707 crop->width = GST_VIDEO_INFO_WIDTH (&state->info);
708 crop->height = GST_VIDEO_INFO_HEIGHT (&state->info);
709 dmabuf_fd_out = gst_ducati_videnc_buffer_lock (self, outbuf);
711 self->inBufs->planeDesc[0].buf = (XDAS_Int8 *) dmabuf_fd_in;
712 self->inBufs->planeDesc[0].memType = XDM_MEMTYPE_RAW;
713 self->inBufs->planeDesc[0].bufSize.tileMem.width =
714 GST_VIDEO_INFO_WIDTH (&state->info);
715 self->inBufs->planeDesc[0].bufSize.tileMem.height =
716 GST_VIDEO_INFO_HEIGHT (&state->info);
717 self->inBufs->planeDesc[0].bufSize.bytes =
718 GST_VIDEO_INFO_WIDTH (&state->info) *
719 GST_VIDEO_INFO_HEIGHT (&state->info);
720 self->inBufs->planeDesc[1].buf = (XDAS_Int8 *) dmabuf_fd_in;
721 self->inBufs->planeDesc[1].memType = XDM_MEMTYPE_RAW;
722 self->inBufs->planeDesc[1].bufSize.tileMem.width =
723 GST_VIDEO_INFO_WIDTH (&state->info);
724 self->inBufs->planeDesc[1].bufSize.tileMem.height =
725 GST_VIDEO_INFO_HEIGHT (&state->info) / 2;
726 self->inBufs->planeDesc[1].bufSize.bytes =
727 GST_VIDEO_INFO_WIDTH (&state->info) *
728 GST_VIDEO_INFO_HEIGHT (&state->info) / 2;
729 /* setting imageRegion doesn't seem to be strictly needed if activeFrameRegion
730 * is set but we set it anyway...
731 */
732 self->inBufs->imageRegion.topLeft.x = self->rect.x;
733 self->inBufs->imageRegion.topLeft.y = self->rect.y;
734 self->inBufs->imageRegion.bottomRight.x = self->rect.x + self->rect.w;
735 self->inBufs->imageRegion.bottomRight.y = self->rect.y + self->rect.h;
736 self->inBufs->activeFrameRegion.topLeft.x = self->rect.x;
737 self->inBufs->activeFrameRegion.topLeft.y = self->rect.y;
738 self->inBufs->activeFrameRegion.bottomRight.x = self->rect.x + self->rect.w;
739 self->inBufs->activeFrameRegion.bottomRight.y = self->rect.y + self->rect.h;
740 self->inBufs->imagePitch[0] = GST_VIDEO_INFO_WIDTH (&state->info);
741 self->inBufs->imagePitch[1] = GST_VIDEO_INFO_WIDTH (&state->info);
742 self->inBufs->topFieldFirstFlag = TRUE;
744 self->outBufs->numBufs = 1;
745 self->outBufs->descs[0].buf = (XDAS_Int8 *) dmabuf_fd_out;
746 self->outBufs->descs[0].bufSize.bytes = self->output_pool->size;
747 self->outBufs->descs[0].memType = XDM_MEMTYPE_RAW;
749 self->inArgs->inputID = GPOINTER_TO_INT (inbuf);
751 GST_DEBUG ("Calling VIDENC2_process");
752 t = gst_util_get_timestamp ();
753 err = VIDENC2_process (self->codec, self->inBufs, self->outBufs,
754 self->inArgs, self->outArgs);
755 t = gst_util_get_timestamp () - t;
756 GST_DEBUG_OBJECT (self, "VIDENC2_process took %10dns (%d ms)", (gint) t,
757 (gint) (t / 1000000));
758 gst_ducati_videnc_buffer_unlock (self, outbuf);
759 if (err) {
760 GST_WARNING_OBJECT (self, "process failed: err=%d, extendedError=%08x",
761 err, self->outArgs->extendedError);
762 gst_ducati_log_extended_error_info (self->outArgs->extendedError,
763 self->error_strings);
765 err = VIDENC2_control (self->codec,
766 XDM_GETSTATUS, (IVIDENC2_DynamicParams *) self->dynParams,
767 self->status);
769 GST_WARNING_OBJECT (self, "XDM_GETSTATUS: err=%d, extendedError=%08x",
770 err, self->status->extendedError);
772 return GST_FLOW_ERROR;
773 }
775 if (self->outArgs->bytesGenerated > 0) {
776 gsize offset, maxsize, totalsize;
777 guint8 *codecdata = NULL;
778 gsize codecdatasize;
779 if (GST_DUCATIVIDENC_GET_CLASS (self)->is_sync_point (self,
780 self->outArgs->encodedFrameType)) {
781 GST_VIDEO_CODEC_FRAME_SET_SYNC_POINT (frame);
782 }
783 if (frame->output_buffer) {
784 gst_buffer_unref (frame->output_buffer);
785 }
788 totalsize = gst_buffer_get_sizes (outbuf, &offset, &maxsize);
789 codecdata = g_slice_alloc0 (self->outArgs->bytesGenerated);
790 codecdatasize =
791 gst_buffer_extract (outbuf, offset, codecdata,
792 self->outArgs->bytesGenerated);
794 frame->output_buffer =
795 gst_video_encoder_allocate_output_buffer (GST_VIDEO_ENCODER (self),
796 self->outArgs->bytesGenerated);
798 gst_buffer_fill (frame->output_buffer, offset, codecdata, codecdatasize);
799 g_free (codecdata);
801 GST_CAT_DEBUG_OBJECT (GST_CAT_PERFORMANCE, self,
802 "Encoded frame in %u bytes", self->outArgs->bytesGenerated);
804 /* As we can get frames in a different order we sent them (if the codec
805 supports B frames and we set it up for generating those), we need to
806 work out what input frame corresponds to the frame we just got, to
807 keep presentation times correct.
808 It seems that the codec will free buffers in the right order for this,
809 but I can not find anything saying this in the docs, so:
810 - it might be subject to change
811 - it might not be true in all setups
812 - it might not be true for all codecs
813 However, that's the only way I can see to do it. So there's a nice
814 assert below that will blow up if the codec does not free exactly one
815 input frame when it outputs a frame. That doesn't catch all cases,
816 such as when it frees them in the wrong order, but that seems less
817 likely to happen.
818 The timestamp and duration are given to the base class, which will
819 in turn set them onto the encoded buffer. */
820 g_assert (self->outArgs->freeBufID[0] && !self->outArgs->freeBufID[1]);
821 inbuf = GST_BUFFER (self->outArgs->freeBufID[0]);
822 frame->pts = GST_BUFFER_PTS (inbuf);
823 frame->duration = GST_BUFFER_DURATION (inbuf);
824 GST_BUFFER_OFFSET_END (frame->output_buffer) = GST_BUFFER_PTS (inbuf);
825 }
827 gst_buffer_unref (outbuf);
829 for (i = 0; self->outArgs->freeBufID[i]; i++) {
830 GstBuffer *buf = (GstBuffer *) self->outArgs->freeBufID[i];
832 GST_LOG_OBJECT (self, "free buffer: %p", buf);
833 gst_ducati_videnc_buffer_unlock (self, buf);
834 gst_buffer_unref (buf);
835 }
837 return gst_video_encoder_finish_frame (base_video_encoder, frame);
838 }
840 static gboolean
841 gst_ducati_videnc_is_sync_point_default (GstDucatiVidEnc * enc, int type)
842 {
843 return type == IVIDEO_I_FRAME;
844 }
846 static gboolean
847 gst_ducati_videnc_event (GstVideoEncoder * enc, GstEvent * event)
848 {
849 gboolean handled = FALSE;
850 GstDucatiVidEnc *self = GST_DUCATIVIDENC (enc);
852 switch (GST_EVENT_TYPE (event)) {
853 default:
854 break;
855 }
857 return handled;
858 }