mpeg2dec: Fix negotiation issue with playbin
[glsdk/gst-plugin-ducati.git] / src / gstducatividenc.c
1 /* GStreamer
2  * Copyright (c) 2011, Texas Instruments Incorporated
3  * Copyright (c) 2011, Collabora Ltd.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  *
20  * Author: Alessandro Decina <alessandro.decina@collabora.com>
21  */
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
27 #include "gstducati.h"
28 #include "gstducatividenc.h"
29 #include "gstducatibufferpriv.h"
31 #include <string.h>
33 #include <math.h>
35 #define GST_CAT_DEFAULT gst_ducati_debug
36 GST_DEBUG_CATEGORY_STATIC (GST_CAT_PERFORMANCE);
38 #define DEFAULT_BITRATE 2048
39 #define DEFAULT_RATE_PRESET GST_DUCATI_VIDENC_RATE_PRESET_STORAGE
40 #define DEFAULT_INTRA_INTERVAL 16
42 #define GST_TYPE_DUCATI_VIDENC_RATE_PRESET (gst_ducati_videnc_rate_preset_get_type ())
45 enum
46 {
47   LAST_SIGNAL
48 };
50 enum
51 {
52   PROP_0,
53   PROP_BITRATE,
54   PROP_RATE_PRESET,
55   PROP_INTRA_INTERVAL
56 };
58 static void gst_ducati_videnc_set_property (GObject * object, guint prop_id,
59     const GValue * value, GParamSpec * pspec);
60 static void gst_ducati_videnc_get_property (GObject * object, guint prop_id,
61     GValue * value, GParamSpec * pspec);
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);
79 static gboolean
80 gst_ducati_videnc_propose_allocation (GstVideoEncoder * encoder,
81     GstQuery * query);
82 static GstBufferPool *gst_drm_buffer_pool_new (GstCaps * caps, guint size);
84 #define gst_ducati_videnc_parent_class parent_class
85 G_DEFINE_TYPE (GstDucatiVidEnc, gst_ducati_videnc, GST_TYPE_VIDEO_ENCODER);
87 /* the values for the following enums are taken from the codec */
89 enum
90 {
91   GST_DUCATI_VIDENC_RATE_PRESET_LOW_DELAY = IVIDEO_LOW_DELAY,   /**< CBR rate control for video conferencing. */
92   GST_DUCATI_VIDENC_RATE_PRESET_STORAGE = IVIDEO_STORAGE,  /**< VBR rate control for local storage (DVD)
93                            *   recording.
94                            */
95   GST_DUCATI_VIDENC_RATE_PRESET_TWOPASS = IVIDEO_TWOPASS,  /**< Two pass rate control for non real time
96                            *   applications.
97                            */
98   GST_DUCATI_VIDENC_RATE_PRESET_NONE = IVIDEO_NONE,        /**< No configurable video rate control
99                             *  mechanism.
100                             */
101   GST_DUCATI_VIDENC_RATE_PRESET_USER_DEFINED = IVIDEO_USER_DEFINED,/**< User defined configuration using extended
102                            *   parameters.
103                            */
104 };
106 static GType
107 gst_ducati_videnc_rate_preset_get_type (void)
109   static GType type = 0;
111   if (!type) {
112     static const GEnumValue vals[] = {
113       {GST_DUCATI_VIDENC_RATE_PRESET_LOW_DELAY, "Low Delay", "low-delay"},
114       {GST_DUCATI_VIDENC_RATE_PRESET_STORAGE, "Storage", "storage"},
115       {GST_DUCATI_VIDENC_RATE_PRESET_TWOPASS, "Two-Pass", "two-pass"},
116       {GST_DUCATI_VIDENC_RATE_PRESET_NONE, "None", "none"},
117       {GST_DUCATI_VIDENC_RATE_PRESET_USER_DEFINED, "User defined",
118           "user-defined"},
119       {0, NULL, NULL},
120     };
122     type = g_enum_register_static ("GstDucatiVidEncRatePreset", vals);
123   }
125   return type;
128 static GstBufferPool *
129 gst_drm_buffer_pool_new (GstCaps * caps, guint size)
131   GstAllocator *allocator;
132   GstStructure *conf;
133   GstBufferPool *ret_pool;
135   allocator = gst_drm_allocator_get ();
136   if (!allocator) {
137     GST_DEBUG
138         ("Failed to get a DRM bufferpool. Proceeding with default allocator");
139   }
140   ret_pool = gst_buffer_pool_new ();
141   conf = gst_buffer_pool_get_config (GST_BUFFER_POOL (ret_pool));
142   if (conf) {
143     gst_buffer_pool_config_set_params (conf, caps, size, 0, 0);
144     gst_buffer_pool_config_set_allocator (conf, allocator, NULL);
145     gst_buffer_pool_set_config (GST_BUFFER_POOL (ret_pool), conf);
146   }
148   if (allocator)
149     gst_object_unref (allocator);
151   return ret_pool;
154 static gboolean
155 gst_ducati_videnc_propose_allocation (GstVideoEncoder * encoder,
156     GstQuery * query)
158   GstDucatiVidEnc *self = GST_DUCATIVIDENC (encoder);
159   GstStructure *config;
160   guint size, min_bufs, max_bufs;
161   GstCaps *allowed_sink_caps;
162   GstVideoInfo info;
164   if (!self->input_pool) {
165     allowed_sink_caps =
166         gst_pad_get_allowed_caps (GST_VIDEO_ENCODER_SINK_PAD (self));
167     if (!allowed_sink_caps) {
168       GST_DEBUG_OBJECT (self, "... but no peer, using template caps");
169       allowed_sink_caps =
170           gst_pad_get_pad_template_caps (GST_VIDEO_ENCODER_SINK_PAD (self));
171     }
172     GST_DEBUG_OBJECT (self, "chose caps %" GST_PTR_FORMAT, allowed_sink_caps);
173     allowed_sink_caps = gst_caps_truncate (allowed_sink_caps);
174     gst_video_info_from_caps (&info, gst_caps_fixate (allowed_sink_caps));
175     self->input_pool =
176         gst_drm_buffer_pool_new (gst_caps_fixate (allowed_sink_caps),
177         info.size);
178   }
180   config = gst_buffer_pool_get_config (self->input_pool);
181   gst_buffer_pool_config_get_params (config, NULL, &size, &min_bufs, &max_bufs);
183   gst_query_add_allocation_pool (query, self->input_pool, size, min_bufs,
184       max_bufs);
185   gst_query_add_allocation_param (query, gst_drm_allocator_get (), NULL);
186   gst_structure_free (config);
188   return TRUE;
192 static void
193 gst_ducati_videnc_class_init (GstDucatiVidEncClass * klass)
195   GObjectClass *gobject_class;
196   GstVideoEncoderClass *basevideoencoder_class;
198   gobject_class = G_OBJECT_CLASS (klass);
199   basevideoencoder_class = GST_VIDEO_ENCODER_CLASS (klass);
200   parent_class = g_type_class_peek_parent (klass);
202   gobject_class->set_property = gst_ducati_videnc_set_property;
203   gobject_class->get_property = gst_ducati_videnc_get_property;
205   basevideoencoder_class->set_format =
206       GST_DEBUG_FUNCPTR (gst_ducati_videnc_set_format);
207   basevideoencoder_class->start = GST_DEBUG_FUNCPTR (gst_ducati_videnc_start);
208   basevideoencoder_class->stop = GST_DEBUG_FUNCPTR (gst_ducati_videnc_stop);
209   basevideoencoder_class->finish = GST_DEBUG_FUNCPTR (gst_ducati_videnc_finish);
210   basevideoencoder_class->handle_frame =
211       GST_DEBUG_FUNCPTR (gst_ducati_videnc_handle_frame);
213   basevideoencoder_class->src_event =
214       GST_DEBUG_FUNCPTR (gst_ducati_videnc_event);
216   basevideoencoder_class->propose_allocation =
217       GST_DEBUG_FUNCPTR (gst_ducati_videnc_propose_allocation);
219   klass->allocate_params = gst_ducati_videnc_allocate_params_default;
220   klass->configure = gst_ducati_videnc_configure_default;
221   klass->is_sync_point = gst_ducati_videnc_is_sync_point_default;
223   g_object_class_install_property (gobject_class, PROP_BITRATE,
224       g_param_spec_int ("bitrate", "Bitrate", "Bitrate in kbit/sec", -1,
225           100 * 1024, DEFAULT_BITRATE, G_PARAM_READWRITE));
227   g_object_class_install_property (gobject_class, PROP_RATE_PRESET,
228       g_param_spec_enum ("rate-preset", "H.264 Rate Control",
229           "H.264 Rate Control",
230           GST_TYPE_DUCATI_VIDENC_RATE_PRESET, DEFAULT_RATE_PRESET,
231           G_PARAM_READWRITE));
233   g_object_class_install_property (gobject_class, PROP_INTRA_INTERVAL,
234       g_param_spec_int ("intra-interval", "Intra-frame interval",
235           "Interval between intra frames (keyframes)", 0, INT_MAX,
236           DEFAULT_INTRA_INTERVAL, G_PARAM_READWRITE));
238   GST_DEBUG_CATEGORY_GET (GST_CAT_PERFORMANCE, "GST_PERFORMANCE");
242 static void
243 gst_ducati_videnc_init (GstDucatiVidEnc * self)
245   GST_DEBUG ("gst_ducati_videnc_init");
247   gst_ducati_set_generic_error_strings (self->error_strings);
249   self->device = NULL;
250   self->engine = NULL;
251   self->codec = NULL;
252   self->params = NULL;
253   self->status = NULL;
254   self->inBufs = NULL;
255   self->outBufs = NULL;
256   self->inArgs = NULL;
257   self->outArgs = NULL;
258   self->input_pool = NULL;
259   self->output_pool = NULL;
261   self->bitrate = DEFAULT_BITRATE * 1000;
262   self->rate_preset = DEFAULT_RATE_PRESET;
263   self->intra_interval = DEFAULT_INTRA_INTERVAL;
266 static gboolean
267 gst_ducati_videnc_set_format (GstVideoEncoder * base_video_encoder,
268     GstVideoCodecState * state)
270   GstDucatiVidEnc *self = GST_DUCATIVIDENC (base_video_encoder);
271   GstVideoCodecState *output_state;
272   GstCaps *allowed_caps = NULL;
274   GST_DEBUG_OBJECT (self, "picking an output format ...");
275   allowed_caps =
276       gst_pad_get_allowed_caps (GST_VIDEO_ENCODER_SRC_PAD (base_video_encoder));
277   if (!allowed_caps) {
278     GST_DEBUG_OBJECT (self, "... but no peer, using template caps");
279     allowed_caps =
280         gst_pad_get_pad_template_caps (GST_VIDEO_ENCODER_SRC_PAD
281         (base_video_encoder));
282   }
283   GST_DEBUG_OBJECT (self, "chose caps %" GST_PTR_FORMAT, allowed_caps);
284   allowed_caps = gst_caps_truncate (allowed_caps);
285   GST_DEBUG_OBJECT (self, "allowed caps %" GST_PTR_FORMAT, allowed_caps);
286   output_state = gst_video_encoder_set_output_state (GST_VIDEO_ENCODER (self),
287       allowed_caps, state);
288   gst_video_codec_state_unref (output_state);
291   if (!gst_video_encoder_negotiate (GST_VIDEO_ENCODER (self))) {
292     GST_DEBUG_OBJECT (self, "negotiate failed");
293     return FALSE;
294   }
297   if (self->input_state)
298     gst_video_codec_state_unref (self->input_state);
299   self->input_state = gst_video_codec_state_ref (state);
300   self->configure = TRUE;
302   return TRUE;
305 static void
306 gst_ducati_videnc_set_property (GObject * object, guint prop_id,
307     const GValue * value, GParamSpec * pspec)
309   GstDucatiVidEnc *self;
311   g_return_if_fail (GST_IS_DUCATIVIDENC (object));
312   self = GST_DUCATIVIDENC (object);
314   switch (prop_id) {
315     case PROP_BITRATE:
316       self->bitrate = g_value_get_int (value) * 1000;
317       break;
318     case PROP_RATE_PRESET:
319       self->rate_preset = g_value_get_enum (value);
320       break;
321     case PROP_INTRA_INTERVAL:
322       self->intra_interval = g_value_get_int (value);
323       break;
324     default:
325       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
326   }
329 static void
330 gst_ducati_videnc_get_property (GObject * object, guint prop_id,
331     GValue * value, GParamSpec * pspec)
333   GstDucatiVidEnc *self;
335   g_return_if_fail (GST_IS_DUCATIVIDENC (object));
336   self = GST_DUCATIVIDENC (object);
338   switch (prop_id) {
339     case PROP_BITRATE:
340       g_value_set_int (value, self->bitrate / 1000);
341       break;
342     case PROP_RATE_PRESET:
343       g_value_set_enum (value, self->rate_preset);
344       break;
345     case PROP_INTRA_INTERVAL:
346       g_value_set_int (value, self->intra_interval);
347       break;
348     default:
349       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
350   }
353 static gboolean
354 gst_ducati_videnc_configure (GstDucatiVidEnc * self)
356   int err;
357   int i;
358   int max_out_size = 0;
359   const GstVideoCodecState *state;
360   GstCaps *allowed_sink_caps = NULL;
361   GstCaps *allowed_src_caps = NULL;
362   state = self->input_state;
364   if (!GST_DUCATIVIDENC_GET_CLASS (self)->configure (self))
365     return FALSE;
367   if (self->codec == NULL) {
368     const gchar *codec_name;
370     codec_name = GST_DUCATIVIDENC_GET_CLASS (self)->codec_name;
371     self->codec = VIDENC2_create (self->engine,
372         (String) codec_name, self->params);
373     if (self->codec == NULL) {
374       GST_ERROR_OBJECT (self, "couldn't create codec");
375       return FALSE;
376     }
377   }
379   err = VIDENC2_control (self->codec,
380       XDM_SETPARAMS, self->dynParams, self->status);
381   if (err) {
382     GST_ERROR_OBJECT (self, "XDM_SETPARAMS err=%d, extendedError=%08x",
383         err, self->status->extendedError);
384     gst_ducati_log_extended_error_info (self->status->extendedError,
385         self->error_strings);
387     return FALSE;
388   }
390   err = VIDENC2_control (self->codec,
391       XDM_GETBUFINFO, self->dynParams, self->status);
392   if (err) {
393     GST_ERROR_OBJECT (self, "XDM_GETBUFINFO err=%d, extendedError=%08x",
394         err, self->status->extendedError);
396     return FALSE;
397   }
399   self->outBufs->numBufs = self->status->bufInfo.minNumOutBufs;
400   for (i = 0; i < self->outBufs->numBufs; i++) {
401     int size = self->status->bufInfo.minOutBufSize[i].bytes;
402     if (size > max_out_size)
403       max_out_size = size;
404   }
406   if (!self->input_pool) {
407     GstVideoInfo info;
408     allowed_sink_caps =
409         gst_pad_get_allowed_caps (GST_VIDEO_ENCODER_SINK_PAD (self));
410     if (!allowed_sink_caps) {
411       GST_DEBUG_OBJECT (self, "... but no peer, using template caps");
412       allowed_sink_caps =
413           gst_pad_get_pad_template_caps (GST_VIDEO_ENCODER_SINK_PAD (self));
414     }
415     GST_DEBUG_OBJECT (self, "chose caps %" GST_PTR_FORMAT, allowed_sink_caps);
416     allowed_sink_caps = gst_caps_truncate (allowed_sink_caps);
417     gst_video_info_from_caps (&info, gst_caps_fixate (allowed_sink_caps));
418     self->input_pool =
419         gst_drm_buffer_pool_new (gst_caps_fixate (allowed_sink_caps),
420         info.size);
421   }
424   gst_buffer_pool_set_active (GST_BUFFER_POOL (self->input_pool), TRUE);
426   g_assert (self->output_pool == NULL);
427   allowed_src_caps =
428       gst_pad_get_allowed_caps (GST_VIDEO_ENCODER_SRC_PAD (self));
429   if (!allowed_src_caps) {
430     GST_DEBUG_OBJECT (self, "... but no peer, using template caps");
431     allowed_src_caps =
432         gst_pad_get_pad_template_caps (GST_VIDEO_ENCODER_SRC_PAD (self));
433   }
434   GST_DEBUG_OBJECT (self, "chose caps %" GST_PTR_FORMAT, allowed_src_caps);
435   allowed_src_caps = gst_caps_truncate (allowed_src_caps);
436   self->output_pool =
437       gst_drm_buffer_pool_new (gst_caps_fixate (allowed_src_caps),
438       max_out_size);
440   gst_buffer_pool_set_active (GST_BUFFER_POOL (self->output_pool), TRUE);
442   GST_INFO_OBJECT (self, "configured");
444   self->configure = FALSE;
446   return TRUE;
449 static gboolean
450 gst_ducati_videnc_configure_default (GstDucatiVidEnc * self)
452   VIDENC2_DynamicParams *dynParams;
453   VIDENC2_Params *params;
454   const GstVideoCodecState *state;
455   int i;
457   state = self->input_state;
459   if (self->rect.w == 0)
460     self->rect.w = GST_VIDEO_INFO_WIDTH (&state->info);
462   if (self->rect.h == 0)
463     self->rect.h = GST_VIDEO_INFO_HEIGHT (&state->info);
465   params = (VIDENC2_Params *) self->params;
466   params->encodingPreset = 0x03;
467   params->rateControlPreset = self->rate_preset;
468   params->maxHeight = self->rect.h;
469   params->maxWidth = self->rect.w;
470   params->dataEndianness = XDM_BYTE;
471   params->maxInterFrameInterval = 1;
472   params->maxBitRate = -1;
473   params->minBitRate = 0;
474   params->inputChromaFormat = XDM_YUV_420SP;
475   params->inputContentType = IVIDEO_PROGRESSIVE;
476   params->operatingMode = IVIDEO_ENCODE_ONLY;
477   params->inputDataMode = IVIDEO_ENTIREFRAME;
478   params->outputDataMode = IVIDEO_ENTIREFRAME;
479   params->numInputDataUnits = 1;
480   params->numOutputDataUnits = 1;
481   for (i = 0; i < IVIDEO_MAX_NUM_METADATA_PLANES; i++) {
482     params->metadataType[i] = IVIDEO_METADATAPLANE_NONE;
483   }
485   dynParams = (VIDENC2_DynamicParams *) self->dynParams;
487   dynParams->refFrameRate =
488       gst_util_uint64_scale (1000, GST_VIDEO_INFO_FPS_N (&state->info),
489       GST_VIDEO_INFO_FPS_D (&state->info));
490   dynParams->targetFrameRate = dynParams->refFrameRate;
491   dynParams->inputWidth = self->rect.w;
492   dynParams->inputHeight = self->rect.h;
493   dynParams->targetBitRate = self->bitrate;
494   dynParams->intraFrameInterval = self->intra_interval;
495   dynParams->captureWidth = dynParams->inputWidth;
497   dynParams->forceFrame = IVIDEO_NA_FRAME;
498   dynParams->interFrameInterval = 1;
499   dynParams->mvAccuracy = IVIDENC2_MOTIONVECTOR_QUARTERPEL;
500   dynParams->sampleAspectRatioHeight = 1;
501   dynParams->sampleAspectRatioWidth = 1;
502   dynParams->generateHeader = XDM_ENCODE_AU;
503   dynParams->ignoreOutbufSizeFlag = 1;
504   dynParams->lateAcquireArg = -1;
506   self->inBufs->chromaFormat = XDM_YUV_420SP;
507   self->inBufs->numPlanes = 2;
509   return TRUE;
512 static gboolean
513 gst_ducati_videnc_open_engine (GstDucatiVidEnc * self)
515   int error_code;
517   if (self->device == NULL) {
518     self->device = dce_init ();
519     if (self->device == NULL)
520       return FALSE;
521   }
523   self->engine = Engine_open ((String) "ivahd_vidsvr", NULL, &error_code);
524   if (self->engine == NULL) {
525     GST_ERROR_OBJECT (self, "couldn't open engine");
526     return FALSE;
527   }
529   return TRUE;
532 static gboolean
533 gst_ducati_videnc_allocate_params (GstDucatiVidEnc * self)
535   return GST_DUCATIVIDENC_GET_CLASS (self)->allocate_params (self,
536       sizeof (IVIDENC2_Params), sizeof (IVIDENC2_DynamicParams),
537       sizeof (IVIDENC2_Status), sizeof (IVIDENC2_InArgs),
538       sizeof (IVIDENC2_OutArgs));
541 static gboolean
542 gst_ducati_videnc_allocate_params_default (GstDucatiVidEnc * self,
543     gint params_sz, gint dynparams_sz, gint status_sz, gint inargs_sz,
544     gint outargs_sz)
546   self->params = dce_alloc (params_sz);
547   memset (self->params, 0, params_sz);
548   self->params->size = params_sz;
550   self->dynParams = dce_alloc (dynparams_sz);
551   memset (self->dynParams, 0, dynparams_sz);
552   self->dynParams->size = dynparams_sz;
554   self->status = dce_alloc (status_sz);
555   memset (self->status, 0, status_sz);
556   self->status->size = status_sz;
558   self->inBufs = dce_alloc (sizeof (IVIDEO2_BufDesc));
559   memset (self->inBufs, 0, sizeof (IVIDEO2_BufDesc));
561   self->outBufs = dce_alloc (sizeof (XDM2_BufDesc));
562   memset (self->outBufs, 0, sizeof (XDM2_BufDesc));
564   self->inArgs = dce_alloc (inargs_sz);
565   memset (self->inArgs, 0, inargs_sz);
566   self->inArgs->size = inargs_sz;
568   self->outArgs = dce_alloc (outargs_sz);
569   memset (self->outArgs, 0, outargs_sz);
570   self->outArgs->size = outargs_sz;
572   GST_INFO_OBJECT (self, "started");
574   return TRUE;
577 static gboolean
578 gst_ducati_videnc_free_params (GstDucatiVidEnc * self)
580   if (self->params) {
581     dce_free (self->params);
582     self->params = NULL;
583   }
585   if (self->dynParams) {
586     dce_free (self->dynParams);
587     self->dynParams = NULL;
588   }
590   if (self->inArgs) {
591     dce_free (self->inArgs);
592     self->inArgs = NULL;
593   }
595   if (self->outArgs) {
596     dce_free (self->outArgs);
597     self->outArgs = NULL;
598   }
600   if (self->status) {
601     dce_free (self->status);
602     self->status = NULL;
603   }
605   if (self->inBufs) {
606     dce_free (self->inBufs);
607     self->inBufs = NULL;
608   }
610   if (self->outBufs) {
611     dce_free (self->outBufs);
612     self->outBufs = NULL;
613   }
615   if (self->codec) {
616     VIDENC2_delete (self->codec);
617     self->codec = NULL;
618   }
620   return TRUE;
623 static void
624 gst_ducati_videnc_close_engine (GstDucatiVidEnc * self)
626   if (self->engine) {
627     Engine_close (self->engine);
628     self->engine = NULL;
629   }
631   if (self->device) {
632     dce_deinit (self->device);
633     self->device = NULL;
634   }
638 static gboolean
639 gst_ducati_videnc_start (GstVideoEncoder * base_video_encoder)
641   GstDucatiVidEnc *self = GST_DUCATIVIDENC (base_video_encoder);
643   self->configure = TRUE;
644   memset (&self->rect, 0, sizeof (GstDucatiVideoRectangle));
646   if (!gst_ducati_videnc_open_engine (self))
647     goto fail;
649   if (!gst_ducati_videnc_allocate_params (self))
650     goto fail;
652   return TRUE;
654 fail:
655   gst_ducati_videnc_free_params (self);
656   gst_ducati_videnc_close_engine (self);
657   return FALSE;
660 static gboolean
661 gst_ducati_videnc_stop (GstVideoEncoder * base_video_encoder)
663   GstDucatiVidEnc *self = GST_DUCATIVIDENC (base_video_encoder);
665   gst_ducati_videnc_free_params (self);
666   gst_ducati_videnc_close_engine (self);
668   if (self->input_pool) {
669     gst_object_unref (self->input_pool);
670     self->input_pool = NULL;
671   }
673   if (self->output_pool) {
674     gst_object_unref (self->output_pool);
675     self->output_pool = NULL;
676   }
678   /* reset cropping rect */
679   memset (&self->rect, 0, sizeof (GstDucatiVideoRectangle));
681   return TRUE;
684 static GstFlowReturn
685 gst_ducati_videnc_finish (GstVideoEncoder * base_video_encoder)
687   GstDucatiVidEnc *self = GST_DUCATIVIDENC (base_video_encoder);
689   GST_DEBUG_OBJECT (self, "finish");
691   return GST_FLOW_OK;
694 static int
695 gst_ducati_videnc_buffer_lock (GstDucatiVidEnc * self, GstBuffer * buf)
697   int fd;
698   GstMemory *mem;
699   mem = gst_buffer_peek_memory (buf, 0);
700   if (!gst_is_drm_memory (mem)) {
701     GST_LOG_OBJECT (self, "Not a dmabuf memory");
702     return -1;
703   }
705   fd = gst_fd_memory_get_fd (mem);
706   if (fd < 0) {
707     GST_ERROR_OBJECT (self, "Invalid dma buf fd %d", fd);
708     return -1;
709   }
710   dce_buf_lock (1, (size_t *) & fd);
711   return fd;
714 static void
715 gst_ducati_videnc_buffer_unlock (GstDucatiVidEnc * self, GstBuffer * buf)
717   int fd;
718   GstMemory *mem;
719   mem = gst_buffer_peek_memory (buf, 0);
720   if (!gst_is_drm_memory (mem)) {
721     GST_LOG_OBJECT (self, "Not a dmabuf memory");
722     return;
723   }
724   fd = gst_fd_memory_get_fd (mem);
725   if (fd < 0) {
726     GST_ERROR_OBJECT (self, "Invalid dma buf fd %d", fd);
727     return;
728   }
729   dce_buf_unlock (1, (size_t *) & fd);
732 static GstFlowReturn
733 gst_ducati_videnc_handle_frame (GstVideoEncoder * base_video_encoder,
734     GstVideoCodecFrame * frame)
736   GstDucatiVidEnc *self = GST_DUCATIVIDENC (base_video_encoder);
737   GstBuffer *inbuf, *outbuf;
738   GstBuffer *output_buffer;
739   int dmabuf_fd_in, dmabuf_fd_out;
740   XDAS_Int32 err;
741   const GstVideoCodecState *state;
742   int i;
743   GstClockTime ts;
744   GstClockTime t;
745   GstVideoCropMeta *crop;
747   state = self->input_state;
749   if (G_UNLIKELY (self->configure)) {
750     if (!gst_ducati_videnc_configure (self)) {
751       GST_DEBUG_OBJECT (self, "configure failed");
752       GST_ELEMENT_ERROR (self, STREAM, ENCODE, (NULL), (NULL));
754       return GST_FLOW_ERROR;
755     }
756   }
758   inbuf = gst_buffer_ref (frame->input_buffer);
759   ts = GST_BUFFER_PTS (inbuf);
760 have_inbuf:
761   dmabuf_fd_in = gst_ducati_videnc_buffer_lock (self, inbuf);
762   if (dmabuf_fd_in < 0) {
763     GstMapInfo info;
764     gboolean mapped;
766     GST_DEBUG_OBJECT (self, "memcpying input");
767     gst_buffer_unref (inbuf);
769     gst_buffer_pool_acquire_buffer (self->input_pool, &inbuf, NULL);
770     mapped = gst_buffer_map (frame->input_buffer, &info, GST_MAP_READ);
771     if (mapped) {
772       gst_buffer_fill (inbuf, 0, info.data, info.size);
773       gst_buffer_unmap (frame->input_buffer, &info);
774     }
776     GST_BUFFER_PTS (inbuf) = ts;
777     goto have_inbuf;
778   }
780   gst_buffer_pool_acquire_buffer (self->output_pool, &outbuf, NULL);
782   crop = gst_buffer_add_video_crop_meta (outbuf);
783   if (crop) {
784     crop->x = 0;
785     crop->y = 0;
786     crop->width = GST_VIDEO_INFO_WIDTH (&state->info);
787     crop->height = GST_VIDEO_INFO_HEIGHT (&state->info);
788   }
789   dmabuf_fd_out = gst_ducati_videnc_buffer_lock (self, outbuf);
791   self->inBufs->planeDesc[0].buf = (XDAS_Int8 *) dmabuf_fd_in;
792   self->inBufs->planeDesc[0].memType = XDM_MEMTYPE_RAW;
793   self->inBufs->planeDesc[0].bufSize.tileMem.width =
794       GST_VIDEO_INFO_WIDTH (&state->info);
795   self->inBufs->planeDesc[0].bufSize.tileMem.height =
796       GST_VIDEO_INFO_HEIGHT (&state->info);
797   self->inBufs->planeDesc[0].bufSize.bytes =
798       GST_VIDEO_INFO_WIDTH (&state->info) *
799       GST_VIDEO_INFO_HEIGHT (&state->info);
800   self->inBufs->planeDesc[1].buf = (XDAS_Int8 *) dmabuf_fd_in;
801   self->inBufs->planeDesc[1].memType = XDM_MEMTYPE_RAW;
802   self->inBufs->planeDesc[1].bufSize.tileMem.width =
803       GST_VIDEO_INFO_WIDTH (&state->info);
804   self->inBufs->planeDesc[1].bufSize.tileMem.height =
805       GST_VIDEO_INFO_HEIGHT (&state->info) / 2;
806   self->inBufs->planeDesc[1].bufSize.bytes =
807       GST_VIDEO_INFO_WIDTH (&state->info) *
808       GST_VIDEO_INFO_HEIGHT (&state->info) / 2;
809   /* setting imageRegion doesn't seem to be strictly needed if activeFrameRegion
810    * is set but we set it anyway...
811    */
812   self->inBufs->imageRegion.topLeft.x = self->rect.x;
813   self->inBufs->imageRegion.topLeft.y = self->rect.y;
814   self->inBufs->imageRegion.bottomRight.x = self->rect.x + self->rect.w;
815   self->inBufs->imageRegion.bottomRight.y = self->rect.y + self->rect.h;
816   self->inBufs->activeFrameRegion.topLeft.x = self->rect.x;
817   self->inBufs->activeFrameRegion.topLeft.y = self->rect.y;
818   self->inBufs->activeFrameRegion.bottomRight.x = self->rect.x + self->rect.w;
819   self->inBufs->activeFrameRegion.bottomRight.y = self->rect.y + self->rect.h;
820   self->inBufs->imagePitch[0] = GST_VIDEO_INFO_WIDTH (&state->info);
821   self->inBufs->imagePitch[1] = GST_VIDEO_INFO_WIDTH (&state->info);
822   self->inBufs->topFieldFirstFlag = TRUE;
824   self->outBufs->numBufs = 1;
825   self->outBufs->descs[0].buf = (XDAS_Int8 *) dmabuf_fd_out;
827   GstStructure *conf;
828   guint size;
829   conf = gst_buffer_pool_get_config (self->output_pool);
830   gst_buffer_pool_config_get_params (conf, NULL, &size, NULL, NULL);
832   self->outBufs->descs[0].bufSize.bytes = size;
833   self->outBufs->descs[0].memType = XDM_MEMTYPE_RAW;
835   self->inArgs->inputID = GPOINTER_TO_INT (inbuf);
837   GST_DEBUG ("Calling VIDENC2_process");
838   t = gst_util_get_timestamp ();
839   err = VIDENC2_process (self->codec, self->inBufs, self->outBufs,
840       self->inArgs, self->outArgs);
841   t = gst_util_get_timestamp () - t;
842   GST_DEBUG_OBJECT (self, "VIDENC2_process took %10dns (%d ms)", (gint) t,
843       (gint) (t / 1000000));
844   gst_ducati_videnc_buffer_unlock (self, outbuf);
845   if (err) {
846     GST_WARNING_OBJECT (self, "process failed: err=%d, extendedError=%08x",
847         err, self->outArgs->extendedError);
848     gst_ducati_log_extended_error_info (self->outArgs->extendedError,
849         self->error_strings);
851     err = VIDENC2_control (self->codec,
852         XDM_GETSTATUS, (IVIDENC2_DynamicParams *) self->dynParams,
853         self->status);
855     GST_WARNING_OBJECT (self, "XDM_GETSTATUS: err=%d, extendedError=%08x",
856         err, self->status->extendedError);
858     return GST_FLOW_ERROR;
859   }
861   if (self->outArgs->bytesGenerated > 0) {
862     GstMapInfo info;
863     gboolean mapped;
864     if (GST_DUCATIVIDENC_GET_CLASS (self)->is_sync_point (self,
865             self->outArgs->encodedFrameType)) {
866       GST_VIDEO_CODEC_FRAME_SET_SYNC_POINT (frame);
867     }
868     if (frame->output_buffer) {
869       gst_buffer_unref (frame->output_buffer);
870     }
872     frame->output_buffer =
873         gst_video_encoder_allocate_output_buffer (GST_VIDEO_ENCODER (self),
874         self->outArgs->bytesGenerated);
875     mapped = gst_buffer_map (outbuf, &info, GST_MAP_READ);
876     if (mapped) {
877       gst_buffer_fill (frame->output_buffer, 0, info.data, info.size);
878       gst_buffer_unmap (outbuf, &info);
879     }
881     GST_CAT_DEBUG_OBJECT (GST_CAT_PERFORMANCE, self,
882         "Encoded frame in %u bytes", self->outArgs->bytesGenerated);
884     /* As we can get frames in a different order we sent them (if the codec
885        supports B frames and we set it up for generating those), we need to
886        work out what input frame corresponds to the frame we just got, to
887        keep presentation times correct.
888        It seems that the codec will free buffers in the right order for this,
889        but I can not find anything saying this in the docs, so:
890        - it might be subject to change
891        - it might not be true in all setups
892        - it might not be true for all codecs
893        However, that's the only way I can see to do it. So there's a nice
894        assert below that will blow up if the codec does not free exactly one
895        input frame when it outputs a frame. That doesn't catch all cases,
896        such as when it frees them in the wrong order, but that seems less
897        likely to happen.
898        The timestamp and duration are given to the base class, which will
899        in turn set them onto the encoded buffer. */
900     g_assert (self->outArgs->freeBufID[0] && !self->outArgs->freeBufID[1]);
901     inbuf = GST_BUFFER (self->outArgs->freeBufID[0]);
902     frame->pts = GST_BUFFER_PTS (inbuf);
903     frame->duration = GST_BUFFER_DURATION (inbuf);
904     GST_BUFFER_OFFSET_END (frame->output_buffer) = GST_BUFFER_PTS (inbuf);
905   }
907   gst_buffer_unref (outbuf);
909   for (i = 0; self->outArgs->freeBufID[i]; i++) {
910     GstBuffer *buf = (GstBuffer *) self->outArgs->freeBufID[i];
912     GST_LOG_OBJECT (self, "free buffer: %p", buf);
913     gst_ducati_videnc_buffer_unlock (self, buf);
914     gst_buffer_unref (buf);
915   }
917   return gst_video_encoder_finish_frame (base_video_encoder, frame);
920 static gboolean
921 gst_ducati_videnc_is_sync_point_default (GstDucatiVidEnc * enc, int type)
923   return type == IVIDEO_I_FRAME;
926 static gboolean
927 gst_ducati_videnc_event (GstVideoEncoder * enc, GstEvent * event)
929   gboolean handled = FALSE;
930   GstDucatiVidEnc *self = GST_DUCATIVIDENC (enc);
932   switch (GST_EVENT_TYPE (event)) {
933     default:
934       break;
935   }
937   return handled;