2 * Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
3 * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation
8 * version 2.1 of the License.
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 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
26 #include <gst/video/gstvideometa.h>
29 #include "gstomxvideo.h"
30 #include "gstomxvideoenc.h"
32 #ifdef USE_OMX_TARGET_RPI
33 #include <OMX_Broadcom.h>
34 #include <OMX_Index.h>
37 //#define CODEC_ENC_INPUT_DUMP
38 GST_DEBUG_CATEGORY_STATIC (gst_omx_video_enc_debug_category);
39 #define GST_CAT_DEFAULT gst_omx_video_enc_debug_category
41 #define GST_TYPE_OMX_VIDEO_ENC_CONTROL_RATE (gst_omx_video_enc_control_rate_get_type ())
43 #ifdef CODEC_ENC_INPUT_DUMP
48 gst_omx_video_enc_control_rate_get_type (void)
50 static GType qtype = 0;
53 static const GEnumValue values[] = {
54 {OMX_Video_ControlRateDisable, "Disable", "disable"},
55 {OMX_Video_ControlRateVariable, "Variable", "variable"},
56 {OMX_Video_ControlRateConstant, "Constant", "constant"},
57 {OMX_Video_ControlRateVariableSkipFrames, "Variable Skip Frames",
58 "variable-skip-frames"},
59 {OMX_Video_ControlRateConstantSkipFrames, "Constant Skip Frames",
60 "constant-skip-frames"},
61 {0xffffffff, "Component Default", "default"},
65 qtype = g_enum_register_static ("GstOMXVideoEncControlRate", values);
71 static void gst_omx_video_enc_finalize (GObject * object);
72 static void gst_omx_video_enc_set_property (GObject * object, guint prop_id,
73 const GValue * value, GParamSpec * pspec);
74 static void gst_omx_video_enc_get_property (GObject * object, guint prop_id,
75 GValue * value, GParamSpec * pspec);
78 static GstStateChangeReturn
79 gst_omx_video_enc_change_state (GstElement * element,
80 GstStateChange transition);
82 static gboolean gst_omx_video_enc_open (GstVideoEncoder * encoder);
83 static gboolean gst_omx_video_enc_close (GstVideoEncoder * encoder);
84 static gboolean gst_omx_video_enc_start (GstVideoEncoder * encoder);
85 static gboolean gst_omx_video_enc_stop (GstVideoEncoder * encoder);
86 static gboolean gst_omx_video_enc_set_format (GstVideoEncoder * encoder,
87 GstVideoCodecState * state);
88 static gboolean gst_omx_video_enc_flush (GstVideoEncoder * encoder);
89 static GstFlowReturn gst_omx_video_enc_handle_frame (GstVideoEncoder * encoder,
90 GstVideoCodecFrame * frame);
91 static gboolean gst_omx_video_enc_finish (GstVideoEncoder * encoder);
92 static gboolean gst_omx_video_enc_propose_allocation (GstVideoEncoder * encoder,
94 static GstCaps *gst_omx_video_enc_getcaps (GstVideoEncoder * encoder,
97 static GstFlowReturn gst_omx_video_enc_drain (GstOMXVideoEnc * self);
99 static GstFlowReturn gst_omx_video_enc_handle_output_frame (GstOMXVideoEnc *
100 self, GstOMXPort * port, GstOMXBuffer * buf, GstVideoCodecFrame * frame);
112 /* FIXME: Better defaults */
113 #define GST_OMX_VIDEO_ENC_CONTROL_RATE_DEFAULT (0xffffffff)
114 #define GST_OMX_VIDEO_ENC_TARGET_BITRATE_DEFAULT (0xffffffff)
115 #define GST_OMX_VIDEO_ENC_QUANT_I_FRAMES_DEFAULT (0xffffffff)
116 #define GST_OMX_VIDEO_ENC_QUANT_P_FRAMES_DEFAULT (0xffffffff)
117 #define GST_OMX_VIDEO_ENC_QUANT_B_FRAMES_DEFAULT (0xffffffff)
120 /* class initialization */
123 GST_DEBUG_CATEGORY_INIT (gst_omx_video_enc_debug_category, "omxvideoenc", 0, \
124 "debug category for gst-omx video encoder base class");
126 G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GstOMXVideoEnc, gst_omx_video_enc,
127 GST_TYPE_VIDEO_ENCODER, DEBUG_INIT);
130 gst_omx_video_enc_class_init (GstOMXVideoEncClass * klass)
132 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
133 GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
134 GstVideoEncoderClass *video_encoder_class = GST_VIDEO_ENCODER_CLASS (klass);
137 gobject_class->finalize = gst_omx_video_enc_finalize;
138 gobject_class->set_property = gst_omx_video_enc_set_property;
139 gobject_class->get_property = gst_omx_video_enc_get_property;
141 g_object_class_install_property (gobject_class, PROP_CONTROL_RATE,
142 g_param_spec_enum ("control-rate", "Control Rate",
143 "Bitrate control method",
144 GST_TYPE_OMX_VIDEO_ENC_CONTROL_RATE,
145 GST_OMX_VIDEO_ENC_CONTROL_RATE_DEFAULT,
146 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
147 GST_PARAM_MUTABLE_READY));
149 g_object_class_install_property (gobject_class, PROP_TARGET_BITRATE,
150 g_param_spec_uint ("target-bitrate", "Target Bitrate",
151 "Target bitrate (0xffffffff=component default)",
152 0, G_MAXUINT, GST_OMX_VIDEO_ENC_TARGET_BITRATE_DEFAULT,
153 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
154 GST_PARAM_MUTABLE_PLAYING));
156 g_object_class_install_property (gobject_class, PROP_QUANT_I_FRAMES,
157 g_param_spec_uint ("quant-i-frames", "I-Frame Quantization",
158 "Quantization parameter for I-frames (0xffffffff=component default)",
159 0, G_MAXUINT, GST_OMX_VIDEO_ENC_QUANT_I_FRAMES_DEFAULT,
160 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
161 GST_PARAM_MUTABLE_READY));
163 g_object_class_install_property (gobject_class, PROP_QUANT_P_FRAMES,
164 g_param_spec_uint ("quant-p-frames", "P-Frame Quantization",
165 "Quantization parameter for P-frames (0xffffffff=component default)",
166 0, G_MAXUINT, GST_OMX_VIDEO_ENC_QUANT_P_FRAMES_DEFAULT,
167 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
168 GST_PARAM_MUTABLE_READY));
170 g_object_class_install_property (gobject_class, PROP_QUANT_B_FRAMES,
171 g_param_spec_uint ("quant-b-frames", "B-Frame Quantization",
172 "Quantization parameter for B-frames (0xffffffff=component default)",
173 0, G_MAXUINT, GST_OMX_VIDEO_ENC_QUANT_B_FRAMES_DEFAULT,
174 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
175 GST_PARAM_MUTABLE_READY));
177 element_class->change_state =
178 GST_DEBUG_FUNCPTR (gst_omx_video_enc_change_state);
180 video_encoder_class->open = GST_DEBUG_FUNCPTR (gst_omx_video_enc_open);
181 video_encoder_class->close = GST_DEBUG_FUNCPTR (gst_omx_video_enc_close);
182 video_encoder_class->start = GST_DEBUG_FUNCPTR (gst_omx_video_enc_start);
183 video_encoder_class->stop = GST_DEBUG_FUNCPTR (gst_omx_video_enc_stop);
184 video_encoder_class->flush = GST_DEBUG_FUNCPTR (gst_omx_video_enc_flush);
185 video_encoder_class->set_format =
186 GST_DEBUG_FUNCPTR (gst_omx_video_enc_set_format);
187 video_encoder_class->handle_frame =
188 GST_DEBUG_FUNCPTR (gst_omx_video_enc_handle_frame);
189 video_encoder_class->finish = GST_DEBUG_FUNCPTR (gst_omx_video_enc_finish);
190 video_encoder_class->propose_allocation =
191 GST_DEBUG_FUNCPTR (gst_omx_video_enc_propose_allocation);
192 video_encoder_class->getcaps = GST_DEBUG_FUNCPTR (gst_omx_video_enc_getcaps);
194 klass->cdata.type = GST_OMX_COMPONENT_TYPE_FILTER;
195 klass->cdata.default_sink_template_caps = "video/x-raw, "
196 "width = " GST_VIDEO_SIZE_RANGE ", "
197 "height = " GST_VIDEO_SIZE_RANGE ", " "framerate = " GST_VIDEO_FPS_RANGE;
199 klass->handle_output_frame =
200 GST_DEBUG_FUNCPTR (gst_omx_video_enc_handle_output_frame);
204 gst_omx_video_enc_init (GstOMXVideoEnc * self)
206 self->control_rate = GST_OMX_VIDEO_ENC_CONTROL_RATE_DEFAULT;
207 self->target_bitrate = GST_OMX_VIDEO_ENC_TARGET_BITRATE_DEFAULT;
208 self->quant_i_frames = GST_OMX_VIDEO_ENC_QUANT_I_FRAMES_DEFAULT;
209 self->quant_p_frames = GST_OMX_VIDEO_ENC_QUANT_P_FRAMES_DEFAULT;
210 self->quant_b_frames = GST_OMX_VIDEO_ENC_QUANT_B_FRAMES_DEFAULT;
212 g_mutex_init (&self->drain_lock);
213 g_cond_init (&self->drain_cond);
214 #ifdef TIZEN_FEATURE_OMX
220 #ifdef CODEC_ENC_INPUT_DUMP
222 gst_omx_video_enc_input_dump (MMVideoBuffer *inbuf)
224 char *temp = (char *)inbuf->data[0];
226 char filename[100]={0};
229 GST_WARNING ("codec enc input dump start. w = %d, h = %d", inbuf->width[0], inbuf->height[0]);
231 sprintf(filename, "/tmp/enc_input_dump_%d_%d.yuv", inbuf->width[0], inbuf->height[0]);
232 fp = fopen(filename, "ab");
234 for (i = 0; i < inbuf->height[0]; i++) {
235 fwrite(temp, inbuf->width[0], 1, fp);
236 temp += inbuf->stride_width[0];
239 temp = (char*)inbuf->data[1];
241 for(i = 0; i < inbuf->height[1] ; i++) {
242 fwrite(temp, inbuf->width[1], 1, fp);
243 temp += inbuf->stride_width[1];
245 GST_WARNING ("codec encoder input dumped!!");
251 gst_omx_video_enc_open (GstVideoEncoder * encoder)
253 GstOMXVideoEnc *self = GST_OMX_VIDEO_ENC (encoder);
254 GstOMXVideoEncClass *klass = GST_OMX_VIDEO_ENC_GET_CLASS (self);
255 gint in_port_index, out_port_index;
258 gst_omx_component_new (GST_OBJECT_CAST (self), klass->cdata.core_name,
259 klass->cdata.component_name, klass->cdata.component_role,
261 self->started = FALSE;
266 if (gst_omx_component_get_state (self->enc,
267 GST_CLOCK_TIME_NONE) != OMX_StateLoaded)
270 in_port_index = klass->cdata.in_port_index;
271 out_port_index = klass->cdata.out_port_index;
273 if (in_port_index == -1 || out_port_index == -1) {
274 OMX_PORT_PARAM_TYPE param;
277 GST_OMX_INIT_STRUCT (¶m);
280 gst_omx_component_get_parameter (self->enc, OMX_IndexParamVideoInit,
282 if (err != OMX_ErrorNone) {
283 GST_WARNING_OBJECT (self, "Couldn't get port information: %s (0x%08x)",
284 gst_omx_error_to_string (err), err);
289 GST_DEBUG_OBJECT (self, "Detected %u ports, starting at %u",
290 (guint) param.nPorts, (guint) param.nStartPortNumber);
291 in_port_index = param.nStartPortNumber + 0;
292 out_port_index = param.nStartPortNumber + 1;
296 self->enc_in_port = gst_omx_component_add_port (self->enc, in_port_index);
297 self->enc_out_port = gst_omx_component_add_port (self->enc, out_port_index);
300 if (!self->enc_in_port || !self->enc_out_port)
307 if (self->control_rate != 0xffffffff || self->target_bitrate != 0xffffffff) {
308 OMX_VIDEO_PARAM_BITRATETYPE bitrate_param;
310 GST_OMX_INIT_STRUCT (&bitrate_param);
311 bitrate_param.nPortIndex = self->enc_out_port->index;
313 err = gst_omx_component_get_parameter (self->enc,
314 OMX_IndexParamVideoBitrate, &bitrate_param);
316 if (err == OMX_ErrorNone) {
317 #ifdef USE_OMX_TARGET_RPI
318 /* FIXME: Workaround for RPi returning garbage for this parameter */
319 if (bitrate_param.nVersion.nVersion == 0) {
320 GST_OMX_INIT_STRUCT (&bitrate_param);
321 bitrate_param.nPortIndex = self->enc_out_port->index;
324 if (self->control_rate != 0xffffffff)
325 bitrate_param.eControlRate = self->control_rate;
326 if (self->target_bitrate != 0xffffffff)
327 bitrate_param.nTargetBitrate = self->target_bitrate;
330 gst_omx_component_set_parameter (self->enc,
331 OMX_IndexParamVideoBitrate, &bitrate_param);
332 if (err == OMX_ErrorUnsupportedIndex) {
333 GST_WARNING_OBJECT (self,
334 "Setting a bitrate not supported by the component");
335 } else if (err == OMX_ErrorUnsupportedSetting) {
336 GST_WARNING_OBJECT (self,
337 "Setting bitrate settings %u %u not supported by the component",
338 self->control_rate, self->target_bitrate);
339 } else if (err != OMX_ErrorNone) {
340 GST_ERROR_OBJECT (self,
341 "Failed to set bitrate parameters: %s (0x%08x)",
342 gst_omx_error_to_string (err), err);
346 GST_ERROR_OBJECT (self, "Failed to get bitrate parameters: %s (0x%08x)",
347 gst_omx_error_to_string (err), err);
351 if (self->quant_i_frames != 0xffffffff ||
352 self->quant_p_frames != 0xffffffff ||
353 self->quant_b_frames != 0xffffffff) {
354 OMX_VIDEO_PARAM_QUANTIZATIONTYPE quant_param;
356 GST_OMX_INIT_STRUCT (&quant_param);
357 quant_param.nPortIndex = self->enc_out_port->index;
359 err = gst_omx_component_get_parameter (self->enc,
360 OMX_IndexParamVideoQuantization, &quant_param);
362 if (err == OMX_ErrorNone) {
364 if (self->quant_i_frames != 0xffffffff)
365 quant_param.nQpI = self->quant_i_frames;
366 if (self->quant_p_frames != 0xffffffff)
367 quant_param.nQpP = self->quant_p_frames;
368 if (self->quant_b_frames != 0xffffffff)
369 quant_param.nQpB = self->quant_b_frames;
372 gst_omx_component_set_parameter (self->enc,
373 OMX_IndexParamVideoQuantization, &quant_param);
374 if (err == OMX_ErrorUnsupportedIndex) {
375 GST_WARNING_OBJECT (self,
376 "Setting quantization parameters not supported by the component");
377 } else if (err == OMX_ErrorUnsupportedSetting) {
378 GST_WARNING_OBJECT (self,
379 "Setting quantization parameters %u %u %u not supported by the component",
380 self->quant_i_frames, self->quant_p_frames, self->quant_b_frames);
381 } else if (err != OMX_ErrorNone) {
382 GST_ERROR_OBJECT (self,
383 "Failed to set quantization parameters: %s (0x%08x)",
384 gst_omx_error_to_string (err), err);
388 GST_ERROR_OBJECT (self,
389 "Failed to get quantization parameters: %s (0x%08x)",
390 gst_omx_error_to_string (err), err);
395 #ifdef TIZEN_FEATURE_OMX
396 self->bufmgr = tbm_bufmgr_init (self->drm_fd);
397 if (self->bufmgr == NULL){
398 GST_ERROR_OBJECT (self, "TBM initialization failed.");
402 self->enc_in_port->use_buffer = klass->cdata.in_port_usebuffer;
403 self->enc_out_port->use_buffer = klass->cdata.out_port_usebuffer;
405 /* get extension index and set platform specific buffer enable */
406 #if defined(USE_OMX_TARGET_EXYNOS) || defined(USE_OMX_TARGET_EXYNOS64)
409 OMX_INDEXTYPE index = OMX_IndexComponentStartUnused;
410 EnableGemBuffersParams gem_param;
412 err = gst_omx_component_get_extension_index (self->enc, (OMX_STRING) EXYNOS_INDEX_PARAM_STORE_METADATA_BUFFER, &index);
413 if (err != OMX_ErrorNone) {
414 GST_WARNING_OBJECT (self, "Failed to get extension index : %s (0x%08x)",
415 gst_omx_error_to_string (err), err);
418 OMX_INIT_PARAM (gem_param);
419 gem_param.enable = OMX_TRUE;
420 gem_param.nPortIndex = 0;
423 err = gst_omx_component_set_parameter (self->enc, index, &gem_param);
424 if (err != OMX_ErrorNone) {
425 GST_ERROR_OBJECT (self, "Failed to set platform specific buffer: %s (0x%08x)",
426 gst_omx_error_to_string (err), err);
436 gst_omx_video_enc_shutdown (GstOMXVideoEnc * self)
440 GST_DEBUG_OBJECT (self, "Shutting down encoder");
442 state = gst_omx_component_get_state (self->enc, 0);
443 if (state > OMX_StateLoaded || state == OMX_StateInvalid) {
444 if (state > OMX_StateIdle) {
445 gst_omx_component_set_state (self->enc, OMX_StateIdle);
446 gst_omx_component_get_state (self->enc, 5 * GST_SECOND);
448 gst_omx_component_set_state (self->enc, OMX_StateLoaded);
449 gst_omx_port_deallocate_buffers (self->enc_in_port);
450 gst_omx_port_deallocate_buffers (self->enc_out_port);
451 if (state > OMX_StateLoaded)
452 gst_omx_component_get_state (self->enc, 5 * GST_SECOND);
459 gst_omx_video_enc_close (GstVideoEncoder * encoder)
461 GstOMXVideoEnc *self = GST_OMX_VIDEO_ENC (encoder);
463 GST_DEBUG_OBJECT (self, "Closing encoder");
465 if (!gst_omx_video_enc_shutdown (self))
468 self->enc_in_port = NULL;
469 self->enc_out_port = NULL;
471 gst_omx_component_free (self->enc);
478 gst_omx_video_enc_finalize (GObject * object)
480 GstOMXVideoEnc *self = GST_OMX_VIDEO_ENC (object);
482 g_mutex_clear (&self->drain_lock);
483 g_cond_clear (&self->drain_cond);
485 G_OBJECT_CLASS (gst_omx_video_enc_parent_class)->finalize (object);
489 gst_omx_video_enc_set_property (GObject * object, guint prop_id,
490 const GValue * value, GParamSpec * pspec)
492 GstOMXVideoEnc *self = GST_OMX_VIDEO_ENC (object);
495 case PROP_CONTROL_RATE:
496 self->control_rate = g_value_get_enum (value);
498 case PROP_TARGET_BITRATE:
499 self->target_bitrate = g_value_get_uint (value);
501 OMX_VIDEO_CONFIG_BITRATETYPE config;
504 GST_OMX_INIT_STRUCT (&config);
505 config.nPortIndex = self->enc_out_port->index;
506 config.nEncodeBitrate = self->target_bitrate;
508 gst_omx_component_set_config (self->enc,
509 OMX_IndexConfigVideoBitrate, &config);
510 if (err != OMX_ErrorNone)
511 GST_ERROR_OBJECT (self,
512 "Failed to set bitrate parameter: %s (0x%08x)",
513 gst_omx_error_to_string (err), err);
516 case PROP_QUANT_I_FRAMES:
517 self->quant_i_frames = g_value_get_uint (value);
519 case PROP_QUANT_P_FRAMES:
520 self->quant_p_frames = g_value_get_uint (value);
522 case PROP_QUANT_B_FRAMES:
523 self->quant_b_frames = g_value_get_uint (value);
526 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
532 gst_omx_video_enc_get_property (GObject * object, guint prop_id, GValue * value,
535 GstOMXVideoEnc *self = GST_OMX_VIDEO_ENC (object);
538 case PROP_CONTROL_RATE:
539 g_value_set_enum (value, self->control_rate);
541 case PROP_TARGET_BITRATE:
542 g_value_set_uint (value, self->target_bitrate);
544 case PROP_QUANT_I_FRAMES:
545 g_value_set_uint (value, self->quant_i_frames);
547 case PROP_QUANT_P_FRAMES:
548 g_value_set_uint (value, self->quant_p_frames);
550 case PROP_QUANT_B_FRAMES:
551 g_value_set_uint (value, self->quant_b_frames);
554 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
559 static GstStateChangeReturn
560 gst_omx_video_enc_change_state (GstElement * element, GstStateChange transition)
562 GstOMXVideoEnc *self;
563 GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
565 g_return_val_if_fail (GST_IS_OMX_VIDEO_ENC (element),
566 GST_STATE_CHANGE_FAILURE);
567 self = GST_OMX_VIDEO_ENC (element);
569 switch (transition) {
570 case GST_STATE_CHANGE_NULL_TO_READY:
572 case GST_STATE_CHANGE_READY_TO_PAUSED:
573 self->downstream_flow_ret = GST_FLOW_OK;
575 self->draining = FALSE;
576 self->started = FALSE;
578 case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
580 case GST_STATE_CHANGE_PAUSED_TO_READY:
581 if (self->enc_in_port)
582 gst_omx_port_set_flushing (self->enc_in_port, 5 * GST_SECOND, TRUE);
583 if (self->enc_out_port)
584 gst_omx_port_set_flushing (self->enc_out_port, 5 * GST_SECOND, TRUE);
586 g_mutex_lock (&self->drain_lock);
587 self->draining = FALSE;
588 g_cond_broadcast (&self->drain_cond);
589 g_mutex_unlock (&self->drain_lock);
596 GST_ELEMENT_CLASS (gst_omx_video_enc_parent_class)->change_state (element,
599 if (ret == GST_STATE_CHANGE_FAILURE)
602 switch (transition) {
603 case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
605 case GST_STATE_CHANGE_PAUSED_TO_READY:
606 self->downstream_flow_ret = GST_FLOW_FLUSHING;
607 self->started = FALSE;
609 if (!gst_omx_video_enc_shutdown (self))
610 ret = GST_STATE_CHANGE_FAILURE;
612 case GST_STATE_CHANGE_READY_TO_NULL:
622 gst_omx_video_enc_handle_output_frame (GstOMXVideoEnc * self, GstOMXPort * port,
623 GstOMXBuffer * buf, GstVideoCodecFrame * frame)
625 GstOMXVideoEncClass *klass = GST_OMX_VIDEO_ENC_GET_CLASS (self);
626 GstFlowReturn flow_ret = GST_FLOW_OK;
628 if ((buf->omx_buf->nFlags & OMX_BUFFERFLAG_CODECCONFIG)
629 && buf->omx_buf->nFilledLen > 0) {
630 GstVideoCodecState *state;
631 GstBuffer *codec_data;
632 GstMapInfo map = GST_MAP_INFO_INIT;
635 GST_DEBUG_OBJECT (self, "Handling codec data");
637 caps = klass->get_caps (self, self->enc_out_port, self->input_state);
638 codec_data = gst_buffer_new_and_alloc (buf->omx_buf->nFilledLen);
640 gst_buffer_map (codec_data, &map, GST_MAP_WRITE);
642 buf->omx_buf->pBuffer + buf->omx_buf->nOffset,
643 buf->omx_buf->nFilledLen);
644 gst_buffer_unmap (codec_data, &map);
646 gst_video_encoder_set_output_state (GST_VIDEO_ENCODER (self), caps,
648 state->codec_data = codec_data;
649 gst_video_codec_state_unref (state);
650 #ifdef TIZEN_FEATURE_OMX
651 /*Modification : codec data already set_caps, so unref frame whenever negotiate ok or not*/
652 if (!gst_video_encoder_negotiate (GST_VIDEO_ENCODER (self)))
653 flow_ret = GST_FLOW_NOT_NEGOTIATED;
655 flow_ret = GST_FLOW_OK;
656 gst_video_codec_frame_unref (frame);
658 if (!gst_video_encoder_negotiate (GST_VIDEO_ENCODER (self))) {
659 gst_video_codec_frame_unref (frame);
660 return GST_FLOW_NOT_NEGOTIATED;
662 flow_ret = GST_FLOW_OK;
664 } else if (buf->omx_buf->nFilledLen > 0) {
666 GstMapInfo map = GST_MAP_INFO_INIT;
668 GST_DEBUG_OBJECT (self, "Handling output data");
670 if (buf->omx_buf->nFilledLen > 0) {
671 outbuf = gst_buffer_new_and_alloc (buf->omx_buf->nFilledLen);
673 gst_buffer_map (outbuf, &map, GST_MAP_WRITE);
675 buf->omx_buf->pBuffer + buf->omx_buf->nOffset,
676 buf->omx_buf->nFilledLen);
677 gst_buffer_unmap (outbuf, &map);
679 outbuf = gst_buffer_new ();
682 GST_BUFFER_TIMESTAMP (outbuf) =
683 gst_util_uint64_scale (buf->omx_buf->nTimeStamp, GST_SECOND,
684 OMX_TICKS_PER_SECOND);
685 if (buf->omx_buf->nTickCount != 0)
686 GST_BUFFER_DURATION (outbuf) =
687 gst_util_uint64_scale (buf->omx_buf->nTickCount, GST_SECOND,
688 OMX_TICKS_PER_SECOND);
690 if ((klass->cdata.hacks & GST_OMX_HACK_SYNCFRAME_FLAG_NOT_USED)
691 || (buf->omx_buf->nFlags & OMX_BUFFERFLAG_SYNCFRAME)) {
693 GST_VIDEO_CODEC_FRAME_SET_SYNC_POINT (frame);
695 GST_BUFFER_FLAG_UNSET (outbuf, GST_BUFFER_FLAG_DELTA_UNIT);
698 GST_VIDEO_CODEC_FRAME_UNSET_SYNC_POINT (frame);
700 GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DELTA_UNIT);
704 frame->output_buffer = outbuf;
706 gst_video_encoder_finish_frame (GST_VIDEO_ENCODER (self), frame);
708 GST_ERROR_OBJECT (self, "No corresponding frame found");
709 flow_ret = gst_pad_push (GST_VIDEO_ENCODER_SRC_PAD (self), outbuf);
711 } else if (frame != NULL) {
712 flow_ret = gst_video_encoder_finish_frame (GST_VIDEO_ENCODER (self), frame);
719 gst_omx_video_enc_loop (GstOMXVideoEnc * self)
721 GstOMXVideoEncClass *klass;
722 GstOMXPort *port = self->enc_out_port;
723 GstOMXBuffer *buf = NULL;
724 GstVideoCodecFrame *frame;
725 GstFlowReturn flow_ret = GST_FLOW_OK;
726 GstOMXAcquireBufferReturn acq_return;
729 klass = GST_OMX_VIDEO_ENC_GET_CLASS (self);
731 acq_return = gst_omx_port_acquire_buffer (port, &buf);
732 if (acq_return == GST_OMX_ACQUIRE_BUFFER_ERROR) {
733 goto component_error;
734 } else if (acq_return == GST_OMX_ACQUIRE_BUFFER_FLUSHING) {
736 } else if (acq_return == GST_OMX_ACQUIRE_BUFFER_EOS) {
740 if (!gst_pad_has_current_caps (GST_VIDEO_ENCODER_SRC_PAD (self))
741 || acq_return == GST_OMX_ACQUIRE_BUFFER_RECONFIGURE) {
743 GstVideoCodecState *state;
745 GST_DEBUG_OBJECT (self, "Port settings have changed, updating caps");
747 if (acq_return == GST_OMX_ACQUIRE_BUFFER_RECONFIGURE
748 && gst_omx_port_is_enabled (port)) {
749 /* Reallocate all buffers */
750 err = gst_omx_port_set_enabled (port, FALSE);
751 if (err != OMX_ErrorNone)
752 goto reconfigure_error;
754 err = gst_omx_port_wait_buffers_released (port, 5 * GST_SECOND);
755 if (err != OMX_ErrorNone)
756 goto reconfigure_error;
758 err = gst_omx_port_deallocate_buffers (port);
759 if (err != OMX_ErrorNone)
760 goto reconfigure_error;
762 err = gst_omx_port_wait_enabled (port, 1 * GST_SECOND);
763 if (err != OMX_ErrorNone)
764 goto reconfigure_error;
767 GST_VIDEO_ENCODER_STREAM_LOCK (self);
769 caps = klass->get_caps (self, self->enc_out_port, self->input_state);
772 gst_omx_port_release_buffer (self->enc_out_port, buf);
773 GST_VIDEO_ENCODER_STREAM_UNLOCK (self);
777 GST_DEBUG_OBJECT (self, "Setting output state: %" GST_PTR_FORMAT, caps);
780 gst_video_encoder_set_output_state (GST_VIDEO_ENCODER (self), caps,
782 gst_video_codec_state_unref (state);
784 if (!gst_video_encoder_negotiate (GST_VIDEO_ENCODER (self))) {
786 gst_omx_port_release_buffer (self->enc_out_port, buf);
787 GST_VIDEO_ENCODER_STREAM_UNLOCK (self);
791 GST_VIDEO_ENCODER_STREAM_UNLOCK (self);
793 if (acq_return == GST_OMX_ACQUIRE_BUFFER_RECONFIGURE) {
794 err = gst_omx_port_set_enabled (port, TRUE);
795 if (err != OMX_ErrorNone)
796 goto reconfigure_error;
797 #ifdef TIZEN_FEATURE_OMX
798 err = gst_omx_port_tbm_allocate_enc_buffers(port, self->bufmgr, port->use_buffer);
800 err = gst_omx_port_allocate_buffers (port);
802 if (err != OMX_ErrorNone)
803 goto reconfigure_error;
805 err = gst_omx_port_wait_enabled (port, 5 * GST_SECOND);
806 if (err != OMX_ErrorNone)
807 goto reconfigure_error;
809 err = gst_omx_port_populate (port);
810 if (err != OMX_ErrorNone)
811 goto reconfigure_error;
813 err = gst_omx_port_mark_reconfigured (port);
814 if (err != OMX_ErrorNone)
815 goto reconfigure_error;
818 /* Now get a buffer */
819 if (acq_return != GST_OMX_ACQUIRE_BUFFER_OK) {
824 g_assert (acq_return == GST_OMX_ACQUIRE_BUFFER_OK);
826 /* This prevents a deadlock between the srcpad stream
827 * lock and the videocodec stream lock, if ::flush()
828 * is called at the wrong time
830 if (gst_omx_port_is_flushing (self->enc_out_port)) {
831 GST_DEBUG_OBJECT (self, "Flushing");
832 gst_omx_port_release_buffer (self->enc_out_port, buf);
836 GST_DEBUG_OBJECT (self, "Handling buffer: 0x%08x %" G_GUINT64_FORMAT,
837 (guint) buf->omx_buf->nFlags, (guint64) buf->omx_buf->nTimeStamp);
839 GST_VIDEO_ENCODER_STREAM_LOCK (self);
840 frame = gst_omx_video_find_nearest_frame (buf,
841 gst_video_encoder_get_frames (GST_VIDEO_ENCODER (self)));
843 g_assert (klass->handle_output_frame);
844 flow_ret = klass->handle_output_frame (self, self->enc_out_port, buf, frame);
846 GST_DEBUG_OBJECT (self, "Finished frame: %s", gst_flow_get_name (flow_ret));
848 err = gst_omx_port_release_buffer (port, buf);
849 if (err != OMX_ErrorNone)
852 self->downstream_flow_ret = flow_ret;
854 GST_DEBUG_OBJECT (self, "Read frame from component");
856 if (flow_ret != GST_FLOW_OK)
859 GST_VIDEO_ENCODER_STREAM_UNLOCK (self);
865 GST_ELEMENT_ERROR (self, LIBRARY, FAILED, (NULL),
866 ("OpenMAX component in error state %s (0x%08x)",
867 gst_omx_component_get_last_error_string (self->enc),
868 gst_omx_component_get_last_error (self->enc)));
869 gst_pad_push_event (GST_VIDEO_ENCODER_SRC_PAD (self), gst_event_new_eos ());
870 gst_pad_pause_task (GST_VIDEO_ENCODER_SRC_PAD (self));
871 self->downstream_flow_ret = GST_FLOW_ERROR;
872 self->started = FALSE;
877 GST_DEBUG_OBJECT (self, "Flushing -- stopping task");
878 g_mutex_lock (&self->drain_lock);
879 if (self->draining) {
880 self->draining = FALSE;
881 g_cond_broadcast (&self->drain_cond);
883 gst_pad_pause_task (GST_VIDEO_ENCODER_SRC_PAD (self));
884 self->downstream_flow_ret = GST_FLOW_FLUSHING;
885 self->started = FALSE;
886 g_mutex_unlock (&self->drain_lock);
892 g_mutex_lock (&self->drain_lock);
893 if (self->draining) {
894 GST_DEBUG_OBJECT (self, "Drained");
895 self->draining = FALSE;
896 g_cond_broadcast (&self->drain_cond);
897 flow_ret = GST_FLOW_OK;
898 gst_pad_pause_task (GST_VIDEO_ENCODER_SRC_PAD (self));
900 GST_DEBUG_OBJECT (self, "Component signalled EOS");
901 flow_ret = GST_FLOW_EOS;
903 g_mutex_unlock (&self->drain_lock);
905 GST_VIDEO_ENCODER_STREAM_LOCK (self);
906 self->downstream_flow_ret = flow_ret;
908 /* Here we fallback and pause the task for the EOS case */
909 if (flow_ret != GST_FLOW_OK)
912 GST_VIDEO_ENCODER_STREAM_UNLOCK (self);
918 if (flow_ret == GST_FLOW_EOS) {
919 GST_DEBUG_OBJECT (self, "EOS");
921 gst_pad_push_event (GST_VIDEO_ENCODER_SRC_PAD (self),
922 gst_event_new_eos ());
923 gst_pad_pause_task (GST_VIDEO_ENCODER_SRC_PAD (self));
924 self->started = FALSE;
925 } else if (flow_ret < GST_FLOW_EOS) {
926 GST_ELEMENT_ERROR (self, STREAM, FAILED, ("Internal data stream error."),
927 ("stream stopped, reason %s", gst_flow_get_name (flow_ret)));
929 gst_pad_push_event (GST_VIDEO_ENCODER_SRC_PAD (self),
930 gst_event_new_eos ());
931 gst_pad_pause_task (GST_VIDEO_ENCODER_SRC_PAD (self));
932 self->started = FALSE;
933 } else if (flow_ret == GST_FLOW_FLUSHING) {
934 GST_DEBUG_OBJECT (self, "Flushing -- stopping task");
935 g_mutex_lock (&self->drain_lock);
936 if (self->draining) {
937 self->draining = FALSE;
938 g_cond_broadcast (&self->drain_cond);
940 gst_pad_pause_task (GST_VIDEO_ENCODER_SRC_PAD (self));
941 self->started = FALSE;
942 g_mutex_unlock (&self->drain_lock);
944 GST_VIDEO_ENCODER_STREAM_UNLOCK (self);
949 GST_ELEMENT_ERROR (self, LIBRARY, SETTINGS, (NULL),
950 ("Unable to reconfigure output port"));
951 gst_pad_push_event (GST_VIDEO_ENCODER_SRC_PAD (self), gst_event_new_eos ());
952 gst_pad_pause_task (GST_VIDEO_ENCODER_SRC_PAD (self));
953 self->downstream_flow_ret = GST_FLOW_NOT_NEGOTIATED;
954 self->started = FALSE;
959 GST_ELEMENT_ERROR (self, LIBRARY, SETTINGS, (NULL), ("Failed to set caps"));
960 gst_pad_push_event (GST_VIDEO_ENCODER_SRC_PAD (self), gst_event_new_eos ());
961 gst_pad_pause_task (GST_VIDEO_ENCODER_SRC_PAD (self));
962 self->downstream_flow_ret = GST_FLOW_NOT_NEGOTIATED;
963 self->started = FALSE;
968 GST_ELEMENT_ERROR (self, LIBRARY, SETTINGS, (NULL),
969 ("Failed to relase output buffer to component: %s (0x%08x)",
970 gst_omx_error_to_string (err), err));
971 gst_pad_push_event (GST_VIDEO_ENCODER_SRC_PAD (self), gst_event_new_eos ());
972 gst_pad_pause_task (GST_VIDEO_ENCODER_SRC_PAD (self));
973 self->downstream_flow_ret = GST_FLOW_ERROR;
974 self->started = FALSE;
975 GST_VIDEO_ENCODER_STREAM_UNLOCK (self);
981 gst_omx_video_enc_start (GstVideoEncoder * encoder)
983 GstOMXVideoEnc *self;
985 self = GST_OMX_VIDEO_ENC (encoder);
987 self->last_upstream_ts = 0;
988 self->downstream_flow_ret = GST_FLOW_OK;
994 gst_omx_video_enc_stop (GstVideoEncoder * encoder)
996 GstOMXVideoEnc *self;
998 self = GST_OMX_VIDEO_ENC (encoder);
1000 GST_DEBUG_OBJECT (self, "Stopping encoder");
1002 gst_omx_port_set_flushing (self->enc_in_port, 5 * GST_SECOND, TRUE);
1003 gst_omx_port_set_flushing (self->enc_out_port, 5 * GST_SECOND, TRUE);
1005 gst_pad_stop_task (GST_VIDEO_ENCODER_SRC_PAD (encoder));
1007 if (gst_omx_component_get_state (self->enc, 0) > OMX_StateIdle)
1008 gst_omx_component_set_state (self->enc, OMX_StateIdle);
1010 self->downstream_flow_ret = GST_FLOW_FLUSHING;
1011 self->started = FALSE;
1013 if (self->input_state)
1014 gst_video_codec_state_unref (self->input_state);
1015 self->input_state = NULL;
1017 g_mutex_lock (&self->drain_lock);
1018 self->draining = FALSE;
1019 g_cond_broadcast (&self->drain_cond);
1020 g_mutex_unlock (&self->drain_lock);
1022 gst_omx_component_get_state (self->enc, 5 * GST_SECOND);
1028 gst_omx_video_enc_set_format (GstVideoEncoder * encoder,
1029 GstVideoCodecState * state)
1031 GstOMXVideoEnc *self;
1032 GstOMXVideoEncClass *klass;
1033 gboolean needs_disable = FALSE;
1034 OMX_PARAM_PORTDEFINITIONTYPE port_def;
1035 GstVideoInfo *info = &state->info;
1036 GList *negotiation_map = NULL, *l;
1038 self = GST_OMX_VIDEO_ENC (encoder);
1039 klass = GST_OMX_VIDEO_ENC_GET_CLASS (encoder);
1041 GST_DEBUG_OBJECT (self, "Setting new format %s",
1042 gst_video_format_to_string (info->finfo->format));
1044 gst_omx_port_get_port_definition (self->enc_in_port, &port_def);
1047 gst_omx_component_get_state (self->enc,
1048 GST_CLOCK_TIME_NONE) != OMX_StateLoaded;
1049 /* If the component is not in Loaded state and a real format change happens
1050 * we have to disable the port and re-allocate all buffers. If no real
1051 * format change happened we can just exit here.
1053 if (needs_disable) {
1054 GST_DEBUG_OBJECT (self, "Need to disable and drain encoder");
1055 gst_omx_video_enc_drain (self);
1056 gst_omx_port_set_flushing (self->enc_out_port, 5 * GST_SECOND, TRUE);
1058 /* Wait until the srcpad loop is finished,
1059 * unlock GST_VIDEO_ENCODER_STREAM_LOCK to prevent deadlocks
1060 * caused by using this lock from inside the loop function */
1061 GST_VIDEO_ENCODER_STREAM_UNLOCK (self);
1062 gst_pad_stop_task (GST_VIDEO_ENCODER_SRC_PAD (encoder));
1063 GST_VIDEO_ENCODER_STREAM_LOCK (self);
1065 if (klass->cdata.hacks & GST_OMX_HACK_NO_COMPONENT_RECONFIGURE) {
1066 GST_VIDEO_ENCODER_STREAM_UNLOCK (self);
1067 gst_omx_video_enc_stop (GST_VIDEO_ENCODER (self));
1068 gst_omx_video_enc_close (GST_VIDEO_ENCODER (self));
1069 GST_VIDEO_ENCODER_STREAM_LOCK (self);
1071 if (!gst_omx_video_enc_open (GST_VIDEO_ENCODER (self)))
1073 needs_disable = FALSE;
1075 if (gst_omx_port_set_enabled (self->enc_in_port, FALSE) != OMX_ErrorNone)
1077 if (gst_omx_port_set_enabled (self->enc_out_port, FALSE) != OMX_ErrorNone)
1079 if (gst_omx_port_wait_buffers_released (self->enc_in_port,
1080 5 * GST_SECOND) != OMX_ErrorNone)
1082 if (gst_omx_port_wait_buffers_released (self->enc_out_port,
1083 1 * GST_SECOND) != OMX_ErrorNone)
1085 if (gst_omx_port_deallocate_buffers (self->enc_in_port) != OMX_ErrorNone)
1087 if (gst_omx_port_deallocate_buffers (self->enc_out_port) != OMX_ErrorNone)
1089 if (gst_omx_port_wait_enabled (self->enc_in_port,
1090 1 * GST_SECOND) != OMX_ErrorNone)
1092 if (gst_omx_port_wait_enabled (self->enc_out_port,
1093 1 * GST_SECOND) != OMX_ErrorNone)
1097 GST_DEBUG_OBJECT (self, "Encoder drained and disabled");
1101 gst_omx_video_get_supported_colorformats (self->enc_in_port,
1103 if (!negotiation_map) {
1105 switch (info->finfo->format) {
1106 case GST_VIDEO_FORMAT_I420:
1107 port_def.format.video.eColorFormat = OMX_COLOR_FormatYUV420Planar;
1109 case GST_VIDEO_FORMAT_NV12:
1110 port_def.format.video.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
1112 case GST_VIDEO_FORMAT_SN12:
1113 port_def.format.video.eColorFormat = OMX_EXT_COLOR_FormatNV12LPhysicalAddress;
1116 GST_ERROR_OBJECT (self, "Unsupported format %s",
1117 gst_video_format_to_string (info->finfo->format));
1122 for (l = negotiation_map; l; l = l->next) {
1123 GstOMXVideoNegotiationMap *m = l->data;
1125 if (m->format == info->finfo->format) {
1126 port_def.format.video.eColorFormat = m->type;
1130 g_list_free_full (negotiation_map,
1131 (GDestroyNotify) gst_omx_video_negotiation_map_free);
1134 port_def.format.video.nFrameWidth = info->width;
1135 #ifdef TIZEN_FEATURE_OMX
1136 port_def.format.video.nStride = ALIGN(info->width, 16);
1138 if (port_def.nBufferAlignment)
1139 port_def.format.video.nStride =
1140 (info->width + port_def.nBufferAlignment - 1) &
1141 (~(port_def.nBufferAlignment - 1));
1143 port_def.format.video.nStride = GST_ROUND_UP_4 (info->width); /* safe (?) default */
1146 port_def.format.video.nFrameHeight = info->height;
1147 #ifdef TIZEN_FEATURE_OMX
1148 port_def.format.video.nSliceHeight = ALIGN(info->width, 16);
1150 port_def.format.video.nSliceHeight = info->height;
1153 switch (port_def.format.video.eColorFormat) {
1154 case OMX_COLOR_FormatYUV420Planar:
1155 case OMX_COLOR_FormatYUV420PackedPlanar:
1156 port_def.nBufferSize =
1157 (port_def.format.video.nStride * port_def.format.video.nFrameHeight) +
1158 2 * ((port_def.format.video.nStride / 2) *
1159 ((port_def.format.video.nFrameHeight + 1) / 2));
1162 case OMX_COLOR_FormatYUV420SemiPlanar:
1163 port_def.nBufferSize =
1164 (port_def.format.video.nStride * port_def.format.video.nFrameHeight) +
1165 (port_def.format.video.nStride *
1166 ((port_def.format.video.nFrameHeight + 1) / 2));
1169 case OMX_EXT_COLOR_FormatNV12LPhysicalAddress: /* FALL THROUGH */
1170 case OMX_EXT_COLOR_FormatNV12TPhysicalAddress:
1171 #ifdef TIZEN_FEATURE_OMX
1172 port_def.nBufferSize = sizeof(MMVideoBuffer);
1177 g_assert_not_reached ();
1180 if (info->fps_n == 0) {
1181 port_def.format.video.xFramerate = 0;
1183 if (!(klass->cdata.hacks & GST_OMX_HACK_VIDEO_FRAMERATE_INTEGER))
1184 port_def.format.video.xFramerate = (info->fps_n << 16) / (info->fps_d);
1186 port_def.format.video.xFramerate = (info->fps_n) / (info->fps_d);
1189 GST_DEBUG_OBJECT (self, "Setting inport port definition");
1190 if (gst_omx_port_update_port_definition (self->enc_in_port,
1191 &port_def) != OMX_ErrorNone)
1194 #ifdef TIZEN_FEATURE_OMX
1195 GST_DEBUG_OBJECT (self, "Updating outport port definition");
1196 gst_omx_port_get_port_definition (self->enc_out_port, &port_def);
1198 port_def.format.video.nFrameWidth = info->width;
1199 port_def.format.video.nFrameHeight = info->height;
1201 if (gst_omx_port_update_port_definition (self->enc_out_port, &port_def) != OMX_ErrorNone)
1205 #ifdef USE_OMX_TARGET_RPI
1209 OMX_CONFIG_POINTTYPE aspect_ratio_param;
1211 GST_OMX_INIT_STRUCT (&aspect_ratio_param);
1212 aspect_ratio_param.nPortIndex = self->enc_out_port->index;
1214 err = gst_omx_component_get_parameter (self->enc,
1215 OMX_IndexParamBrcmPixelAspectRatio, &aspect_ratio_param);
1217 if (err == OMX_ErrorNone) {
1219 aspect_ratio_param.nX = info->par_n;
1220 aspect_ratio_param.nY = info->par_d;
1223 gst_omx_component_set_parameter (self->enc,
1224 OMX_IndexParamBrcmPixelAspectRatio, &aspect_ratio_param);
1226 if (err == OMX_ErrorUnsupportedIndex) {
1227 GST_WARNING_OBJECT (self,
1228 "Setting aspect ratio parameters not supported by the component");
1229 } else if (err == OMX_ErrorUnsupportedSetting) {
1230 GST_WARNING_OBJECT (self,
1231 "Setting aspect ratio %u %u not supported by the component",
1232 aspect_ratio_param.nX, aspect_ratio_param.nY);
1233 } else if (err != OMX_ErrorNone) {
1234 GST_ERROR_OBJECT (self,
1235 "Failed to set aspect ratio: %s (0x%08x)",
1236 gst_omx_error_to_string (err), err);
1241 #endif // USE_OMX_TARGET_RPI
1243 if (klass->set_format) {
1244 if (!klass->set_format (self, self->enc_in_port, state)) {
1245 GST_ERROR_OBJECT (self, "Subclass failed to set the new format");
1250 GST_DEBUG_OBJECT (self, "Updating outport port definition");
1251 if (gst_omx_port_update_port_definition (self->enc_out_port,
1252 NULL) != OMX_ErrorNone)
1255 if (self->target_bitrate != 0xffffffff) {
1256 OMX_VIDEO_PARAM_BITRATETYPE config;
1259 GST_OMX_INIT_STRUCT (&config);
1260 config.nPortIndex = self->enc_out_port->index;
1261 config.nTargetBitrate = self->target_bitrate;
1262 config.eControlRate = self->control_rate;
1263 err = gst_omx_component_set_parameter (self->enc,
1264 OMX_IndexParamVideoBitrate, &config);
1265 if (err != OMX_ErrorNone)
1266 GST_ERROR_OBJECT (self, "Failed to set bitrate parameter: %s (0x%08x)",
1267 gst_omx_error_to_string (err), err);
1270 GST_DEBUG_OBJECT (self, "Enabling component");
1271 if (needs_disable) {
1272 if (gst_omx_port_set_enabled (self->enc_in_port, TRUE) != OMX_ErrorNone)
1274 #ifdef TIZEN_FEATURE_OMX
1275 if (gst_omx_port_tbm_allocate_enc_buffers (self->enc_in_port, self->bufmgr,
1276 self->enc_in_port->use_buffer) != OMX_ErrorNone)
1279 if (gst_omx_port_allocate_buffers (self->enc_in_port) != OMX_ErrorNone)
1282 if ((klass->cdata.hacks & GST_OMX_HACK_NO_DISABLE_OUTPORT)) {
1283 if (gst_omx_port_set_enabled (self->enc_out_port, TRUE) != OMX_ErrorNone)
1285 if (gst_omx_port_allocate_buffers (self->enc_out_port) != OMX_ErrorNone)
1288 if (gst_omx_port_wait_enabled (self->enc_out_port,
1289 5 * GST_SECOND) != OMX_ErrorNone)
1293 if (gst_omx_port_wait_enabled (self->enc_in_port,
1294 5 * GST_SECOND) != OMX_ErrorNone)
1296 if (gst_omx_port_mark_reconfigured (self->enc_in_port) != OMX_ErrorNone)
1299 if (!(klass->cdata.hacks & GST_OMX_HACK_NO_DISABLE_OUTPORT)) {
1300 /* Disable output port */
1301 if (gst_omx_port_set_enabled (self->enc_out_port, FALSE) != OMX_ErrorNone)
1304 if (gst_omx_port_wait_enabled (self->enc_out_port,
1305 1 * GST_SECOND) != OMX_ErrorNone)
1308 if (gst_omx_component_set_state (self->enc,
1309 OMX_StateIdle) != OMX_ErrorNone)
1312 /* Need to allocate buffers to reach Idle state */
1314 if (gst_omx_port_allocate_buffers (self->enc_in_port) != OMX_ErrorNone)
1317 if (gst_omx_component_set_state (self->enc,
1318 OMX_StateIdle) != OMX_ErrorNone)
1321 /* Need to allocate buffers to reach Idle state */
1322 #ifdef TIZEN_FEATURE_OMX
1323 if (gst_omx_port_tbm_allocate_enc_buffers(self->enc_in_port, self->bufmgr,
1324 self->enc_in_port->use_buffer) != OMX_ErrorNone)
1327 if (gst_omx_port_allocate_buffers (self->enc_in_port) != OMX_ErrorNone)
1331 #ifdef TIZEN_FEATURE_OMX
1332 if (gst_omx_port_tbm_allocate_enc_buffers(self->enc_out_port, self->bufmgr,
1333 self->enc_out_port->use_buffer) != OMX_ErrorNone)
1335 if (gst_omx_port_allocate_buffers (self->enc_out_port) != OMX_ErrorNone)
1340 if (gst_omx_component_get_state (self->enc,
1341 GST_CLOCK_TIME_NONE) != OMX_StateIdle)
1344 if (gst_omx_component_set_state (self->enc,
1345 OMX_StateExecuting) != OMX_ErrorNone)
1348 if (gst_omx_component_get_state (self->enc,
1349 GST_CLOCK_TIME_NONE) != OMX_StateExecuting)
1353 /* Unset flushing to allow ports to accept data again */
1354 gst_omx_port_set_flushing (self->enc_in_port, 5 * GST_SECOND, FALSE);
1355 gst_omx_port_set_flushing (self->enc_out_port, 5 * GST_SECOND, FALSE);
1357 if (gst_omx_component_get_last_error (self->enc) != OMX_ErrorNone) {
1358 GST_ERROR_OBJECT (self, "Component in error state: %s (0x%08x)",
1359 gst_omx_component_get_last_error_string (self->enc),
1360 gst_omx_component_get_last_error (self->enc));
1364 if (self->input_state)
1365 gst_video_codec_state_unref (self->input_state);
1366 self->input_state = gst_video_codec_state_ref (state);
1368 /* Start the srcpad loop again */
1369 GST_DEBUG_OBJECT (self, "Starting task again");
1370 self->downstream_flow_ret = GST_FLOW_OK;
1371 gst_pad_start_task (GST_VIDEO_ENCODER_SRC_PAD (self),
1372 (GstTaskFunction) gst_omx_video_enc_loop, encoder, NULL);
1378 gst_omx_video_enc_flush (GstVideoEncoder * encoder)
1380 GstOMXVideoEnc *self;
1382 self = GST_OMX_VIDEO_ENC (encoder);
1384 GST_DEBUG_OBJECT (self, "Flushing encoder");
1386 if (gst_omx_component_get_state (self->enc, 0) == OMX_StateLoaded)
1389 gst_omx_port_set_flushing (self->enc_in_port, 5 * GST_SECOND, TRUE);
1390 gst_omx_port_set_flushing (self->enc_out_port, 5 * GST_SECOND, TRUE);
1392 /* Wait until the srcpad loop is finished,
1393 * unlock GST_VIDEO_ENCODER_STREAM_LOCK to prevent deadlocks
1394 * caused by using this lock from inside the loop function */
1395 GST_VIDEO_ENCODER_STREAM_UNLOCK (self);
1396 GST_PAD_STREAM_LOCK (GST_VIDEO_ENCODER_SRC_PAD (self));
1397 GST_PAD_STREAM_UNLOCK (GST_VIDEO_ENCODER_SRC_PAD (self));
1398 GST_VIDEO_ENCODER_STREAM_LOCK (self);
1400 gst_omx_port_set_flushing (self->enc_in_port, 5 * GST_SECOND, FALSE);
1401 gst_omx_port_set_flushing (self->enc_out_port, 5 * GST_SECOND, FALSE);
1402 gst_omx_port_populate (self->enc_out_port);
1404 /* Start the srcpad loop again */
1405 self->last_upstream_ts = 0;
1406 self->downstream_flow_ret = GST_FLOW_OK;
1407 gst_pad_start_task (GST_VIDEO_ENCODER_SRC_PAD (self),
1408 (GstTaskFunction) gst_omx_video_enc_loop, encoder, NULL);
1414 gst_omx_video_enc_fill_buffer (GstOMXVideoEnc * self, GstBuffer * inbuf,
1415 GstOMXBuffer * outbuf)
1417 GstVideoCodecState *state = gst_video_codec_state_ref (self->input_state);
1418 GstVideoInfo *info = &state->info;
1419 OMX_PARAM_PORTDEFINITIONTYPE *port_def = &self->enc_in_port->port_def;
1420 gboolean ret = FALSE;
1421 GstVideoFrame frame;
1423 if (info->width != port_def->format.video.nFrameWidth ||
1424 info->height != port_def->format.video.nFrameHeight) {
1425 GST_ERROR_OBJECT (self, "Width or height do not match");
1428 #ifndef TIZEN_FEATURE_OMX
1429 /* Same strides and everything */
1430 if (gst_buffer_get_size (inbuf) ==
1431 outbuf->omx_buf->nAllocLen - outbuf->omx_buf->nOffset) {
1432 outbuf->omx_buf->nFilledLen = gst_buffer_get_size (inbuf);
1434 gst_buffer_extract (inbuf, 0,
1435 outbuf->omx_buf->pBuffer + outbuf->omx_buf->nOffset,
1436 outbuf->omx_buf->nFilledLen);
1441 /* Different strides */
1443 switch (info->finfo->format) {
1444 case GST_VIDEO_FORMAT_I420:{
1445 gint i, j, height, width;
1447 gint src_stride, dest_stride;
1449 outbuf->omx_buf->nFilledLen = 0;
1451 if (!gst_video_frame_map (&frame, info, inbuf, GST_MAP_READ)) {
1452 GST_ERROR_OBJECT (self, "Invalid input buffer size");
1457 for (i = 0; i < 3; i++) {
1459 dest_stride = port_def->format.video.nStride;
1460 src_stride = GST_VIDEO_FRAME_COMP_STRIDE (&frame, 0);
1462 /* XXX: Try this if no stride was set */
1463 if (dest_stride == 0)
1464 dest_stride = src_stride;
1466 dest_stride = port_def->format.video.nStride / 2;
1467 src_stride = GST_VIDEO_FRAME_COMP_STRIDE (&frame, 1);
1469 /* XXX: Try this if no stride was set */
1470 if (dest_stride == 0)
1471 dest_stride = src_stride;
1474 dest = outbuf->omx_buf->pBuffer + outbuf->omx_buf->nOffset;
1477 port_def->format.video.nSliceHeight *
1478 port_def->format.video.nStride;
1481 (port_def->format.video.nSliceHeight / 2) *
1482 (port_def->format.video.nStride / 2);
1484 src = GST_VIDEO_FRAME_COMP_DATA (&frame, i);
1485 height = GST_VIDEO_FRAME_COMP_HEIGHT (&frame, i);
1486 width = GST_VIDEO_FRAME_COMP_WIDTH (&frame, i);
1488 if (dest + dest_stride * height >
1489 outbuf->omx_buf->pBuffer + outbuf->omx_buf->nAllocLen) {
1490 gst_video_frame_unmap (&frame);
1491 GST_ERROR_OBJECT (self, "Invalid output buffer size");
1496 for (j = 0; j < height; j++) {
1497 memcpy (dest, src, width);
1498 outbuf->omx_buf->nFilledLen += dest_stride;
1500 dest += dest_stride;
1503 gst_video_frame_unmap (&frame);
1507 case GST_VIDEO_FORMAT_NV12:{
1508 gint i, j, height, width;
1510 gint src_stride, dest_stride;
1512 outbuf->omx_buf->nFilledLen = 0;
1514 if (!gst_video_frame_map (&frame, info, inbuf, GST_MAP_READ)) {
1515 GST_ERROR_OBJECT (self, "Invalid input buffer size");
1520 for (i = 0; i < 2; i++) {
1522 dest_stride = port_def->format.video.nStride;
1523 src_stride = GST_VIDEO_FRAME_COMP_STRIDE (&frame, 0);
1524 /* XXX: Try this if no stride was set */
1525 if (dest_stride == 0)
1526 dest_stride = src_stride;
1528 dest_stride = port_def->format.video.nStride;
1529 src_stride = GST_VIDEO_FRAME_COMP_STRIDE (&frame, 1);
1531 /* XXX: Try this if no stride was set */
1532 if (dest_stride == 0)
1533 dest_stride = src_stride;
1536 dest = outbuf->omx_buf->pBuffer + outbuf->omx_buf->nOffset;
1539 port_def->format.video.nSliceHeight *
1540 port_def->format.video.nStride;
1542 src = GST_VIDEO_FRAME_COMP_DATA (&frame, i);
1543 height = GST_VIDEO_FRAME_COMP_HEIGHT (&frame, i);
1544 width = GST_VIDEO_FRAME_COMP_WIDTH (&frame, i) * (i == 0 ? 1 : 2);
1546 if (dest + dest_stride * height >
1547 outbuf->omx_buf->pBuffer + outbuf->omx_buf->nAllocLen) {
1548 gst_video_frame_unmap (&frame);
1549 GST_ERROR_OBJECT (self, "Invalid output buffer size");
1554 for (j = 0; j < height; j++) {
1555 memcpy (dest, src, width);
1556 outbuf->omx_buf->nFilledLen += dest_stride;
1558 dest += dest_stride;
1562 gst_video_frame_unmap (&frame);
1566 case GST_VIDEO_FORMAT_ST12:
1567 case GST_VIDEO_FORMAT_SN12:
1569 GstMemory* ext_memory = gst_buffer_peek_memory(inbuf, 1);
1570 GstMapInfo ext_info = GST_MAP_INFO_INIT;
1571 MMVideoBuffer *mm_vbuffer = NULL;
1574 GST_WARNING_OBJECT (self, "null MMVideoBuffer pointer in hw color format. skip this.");
1578 gst_memory_map(ext_memory, &ext_info, GST_MAP_READ);
1579 mm_vbuffer = (MMVideoBuffer*)ext_info.data;
1580 gst_memory_unmap(ext_memory, &ext_info);
1582 if (mm_vbuffer != NULL && mm_vbuffer->type == MM_VIDEO_BUFFER_TYPE_TBM_BO) {
1583 mm_vbuffer->handle.dmabuf_fd[0] = tbm_bo_get_handle (mm_vbuffer->handle.bo[0], TBM_DEVICE_MM).u32;
1584 mm_vbuffer->handle.dmabuf_fd[1] = tbm_bo_get_handle (mm_vbuffer->handle.bo[1], TBM_DEVICE_MM).u32;
1585 mm_vbuffer->data[0] = tbm_bo_get_handle (mm_vbuffer->handle.bo[0], TBM_DEVICE_CPU).ptr;
1586 mm_vbuffer->data[1] = tbm_bo_get_handle (mm_vbuffer->handle.bo[1], TBM_DEVICE_CPU).ptr;
1588 GST_LOG_OBJECT (self, "enc. fd[0]:%d fd[1]:%d a[0]:%p, a[1]:%p, w[0]:%d h[0]:%d %d, %d, buf_share_method:%d",
1589 mm_vbuffer->handle.dmabuf_fd[0], mm_vbuffer->handle.dmabuf_fd[1], mm_vbuffer->data[0], mm_vbuffer->data[1],
1590 mm_vbuffer->width[0], mm_vbuffer->height[0], mm_vbuffer->width[1], mm_vbuffer->height[1], mm_vbuffer->type);
1592 outbuf->omx_buf->nAllocLen = sizeof (MMVideoBuffer);
1593 outbuf->omx_buf->nFilledLen = sizeof (MMVideoBuffer);
1594 memcpy (outbuf->omx_buf->pBuffer, mm_vbuffer, sizeof (MMVideoBuffer));
1596 GST_WARNING_OBJECT (self, "enc input has wrong buf");
1599 #ifdef CODEC_ENC_INPUT_DUMP
1600 gst_omx_video_enc_input_dump(mm_vbuffer);
1607 GST_ERROR_OBJECT (self, "Unsupported format");
1614 gst_video_codec_state_unref (state);
1619 static GstFlowReturn
1620 gst_omx_video_enc_handle_frame (GstVideoEncoder * encoder,
1621 GstVideoCodecFrame * frame)
1623 GstOMXAcquireBufferReturn acq_ret = GST_OMX_ACQUIRE_BUFFER_ERROR;
1624 GstOMXVideoEnc *self;
1629 self = GST_OMX_VIDEO_ENC (encoder);
1631 GST_DEBUG_OBJECT (self, "Handling frame");
1633 if (self->downstream_flow_ret != GST_FLOW_OK) {
1634 gst_video_codec_frame_unref (frame);
1635 return self->downstream_flow_ret;
1638 port = self->enc_in_port;
1640 while (acq_ret != GST_OMX_ACQUIRE_BUFFER_OK) {
1641 GstClockTime timestamp, duration;
1643 /* Make sure to release the base class stream lock, otherwise
1644 * _loop() can't call _finish_frame() and we might block forever
1645 * because no input buffers are released */
1646 GST_VIDEO_ENCODER_STREAM_UNLOCK (self);
1647 acq_ret = gst_omx_port_acquire_buffer (port, &buf);
1649 if (acq_ret == GST_OMX_ACQUIRE_BUFFER_ERROR) {
1650 GST_VIDEO_ENCODER_STREAM_LOCK (self);
1651 goto component_error;
1652 } else if (acq_ret == GST_OMX_ACQUIRE_BUFFER_FLUSHING) {
1653 GST_VIDEO_ENCODER_STREAM_LOCK (self);
1655 } else if (acq_ret == GST_OMX_ACQUIRE_BUFFER_RECONFIGURE) {
1656 /* Reallocate all buffers */
1657 err = gst_omx_port_set_enabled (port, FALSE);
1658 if (err != OMX_ErrorNone) {
1659 GST_VIDEO_ENCODER_STREAM_LOCK (self);
1660 goto reconfigure_error;
1663 err = gst_omx_port_wait_buffers_released (port, 5 * GST_SECOND);
1664 if (err != OMX_ErrorNone) {
1665 GST_VIDEO_ENCODER_STREAM_LOCK (self);
1666 goto reconfigure_error;
1669 err = gst_omx_port_deallocate_buffers (port);
1670 if (err != OMX_ErrorNone) {
1671 GST_VIDEO_ENCODER_STREAM_LOCK (self);
1672 goto reconfigure_error;
1675 err = gst_omx_port_wait_enabled (port, 1 * GST_SECOND);
1676 if (err != OMX_ErrorNone) {
1677 GST_VIDEO_ENCODER_STREAM_LOCK (self);
1678 goto reconfigure_error;
1681 err = gst_omx_port_set_enabled (port, TRUE);
1682 if (err != OMX_ErrorNone) {
1683 GST_VIDEO_ENCODER_STREAM_LOCK (self);
1684 goto reconfigure_error;
1686 #ifdef TIZEN_FEATURE_OMX
1687 err = gst_omx_port_tbm_allocate_enc_buffers (port, self->bufmgr, port->use_buffer);
1689 err = gst_omx_port_allocate_buffers (port);
1691 if (err != OMX_ErrorNone) {
1692 GST_VIDEO_ENCODER_STREAM_LOCK (self);
1693 goto reconfigure_error;
1696 err = gst_omx_port_wait_enabled (port, 5 * GST_SECOND);
1697 if (err != OMX_ErrorNone) {
1698 GST_VIDEO_ENCODER_STREAM_LOCK (self);
1699 goto reconfigure_error;
1702 err = gst_omx_port_mark_reconfigured (port);
1703 if (err != OMX_ErrorNone) {
1704 GST_VIDEO_ENCODER_STREAM_LOCK (self);
1705 goto reconfigure_error;
1708 /* Now get a new buffer and fill it */
1709 GST_VIDEO_ENCODER_STREAM_LOCK (self);
1712 GST_VIDEO_ENCODER_STREAM_LOCK (self);
1714 g_assert (acq_ret == GST_OMX_ACQUIRE_BUFFER_OK && buf != NULL);
1716 if (buf->omx_buf->nAllocLen - buf->omx_buf->nOffset <= 0) {
1717 gst_omx_port_release_buffer (port, buf);
1721 if (self->downstream_flow_ret != GST_FLOW_OK) {
1722 gst_omx_port_release_buffer (port, buf);
1726 /* Now handle the frame */
1727 GST_DEBUG_OBJECT (self, "Handling frame");
1729 if (GST_VIDEO_CODEC_FRAME_IS_FORCE_KEYFRAME (frame)) {
1730 #ifdef USE_OMX_TARGET_RPI
1731 OMX_CONFIG_BOOLEANTYPE config;
1733 GST_OMX_INIT_STRUCT (&config);
1734 config.bEnabled = OMX_TRUE;
1736 GST_DEBUG_OBJECT (self, "Forcing a keyframe (iframe on the RPi)");
1739 gst_omx_component_set_config (self->enc,
1740 OMX_IndexConfigBrcmVideoRequestIFrame, &config);
1742 OMX_CONFIG_INTRAREFRESHVOPTYPE config;
1744 GST_OMX_INIT_STRUCT (&config);
1745 config.nPortIndex = port->index;
1746 config.IntraRefreshVOP = OMX_TRUE;
1748 GST_DEBUG_OBJECT (self, "Forcing a keyframe");
1750 gst_omx_component_set_config (self->enc,
1751 OMX_IndexConfigVideoIntraVOPRefresh, &config);
1753 if (err != OMX_ErrorNone)
1754 GST_ERROR_OBJECT (self, "Failed to force a keyframe: %s (0x%08x)",
1755 gst_omx_error_to_string (err), err);
1758 /* Copy the buffer content in chunks of size as requested
1760 if (!gst_omx_video_enc_fill_buffer (self, frame->input_buffer, buf)) {
1761 gst_omx_port_release_buffer (port, buf);
1762 goto buffer_fill_error;
1765 timestamp = frame->pts;
1766 if (timestamp != GST_CLOCK_TIME_NONE) {
1767 buf->omx_buf->nTimeStamp =
1768 gst_util_uint64_scale (timestamp, OMX_TICKS_PER_SECOND, GST_SECOND);
1769 self->last_upstream_ts = timestamp;
1772 duration = frame->duration;
1773 if (duration != GST_CLOCK_TIME_NONE) {
1774 buf->omx_buf->nTickCount =
1775 gst_util_uint64_scale (duration, OMX_TICKS_PER_SECOND, GST_SECOND);
1776 self->last_upstream_ts += duration;
1778 buf->omx_buf->nTickCount = 0;
1781 self->started = TRUE;
1782 err = gst_omx_port_release_buffer (port, buf);
1783 if (err != OMX_ErrorNone)
1786 GST_DEBUG_OBJECT (self, "Passed frame to component");
1789 gst_video_codec_frame_unref (frame);
1791 return self->downstream_flow_ret;
1795 GST_ELEMENT_ERROR (self, LIBRARY, FAILED, (NULL),
1796 ("Got OpenMAX buffer with no free space (%p, %u/%u)", buf,
1797 (guint) buf->omx_buf->nOffset, (guint) buf->omx_buf->nAllocLen));
1798 gst_video_codec_frame_unref (frame);
1799 return GST_FLOW_ERROR;
1804 gst_video_codec_frame_unref (frame);
1805 return self->downstream_flow_ret;
1810 GST_ELEMENT_ERROR (self, LIBRARY, FAILED, (NULL),
1811 ("OpenMAX component in error state %s (0x%08x)",
1812 gst_omx_component_get_last_error_string (self->enc),
1813 gst_omx_component_get_last_error (self->enc)));
1814 gst_video_codec_frame_unref (frame);
1815 return GST_FLOW_ERROR;
1820 GST_DEBUG_OBJECT (self, "Flushing -- returning FLUSHING");
1821 gst_video_codec_frame_unref (frame);
1822 return GST_FLOW_FLUSHING;
1826 GST_ELEMENT_ERROR (self, LIBRARY, SETTINGS, (NULL),
1827 ("Unable to reconfigure input port"));
1828 gst_video_codec_frame_unref (frame);
1829 return GST_FLOW_ERROR;
1833 GST_ELEMENT_ERROR (self, RESOURCE, WRITE, (NULL),
1834 ("Failed to write input into the OpenMAX buffer"));
1835 gst_video_codec_frame_unref (frame);
1836 return GST_FLOW_ERROR;
1840 gst_video_codec_frame_unref (frame);
1841 GST_ELEMENT_ERROR (self, LIBRARY, SETTINGS, (NULL),
1842 ("Failed to relase input buffer to component: %s (0x%08x)",
1843 gst_omx_error_to_string (err), err));
1844 return GST_FLOW_ERROR;
1848 static GstFlowReturn
1849 gst_omx_video_enc_finish (GstVideoEncoder * encoder)
1851 GstOMXVideoEnc *self;
1853 self = GST_OMX_VIDEO_ENC (encoder);
1855 return gst_omx_video_enc_drain (self);
1858 static GstFlowReturn
1859 gst_omx_video_enc_drain (GstOMXVideoEnc * self)
1861 GstOMXVideoEncClass *klass;
1863 GstOMXAcquireBufferReturn acq_ret;
1866 GST_DEBUG_OBJECT (self, "Draining component");
1868 klass = GST_OMX_VIDEO_ENC_GET_CLASS (self);
1870 if (!self->started) {
1871 GST_DEBUG_OBJECT (self, "Component not started yet");
1874 self->started = FALSE;
1876 if ((klass->cdata.hacks & GST_OMX_HACK_NO_EMPTY_EOS_BUFFER)) {
1877 GST_WARNING_OBJECT (self, "Component does not support empty EOS buffers");
1881 /* Make sure to release the base class stream lock, otherwise
1882 * _loop() can't call _finish_frame() and we might block forever
1883 * because no input buffers are released */
1884 GST_VIDEO_ENCODER_STREAM_UNLOCK (self);
1886 /* Send an EOS buffer to the component and let the base
1887 * class drop the EOS event. We will send it later when
1888 * the EOS buffer arrives on the output port. */
1889 acq_ret = gst_omx_port_acquire_buffer (self->enc_in_port, &buf);
1890 if (acq_ret != GST_OMX_ACQUIRE_BUFFER_OK) {
1891 GST_VIDEO_ENCODER_STREAM_LOCK (self);
1892 GST_ERROR_OBJECT (self, "Failed to acquire buffer for draining: %d",
1894 return GST_FLOW_ERROR;
1897 g_mutex_lock (&self->drain_lock);
1898 self->draining = TRUE;
1899 buf->omx_buf->nFilledLen = 0;
1900 buf->omx_buf->nTimeStamp =
1901 gst_util_uint64_scale (self->last_upstream_ts, OMX_TICKS_PER_SECOND,
1903 buf->omx_buf->nTickCount = 0;
1904 buf->omx_buf->nFlags |= OMX_BUFFERFLAG_EOS;
1905 err = gst_omx_port_release_buffer (self->enc_in_port, buf);
1906 if (err != OMX_ErrorNone) {
1907 GST_ERROR_OBJECT (self, "Failed to drain component: %s (0x%08x)",
1908 gst_omx_error_to_string (err), err);
1909 GST_VIDEO_ENCODER_STREAM_LOCK (self);
1910 return GST_FLOW_ERROR;
1912 GST_DEBUG_OBJECT (self, "Waiting until component is drained");
1913 g_cond_wait (&self->drain_cond, &self->drain_lock);
1914 GST_DEBUG_OBJECT (self, "Drained component");
1915 g_mutex_unlock (&self->drain_lock);
1916 GST_VIDEO_ENCODER_STREAM_LOCK (self);
1918 self->started = FALSE;
1924 gst_omx_video_enc_propose_allocation (GstVideoEncoder * encoder,
1927 gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL);
1930 GST_VIDEO_ENCODER_CLASS
1931 (gst_omx_video_enc_parent_class)->propose_allocation (encoder, query);
1935 gst_omx_video_enc_getcaps (GstVideoEncoder * encoder, GstCaps * filter)
1937 GstOMXVideoEnc *self = GST_OMX_VIDEO_ENC (encoder);
1938 GList *negotiation_map = NULL;
1939 GstCaps *comp_supported_caps;
1942 return gst_video_encoder_proxy_getcaps (encoder, NULL, filter);
1945 gst_omx_video_get_supported_colorformats (self->enc_in_port,
1947 comp_supported_caps = gst_omx_video_get_caps_for_map (negotiation_map);
1948 g_list_free_full (negotiation_map,
1949 (GDestroyNotify) gst_omx_video_negotiation_map_free);
1951 if (!gst_caps_is_empty (comp_supported_caps)) {
1953 gst_video_encoder_proxy_getcaps (encoder, comp_supported_caps, filter);
1955 gst_caps_unref (comp_supported_caps);
1958 gst_caps_unref (comp_supported_caps);
1959 return gst_video_encoder_proxy_getcaps (encoder, NULL, filter);