Added exception handling for null buffer
[platform/upstream/gstreamer.git] / omx / gstomxvideodec.c
1 /*
2  * Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
3  *   Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
4  * Copyright (C) 2013, Collabora Ltd.
5  *   Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation
10  * version 2.1 of the License.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
20  *
21  */
22
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include <gst/gst.h>
28
29 #if defined (USE_OMX_TARGET_RPI) && defined(__GNUC__)
30 #ifndef __VCCOREVER__
31 #define __VCCOREVER__ 0x04000000
32 #endif
33
34 #pragma GCC diagnostic push
35 #pragma GCC diagnostic ignored "-Wredundant-decls"
36 #pragma GCC optimize ("gnu89-inline")
37 #endif
38
39 #if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
40 #include <gst/gl/gl.h>
41 #include <gst/gl/egl/gsteglimagememory.h>
42 #endif
43
44 #if defined (USE_OMX_TARGET_RPI) && defined(__GNUC__)
45 #pragma GCC reset_options
46 #pragma GCC diagnostic pop
47 #endif
48
49 //#define CODEC_DEC_INTPUT_DUMP
50 //#define CODEC_DEC_OUTPUT_DUMP
51 #include <stdio.h>
52 #include <string.h>
53
54 #include "gstomxbufferpool.h"
55 #include "gstomxvideo.h"
56 #include "gstomxvideodec.h"
57
58 GST_DEBUG_CATEGORY_STATIC (gst_omx_video_dec_debug_category);
59 #define GST_CAT_DEFAULT gst_omx_video_dec_debug_category
60
61 /* prototypes */
62 static void gst_omx_video_dec_finalize (GObject * object);
63
64 static GstStateChangeReturn
65 gst_omx_video_dec_change_state (GstElement * element,
66     GstStateChange transition);
67
68 static gboolean gst_omx_video_dec_open (GstVideoDecoder * decoder);
69 static gboolean gst_omx_video_dec_close (GstVideoDecoder * decoder);
70 static gboolean gst_omx_video_dec_start (GstVideoDecoder * decoder);
71 static gboolean gst_omx_video_dec_stop (GstVideoDecoder * decoder);
72 static gboolean gst_omx_video_dec_set_format (GstVideoDecoder * decoder,
73     GstVideoCodecState * state);
74 static gboolean gst_omx_video_dec_flush (GstVideoDecoder * decoder);
75 static GstFlowReturn gst_omx_video_dec_handle_frame (GstVideoDecoder * decoder,
76     GstVideoCodecFrame * frame);
77 static GstFlowReturn gst_omx_video_dec_finish (GstVideoDecoder * decoder);
78 static gboolean gst_omx_video_dec_decide_allocation (GstVideoDecoder * bdec,
79     GstQuery * query);
80
81 static GstFlowReturn gst_omx_video_dec_drain (GstOMXVideoDec * self);
82
83 static OMX_ERRORTYPE gst_omx_video_dec_allocate_output_buffers (GstOMXVideoDec *
84     self);
85 static OMX_ERRORTYPE gst_omx_video_dec_deallocate_output_buffers (GstOMXVideoDec
86     * self);
87
88 #ifdef TIZEN_FEATURE_OMX
89 static gboolean gst_omx_video_dec_acquire_request_flush_buffer (GstOMXVideoDec * self, GstBuffer ** flush_request_buffer);
90 static gboolean gst_omx_video_dec_handle_event (GstVideoDecoder * decoder, GstEvent *event);
91 #endif
92
93 enum
94 {
95   PROP_0
96 };
97
98 /* class initialization */
99
100 #define DEBUG_INIT \
101   GST_DEBUG_CATEGORY_INIT (gst_omx_video_dec_debug_category, "omxvideodec", 0, \
102       "debug category for gst-omx video decoder base class");
103
104
105 G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GstOMXVideoDec, gst_omx_video_dec,
106     GST_TYPE_VIDEO_DECODER, DEBUG_INIT);
107
108 static void
109 gst_omx_video_dec_class_init (GstOMXVideoDecClass * klass)
110 {
111   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
112   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
113   GstVideoDecoderClass *video_decoder_class = GST_VIDEO_DECODER_CLASS (klass);
114
115   gobject_class->finalize = gst_omx_video_dec_finalize;
116
117   element_class->change_state =
118       GST_DEBUG_FUNCPTR (gst_omx_video_dec_change_state);
119
120   video_decoder_class->open = GST_DEBUG_FUNCPTR (gst_omx_video_dec_open);
121   video_decoder_class->close = GST_DEBUG_FUNCPTR (gst_omx_video_dec_close);
122   video_decoder_class->start = GST_DEBUG_FUNCPTR (gst_omx_video_dec_start);
123   video_decoder_class->stop = GST_DEBUG_FUNCPTR (gst_omx_video_dec_stop);
124   video_decoder_class->flush = GST_DEBUG_FUNCPTR (gst_omx_video_dec_flush);
125   video_decoder_class->set_format =
126       GST_DEBUG_FUNCPTR (gst_omx_video_dec_set_format);
127   video_decoder_class->handle_frame =
128       GST_DEBUG_FUNCPTR (gst_omx_video_dec_handle_frame);
129   video_decoder_class->finish = GST_DEBUG_FUNCPTR (gst_omx_video_dec_finish);
130   video_decoder_class->decide_allocation =
131       GST_DEBUG_FUNCPTR (gst_omx_video_dec_decide_allocation);
132
133 #ifdef TIZEN_FEATURE_OMX
134   video_decoder_class->sink_event = GST_DEBUG_FUNCPTR (gst_omx_video_dec_handle_event);
135 #endif
136
137   klass->cdata.type = GST_OMX_COMPONENT_TYPE_FILTER;
138   klass->cdata.default_src_template_caps =
139 #if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
140       GST_VIDEO_CAPS_MAKE_WITH_FEATURES (GST_CAPS_FEATURE_MEMORY_EGL_IMAGE,
141       "RGBA") "; "
142 #endif
143       "video/x-raw, "
144       "width = " GST_VIDEO_SIZE_RANGE ", "
145           "height = " GST_VIDEO_SIZE_RANGE ", " "framerate = " GST_VIDEO_FPS_RANGE ", "
146       "format = (string)SN12";
147 }
148
149 static void
150 gst_omx_video_dec_init (GstOMXVideoDec * self)
151 {
152   gst_video_decoder_set_packetized (GST_VIDEO_DECODER (self), TRUE);
153   gst_video_decoder_set_use_default_pad_acceptcaps (GST_VIDEO_DECODER_CAST
154       (self), TRUE);
155   GST_PAD_SET_ACCEPT_TEMPLATE (GST_VIDEO_DECODER_SINK_PAD (self));
156
157   g_mutex_init (&self->drain_lock);
158   g_cond_init (&self->drain_cond);
159
160 #ifdef TIZEN_FEATURE_OMX
161   self->bufmgr = NULL;
162   self->drm_fd = -1;
163 #endif
164 }
165
166 static gboolean
167 gst_omx_video_dec_open (GstVideoDecoder * decoder)
168 {
169   GstOMXVideoDec *self = GST_OMX_VIDEO_DEC (decoder);
170   GstOMXVideoDecClass *klass = GST_OMX_VIDEO_DEC_GET_CLASS (self);
171   gint in_port_index, out_port_index;
172
173   GST_DEBUG_OBJECT (self, "Opening decoder");
174
175   self->dec =
176       gst_omx_component_new (GST_OBJECT_CAST (self), klass->cdata.core_name,
177       klass->cdata.component_name, klass->cdata.component_role,
178       klass->cdata.hacks);
179   self->started = FALSE;
180
181   if (!self->dec)
182     return FALSE;
183
184   if (gst_omx_component_get_state (self->dec,
185           GST_CLOCK_TIME_NONE) != OMX_StateLoaded)
186     return FALSE;
187
188   in_port_index = klass->cdata.in_port_index;
189   out_port_index = klass->cdata.out_port_index;
190
191   if (in_port_index == -1 || out_port_index == -1) {
192     OMX_PORT_PARAM_TYPE param;
193     OMX_ERRORTYPE err;
194
195     GST_OMX_INIT_STRUCT (&param);
196
197     err =
198         gst_omx_component_get_parameter (self->dec, OMX_IndexParamVideoInit,
199         &param);
200     if (err != OMX_ErrorNone) {
201       GST_WARNING_OBJECT (self, "Couldn't get port information: %s (0x%08x)",
202           gst_omx_error_to_string (err), err);
203       /* Fallback */
204       in_port_index = 0;
205       out_port_index = 1;
206     } else {
207       GST_DEBUG_OBJECT (self, "Detected %u ports, starting at %u",
208           (guint) param.nPorts, (guint) param.nStartPortNumber);
209       in_port_index = param.nStartPortNumber + 0;
210       out_port_index = param.nStartPortNumber + 1;
211     }
212   }
213
214   self->dec_in_port = gst_omx_component_add_port (self->dec, in_port_index);
215   self->dec_out_port = gst_omx_component_add_port (self->dec, out_port_index);
216
217   if (!self->dec_in_port || !self->dec_out_port)
218     return FALSE;
219
220 #ifdef TIZEN_FEATURE_OMX
221   self->bufmgr = tbm_bufmgr_init(self->drm_fd);
222   if (self->bufmgr == NULL) {
223     GST_ERROR_OBJECT (self, "TBM initialization failed.");
224     return FALSE;
225   }
226
227 #if defined(USE_OMX_TARGET_EXYNOS) || defined(USE_OMX_TARGET_EXYNOS64)
228   {
229     /* set plateform specific gem buffer settings. */
230     OMX_ERRORTYPE err;
231     EnableGemBuffersParams gem_param;
232     OMX_INDEXTYPE index = OMX_IndexComponentStartUnused;
233
234     err = gst_omx_component_get_extension_index (self->dec, (OMX_STRING) EXYNOS_INDEX_PARAM_STORE_METADATA_BUFFER, &index);
235     if (err != OMX_ErrorNone) {
236       GST_WARNING_OBJECT (self, "Failed to get extension index : %s (0x%08x)",
237           gst_omx_error_to_string (err), err);
238     }
239
240     OMX_INIT_PARAM (gem_param);
241     gem_param.enable = OMX_TRUE;
242     gem_param.nPortIndex = 1;
243
244     err = gst_omx_component_set_parameter(self->dec, index, &gem_param);
245     if (err != OMX_ErrorNone) {
246       GST_ERROR_OBJECT (self, "Failed to set platform specific buffer: %s (0x%08x)",
247           gst_omx_error_to_string (err), err);
248     }
249
250     self->dec_in_port->use_buffer = klass->cdata.in_port_usebuffer;
251     self->dec_out_port->use_buffer = klass->cdata.out_port_usebuffer;
252   }
253 #endif
254 #endif
255
256   GST_DEBUG_OBJECT (self, "Opened decoder");
257
258 #if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
259   GST_DEBUG_OBJECT (self, "Opening EGL renderer");
260   self->egl_render =
261       gst_omx_component_new (GST_OBJECT_CAST (self), klass->cdata.core_name,
262       "OMX.broadcom.egl_render", NULL, klass->cdata.hacks);
263
264   if (!self->egl_render)
265     return FALSE;
266
267   if (gst_omx_component_get_state (self->egl_render,
268           GST_CLOCK_TIME_NONE) != OMX_StateLoaded)
269     return FALSE;
270
271   {
272     OMX_PORT_PARAM_TYPE param;
273     OMX_ERRORTYPE err;
274
275     GST_OMX_INIT_STRUCT (&param);
276
277     err =
278         gst_omx_component_get_parameter (self->egl_render,
279         OMX_IndexParamVideoInit, &param);
280     if (err != OMX_ErrorNone) {
281       GST_WARNING_OBJECT (self, "Couldn't get port information: %s (0x%08x)",
282           gst_omx_error_to_string (err), err);
283       /* Fallback */
284       in_port_index = 0;
285       out_port_index = 1;
286     } else {
287       GST_DEBUG_OBJECT (self, "Detected %u ports, starting at %u", param.nPorts,
288           param.nStartPortNumber);
289       in_port_index = param.nStartPortNumber + 0;
290       out_port_index = param.nStartPortNumber + 1;
291     }
292   }
293
294   self->egl_in_port =
295       gst_omx_component_add_port (self->egl_render, in_port_index);
296   self->egl_out_port =
297       gst_omx_component_add_port (self->egl_render, out_port_index);
298
299   if (!self->egl_in_port || !self->egl_out_port)
300     return FALSE;
301
302   GST_DEBUG_OBJECT (self, "Opened EGL renderer");
303 #endif
304
305   return TRUE;
306 }
307
308 static gboolean
309 gst_omx_video_dec_shutdown (GstOMXVideoDec * self)
310 {
311   OMX_STATETYPE state;
312
313   GST_DEBUG_OBJECT (self, "Shutting down decoder");
314
315 #if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
316   state = gst_omx_component_get_state (self->egl_render, 0);
317   if (state > OMX_StateLoaded || state == OMX_StateInvalid) {
318     if (state > OMX_StateIdle) {
319       gst_omx_component_set_state (self->egl_render, OMX_StateIdle);
320       gst_omx_component_set_state (self->dec, OMX_StateIdle);
321       gst_omx_component_get_state (self->egl_render, 5 * GST_SECOND);
322       gst_omx_component_get_state (self->dec, 1 * GST_SECOND);
323     }
324     gst_omx_component_set_state (self->egl_render, OMX_StateLoaded);
325     gst_omx_component_set_state (self->dec, OMX_StateLoaded);
326
327     gst_omx_port_deallocate_buffers (self->dec_in_port);
328     gst_omx_video_dec_deallocate_output_buffers (self);
329     gst_omx_close_tunnel (self->dec_out_port, self->egl_in_port);
330     if (state > OMX_StateLoaded) {
331       gst_omx_component_get_state (self->egl_render, 5 * GST_SECOND);
332       gst_omx_component_get_state (self->dec, 1 * GST_SECOND);
333     }
334   }
335
336   /* Otherwise we didn't use EGL and just fall back to
337    * shutting down the decoder */
338 #endif
339
340   state = gst_omx_component_get_state (self->dec, 0);
341   if (state > OMX_StateLoaded || state == OMX_StateInvalid) {
342     if (state > OMX_StateIdle) {
343       gst_omx_component_set_state (self->dec, OMX_StateIdle);
344       gst_omx_component_get_state (self->dec, 5 * GST_SECOND);
345     }
346     gst_omx_component_set_state (self->dec, OMX_StateLoaded);
347     gst_omx_port_deallocate_buffers (self->dec_in_port);
348     gst_omx_video_dec_deallocate_output_buffers (self);
349     if (state > OMX_StateLoaded)
350       gst_omx_component_get_state (self->dec, 5 * GST_SECOND);
351   }
352
353 #ifdef TIZEN_FEATURE_OMX
354    /* uninitialize tbm buffer manager */
355    if(self->bufmgr != NULL){
356     tbm_bufmgr_deinit(self->bufmgr);
357     self->bufmgr = NULL;
358    }
359
360    if(self->drm_fd != -1) {
361        GST_DEBUG_OBJECT (self, "close drm fd");
362        close(self->drm_fd);
363        self->drm_fd = -1;
364    }
365 #endif
366
367   return TRUE;
368 }
369
370 static gboolean
371 gst_omx_video_dec_close (GstVideoDecoder * decoder)
372 {
373   GstOMXVideoDec *self = GST_OMX_VIDEO_DEC (decoder);
374
375   GST_DEBUG_OBJECT (self, "Closing decoder");
376
377   if (!gst_omx_video_dec_shutdown (self))
378     return FALSE;
379
380   self->dec_in_port = NULL;
381   self->dec_out_port = NULL;
382   if (self->dec)
383     gst_omx_component_free (self->dec);
384   self->dec = NULL;
385
386 #if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
387   self->egl_in_port = NULL;
388   self->egl_out_port = NULL;
389   if (self->egl_render)
390     gst_omx_component_free (self->egl_render);
391   self->egl_render = NULL;
392 #endif
393
394   self->started = FALSE;
395
396   GST_DEBUG_OBJECT (self, "Closed decoder");
397
398   return TRUE;
399 }
400
401 static void
402 gst_omx_video_dec_finalize (GObject * object)
403 {
404   GstOMXVideoDec *self = GST_OMX_VIDEO_DEC (object);
405
406   g_mutex_clear (&self->drain_lock);
407   g_cond_clear (&self->drain_cond);
408
409   G_OBJECT_CLASS (gst_omx_video_dec_parent_class)->finalize (object);
410 }
411
412 static GstStateChangeReturn
413 gst_omx_video_dec_change_state (GstElement * element, GstStateChange transition)
414 {
415   GstOMXVideoDec *self;
416   GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
417
418   g_return_val_if_fail (GST_IS_OMX_VIDEO_DEC (element),
419       GST_STATE_CHANGE_FAILURE);
420   self = GST_OMX_VIDEO_DEC (element);
421
422   switch (transition) {
423     case GST_STATE_CHANGE_NULL_TO_READY:
424       break;
425     case GST_STATE_CHANGE_READY_TO_PAUSED:
426       self->downstream_flow_ret = GST_FLOW_OK;
427       self->draining = FALSE;
428       self->started = FALSE;
429       break;
430     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
431       break;
432     case GST_STATE_CHANGE_PAUSED_TO_READY:
433       if (self->dec_in_port)
434         gst_omx_port_set_flushing (self->dec_in_port, 5 * GST_SECOND, TRUE);
435       if (self->dec_out_port)
436         gst_omx_port_set_flushing (self->dec_out_port, 5 * GST_SECOND, TRUE);
437 #if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
438       if (self->egl_in_port)
439         gst_omx_port_set_flushing (self->egl_in_port, 5 * GST_SECOND, TRUE);
440       if (self->egl_out_port)
441         gst_omx_port_set_flushing (self->egl_out_port, 5 * GST_SECOND, TRUE);
442 #endif
443
444       g_mutex_lock (&self->drain_lock);
445       self->draining = FALSE;
446       g_cond_broadcast (&self->drain_cond);
447       g_mutex_unlock (&self->drain_lock);
448       break;
449     default:
450       break;
451   }
452
453   ret =
454       GST_ELEMENT_CLASS (gst_omx_video_dec_parent_class)->change_state
455       (element, transition);
456
457   if (ret == GST_STATE_CHANGE_FAILURE)
458     return ret;
459
460   switch (transition) {
461     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
462       break;
463     case GST_STATE_CHANGE_PAUSED_TO_READY:
464       self->downstream_flow_ret = GST_FLOW_FLUSHING;
465       self->started = FALSE;
466
467       if (!gst_omx_video_dec_shutdown (self))
468         ret = GST_STATE_CHANGE_FAILURE;
469       break;
470     case GST_STATE_CHANGE_READY_TO_NULL:
471       break;
472     default:
473       break;
474   }
475
476   return ret;
477 }
478
479 #ifdef CODEC_DEC_INTPUT_DUMP /* for decoder input dump */
480 static inline void
481 decoder_input_dump (GstOMXBuffer * buf, gboolean use_buffer)
482 {
483   gchar *temp;
484   gchar filename[100]={0};
485   FILE *fp = NULL;
486
487   temp = use_buffer ? buf->mm_vbuffer->data[0] : buf->omx_buf->pBuffer;
488
489   sprintf(filename, "/tmp/dec_input_dump.out");
490   fp = fopen(filename, "ab");
491
492   fwrite(temp, buf->omx_buf->nFilledLen, 1, fp);
493
494   fclose(fp);
495 }
496 #endif
497
498 #ifdef CODEC_DEC_OUTPUT_DUMP /* for decoder output dump */
499 static inline void
500 decoder_output_dump(GstOMXVideoDec *self, MMVideoBuffer *outbuf)
501 {
502   char *temp = (char *)outbuf->data[0];
503   int i = 0;
504   char filename[100]={0};
505   FILE *fp = NULL;
506   int ret =0;
507
508   GST_ERROR_OBJECT (self, "codec dec output dump start. w = %d, h = %d", outbuf->width[0], outbuf->height[0]);
509
510   sprintf(filename, "/tmp/dec_output_dump_%d_%d.yuv", outbuf->width[0], outbuf->height[0]);
511   fp = fopen(filename, "ab");
512
513   for (i = 0; i < outbuf->height[0]; i++) {
514     ret = fwrite(temp, outbuf->width[0], 1, fp);
515     temp += outbuf->stride_width[0];
516   }
517
518   temp = (char *)outbuf->data[1];
519
520   for(i = 0; i < outbuf->height[1]; i++) {
521    ret = fwrite(temp, outbuf->width[1], 1, fp);
522     temp += outbuf->stride_width[1];
523   }
524
525   GST_ERROR_OBJECT (self,"codec dec output dumped!! ret = %d", ret);
526   fclose(fp);
527 }
528 #endif
529
530 static gboolean
531 gst_omx_video_dec_fill_buffer (GstOMXVideoDec * self,
532     GstOMXBuffer * inbuf, GstBuffer * outbuf)
533 {
534   GstVideoCodecState *state =
535       gst_video_decoder_get_output_state (GST_VIDEO_DECODER (self));
536   GstVideoInfo *vinfo = &state->info;
537   OMX_PARAM_PORTDEFINITIONTYPE *port_def = &self->dec_out_port->port_def;
538   gboolean ret = FALSE;
539 #ifndef TIZEN_FEATURE_OMX
540   GstVideoFrame frame;
541 #endif
542
543   if (vinfo->width != port_def->format.video.nFrameWidth ||
544       vinfo->height != port_def->format.video.nFrameHeight) {
545     GST_ERROR_OBJECT (self, "Resolution do not match: port=%ux%u vinfo=%dx%d",
546         (guint) port_def->format.video.nFrameWidth,
547         (guint) port_def->format.video.nFrameHeight,
548         vinfo->width, vinfo->height);
549     goto done;
550   }
551
552   /* Same strides and everything */
553 #ifndef TIZEN_FEATURE_OMX
554   if (gst_buffer_get_size (outbuf) == inbuf->omx_buf->nFilledLen) {
555     GstMapInfo map = GST_MAP_INFO_INIT;
556
557     if (!gst_buffer_map (outbuf, &map, GST_MAP_WRITE)) {
558       GST_ERROR_OBJECT (self, "Failed to map output buffer");
559       goto done;
560     }
561
562     memcpy (map.data,
563         inbuf->omx_buf->pBuffer + inbuf->omx_buf->nOffset,
564         inbuf->omx_buf->nFilledLen);
565     gst_buffer_unmap (outbuf, &map);
566     ret = TRUE;
567     goto done;
568   }
569 #endif  //ENS:a
570
571   /* Different strides */
572 #ifndef TIZEN_FEATURE_OMX
573   if (gst_video_frame_map (&frame, vinfo, outbuf, GST_MAP_WRITE)) {
574   const guint nstride = port_def->format.video.nStride;
575   const guint nslice = port_def->format.video.nSliceHeight;
576   guint src_stride[GST_VIDEO_MAX_PLANES] = { nstride, 0, };
577   guint src_size[GST_VIDEO_MAX_PLANES] = { nstride * nslice, 0, };
578   gint dst_width[GST_VIDEO_MAX_PLANES] = { 0, };
579   gint dst_height[GST_VIDEO_MAX_PLANES] =
580       { GST_VIDEO_INFO_HEIGHT (vinfo), 0, };
581   const guint8 *src;
582   guint p;
583 #endif
584
585   switch (GST_VIDEO_INFO_FORMAT (vinfo)) {
586 #ifndef TIZEN_FEATURE_OMX
587     case GST_VIDEO_FORMAT_ABGR:
588     case GST_VIDEO_FORMAT_ARGB:
589       dst_width[0] = GST_VIDEO_INFO_WIDTH (vinfo) * 4;
590       break;
591     case GST_VIDEO_FORMAT_RGB16:
592     case GST_VIDEO_FORMAT_BGR16:
593     case GST_VIDEO_FORMAT_YUY2:
594     case GST_VIDEO_FORMAT_UYVY:
595     case GST_VIDEO_FORMAT_YVYU:
596       dst_width[0] = GST_VIDEO_INFO_WIDTH (vinfo) * 2;
597       break;
598     case GST_VIDEO_FORMAT_GRAY8:
599       dst_width[0] = GST_VIDEO_INFO_WIDTH (vinfo);
600       break;
601     case GST_VIDEO_FORMAT_I420:
602       dst_width[0] = GST_VIDEO_INFO_WIDTH (vinfo);
603       src_stride[1] = nstride / 2;
604       src_size[1] = (src_stride[1] * nslice) / 2;
605       dst_width[1] = GST_VIDEO_INFO_WIDTH (vinfo) / 2;
606       dst_height[1] = GST_VIDEO_INFO_HEIGHT (vinfo) / 2;
607       src_stride[2] = nstride / 2;
608       src_size[2] = (src_stride[1] * nslice) / 2;
609       dst_width[2] = GST_VIDEO_INFO_WIDTH (vinfo) / 2;
610       dst_height[2] = GST_VIDEO_INFO_HEIGHT (vinfo) / 2;
611       break;
612     case GST_VIDEO_FORMAT_NV12:
613       dst_width[0] = GST_VIDEO_INFO_WIDTH (vinfo);
614       src_stride[1] = nstride;
615       src_size[1] = src_stride[1] * nslice / 2;
616       dst_width[1] = GST_VIDEO_INFO_WIDTH (vinfo);
617       dst_height[1] = GST_VIDEO_INFO_HEIGHT (vinfo) / 2;
618       break;
619     case GST_VIDEO_FORMAT_NV16:
620       dst_width[0] = GST_VIDEO_INFO_WIDTH (vinfo);
621       src_stride[1] = nstride;
622       src_size[1] = src_stride[1] * nslice;
623       dst_width[1] = GST_VIDEO_INFO_WIDTH (vinfo);
624       dst_height[1] = GST_VIDEO_INFO_HEIGHT (vinfo);
625       break;
626 #endif
627 #ifdef TIZEN_FEATURE_OMX
628     case GST_VIDEO_FORMAT_SN12:
629     case GST_VIDEO_FORMAT_ST12: {
630       GstMemory *mem = NULL;
631       void *data = NULL;
632       MMVideoBuffer *mm_vbuffer = NULL;
633       mm_vbuffer = (MMVideoBuffer*)(inbuf->omx_buf->pBuffer);
634
635       if (mm_vbuffer->type == MM_VIDEO_BUFFER_TYPE_TBM_BO) {
636         GST_LOG_OBJECT (self, "dec output buf: bo[0] :%p, bo[1] : %p, fd[0]:%d  fd[1]:%d fd[2]:%d  w[0]:%d h[0]:%d  buf_share_method:%d",
637             mm_vbuffer->handle.bo[0], mm_vbuffer->handle.bo[1], mm_vbuffer->handle.dmabuf_fd[0], mm_vbuffer->handle.dmabuf_fd[1], mm_vbuffer->handle.dmabuf_fd[2],
638             mm_vbuffer->width[0], mm_vbuffer->height[0], mm_vbuffer->type);
639       } else if (mm_vbuffer->type == MM_VIDEO_BUFFER_TYPE_PHYSICAL_ADDRESS) {
640         GST_LOG_OBJECT (self, "dec output uses hw addr");
641       } else {
642         GST_WARNING_OBJECT (self, "dec output buf has TBM_BO buf_share_method");
643       }
644 #ifdef CODEC_DEC_OUTPUT_DUMP
645      decoder_output_dump(self, mm_vbuffer);
646 #endif
647       if (gst_buffer_n_memory (outbuf) < 2) {
648         data = g_malloc0 (sizeof (MMVideoBuffer));
649         mem = gst_memory_new_wrapped (0, data, sizeof (MMVideoBuffer), 0, sizeof (MMVideoBuffer), data, g_free);
650         gst_buffer_append_memory (outbuf, mem);
651       } else {
652         GstMapInfo info = GST_MAP_INFO_INIT;
653
654         mem = gst_buffer_peek_memory (outbuf, 1);
655         gst_memory_map (mem, &info, GST_MAP_WRITE);
656         data = info.data;
657         gst_memory_unmap (mem, &info);
658       }
659       memcpy (data, mm_vbuffer, sizeof (MMVideoBuffer));
660
661       ret = TRUE;
662       break;
663     }
664 #endif
665
666       default:
667         g_assert_not_reached ();
668         break;
669     }
670 #ifndef TIZEN_FEATURE_OMX
671     src = inbuf->omx_buf->pBuffer + inbuf->omx_buf->nOffset;
672     for (p = 0; p < GST_VIDEO_INFO_N_PLANES (vinfo); p++) {
673       const guint8 *data;
674       guint8 *dst;
675       guint h;
676
677       dst = GST_VIDEO_FRAME_PLANE_DATA (&frame, p);
678       data = src;
679       for (h = 0; h < dst_height[p]; h++) {
680         memcpy (dst, data, dst_width[p]);
681         dst += GST_VIDEO_INFO_PLANE_STRIDE (vinfo, p);
682         data += src_stride[p];
683       }
684       src += src_size[p];
685     }
686 #endif
687
688 #ifndef TIZEN_FEATURE_OMX
689     gst_video_frame_unmap (&frame);
690     ret = TRUE;
691   } else {
692     GST_ERROR_OBJECT (self, "Can't map output buffer to frame");
693     goto done;
694   }
695 #endif
696
697 done:
698   if (ret) {
699     GST_BUFFER_PTS (outbuf) =
700         gst_util_uint64_scale (inbuf->omx_buf->nTimeStamp, GST_SECOND,
701         OMX_TICKS_PER_SECOND);
702     if (inbuf->omx_buf->nTickCount != 0)
703       GST_BUFFER_DURATION (outbuf) =
704           gst_util_uint64_scale (inbuf->omx_buf->nTickCount, GST_SECOND,
705           OMX_TICKS_PER_SECOND);
706   }
707
708   gst_video_codec_state_unref (state);
709
710   return ret;
711 }
712
713 static OMX_ERRORTYPE
714 gst_omx_video_dec_allocate_output_buffers (GstOMXVideoDec * self)
715 {
716   OMX_ERRORTYPE err = OMX_ErrorNone;
717   GstOMXPort *port;
718   GstBufferPool *pool = NULL;
719   GstStructure *config;
720   gboolean eglimage = FALSE, add_videometa = FALSE;
721   GstCaps *caps = NULL;
722   guint min = 0, max = 0;
723   GstVideoCodecState *state =
724       gst_video_decoder_get_output_state (GST_VIDEO_DECODER (self));
725
726 #if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
727   port = self->eglimage ? self->egl_out_port : self->dec_out_port;
728 #else
729   port = self->dec_out_port;
730 #endif
731
732   pool = gst_video_decoder_get_buffer_pool (GST_VIDEO_DECODER (self));
733   if (pool) {
734     GstAllocator *allocator;
735
736     config = gst_buffer_pool_get_config (pool);
737     if (!gst_buffer_pool_config_get_params (config, &caps, NULL, &min, &max)) {
738       GST_ERROR_OBJECT (self, "Can't get buffer pool params");
739       gst_structure_free (config);
740       err = OMX_ErrorUndefined;
741       goto done;
742     }
743     if (!gst_buffer_pool_config_get_allocator (config, &allocator, NULL)) {
744       GST_ERROR_OBJECT (self, "Can't get buffer pool allocator");
745       gst_structure_free (config);
746       err = OMX_ErrorUndefined;
747       goto done;
748     }
749
750     /* Need at least 2 buffers for anything meaningful */
751     min = MAX (MAX (min, port->port_def.nBufferCountMin), 4);
752     if (max == 0) {
753       max = min;
754     } else if (max < port->port_def.nBufferCountMin || max < 2) {
755       /* Can't use pool because can't have enough buffers */
756       gst_caps_replace (&caps, NULL);
757     } else {
758       min = max;
759     }
760
761     add_videometa = gst_buffer_pool_config_has_option (config,
762         GST_BUFFER_POOL_OPTION_VIDEO_META);
763     gst_structure_free (config);
764
765 #if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
766     eglimage = self->eglimage && (allocator
767         && g_strcmp0 (allocator->mem_type, GST_EGL_IMAGE_MEMORY_TYPE) == 0);
768 #else
769     /* TODO: Implement something that works for other targets too */
770     eglimage = FALSE;
771 #endif
772     caps = caps ? gst_caps_ref (caps) : NULL;
773
774     GST_DEBUG_OBJECT (self, "Trying to use pool %p with caps %" GST_PTR_FORMAT
775         " and memory type %s", pool, caps,
776         (allocator ? allocator->mem_type : "(null)"));
777   } else {
778     gst_caps_replace (&caps, NULL);
779     min = max = port->port_def.nBufferCountMin;
780     GST_DEBUG_OBJECT (self, "No pool available, not negotiated yet");
781   }
782
783 #if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
784   /* Will retry without EGLImage */
785   if (self->eglimage && !eglimage) {
786     GST_DEBUG_OBJECT (self,
787         "Wanted to use EGLImage but downstream doesn't support it");
788     err = OMX_ErrorUndefined;
789     goto done;
790   }
791 #endif
792
793   if (caps)
794     self->out_port_pool =
795         gst_omx_buffer_pool_new (GST_ELEMENT_CAST (self), self->dec, port);
796
797 #if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
798   if (eglimage) {
799     GList *buffers = NULL;
800     GList *images = NULL;
801     gint i;
802     GstBufferPoolAcquireParams params = { 0, };
803     EGLDisplay egl_display = EGL_NO_DISPLAY;
804
805     GST_DEBUG_OBJECT (self, "Trying to allocate %d EGLImages", min);
806
807     for (i = 0; i < min; i++) {
808       GstBuffer *buffer;
809       GstMemory *mem;
810
811       if (gst_buffer_pool_acquire_buffer (pool, &buffer, &params) != GST_FLOW_OK
812           || gst_buffer_n_memory (buffer) != 1
813           || !(mem = gst_buffer_peek_memory (buffer, 0))
814           || g_strcmp0 (mem->allocator->mem_type,
815               GST_EGL_IMAGE_MEMORY_TYPE) != 0) {
816         GST_INFO_OBJECT (self, "Failed to allocated %d-th EGLImage", i);
817         g_list_free_full (buffers, (GDestroyNotify) gst_buffer_unref);
818         g_list_free (images);
819         buffers = NULL;
820         images = NULL;
821         /* TODO: For non-RPi targets we want to use the normal memory code below */
822         /* Retry without EGLImage */
823         err = OMX_ErrorUndefined;
824         goto done;
825       }
826
827       buffers = g_list_append (buffers, buffer);
828       gst_egl_image_memory_set_orientation (mem,
829           GST_VIDEO_GL_TEXTURE_ORIENTATION_X_NORMAL_Y_FLIP);
830       images = g_list_append (images, gst_egl_image_memory_get_image (mem));
831       if (egl_display == EGL_NO_DISPLAY)
832         egl_display = gst_egl_image_memory_get_display (mem);
833     }
834
835     GST_DEBUG_OBJECT (self, "Allocated %d EGLImages successfully", min);
836
837     /* Everything went fine? */
838     if (eglimage) {
839       GST_DEBUG_OBJECT (self, "Setting EGLDisplay");
840       self->egl_out_port->port_def.format.video.pNativeWindow = egl_display;
841       err =
842           gst_omx_port_update_port_definition (self->egl_out_port,
843           &self->egl_out_port->port_def);
844       if (err != OMX_ErrorNone) {
845         GST_INFO_OBJECT (self,
846             "Failed to set EGLDisplay on port: %s (0x%08x)",
847             gst_omx_error_to_string (err), err);
848         g_list_free_full (buffers, (GDestroyNotify) gst_buffer_unref);
849         g_list_free (images);
850         /* TODO: For non-RPi targets we want to use the normal memory code below */
851         /* Retry without EGLImage */
852         goto done;
853       } else {
854         GList *l;
855
856         if (min != port->port_def.nBufferCountActual) {
857           err = gst_omx_port_update_port_definition (port, NULL);
858           if (err == OMX_ErrorNone) {
859             port->port_def.nBufferCountActual = min;
860             err = gst_omx_port_update_port_definition (port, &port->port_def);
861           }
862
863           if (err != OMX_ErrorNone) {
864             GST_INFO_OBJECT (self,
865                 "Failed to configure %u output buffers: %s (0x%08x)", min,
866                 gst_omx_error_to_string (err), err);
867             g_list_free_full (buffers, (GDestroyNotify) gst_buffer_unref);
868             g_list_free (images);
869             /* TODO: For non-RPi targets we want to use the normal memory code below */
870             /* Retry without EGLImage */
871
872             goto done;
873           }
874         }
875
876         if (!gst_omx_port_is_enabled (port)) {
877           err = gst_omx_port_set_enabled (port, TRUE);
878           if (err != OMX_ErrorNone) {
879             GST_INFO_OBJECT (self,
880                 "Failed to enable port: %s (0x%08x)",
881                 gst_omx_error_to_string (err), err);
882             g_list_free_full (buffers, (GDestroyNotify) gst_buffer_unref);
883             g_list_free (images);
884             /* TODO: For non-RPi targets we want to use the normal memory code below */
885             /* Retry without EGLImage */
886             goto done;
887           }
888         }
889
890         err = gst_omx_port_use_eglimages (port, images);
891         g_list_free (images);
892
893         if (err != OMX_ErrorNone) {
894           GST_INFO_OBJECT (self,
895               "Failed to pass EGLImages to port: %s (0x%08x)",
896               gst_omx_error_to_string (err), err);
897           g_list_free_full (buffers, (GDestroyNotify) gst_buffer_unref);
898           /* TODO: For non-RPi targets we want to use the normal memory code below */
899           /* Retry without EGLImage */
900           goto done;
901         }
902
903         err = gst_omx_port_wait_enabled (port, 2 * GST_SECOND);
904         if (err != OMX_ErrorNone) {
905           GST_INFO_OBJECT (self,
906               "Failed to wait until port is enabled: %s (0x%08x)",
907               gst_omx_error_to_string (err), err);
908           g_list_free_full (buffers, (GDestroyNotify) gst_buffer_unref);
909           /* TODO: For non-RPi targets we want to use the normal memory code below */
910           /* Retry without EGLImage */
911           goto done;
912         }
913
914         GST_DEBUG_OBJECT (self, "Populating internal buffer pool");
915         GST_OMX_BUFFER_POOL (self->out_port_pool)->other_pool =
916             GST_BUFFER_POOL (gst_object_ref (pool));
917         for (l = buffers; l; l = l->next) {
918           g_ptr_array_add (GST_OMX_BUFFER_POOL (self->out_port_pool)->buffers,
919               l->data);
920         }
921         g_list_free (buffers);
922         /* All good and done, set caps below */
923       }
924     }
925   }
926 #endif
927
928   /* If not using EGLImage or trying to use EGLImage failed */
929   if (!eglimage) {
930     gboolean was_enabled = TRUE;
931
932     if (min != port->port_def.nBufferCountActual) {
933       err = gst_omx_port_update_port_definition (port, NULL);
934       if (err == OMX_ErrorNone) {
935         port->port_def.nBufferCountActual = min;
936         err = gst_omx_port_update_port_definition (port, &port->port_def);
937       }
938
939       if (err != OMX_ErrorNone) {
940         GST_ERROR_OBJECT (self,
941             "Failed to configure %u output buffers: %s (0x%08x)", min,
942             gst_omx_error_to_string (err), err);
943         goto done;
944       }
945     }
946
947     if (!gst_omx_port_is_enabled (port)) {
948       err = gst_omx_port_set_enabled (port, TRUE);
949       if (err != OMX_ErrorNone) {
950         GST_INFO_OBJECT (self,
951             "Failed to enable port: %s (0x%08x)",
952             gst_omx_error_to_string (err), err);
953         goto done;
954       }
955       was_enabled = FALSE;
956     }
957 #ifdef TIZEN_FEATURE_OMX
958     err = gst_omx_port_tbm_allocate_dec_buffers (port, self->bufmgr, port->use_buffer);
959 #else
960     err = gst_omx_port_allocate_buffers (port);
961 #endif
962     if (err != OMX_ErrorNone && min > port->port_def.nBufferCountMin) {
963       GST_ERROR_OBJECT (self,
964           "Failed to allocate required number of buffers %d, trying less and copying",
965           min);
966       min = port->port_def.nBufferCountMin;
967
968       if (!was_enabled) {
969         err = gst_omx_port_set_enabled (port, FALSE);
970         if (err != OMX_ErrorNone) {
971           GST_INFO_OBJECT (self,
972               "Failed to disable port again: %s (0x%08x)",
973               gst_omx_error_to_string (err), err);
974           goto done;
975         }
976       }
977
978       if (min != port->port_def.nBufferCountActual) {
979         err = gst_omx_port_update_port_definition (port, NULL);
980         if (err == OMX_ErrorNone) {
981           port->port_def.nBufferCountActual = min;
982           err = gst_omx_port_update_port_definition (port, &port->port_def);
983         }
984
985         if (err != OMX_ErrorNone) {
986           GST_ERROR_OBJECT (self,
987               "Failed to configure %u output buffers: %s (0x%08x)", min,
988               gst_omx_error_to_string (err), err);
989           goto done;
990         }
991       }
992 #ifdef TIZEN_FEATURE_OMX
993       err = gst_omx_port_tbm_allocate_dec_buffers (port, self->bufmgr, port->use_buffer);
994 #else
995       err = gst_omx_port_allocate_buffers (port);
996 #endif
997       /* Can't provide buffers downstream in this case */
998       gst_caps_replace (&caps, NULL);
999     }
1000
1001     if (err != OMX_ErrorNone) {
1002       GST_ERROR_OBJECT (self, "Failed to allocate %d buffers: %s (0x%08x)", min,
1003           gst_omx_error_to_string (err), err);
1004       goto done;
1005     }
1006
1007     if (!was_enabled) {
1008       err = gst_omx_port_wait_enabled (port, 2 * GST_SECOND);
1009       if (err != OMX_ErrorNone) {
1010         GST_ERROR_OBJECT (self,
1011             "Failed to wait until port is enabled: %s (0x%08x)",
1012             gst_omx_error_to_string (err), err);
1013         goto done;
1014       }
1015     }
1016
1017
1018   }
1019
1020   err = OMX_ErrorNone;
1021
1022   if (caps) {
1023     config = gst_buffer_pool_get_config (self->out_port_pool);
1024
1025     if (add_videometa)
1026       gst_buffer_pool_config_add_option (config,
1027           GST_BUFFER_POOL_OPTION_VIDEO_META);
1028
1029     gst_buffer_pool_config_set_params (config, caps,
1030         self->dec_out_port->port_def.nBufferSize, min, max);
1031
1032     if (!gst_buffer_pool_set_config (self->out_port_pool, config)) {
1033       GST_INFO_OBJECT (self, "Failed to set config on internal pool");
1034       gst_object_unref (self->out_port_pool);
1035       self->out_port_pool = NULL;
1036       goto done;
1037     }
1038
1039     GST_OMX_BUFFER_POOL (self->out_port_pool)->allocating = TRUE;
1040     /* This now allocates all the buffers */
1041     if (!gst_buffer_pool_set_active (self->out_port_pool, TRUE)) {
1042       GST_INFO_OBJECT (self, "Failed to activate internal pool");
1043       gst_object_unref (self->out_port_pool);
1044       self->out_port_pool = NULL;
1045     } else {
1046       GST_OMX_BUFFER_POOL (self->out_port_pool)->allocating = FALSE;
1047     }
1048   } else if (self->out_port_pool) {
1049     gst_object_unref (self->out_port_pool);
1050     self->out_port_pool = NULL;
1051   }
1052
1053 done:
1054   if (!self->out_port_pool && err == OMX_ErrorNone)
1055     GST_DEBUG_OBJECT (self,
1056         "Not using our internal pool and copying buffers for downstream");
1057
1058   if (caps)
1059     gst_caps_unref (caps);
1060   if (pool)
1061     gst_object_unref (pool);
1062   if (state)
1063     gst_video_codec_state_unref (state);
1064
1065   return err;
1066 }
1067
1068 static OMX_ERRORTYPE
1069 gst_omx_video_dec_deallocate_output_buffers (GstOMXVideoDec * self)
1070 {
1071   OMX_ERRORTYPE err;
1072
1073   if (self->out_port_pool) {
1074     gst_buffer_pool_set_active (self->out_port_pool, FALSE);
1075 #if 0
1076     gst_buffer_pool_wait_released (self->out_port_pool);
1077 #endif
1078     GST_OMX_BUFFER_POOL (self->out_port_pool)->deactivated = TRUE;
1079     gst_object_unref (self->out_port_pool);
1080     self->out_port_pool = NULL;
1081   }
1082 #if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
1083   err =
1084       gst_omx_port_deallocate_buffers (self->
1085       eglimage ? self->egl_out_port : self->dec_out_port);
1086 #else
1087   err = gst_omx_port_deallocate_buffers (self->dec_out_port);
1088 #endif
1089
1090   return err;
1091 }
1092
1093 static OMX_ERRORTYPE
1094 gst_omx_video_dec_reconfigure_output_port (GstOMXVideoDec * self)
1095 {
1096   GstOMXPort *port;
1097   OMX_ERRORTYPE err;
1098   GstVideoCodecState *state;
1099   OMX_PARAM_PORTDEFINITIONTYPE port_def;
1100   GstVideoFormat format;
1101
1102   /* At this point the decoder output port is disabled */
1103
1104 #if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
1105   {
1106     OMX_STATETYPE egl_state;
1107
1108     if (self->eglimage) {
1109       /* Nothing to do here, we could however fall back to non-EGLImage in theory */
1110       port = self->egl_out_port;
1111       err = OMX_ErrorNone;
1112       goto enable_port;
1113     } else {
1114       /* Set up egl_render */
1115
1116       self->eglimage = TRUE;
1117
1118       gst_omx_port_get_port_definition (self->dec_out_port, &port_def);
1119       GST_VIDEO_DECODER_STREAM_LOCK (self);
1120       state = gst_video_decoder_set_output_state (GST_VIDEO_DECODER (self),
1121           GST_VIDEO_FORMAT_RGBA, port_def.format.video.nFrameWidth,
1122           port_def.format.video.nFrameHeight, self->input_state);
1123
1124       /* at this point state->caps is NULL */
1125       if (state->caps)
1126         gst_caps_unref (state->caps);
1127       state->caps = gst_video_info_to_caps (&state->info);
1128       gst_caps_set_features (state->caps, 0,
1129           gst_caps_features_new (GST_CAPS_FEATURE_MEMORY_EGL_IMAGE, NULL));
1130
1131       /* try to negotiate with caps feature */
1132       if (!gst_video_decoder_negotiate (GST_VIDEO_DECODER (self))) {
1133
1134         GST_DEBUG_OBJECT (self,
1135             "Failed to negotiate with feature %s",
1136             GST_CAPS_FEATURE_MEMORY_EGL_IMAGE);
1137
1138         if (state->caps)
1139           gst_caps_replace (&state->caps, NULL);
1140
1141         /* fallback: try to use EGLImage even if it is not in the caps feature */
1142         if (!gst_video_decoder_negotiate (GST_VIDEO_DECODER (self))) {
1143           gst_video_codec_state_unref (state);
1144           GST_ERROR_OBJECT (self, "Failed to negotiate RGBA for EGLImage");
1145           GST_VIDEO_DECODER_STREAM_UNLOCK (self);
1146           goto no_egl;
1147         }
1148       }
1149
1150       gst_video_codec_state_unref (state);
1151       GST_VIDEO_DECODER_STREAM_UNLOCK (self);
1152
1153       /* Now link it all together */
1154
1155       err = gst_omx_port_set_enabled (self->egl_in_port, FALSE);
1156       if (err != OMX_ErrorNone)
1157         goto no_egl;
1158
1159       err = gst_omx_port_wait_enabled (self->egl_in_port, 1 * GST_SECOND);
1160       if (err != OMX_ErrorNone)
1161         goto no_egl;
1162
1163       err = gst_omx_port_set_enabled (self->egl_out_port, FALSE);
1164       if (err != OMX_ErrorNone)
1165         goto no_egl;
1166
1167       err = gst_omx_port_wait_enabled (self->egl_out_port, 1 * GST_SECOND);
1168       if (err != OMX_ErrorNone)
1169         goto no_egl;
1170
1171       {
1172 #define OMX_IndexParamBrcmVideoEGLRenderDiscardMode 0x7f0000db
1173         OMX_CONFIG_PORTBOOLEANTYPE discardMode;
1174         memset (&discardMode, 0, sizeof (discardMode));
1175         discardMode.nSize = sizeof (discardMode);
1176         discardMode.nPortIndex = 220;
1177         discardMode.nVersion.nVersion = OMX_VERSION;
1178         discardMode.bEnabled = OMX_FALSE;
1179         if (gst_omx_component_set_parameter (self->egl_render,
1180                 OMX_IndexParamBrcmVideoEGLRenderDiscardMode,
1181                 &discardMode) != OMX_ErrorNone)
1182           goto no_egl;
1183 #undef OMX_IndexParamBrcmVideoEGLRenderDiscardMode
1184       }
1185
1186       err = gst_omx_setup_tunnel (self->dec_out_port, self->egl_in_port);
1187       if (err != OMX_ErrorNone)
1188         goto no_egl;
1189
1190       err = gst_omx_port_set_enabled (self->egl_in_port, TRUE);
1191       if (err != OMX_ErrorNone)
1192         goto no_egl;
1193
1194       err = gst_omx_component_set_state (self->egl_render, OMX_StateIdle);
1195       if (err != OMX_ErrorNone)
1196         goto no_egl;
1197
1198       err = gst_omx_port_wait_enabled (self->egl_in_port, 1 * GST_SECOND);
1199       if (err != OMX_ErrorNone)
1200         goto no_egl;
1201
1202       if (gst_omx_component_get_state (self->egl_render,
1203               GST_CLOCK_TIME_NONE) != OMX_StateIdle)
1204         goto no_egl;
1205
1206       err = gst_omx_video_dec_allocate_output_buffers (self);
1207       if (err != OMX_ErrorNone)
1208         goto no_egl;
1209
1210       if (gst_omx_component_set_state (self->egl_render,
1211               OMX_StateExecuting) != OMX_ErrorNone)
1212         goto no_egl;
1213
1214       if (gst_omx_component_get_state (self->egl_render,
1215               GST_CLOCK_TIME_NONE) != OMX_StateExecuting)
1216         goto no_egl;
1217
1218       err =
1219           gst_omx_port_set_flushing (self->dec_out_port, 5 * GST_SECOND, FALSE);
1220       if (err != OMX_ErrorNone)
1221         goto no_egl;
1222
1223       err =
1224           gst_omx_port_set_flushing (self->egl_in_port, 5 * GST_SECOND, FALSE);
1225       if (err != OMX_ErrorNone)
1226         goto no_egl;
1227
1228       err =
1229           gst_omx_port_set_flushing (self->egl_out_port, 5 * GST_SECOND, FALSE);
1230       if (err != OMX_ErrorNone)
1231         goto no_egl;
1232
1233       err = gst_omx_port_populate (self->egl_out_port);
1234       if (err != OMX_ErrorNone)
1235         goto no_egl;
1236
1237       err = gst_omx_port_set_enabled (self->dec_out_port, TRUE);
1238       if (err != OMX_ErrorNone)
1239         goto no_egl;
1240
1241       err = gst_omx_port_wait_enabled (self->dec_out_port, 1 * GST_SECOND);
1242       if (err != OMX_ErrorNone)
1243         goto no_egl;
1244
1245
1246       err = gst_omx_port_mark_reconfigured (self->dec_out_port);
1247       if (err != OMX_ErrorNone)
1248         goto no_egl;
1249
1250       err = gst_omx_port_mark_reconfigured (self->egl_out_port);
1251       if (err != OMX_ErrorNone)
1252         goto no_egl;
1253
1254       goto done;
1255     }
1256
1257   no_egl:
1258
1259     gst_omx_port_set_enabled (self->dec_out_port, FALSE);
1260     gst_omx_port_wait_enabled (self->dec_out_port, 1 * GST_SECOND);
1261     egl_state = gst_omx_component_get_state (self->egl_render, 0);
1262     if (egl_state > OMX_StateLoaded || egl_state == OMX_StateInvalid) {
1263       if (egl_state > OMX_StateIdle) {
1264         gst_omx_component_set_state (self->egl_render, OMX_StateIdle);
1265         gst_omx_component_get_state (self->egl_render, 5 * GST_SECOND);
1266       }
1267       gst_omx_component_set_state (self->egl_render, OMX_StateLoaded);
1268
1269       gst_omx_video_dec_deallocate_output_buffers (self);
1270       gst_omx_close_tunnel (self->dec_out_port, self->egl_in_port);
1271
1272       if (egl_state > OMX_StateLoaded) {
1273         gst_omx_component_get_state (self->egl_render, 5 * GST_SECOND);
1274       }
1275     }
1276
1277     /* After this egl_render should be deactivated
1278      * and the decoder's output port disabled */
1279     self->eglimage = FALSE;
1280   }
1281 #endif
1282   port = self->dec_out_port;
1283
1284   /* Update caps */
1285   GST_VIDEO_DECODER_STREAM_LOCK (self);
1286
1287   gst_omx_port_get_port_definition (port, &port_def);
1288   g_assert (port_def.format.video.eCompressionFormat == OMX_VIDEO_CodingUnused);
1289
1290   format =
1291       gst_omx_video_get_format_from_omx (port_def.format.video.eColorFormat);
1292
1293   if (format == GST_VIDEO_FORMAT_UNKNOWN) {
1294     GST_ERROR_OBJECT (self, "Unsupported color format: %d",
1295         port_def.format.video.eColorFormat);
1296     GST_VIDEO_DECODER_STREAM_UNLOCK (self);
1297     err = OMX_ErrorUndefined;
1298     goto done;
1299   }
1300
1301   GST_DEBUG_OBJECT (self,
1302       "Setting output state: format %s (%d), width %u, height %u",
1303       gst_video_format_to_string (format),
1304       port_def.format.video.eColorFormat,
1305       (guint) port_def.format.video.nFrameWidth,
1306       (guint) port_def.format.video.nFrameHeight);
1307
1308   state = gst_video_decoder_set_output_state (GST_VIDEO_DECODER (self),
1309       format, port_def.format.video.nFrameWidth,
1310       port_def.format.video.nFrameHeight, self->input_state);
1311
1312   if (!gst_video_decoder_negotiate (GST_VIDEO_DECODER (self))) {
1313     gst_video_codec_state_unref (state);
1314     GST_ERROR_OBJECT (self, "Failed to negotiate");
1315     err = OMX_ErrorUndefined;
1316     GST_VIDEO_DECODER_STREAM_UNLOCK (self);
1317     goto done;
1318   }
1319
1320   gst_video_codec_state_unref (state);
1321
1322   GST_VIDEO_DECODER_STREAM_UNLOCK (self);
1323
1324 #if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
1325 enable_port:
1326 #endif
1327   err = gst_omx_video_dec_allocate_output_buffers (self);
1328   if (err != OMX_ErrorNone)
1329     goto done;
1330
1331   err = gst_omx_port_populate (port);
1332   if (err != OMX_ErrorNone)
1333     goto done;
1334
1335   err = gst_omx_port_mark_reconfigured (port);
1336   if (err != OMX_ErrorNone)
1337     goto done;
1338
1339 done:
1340
1341   return err;
1342 }
1343
1344 static void
1345 gst_omx_video_dec_clean_older_frames (GstOMXVideoDec * self,
1346     GstOMXBuffer * buf, GList * frames)
1347 {
1348   GList *l;
1349   GstClockTime timestamp;
1350
1351   timestamp = gst_util_uint64_scale (buf->omx_buf->nTimeStamp, GST_SECOND,
1352       OMX_TICKS_PER_SECOND);
1353
1354   if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
1355     /* We could release all frames stored with pts < timestamp since the
1356      * decoder will likely output frames in display order */
1357     for (l = frames; l; l = l->next) {
1358       GstVideoCodecFrame *tmp = l->data;
1359
1360       if (tmp->pts < timestamp) {
1361         gst_video_decoder_release_frame (GST_VIDEO_DECODER (self), tmp);
1362         GST_LOG_OBJECT (self,
1363             "discarding ghost frame %p (#%d) PTS:%" GST_TIME_FORMAT " DTS:%"
1364             GST_TIME_FORMAT, tmp, tmp->system_frame_number,
1365             GST_TIME_ARGS (tmp->pts), GST_TIME_ARGS (tmp->dts));
1366       } else {
1367         gst_video_codec_frame_unref (tmp);
1368       }
1369     }
1370   } else {
1371     /* We will release all frames with invalid timestamp because we don't even
1372      * know if they will be output some day. */
1373     for (l = frames; l; l = l->next) {
1374       GstVideoCodecFrame *tmp = l->data;
1375
1376       if (!GST_CLOCK_TIME_IS_VALID (tmp->pts)) {
1377         gst_video_decoder_release_frame (GST_VIDEO_DECODER (self), tmp);
1378         GST_LOG_OBJECT (self,
1379             "discarding frame %p (#%d) with invalid PTS:%" GST_TIME_FORMAT
1380             " DTS:%" GST_TIME_FORMAT, tmp, tmp->system_frame_number,
1381             GST_TIME_ARGS (tmp->pts), GST_TIME_ARGS (tmp->dts));
1382       } else {
1383         gst_video_codec_frame_unref (tmp);
1384       }
1385     }
1386   }
1387
1388   g_list_free (frames);
1389 }
1390
1391 static GstBuffer *
1392 copy_frame (const GstVideoInfo * info, GstBuffer * outbuf)
1393 {
1394   GstVideoInfo out_info, tmp_info;
1395   GstBuffer *tmpbuf;
1396   GstVideoFrame out_frame, tmp_frame;
1397
1398   out_info = *info;
1399   tmp_info = *info;
1400
1401   tmpbuf = gst_buffer_new_and_alloc (out_info.size);
1402
1403   gst_video_frame_map (&out_frame, &out_info, outbuf, GST_MAP_READ);
1404   gst_video_frame_map (&tmp_frame, &tmp_info, tmpbuf, GST_MAP_WRITE);
1405   gst_video_frame_copy (&tmp_frame, &out_frame);
1406   gst_video_frame_unmap (&out_frame);
1407   gst_video_frame_unmap (&tmp_frame);
1408
1409   gst_buffer_unref (outbuf);
1410
1411   return tmpbuf;
1412 }
1413
1414 static void
1415 gst_omx_video_dec_loop (GstOMXVideoDec * self)
1416 {
1417   GstOMXPort *port;
1418   GstOMXBuffer *buf = NULL;
1419   GstVideoCodecFrame *frame;
1420   GstFlowReturn flow_ret = GST_FLOW_OK;
1421   GstOMXAcquireBufferReturn acq_return;
1422   GstClockTimeDiff deadline;
1423   OMX_ERRORTYPE err;
1424 #ifdef TIZEN_FEATURE_OMX
1425   GstBuffer *flush_request_buffer = NULL;
1426   GstMessage *msg = NULL;
1427 #endif
1428
1429 #if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
1430   port = self->eglimage ? self->egl_out_port : self->dec_out_port;
1431 #else
1432   port = self->dec_out_port;
1433 #endif
1434
1435   acq_return = gst_omx_port_acquire_buffer (port, &buf);
1436   if (acq_return == GST_OMX_ACQUIRE_BUFFER_ERROR) {
1437     goto component_error;
1438   } else if (acq_return == GST_OMX_ACQUIRE_BUFFER_FLUSHING) {
1439     goto flushing;
1440   } else if (acq_return == GST_OMX_ACQUIRE_BUFFER_EOS) {
1441     goto eos;
1442   }
1443
1444   if (!gst_pad_has_current_caps (GST_VIDEO_DECODER_SRC_PAD (self)) ||
1445       acq_return == GST_OMX_ACQUIRE_BUFFER_RECONFIGURE) {
1446     GstVideoCodecState *state;
1447     OMX_PARAM_PORTDEFINITIONTYPE port_def;
1448     GstVideoFormat format;
1449
1450     GST_DEBUG_OBJECT (self, "Port settings have changed, updating caps");
1451
1452     /* Reallocate all buffers */
1453     if (acq_return == GST_OMX_ACQUIRE_BUFFER_RECONFIGURE
1454         && gst_omx_port_is_enabled (port)) {
1455 #ifdef TIZEN_FEATURE_OMX
1456       if (gst_omx_video_dec_acquire_request_flush_buffer (self, &flush_request_buffer)) {
1457         flow_ret = gst_pad_push (GST_VIDEO_DECODER_SRC_PAD (self), flush_request_buffer);
1458
1459         if (flow_ret != GST_FLOW_OK) {
1460           gst_buffer_unref (flush_request_buffer);
1461           flush_request_buffer = NULL;
1462           goto reconfigure_error;
1463         }
1464       }
1465 #endif
1466       err = gst_omx_port_set_enabled (port, FALSE);
1467       if (err != OMX_ErrorNone)
1468         goto reconfigure_error;
1469
1470       err = gst_omx_port_wait_buffers_released (port, 5 * GST_SECOND);
1471       if (err != OMX_ErrorNone)
1472         goto reconfigure_error;
1473
1474       err = gst_omx_video_dec_deallocate_output_buffers (self);
1475       if (err != OMX_ErrorNone)
1476         goto reconfigure_error;
1477
1478       err = gst_omx_port_wait_enabled (port, 1 * GST_SECOND);
1479       if (err != OMX_ErrorNone)
1480         goto reconfigure_error;
1481     }
1482
1483     if (acq_return == GST_OMX_ACQUIRE_BUFFER_RECONFIGURE) {
1484       /* We have the possibility to reconfigure everything now */
1485       err = gst_omx_video_dec_reconfigure_output_port (self);
1486       if (err != OMX_ErrorNone)
1487         goto reconfigure_error;
1488 #ifdef TIZEN_FEATURE_OMX
1489       msg = gst_message_new_element (GST_OBJECT_CAST (self), gst_structure_new ("prepare-decode-buffers",
1490                                  "num_buffers", G_TYPE_INT, self->dec_out_port->port_def.nBufferCountActual,
1491                                  "extra_num_buffers", G_TYPE_INT, EXTRA_DECODER_OUTPUT_BUF, NULL));
1492
1493       gst_element_post_message (GST_ELEMENT_CAST (self), msg);
1494 #endif
1495     } else {
1496       /* Just update caps */
1497       GST_VIDEO_DECODER_STREAM_LOCK (self);
1498
1499       gst_omx_port_get_port_definition (port, &port_def);
1500       g_assert (port_def.format.video.eCompressionFormat ==
1501           OMX_VIDEO_CodingUnused);
1502
1503       format =
1504           gst_omx_video_get_format_from_omx (port_def.format.
1505           video.eColorFormat);
1506
1507       if (format == GST_VIDEO_FORMAT_UNKNOWN) {
1508         GST_ERROR_OBJECT (self, "Unsupported color format: %d",
1509             port_def.format.video.eColorFormat);
1510         if (buf)
1511           gst_omx_port_release_buffer (port, buf);
1512         GST_VIDEO_DECODER_STREAM_UNLOCK (self);
1513         goto caps_failed;
1514       }
1515
1516       GST_DEBUG_OBJECT (self,
1517           "Setting output state: format %s (%d), width %u, height %u",
1518           gst_video_format_to_string (format),
1519           port_def.format.video.eColorFormat,
1520           (guint) port_def.format.video.nFrameWidth,
1521           (guint) port_def.format.video.nFrameHeight);
1522
1523       state = gst_video_decoder_set_output_state (GST_VIDEO_DECODER (self),
1524           format, port_def.format.video.nFrameWidth,
1525           port_def.format.video.nFrameHeight, self->input_state);
1526
1527       /* Take framerate and pixel-aspect-ratio from sinkpad caps */
1528
1529       if (!gst_video_decoder_negotiate (GST_VIDEO_DECODER (self))) {
1530         if (buf)
1531           gst_omx_port_release_buffer (port, buf);
1532         gst_video_codec_state_unref (state);
1533         goto caps_failed;
1534       }
1535
1536       gst_video_codec_state_unref (state);
1537
1538       GST_VIDEO_DECODER_STREAM_UNLOCK (self);
1539     }
1540
1541     /* Now get a buffer */
1542     if (acq_return != GST_OMX_ACQUIRE_BUFFER_OK) {
1543       return;
1544     }
1545   }
1546
1547   g_assert (acq_return == GST_OMX_ACQUIRE_BUFFER_OK);
1548
1549   /* This prevents a deadlock between the srcpad stream
1550    * lock and the videocodec stream lock, if ::reset()
1551    * is called at the wrong time
1552    */
1553   if (gst_omx_port_is_flushing (port)) {
1554     GST_DEBUG_OBJECT (self, "Flushing");
1555     gst_omx_port_release_buffer (port, buf);
1556     goto flushing;
1557   }
1558
1559   GST_DEBUG_OBJECT (self, "Handling buffer: 0x%08x %" G_GUINT64_FORMAT,
1560       (guint) buf->omx_buf->nFlags, (guint64) buf->omx_buf->nTimeStamp);
1561
1562   GST_VIDEO_DECODER_STREAM_LOCK (self);
1563   frame = gst_omx_video_find_nearest_frame (buf,
1564       gst_video_decoder_get_frames (GST_VIDEO_DECODER (self)));
1565
1566   /* So we have a timestamped OMX buffer and get, or not, corresponding frame.
1567    * Assuming decoder output frames in display order, frames preceding this
1568    * frame could be discarded as they seems useless due to e.g interlaced
1569    * stream, corrupted input data...
1570    * In any cases, not likely to be seen again. so drop it before they pile up
1571    * and use all the memory. */
1572   gst_omx_video_dec_clean_older_frames (self, buf,
1573       gst_video_decoder_get_frames (GST_VIDEO_DECODER (self)));
1574
1575   if (frame
1576       && (deadline = gst_video_decoder_get_max_decode_time
1577           (GST_VIDEO_DECODER (self), frame)) < 0) {
1578     GST_WARNING_OBJECT (self,
1579         "Frame is too late, dropping (deadline %" GST_TIME_FORMAT ")",
1580         GST_TIME_ARGS (-deadline));
1581     flow_ret = gst_video_decoder_drop_frame (GST_VIDEO_DECODER (self), frame);
1582     frame = NULL;
1583   } else if (!frame && (buf->omx_buf->nFilledLen > 0 || buf->eglimage)) {
1584     GstBuffer *outbuf = NULL;
1585
1586     /* This sometimes happens at EOS or if the input is not properly framed,
1587      * let's handle it gracefully by allocating a new buffer for the current
1588      * caps and filling it
1589      */
1590
1591     GST_ERROR_OBJECT (self, "No corresponding frame found");
1592
1593     if (self->out_port_pool) {
1594       gint i, n;
1595       GstBufferPoolAcquireParams params = { 0, };
1596
1597       n = port->buffers->len;
1598       for (i = 0; i < n; i++) {
1599         GstOMXBuffer *tmp = g_ptr_array_index (port->buffers, i);
1600
1601         if (tmp == buf)
1602           break;
1603       }
1604       g_assert (i != n);
1605
1606       GST_OMX_BUFFER_POOL (self->out_port_pool)->current_buffer_index = i;
1607       flow_ret =
1608           gst_buffer_pool_acquire_buffer (self->out_port_pool, &outbuf,
1609           &params);
1610       if (flow_ret != GST_FLOW_OK) {
1611         gst_omx_port_release_buffer (port, buf);
1612         goto invalid_buffer;
1613       }
1614
1615       if (GST_OMX_BUFFER_POOL (self->out_port_pool)->need_copy)
1616         outbuf =
1617             copy_frame (&GST_OMX_BUFFER_POOL (self->out_port_pool)->video_info,
1618             outbuf);
1619
1620     } else {
1621       outbuf =
1622           gst_video_decoder_allocate_output_buffer (GST_VIDEO_DECODER (self));
1623       if (!gst_omx_video_dec_fill_buffer (self, buf, outbuf)) {
1624         gst_buffer_unref (outbuf);
1625         gst_omx_port_release_buffer (port, buf);
1626         goto invalid_buffer;
1627       }
1628     }
1629 #ifdef TIZEN_FEATURE_OMX
1630     {
1631       MMVideoBuffer *mm_vbuffer = NULL;
1632       GstMemory *mem = NULL;
1633       guint8 *data = NULL;
1634       mm_vbuffer = (MMVideoBuffer*)(buf->omx_buf->pBuffer);
1635
1636       if (gst_buffer_n_memory (outbuf) < 2) {
1637         data = g_malloc0 (sizeof (MMVideoBuffer));
1638         mem = gst_memory_new_wrapped (0, data, sizeof(MMVideoBuffer), 0, sizeof(MMVideoBuffer), data, g_free);
1639         gst_buffer_append_memory (outbuf, mem);
1640       } else {
1641         GstMapInfo info = GST_MAP_INFO_INIT;
1642         mem = gst_buffer_peek_memory (outbuf, 1);
1643         gst_memory_map (mem, &info, GST_MAP_WRITE);
1644         data = info.data;
1645         gst_memory_unmap (mem, &info);
1646       }
1647       memcpy(data, mm_vbuffer, sizeof(MMVideoBuffer));
1648       buf = NULL;
1649
1650       if (mm_vbuffer->type == MM_VIDEO_BUFFER_TYPE_TBM_BO) {
1651         GST_LOG_OBJECT (self, "frame not found: bo[0] :%p, bo[1] : %p, fd[0]:%d  fd[1]:%d fd[2]:%d  w[0]:%d h[0]:%d  buf_share_method:%d",
1652             mm_vbuffer->handle.bo[0], mm_vbuffer->handle.bo[1], mm_vbuffer->handle.dmabuf_fd[0], mm_vbuffer->handle.dmabuf_fd[1], mm_vbuffer->handle.dmabuf_fd[2],
1653             mm_vbuffer->width[0], mm_vbuffer->height[0], mm_vbuffer->type);
1654       } else if (mm_vbuffer->type == MM_VIDEO_BUFFER_TYPE_PHYSICAL_ADDRESS) {
1655         GST_LOG_OBJECT (self, "dec output uses hw addr");
1656       } else {
1657         GST_WARNING_OBJECT (self, "dec output buf has TBM_BO buf_share_method");
1658       }
1659     }
1660 #endif
1661     flow_ret = gst_pad_push (GST_VIDEO_DECODER_SRC_PAD (self), outbuf);
1662   } else if (buf->omx_buf->nFilledLen > 0 || buf->eglimage) {
1663     if (self->out_port_pool) {
1664       gint i, n;
1665       GstBuffer *outbuf = NULL;
1666       GstBufferPoolAcquireParams params = { 0, };
1667
1668       n = port->buffers->len;
1669       for (i = 0; i < n; i++) {
1670         GstOMXBuffer *tmp = g_ptr_array_index (port->buffers, i);
1671
1672         if (tmp == buf)
1673           break;
1674       }
1675       g_assert (i != n);
1676
1677       GST_OMX_BUFFER_POOL (self->out_port_pool)->current_buffer_index = i;
1678       flow_ret =
1679           gst_buffer_pool_acquire_buffer (self->out_port_pool,
1680           &frame->output_buffer, &params);
1681       if (flow_ret != GST_FLOW_OK) {
1682         flow_ret =
1683             gst_video_decoder_drop_frame (GST_VIDEO_DECODER (self), frame);
1684         frame = NULL;
1685         gst_omx_port_release_buffer (port, buf);
1686         goto invalid_buffer;
1687       }
1688
1689       if (GST_OMX_BUFFER_POOL (self->out_port_pool)->need_copy){
1690         outbuf =
1691             copy_frame (&GST_OMX_BUFFER_POOL (self->out_port_pool)->video_info,
1692             outbuf);
1693       frame->output_buffer = outbuf;
1694
1695       flow_ret =
1696           gst_video_decoder_finish_frame (GST_VIDEO_DECODER (self), frame);
1697       frame = NULL;
1698       buf = NULL;
1699       } else {
1700         if (!gst_omx_video_dec_fill_buffer (self, buf, frame->output_buffer)) {
1701           gst_buffer_replace (&frame->output_buffer, NULL);
1702
1703           flow_ret =
1704               gst_video_decoder_drop_frame (GST_VIDEO_DECODER (self), frame);
1705           frame = NULL;
1706           gst_omx_port_release_buffer (port, buf);
1707           goto invalid_buffer;
1708         }
1709         flow_ret =
1710             gst_video_decoder_finish_frame (GST_VIDEO_DECODER (self), frame);
1711         frame = NULL;
1712         buf = NULL;
1713       }
1714     } else {
1715       if ((flow_ret =
1716               gst_video_decoder_allocate_output_frame (GST_VIDEO_DECODER
1717                   (self), frame)) == GST_FLOW_OK) {
1718         /* FIXME: This currently happens because of a race condition too.
1719          * We first need to reconfigure the output port and then the input
1720          * port if both need reconfiguration.
1721          */
1722         if (!gst_omx_video_dec_fill_buffer (self, buf, frame->output_buffer)) {
1723           gst_buffer_replace (&frame->output_buffer, NULL);
1724           flow_ret =
1725               gst_video_decoder_drop_frame (GST_VIDEO_DECODER (self), frame);
1726           frame = NULL;
1727           gst_omx_port_release_buffer (port, buf);
1728           goto invalid_buffer;
1729         }
1730         flow_ret =
1731             gst_video_decoder_finish_frame (GST_VIDEO_DECODER (self), frame);
1732         frame = NULL;
1733       }
1734     }
1735   } else if (frame != NULL) {
1736     flow_ret = gst_video_decoder_drop_frame (GST_VIDEO_DECODER (self), frame);
1737     frame = NULL;
1738   }
1739
1740   GST_DEBUG_OBJECT (self, "Read frame from component");
1741
1742   GST_DEBUG_OBJECT (self, "Finished frame: %s", gst_flow_get_name (flow_ret));
1743
1744   if (buf) {
1745     err = gst_omx_port_release_buffer (port, buf);
1746     if (err != OMX_ErrorNone)
1747       goto release_error;
1748   }
1749
1750   self->downstream_flow_ret = flow_ret;
1751
1752   if (flow_ret != GST_FLOW_OK)
1753     goto flow_error;
1754
1755   GST_VIDEO_DECODER_STREAM_UNLOCK (self);
1756
1757   return;
1758
1759 component_error:
1760   {
1761     GST_ELEMENT_ERROR (self, LIBRARY, FAILED, (NULL),
1762         ("OpenMAX component in error state %s (0x%08x)",
1763             gst_omx_component_get_last_error_string (self->dec),
1764             gst_omx_component_get_last_error (self->dec)));
1765     gst_pad_push_event (GST_VIDEO_DECODER_SRC_PAD (self), gst_event_new_eos ());
1766     gst_pad_pause_task (GST_VIDEO_DECODER_SRC_PAD (self));
1767     self->downstream_flow_ret = GST_FLOW_ERROR;
1768     self->started = FALSE;
1769     return;
1770   }
1771
1772 flushing:
1773   {
1774     GST_DEBUG_OBJECT (self, "Flushing -- stopping task");
1775     g_mutex_lock (&self->drain_lock);
1776     if (self->draining) {
1777       self->draining = FALSE;
1778       g_cond_broadcast (&self->drain_cond);
1779     }
1780     gst_pad_pause_task (GST_VIDEO_DECODER_SRC_PAD (self));
1781     self->downstream_flow_ret = GST_FLOW_FLUSHING;
1782     self->started = FALSE;
1783     g_mutex_unlock (&self->drain_lock);
1784     return;
1785   }
1786
1787 eos:
1788   {
1789     g_mutex_lock (&self->drain_lock);
1790     if (self->draining) {
1791       GstQuery *query = gst_query_new_drain ();
1792
1793       /* Drain the pipeline to reclaim all memories back to the pool */
1794       if (!gst_pad_peer_query (GST_VIDEO_DECODER_SRC_PAD (self), query))
1795         GST_DEBUG_OBJECT (self, "drain query failed");
1796       gst_query_unref (query);
1797
1798       GST_DEBUG_OBJECT (self, "Drained");
1799       self->draining = FALSE;
1800       g_cond_broadcast (&self->drain_cond);
1801       flow_ret = GST_FLOW_OK;
1802       gst_pad_pause_task (GST_VIDEO_DECODER_SRC_PAD (self));
1803     } else {
1804       GST_DEBUG_OBJECT (self, "Component signalled EOS");
1805       flow_ret = GST_FLOW_EOS;
1806     }
1807     g_mutex_unlock (&self->drain_lock);
1808
1809     GST_VIDEO_DECODER_STREAM_LOCK (self);
1810     self->downstream_flow_ret = flow_ret;
1811
1812     /* Here we fallback and pause the task for the EOS case */
1813     if (flow_ret != GST_FLOW_OK)
1814       goto flow_error;
1815
1816     GST_VIDEO_DECODER_STREAM_UNLOCK (self);
1817
1818     return;
1819   }
1820
1821 flow_error:
1822   {
1823     if (flow_ret == GST_FLOW_EOS) {
1824       GST_DEBUG_OBJECT (self, "EOS");
1825
1826       gst_pad_push_event (GST_VIDEO_DECODER_SRC_PAD (self),
1827           gst_event_new_eos ());
1828       gst_pad_pause_task (GST_VIDEO_DECODER_SRC_PAD (self));
1829       self->started = FALSE;
1830     } else if (flow_ret < GST_FLOW_EOS) {
1831       GST_ELEMENT_ERROR (self, STREAM, FAILED,
1832           ("Internal data stream error."), ("stream stopped, reason %s",
1833               gst_flow_get_name (flow_ret)));
1834
1835       gst_pad_push_event (GST_VIDEO_DECODER_SRC_PAD (self),
1836           gst_event_new_eos ());
1837       gst_pad_pause_task (GST_VIDEO_DECODER_SRC_PAD (self));
1838       self->started = FALSE;
1839     } else if (flow_ret == GST_FLOW_FLUSHING) {
1840       GST_DEBUG_OBJECT (self, "Flushing -- stopping task");
1841       g_mutex_lock (&self->drain_lock);
1842       if (self->draining) {
1843         self->draining = FALSE;
1844         g_cond_broadcast (&self->drain_cond);
1845       }
1846       gst_pad_pause_task (GST_VIDEO_DECODER_SRC_PAD (self));
1847       self->started = FALSE;
1848       g_mutex_unlock (&self->drain_lock);
1849     }
1850     GST_VIDEO_DECODER_STREAM_UNLOCK (self);
1851     return;
1852   }
1853
1854 reconfigure_error:
1855   {
1856     GST_ELEMENT_ERROR (self, LIBRARY, SETTINGS, (NULL),
1857         ("Unable to reconfigure output port"));
1858     gst_pad_push_event (GST_VIDEO_DECODER_SRC_PAD (self), gst_event_new_eos ());
1859     gst_pad_pause_task (GST_VIDEO_DECODER_SRC_PAD (self));
1860     self->downstream_flow_ret = GST_FLOW_ERROR;
1861     self->started = FALSE;
1862     return;
1863   }
1864
1865 invalid_buffer:
1866   {
1867     GST_ELEMENT_ERROR (self, LIBRARY, SETTINGS, (NULL),
1868         ("Invalid sized input buffer"));
1869     gst_pad_push_event (GST_VIDEO_DECODER_SRC_PAD (self), gst_event_new_eos ());
1870     gst_pad_pause_task (GST_VIDEO_DECODER_SRC_PAD (self));
1871     self->downstream_flow_ret = GST_FLOW_NOT_NEGOTIATED;
1872     self->started = FALSE;
1873     GST_VIDEO_DECODER_STREAM_UNLOCK (self);
1874     return;
1875   }
1876
1877 caps_failed:
1878   {
1879     GST_ELEMENT_ERROR (self, LIBRARY, SETTINGS, (NULL), ("Failed to set caps"));
1880     gst_pad_push_event (GST_VIDEO_DECODER_SRC_PAD (self), gst_event_new_eos ());
1881     gst_pad_pause_task (GST_VIDEO_DECODER_SRC_PAD (self));
1882     GST_VIDEO_DECODER_STREAM_UNLOCK (self);
1883     self->downstream_flow_ret = GST_FLOW_NOT_NEGOTIATED;
1884     self->started = FALSE;
1885     return;
1886   }
1887 release_error:
1888   {
1889     GST_ELEMENT_ERROR (self, LIBRARY, SETTINGS, (NULL),
1890         ("Failed to relase output buffer to component: %s (0x%08x)",
1891             gst_omx_error_to_string (err), err));
1892     gst_pad_push_event (GST_VIDEO_DECODER_SRC_PAD (self), gst_event_new_eos ());
1893     gst_pad_pause_task (GST_VIDEO_DECODER_SRC_PAD (self));
1894     self->downstream_flow_ret = GST_FLOW_ERROR;
1895     self->started = FALSE;
1896     GST_VIDEO_DECODER_STREAM_UNLOCK (self);
1897     return;
1898   }
1899 }
1900
1901 static gboolean
1902 gst_omx_video_dec_start (GstVideoDecoder * decoder)
1903 {
1904   GstOMXVideoDec *self;
1905
1906   self = GST_OMX_VIDEO_DEC (decoder);
1907
1908   self->last_upstream_ts = 0;
1909   self->downstream_flow_ret = GST_FLOW_OK;
1910
1911   return TRUE;
1912 }
1913
1914 static gboolean
1915 gst_omx_video_dec_stop (GstVideoDecoder * decoder)
1916 {
1917   GstOMXVideoDec *self;
1918
1919   self = GST_OMX_VIDEO_DEC (decoder);
1920
1921   GST_DEBUG_OBJECT (self, "Stopping decoder");
1922
1923   gst_omx_port_set_flushing (self->dec_in_port, 5 * GST_SECOND, TRUE);
1924   gst_omx_port_set_flushing (self->dec_out_port, 5 * GST_SECOND, TRUE);
1925
1926 #if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
1927   gst_omx_port_set_flushing (self->egl_in_port, 5 * GST_SECOND, TRUE);
1928   gst_omx_port_set_flushing (self->egl_out_port, 5 * GST_SECOND, TRUE);
1929 #endif
1930
1931   gst_pad_stop_task (GST_VIDEO_DECODER_SRC_PAD (decoder));
1932
1933   if (gst_omx_component_get_state (self->dec, 0) > OMX_StateIdle)
1934     gst_omx_component_set_state (self->dec, OMX_StateIdle);
1935 #if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
1936   if (gst_omx_component_get_state (self->egl_render, 0) > OMX_StateIdle)
1937     gst_omx_component_set_state (self->egl_render, OMX_StateIdle);
1938 #endif
1939
1940   self->downstream_flow_ret = GST_FLOW_FLUSHING;
1941   self->started = FALSE;
1942
1943   g_mutex_lock (&self->drain_lock);
1944   self->draining = FALSE;
1945   g_cond_broadcast (&self->drain_cond);
1946   g_mutex_unlock (&self->drain_lock);
1947
1948   gst_omx_component_get_state (self->dec, 5 * GST_SECOND);
1949 #if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
1950   gst_omx_component_get_state (self->egl_render, 1 * GST_SECOND);
1951 #endif
1952
1953   gst_buffer_replace (&self->codec_data, NULL);
1954
1955   if (self->input_state)
1956     gst_video_codec_state_unref (self->input_state);
1957   self->input_state = NULL;
1958
1959   GST_DEBUG_OBJECT (self, "Stopped decoder");
1960
1961   return TRUE;
1962 }
1963
1964 static gboolean
1965 gst_omx_video_dec_negotiate (GstOMXVideoDec * self)
1966 {
1967   OMX_VIDEO_PARAM_PORTFORMATTYPE param;
1968   OMX_ERRORTYPE err;
1969   GstCaps *comp_supported_caps;
1970   GList *negotiation_map = NULL, *l;
1971   GstCaps *templ_caps, *intersection;
1972   GstVideoFormat format;
1973   GstStructure *s;
1974   const gchar *format_str = NULL;
1975 #ifdef TIZEN_FEATURE_OMX
1976   const gchar *format_tmp;
1977   int i;
1978 #endif
1979
1980   GST_DEBUG_OBJECT (self, "Trying to negotiate a video format with downstream");
1981
1982   templ_caps = gst_pad_get_pad_template_caps (GST_VIDEO_DECODER_SRC_PAD (self));
1983   intersection =
1984       gst_pad_peer_query_caps (GST_VIDEO_DECODER_SRC_PAD (self), templ_caps);
1985   gst_caps_unref (templ_caps);
1986
1987   GST_DEBUG_OBJECT (self, "Allowed downstream caps: %" GST_PTR_FORMAT,
1988       intersection);
1989
1990   negotiation_map =
1991       gst_omx_video_get_supported_colorformats (self->dec_out_port,
1992       self->input_state);
1993
1994   comp_supported_caps = gst_omx_video_get_caps_for_map (negotiation_map);
1995
1996   if (!gst_caps_is_empty (comp_supported_caps)) {
1997     GstCaps *tmp;
1998
1999     tmp = gst_caps_intersect (comp_supported_caps, intersection);
2000     gst_caps_unref (intersection);
2001     intersection = tmp;
2002   }
2003   gst_caps_unref (comp_supported_caps);
2004
2005   if (gst_caps_is_empty (intersection)) {
2006     gst_caps_unref (intersection);
2007     GST_ERROR_OBJECT (self, "Empty caps");
2008     g_list_free_full (negotiation_map,
2009         (GDestroyNotify) gst_omx_video_negotiation_map_free);
2010     return FALSE;
2011   }
2012
2013 #ifdef TIZEN_FEATURE_OMX
2014   for(i = 0; i < gst_caps_get_size (intersection); i++)
2015   {
2016       s = gst_caps_get_structure (intersection, i);
2017       if ((format_tmp = gst_structure_get_string (s, "format"))) {
2018
2019         if (!strncmp (format_tmp, "S", 1)) {
2020           format_str = format_tmp;
2021           GST_DEBUG_OBJECT (self, "SEC format found");
2022           break;
2023         }
2024       }
2025   }
2026
2027   if (!format_str) {
2028     intersection = gst_caps_truncate (intersection);
2029     intersection = gst_caps_fixate (intersection);
2030
2031     s = gst_caps_get_structure (intersection, 0);
2032     format_str = gst_structure_get_string (s, "format");
2033     GST_DEBUG_OBJECT (self, "first structure will be fixated");
2034   }
2035 #endif
2036
2037   if (!format_str ||
2038       (format =
2039           gst_video_format_from_string (format_str)) ==
2040       GST_VIDEO_FORMAT_UNKNOWN) {
2041     GST_ERROR_OBJECT (self, "Invalid caps: %" GST_PTR_FORMAT, intersection);
2042     gst_caps_unref (intersection);
2043     g_list_free_full (negotiation_map,
2044         (GDestroyNotify) gst_omx_video_negotiation_map_free);
2045     return FALSE;
2046   }
2047
2048   GST_OMX_INIT_STRUCT (&param);
2049   param.nPortIndex = self->dec_out_port->index;
2050
2051   for (l = negotiation_map; l; l = l->next) {
2052     GstOMXVideoNegotiationMap *m = l->data;
2053
2054     if (m->format == format) {
2055       param.eColorFormat = m->type;
2056       break;
2057     }
2058   }
2059
2060   GST_DEBUG_OBJECT (self, "Negotiating color format %s (%d)", format_str,
2061       param.eColorFormat);
2062
2063   /* We must find something here */
2064   g_assert (l != NULL);
2065   g_list_free_full (negotiation_map,
2066       (GDestroyNotify) gst_omx_video_negotiation_map_free);
2067
2068   err =
2069       gst_omx_component_set_parameter (self->dec,
2070       OMX_IndexParamVideoPortFormat, &param);
2071   if (err != OMX_ErrorNone) {
2072     GST_ERROR_OBJECT (self, "Failed to set video port format: %s (0x%08x)",
2073         gst_omx_error_to_string (err), err);
2074   }
2075
2076   gst_caps_unref (intersection);
2077   return (err == OMX_ErrorNone);
2078 }
2079
2080 static gboolean
2081 gst_omx_video_dec_set_format (GstVideoDecoder * decoder,
2082     GstVideoCodecState * state)
2083 {
2084   GstOMXVideoDec *self;
2085   GstOMXVideoDecClass *klass;
2086   GstVideoInfo *info = &state->info;
2087   gboolean is_format_change = FALSE;
2088   gboolean needs_disable = FALSE;
2089   OMX_PARAM_PORTDEFINITIONTYPE port_def;
2090
2091   self = GST_OMX_VIDEO_DEC (decoder);
2092   klass = GST_OMX_VIDEO_DEC_GET_CLASS (decoder);
2093
2094   GST_DEBUG_OBJECT (self, "Setting new caps %" GST_PTR_FORMAT, state->caps);
2095
2096   gst_omx_port_get_port_definition (self->dec_in_port, &port_def);
2097
2098   /* Check if the caps change is a real format change or if only irrelevant
2099    * parts of the caps have changed or nothing at all.
2100    */
2101   is_format_change |= port_def.format.video.nFrameWidth != info->width;
2102   is_format_change |= port_def.format.video.nFrameHeight != info->height;
2103   is_format_change |= (port_def.format.video.xFramerate == 0
2104       && info->fps_n != 0)
2105       || (port_def.format.video.xFramerate !=
2106       (info->fps_n << 16) / (info->fps_d));
2107   is_format_change |= (self->codec_data != state->codec_data);
2108   if (klass->is_format_change)
2109     is_format_change |=
2110         klass->is_format_change (self, self->dec_in_port, state);
2111
2112   needs_disable =
2113       gst_omx_component_get_state (self->dec,
2114       GST_CLOCK_TIME_NONE) != OMX_StateLoaded;
2115   /* If the component is not in Loaded state and a real format change happens
2116    * we have to disable the port and re-allocate all buffers. If no real
2117    * format change happened we can just exit here.
2118    */
2119   if (needs_disable && !is_format_change) {
2120     GST_DEBUG_OBJECT (self,
2121         "Already running and caps did not change the format");
2122     if (self->input_state)
2123       gst_video_codec_state_unref (self->input_state);
2124     self->input_state = gst_video_codec_state_ref (state);
2125     return TRUE;
2126   }
2127
2128   if (needs_disable && is_format_change) {
2129 #if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
2130     GstOMXPort *out_port =
2131         self->eglimage ? self->egl_out_port : self->dec_out_port;
2132 #else
2133     GstOMXPort *out_port = self->dec_out_port;
2134 #endif
2135
2136     GST_DEBUG_OBJECT (self, "Need to disable and drain decoder");
2137
2138     gst_omx_video_dec_drain (self);
2139     gst_omx_video_dec_flush (decoder);
2140     gst_omx_port_set_flushing (out_port, 5 * GST_SECOND, TRUE);
2141
2142     if (klass->cdata.hacks & GST_OMX_HACK_NO_COMPONENT_RECONFIGURE) {
2143       GST_VIDEO_DECODER_STREAM_UNLOCK (self);
2144       gst_omx_video_dec_stop (GST_VIDEO_DECODER (self));
2145       gst_omx_video_dec_close (GST_VIDEO_DECODER (self));
2146       GST_VIDEO_DECODER_STREAM_LOCK (self);
2147
2148       if (!gst_omx_video_dec_open (GST_VIDEO_DECODER (self)))
2149         return FALSE;
2150       needs_disable = FALSE;
2151 #ifdef TIZEN_FEATURE_OMX
2152       gst_omx_port_get_port_definition (self->dec_in_port, &port_def);
2153 #endif
2154     } else {
2155 #if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
2156       if (self->eglimage) {
2157         gst_omx_port_set_flushing (self->dec_in_port, 5 * GST_SECOND, TRUE);
2158         gst_omx_port_set_flushing (self->dec_out_port, 5 * GST_SECOND, TRUE);
2159         gst_omx_port_set_flushing (self->egl_in_port, 5 * GST_SECOND, TRUE);
2160         gst_omx_port_set_flushing (self->egl_out_port, 5 * GST_SECOND, TRUE);
2161       }
2162 #endif
2163       if (gst_omx_port_set_enabled (self->dec_in_port, FALSE) != OMX_ErrorNone)
2164         return FALSE;
2165
2166       if (gst_omx_port_wait_buffers_released (self->dec_in_port,
2167               5 * GST_SECOND) != OMX_ErrorNone)
2168         return FALSE;
2169
2170       if (gst_omx_port_deallocate_buffers (self->dec_in_port) != OMX_ErrorNone)
2171         return FALSE;
2172
2173       if (gst_omx_port_wait_enabled (self->dec_in_port,
2174               1 * GST_SECOND) != OMX_ErrorNone)
2175         return FALSE;
2176 #ifndef TIZEN_FEATURE_OMX
2177       if (gst_omx_port_set_enabled (out_port, FALSE) != OMX_ErrorNone)
2178         return FALSE;
2179
2180       if (gst_omx_port_wait_buffers_released (out_port,
2181               1 * GST_SECOND) != OMX_ErrorNone)
2182         return FALSE;
2183
2184       if (gst_omx_video_dec_deallocate_output_buffers (self) != OMX_ErrorNone)
2185         return FALSE;
2186
2187       if (gst_omx_port_wait_enabled (out_port, 1 * GST_SECOND) != OMX_ErrorNone)
2188         return FALSE;
2189 #endif
2190 #if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
2191       if (self->eglimage) {
2192         OMX_STATETYPE egl_state;
2193
2194         egl_state = gst_omx_component_get_state (self->egl_render, 0);
2195         if (egl_state > OMX_StateLoaded || egl_state == OMX_StateInvalid) {
2196
2197           if (egl_state > OMX_StateIdle) {
2198             gst_omx_component_set_state (self->egl_render, OMX_StateIdle);
2199             gst_omx_component_set_state (self->dec, OMX_StateIdle);
2200             egl_state = gst_omx_component_get_state (self->egl_render,
2201                 5 * GST_SECOND);
2202             gst_omx_component_get_state (self->dec, 1 * GST_SECOND);
2203           }
2204           gst_omx_component_set_state (self->egl_render, OMX_StateLoaded);
2205           gst_omx_component_set_state (self->dec, OMX_StateLoaded);
2206
2207           gst_omx_close_tunnel (self->dec_out_port, self->egl_in_port);
2208
2209           if (egl_state > OMX_StateLoaded) {
2210             gst_omx_component_get_state (self->egl_render, 5 * GST_SECOND);
2211           }
2212
2213           gst_omx_component_set_state (self->dec, OMX_StateIdle);
2214
2215           gst_omx_component_set_state (self->dec, OMX_StateExecuting);
2216           gst_omx_component_get_state (self->dec, GST_CLOCK_TIME_NONE);
2217         }
2218         self->eglimage = FALSE;
2219       }
2220 #endif
2221     }
2222     if (self->input_state)
2223       gst_video_codec_state_unref (self->input_state);
2224     self->input_state = NULL;
2225
2226     GST_DEBUG_OBJECT (self, "Decoder drained and disabled");
2227   }
2228
2229   port_def.format.video.nFrameWidth = info->width;
2230   port_def.format.video.nFrameHeight = info->height;
2231   if (info->fps_n == 0)
2232     port_def.format.video.xFramerate = 0;
2233   else
2234     port_def.format.video.xFramerate = (info->fps_n << 16) / (info->fps_d);
2235
2236   GST_DEBUG_OBJECT (self, "Setting inport port definition");
2237
2238   if (gst_omx_port_update_port_definition (self->dec_in_port,
2239           &port_def) != OMX_ErrorNone)
2240     return FALSE;
2241
2242   if (klass->set_format) {
2243     if (!klass->set_format (self, self->dec_in_port, state)) {
2244       GST_ERROR_OBJECT (self, "Subclass failed to set the new format");
2245       return FALSE;
2246     }
2247   }
2248
2249   GST_DEBUG_OBJECT (self, "Updating outport port definition");
2250   if (gst_omx_port_update_port_definition (self->dec_out_port,
2251           NULL) != OMX_ErrorNone)
2252     return FALSE;
2253
2254   gst_buffer_replace (&self->codec_data, state->codec_data);
2255   self->input_state = gst_video_codec_state_ref (state);
2256
2257   GST_DEBUG_OBJECT (self, "Enabling component");
2258
2259   if (needs_disable) {
2260     if (gst_omx_port_set_enabled (self->dec_in_port, TRUE) != OMX_ErrorNone)
2261       return FALSE;
2262 #ifdef TIZEN_FEATURE_OMX
2263     if (gst_omx_port_tbm_allocate_dec_buffers (self->dec_in_port,
2264         self->bufmgr, self->dec_in_port->use_buffer) != OMX_ErrorNone)
2265      return FALSE;
2266 #else
2267     if (gst_omx_port_allocate_buffers (self->dec_in_port) != OMX_ErrorNone)
2268       return FALSE;
2269 #endif
2270 #ifndef TIZEN_FEATURE_OMX
2271     if ((klass->cdata.hacks & GST_OMX_HACK_NO_DISABLE_OUTPORT)) {
2272       if (gst_omx_port_set_enabled (self->dec_out_port, TRUE) != OMX_ErrorNone)
2273         return FALSE;
2274       if (gst_omx_port_allocate_buffers (self->dec_out_port) != OMX_ErrorNone)
2275         return FALSE;
2276
2277       if (gst_omx_port_wait_enabled (self->dec_out_port,
2278               5 * GST_SECOND) != OMX_ErrorNone)
2279         return FALSE;
2280     }
2281 #endif
2282     if (gst_omx_port_wait_enabled (self->dec_in_port,
2283             5 * GST_SECOND) != OMX_ErrorNone)
2284       return FALSE;
2285
2286     if (gst_omx_port_mark_reconfigured (self->dec_in_port) != OMX_ErrorNone)
2287       return FALSE;
2288   } else {
2289     if (!gst_omx_video_dec_negotiate (self))
2290       GST_LOG_OBJECT (self, "Negotiation failed, will get output format later");
2291
2292     if (!(klass->cdata.hacks & GST_OMX_HACK_NO_DISABLE_OUTPORT)) {
2293       /* Disable output port */
2294       if (gst_omx_port_set_enabled (self->dec_out_port, FALSE) != OMX_ErrorNone)
2295         return FALSE;
2296
2297       if (gst_omx_port_wait_enabled (self->dec_out_port,
2298               1 * GST_SECOND) != OMX_ErrorNone)
2299         return FALSE;
2300
2301       if (gst_omx_component_set_state (self->dec,
2302               OMX_StateIdle) != OMX_ErrorNone)
2303         return FALSE;
2304
2305       /* Need to allocate buffers to reach Idle state */
2306 #ifdef TIZEN_FEATURE_OMX
2307       if (gst_omx_port_tbm_allocate_dec_buffers (self->dec_in_port,
2308           self->bufmgr, self->dec_in_port->use_buffer) != OMX_ErrorNone)
2309           return FALSE;
2310       if (gst_omx_port_tbm_allocate_dec_buffers (self->dec_out_port,
2311           self->bufmgr, self->dec_out_port->use_buffer) != OMX_ErrorNone)
2312           return FALSE;
2313 #else
2314       if (gst_omx_port_allocate_buffers (self->dec_in_port) != OMX_ErrorNone)
2315         return FALSE;
2316       if (gst_omx_port_allocate_buffers (self->dec_out_port) != OMX_ErrorNone)
2317         return FALSE;
2318 #endif
2319     } else {
2320
2321       if (gst_omx_component_set_state (self->dec,
2322               OMX_StateIdle) != OMX_ErrorNone)
2323         return FALSE;
2324
2325       /* Need to allocate buffers to reach Idle state */
2326 #ifdef TIZEN_FEATURE_OMX
2327       if (gst_omx_port_tbm_allocate_dec_buffers (self->dec_in_port,
2328           self->bufmgr, self->dec_in_port->use_buffer) != OMX_ErrorNone)
2329           return FALSE;
2330       if (gst_omx_port_tbm_allocate_dec_buffers (self->dec_out_port,
2331           self->bufmgr, self->dec_out_port->use_buffer) != OMX_ErrorNone)
2332           return FALSE;
2333 #else
2334       if (gst_omx_port_allocate_buffers (self->dec_in_port) != OMX_ErrorNone)
2335         return FALSE;
2336       if (gst_omx_port_allocate_buffers (self->dec_out_port) != OMX_ErrorNone)
2337         return FALSE;
2338 #endif
2339   }
2340
2341     if (gst_omx_component_get_state (self->dec,
2342             GST_CLOCK_TIME_NONE) != OMX_StateIdle)
2343       return FALSE;
2344
2345     if (gst_omx_component_set_state (self->dec,
2346             OMX_StateExecuting) != OMX_ErrorNone)
2347       return FALSE;
2348
2349     if (gst_omx_component_get_state (self->dec,
2350             GST_CLOCK_TIME_NONE) != OMX_StateExecuting)
2351       return FALSE;
2352   }
2353
2354   /* Unset flushing to allow ports to accept data again */
2355   gst_omx_port_set_flushing (self->dec_in_port, 5 * GST_SECOND, FALSE);
2356   gst_omx_port_set_flushing (self->dec_out_port, 5 * GST_SECOND, FALSE);
2357
2358   if (gst_omx_component_get_last_error (self->dec) != OMX_ErrorNone) {
2359     GST_ERROR_OBJECT (self, "Component in error state: %s (0x%08x)",
2360         gst_omx_component_get_last_error_string (self->dec),
2361         gst_omx_component_get_last_error (self->dec));
2362     return FALSE;
2363   }
2364
2365   self->downstream_flow_ret = GST_FLOW_OK;
2366   return TRUE;
2367 }
2368
2369 static gboolean
2370 gst_omx_video_dec_flush (GstVideoDecoder * decoder)
2371 {
2372   GstOMXVideoDec *self = GST_OMX_VIDEO_DEC (decoder);
2373   OMX_ERRORTYPE err = OMX_ErrorNone;
2374
2375   GST_DEBUG_OBJECT (self, "Flushing decoder");
2376
2377   if (gst_omx_component_get_state (self->dec, 0) == OMX_StateLoaded)
2378     return TRUE;
2379
2380   /* 0) Pause the components */
2381   if (gst_omx_component_get_state (self->dec, 0) == OMX_StateExecuting) {
2382     gst_omx_component_set_state (self->dec, OMX_StatePause);
2383     gst_omx_component_get_state (self->dec, GST_CLOCK_TIME_NONE);
2384   }
2385 #if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
2386   if (self->eglimage) {
2387     if (gst_omx_component_get_state (self->egl_render, 0) == OMX_StateExecuting) {
2388       gst_omx_component_set_state (self->egl_render, OMX_StatePause);
2389       gst_omx_component_get_state (self->egl_render, GST_CLOCK_TIME_NONE);
2390     }
2391   }
2392 #endif
2393
2394   /* 1) Wait until the srcpad loop is stopped,
2395    * unlock GST_VIDEO_DECODER_STREAM_LOCK to prevent deadlocks
2396    * caused by using this lock from inside the loop function */
2397   GST_VIDEO_DECODER_STREAM_UNLOCK (self);
2398   gst_pad_stop_task (GST_VIDEO_DECODER_SRC_PAD (decoder));
2399   GST_DEBUG_OBJECT (self, "Flushing -- task stopped");
2400   GST_VIDEO_DECODER_STREAM_LOCK (self);
2401
2402   /* 2) Flush the ports */
2403   GST_DEBUG_OBJECT (self, "flushing ports");
2404   gst_omx_port_set_flushing (self->dec_in_port, 5 * GST_SECOND, TRUE);
2405   gst_omx_port_set_flushing (self->dec_out_port, 5 * GST_SECOND, TRUE);
2406
2407 #if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
2408   if (self->eglimage) {
2409     gst_omx_port_set_flushing (self->egl_in_port, 5 * GST_SECOND, TRUE);
2410     gst_omx_port_set_flushing (self->egl_out_port, 5 * GST_SECOND, TRUE);
2411   }
2412 #endif
2413
2414   /* 3) Resume components */
2415   gst_omx_component_set_state (self->dec, OMX_StateExecuting);
2416   gst_omx_component_get_state (self->dec, GST_CLOCK_TIME_NONE);
2417 #if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
2418   if (self->eglimage) {
2419     gst_omx_component_set_state (self->egl_render, OMX_StateExecuting);
2420     gst_omx_component_get_state (self->egl_render, GST_CLOCK_TIME_NONE);
2421   }
2422 #endif
2423
2424   /* 4) Unset flushing to allow ports to accept data again */
2425   gst_omx_port_set_flushing (self->dec_in_port, 5 * GST_SECOND, FALSE);
2426   gst_omx_port_set_flushing (self->dec_out_port, 5 * GST_SECOND, FALSE);
2427
2428 #if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
2429   if (self->eglimage) {
2430     gst_omx_port_set_flushing (self->egl_in_port, 5 * GST_SECOND, FALSE);
2431     gst_omx_port_set_flushing (self->egl_out_port, 5 * GST_SECOND, FALSE);
2432     err = gst_omx_port_populate (self->egl_out_port);
2433     gst_omx_port_mark_reconfigured (self->egl_out_port);
2434   } else {
2435     err = gst_omx_port_populate (self->dec_out_port);
2436   }
2437 #else
2438   err = gst_omx_port_populate (self->dec_out_port);
2439 #endif
2440
2441   if (err != OMX_ErrorNone) {
2442     GST_WARNING_OBJECT (self, "Failed to populate output port: %s (0x%08x)",
2443         gst_omx_error_to_string (err), err);
2444   }
2445
2446   /* Reset our state */
2447   self->last_upstream_ts = 0;
2448   self->downstream_flow_ret = GST_FLOW_OK;
2449   self->started = FALSE;
2450   GST_DEBUG_OBJECT (self, "Flush finished");
2451
2452   return TRUE;
2453 }
2454
2455 static GstFlowReturn
2456 gst_omx_video_dec_handle_frame (GstVideoDecoder * decoder,
2457     GstVideoCodecFrame * frame)
2458 {
2459   GstOMXAcquireBufferReturn acq_ret = GST_OMX_ACQUIRE_BUFFER_ERROR;
2460   GstOMXVideoDec *self;
2461   GstOMXVideoDecClass *klass;
2462   GstOMXPort *port;
2463   GstOMXBuffer *buf;
2464   GstBuffer *codec_data = NULL;
2465   guint offset = 0, size;
2466   GstClockTime timestamp, duration;
2467   OMX_ERRORTYPE err;
2468
2469   self = GST_OMX_VIDEO_DEC (decoder);
2470   klass = GST_OMX_VIDEO_DEC_GET_CLASS (self);
2471
2472   GST_DEBUG_OBJECT (self, "Handling frame");
2473
2474   if (!self->started) {
2475     if (!GST_VIDEO_CODEC_FRAME_IS_SYNC_POINT (frame)) {
2476       gst_video_decoder_drop_frame (GST_VIDEO_DECODER (self), frame);
2477       return GST_FLOW_OK;
2478     }
2479     GST_DEBUG_OBJECT (self, "Starting task");
2480     gst_pad_start_task (GST_VIDEO_DECODER_SRC_PAD (self),
2481         (GstTaskFunction) gst_omx_video_dec_loop, decoder, NULL);
2482   }
2483
2484   timestamp = frame->pts;
2485   duration = frame->duration;
2486
2487   if (self->downstream_flow_ret != GST_FLOW_OK) {
2488     gst_video_codec_frame_unref (frame);
2489     return self->downstream_flow_ret;
2490   }
2491
2492   if (klass->prepare_frame) {
2493     GstFlowReturn ret;
2494
2495     ret = klass->prepare_frame (self, frame);
2496     if (ret != GST_FLOW_OK) {
2497       GST_ERROR_OBJECT (self, "Preparing frame failed: %s",
2498           gst_flow_get_name (ret));
2499       gst_video_codec_frame_unref (frame);
2500       return ret;
2501     }
2502   }
2503
2504   port = self->dec_in_port;
2505
2506   size = gst_buffer_get_size (frame->input_buffer);
2507   while (offset < size) {
2508     /* Make sure to release the base class stream lock, otherwise
2509      * _loop() can't call _finish_frame() and we might block forever
2510      * because no input buffers are released */
2511     GST_VIDEO_DECODER_STREAM_UNLOCK (self);
2512     acq_ret = gst_omx_port_acquire_buffer (port, &buf);
2513
2514     if (acq_ret == GST_OMX_ACQUIRE_BUFFER_ERROR) {
2515       GST_VIDEO_DECODER_STREAM_LOCK (self);
2516       goto component_error;
2517     } else if (acq_ret == GST_OMX_ACQUIRE_BUFFER_FLUSHING) {
2518       GST_VIDEO_DECODER_STREAM_LOCK (self);
2519       goto flushing;
2520     } else if (acq_ret == GST_OMX_ACQUIRE_BUFFER_RECONFIGURE) {
2521       /* Reallocate all buffers */
2522       err = gst_omx_port_set_enabled (port, FALSE);
2523       if (err != OMX_ErrorNone) {
2524         GST_VIDEO_DECODER_STREAM_LOCK (self);
2525         goto reconfigure_error;
2526       }
2527
2528       err = gst_omx_port_wait_buffers_released (port, 5 * GST_SECOND);
2529       if (err != OMX_ErrorNone) {
2530         GST_VIDEO_DECODER_STREAM_LOCK (self);
2531         goto reconfigure_error;
2532       }
2533
2534       err = gst_omx_port_deallocate_buffers (port);
2535       if (err != OMX_ErrorNone) {
2536         GST_VIDEO_DECODER_STREAM_LOCK (self);
2537         goto reconfigure_error;
2538       }
2539
2540       err = gst_omx_port_wait_enabled (port, 1 * GST_SECOND);
2541       if (err != OMX_ErrorNone) {
2542         GST_VIDEO_DECODER_STREAM_LOCK (self);
2543         goto reconfigure_error;
2544       }
2545
2546       err = gst_omx_port_set_enabled (port, TRUE);
2547       if (err != OMX_ErrorNone) {
2548         GST_VIDEO_DECODER_STREAM_LOCK (self);
2549         goto reconfigure_error;
2550       }
2551 #ifdef TIZEN_FEATURE_OMX
2552       err = gst_omx_port_tbm_allocate_dec_buffers (port, self->bufmgr, port->use_buffer);
2553 #else
2554       err = gst_omx_port_allocate_buffers (port);
2555 #endif
2556       if (err != OMX_ErrorNone) {
2557         GST_VIDEO_DECODER_STREAM_LOCK (self);
2558         goto reconfigure_error;
2559       }
2560
2561       err = gst_omx_port_wait_enabled (port, 5 * GST_SECOND);
2562       if (err != OMX_ErrorNone) {
2563         GST_VIDEO_DECODER_STREAM_LOCK (self);
2564         goto reconfigure_error;
2565       }
2566
2567       err = gst_omx_port_mark_reconfigured (port);
2568       if (err != OMX_ErrorNone) {
2569         GST_VIDEO_DECODER_STREAM_LOCK (self);
2570         goto reconfigure_error;
2571       }
2572
2573       /* Now get a new buffer and fill it */
2574       GST_VIDEO_DECODER_STREAM_LOCK (self);
2575       continue;
2576     }
2577     GST_VIDEO_DECODER_STREAM_LOCK (self);
2578
2579     g_assert (acq_ret == GST_OMX_ACQUIRE_BUFFER_OK && buf != NULL);
2580
2581     if (buf->omx_buf->nAllocLen - buf->omx_buf->nOffset <= 0) {
2582       gst_omx_port_release_buffer (port, buf);
2583       goto full_buffer;
2584     }
2585
2586     if (self->downstream_flow_ret != GST_FLOW_OK) {
2587       gst_omx_port_release_buffer (port, buf);
2588       goto flow_error;
2589     }
2590
2591     if (self->codec_data) {
2592       GST_DEBUG_OBJECT (self, "Passing codec data to the component");
2593
2594       codec_data = self->codec_data;
2595
2596       if (buf->omx_buf->nAllocLen - buf->omx_buf->nOffset <
2597           gst_buffer_get_size (codec_data)) {
2598         gst_omx_port_release_buffer (port, buf);
2599         goto too_large_codec_data;
2600       }
2601
2602       buf->omx_buf->nFlags |= OMX_BUFFERFLAG_CODECCONFIG;
2603       buf->omx_buf->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME;
2604       buf->omx_buf->nFilledLen = gst_buffer_get_size (codec_data);;
2605
2606 #ifdef TIZEN_FEATURE_OMX
2607       if (port->use_buffer) {
2608         gst_buffer_extract (codec_data, 0,
2609             (OMX_U8 *) buf->mm_vbuffer->data[0] + buf->omx_buf->nOffset,
2610             buf->omx_buf->nFilledLen);
2611       } else {
2612         gst_buffer_extract (codec_data, 0,
2613             buf->omx_buf->pBuffer + buf->omx_buf->nOffset,
2614             buf->omx_buf->nFilledLen);
2615       }
2616 #ifdef CODEC_DEC_INTPUT_DUMP
2617       decoder_input_dump (buf, port->use_buffer);
2618 #endif
2619 #endif
2620
2621       if (GST_CLOCK_TIME_IS_VALID (timestamp))
2622         buf->omx_buf->nTimeStamp =
2623             gst_util_uint64_scale (timestamp, OMX_TICKS_PER_SECOND, GST_SECOND);
2624       else
2625         buf->omx_buf->nTimeStamp = 0;
2626       buf->omx_buf->nTickCount = 0;
2627
2628       self->started = TRUE;
2629       err = gst_omx_port_release_buffer (port, buf);
2630       gst_buffer_replace (&self->codec_data, NULL);
2631       if (err != OMX_ErrorNone)
2632         goto release_error;
2633       /* Acquire new buffer for the actual frame */
2634       continue;
2635     }
2636
2637     /* Now handle the frame */
2638     GST_DEBUG_OBJECT (self, "Passing frame offset %d to the component", offset);
2639
2640     /* Copy the buffer content in chunks of size as requested
2641      * by the port */
2642     buf->omx_buf->nFilledLen =
2643         MIN (size - offset, buf->omx_buf->nAllocLen - buf->omx_buf->nOffset);
2644     GST_DEBUG_OBJECT (self, "nFilledLen %lu, %p", buf->omx_buf->nFilledLen, buf->omx_buf->pBuffer);
2645
2646 #ifdef TIZEN_FEATURE_OMX
2647     if (port->use_buffer) {
2648       gst_buffer_extract (frame->input_buffer, offset,
2649           (OMX_U8 *) buf->mm_vbuffer->data[0] + buf->omx_buf->nOffset,
2650           buf->omx_buf->nFilledLen);
2651     } else {
2652       gst_buffer_extract (frame->input_buffer, offset,
2653           buf->omx_buf->pBuffer + buf->omx_buf->nOffset,
2654           buf->omx_buf->nFilledLen);
2655     }
2656 #ifdef CODEC_DEC_INTPUT_DUMP
2657       decoder_input_dump (buf, port->use_buffer);
2658 #endif
2659 #endif
2660     if (timestamp != GST_CLOCK_TIME_NONE) {
2661       buf->omx_buf->nTimeStamp =
2662           gst_util_uint64_scale (timestamp, OMX_TICKS_PER_SECOND, GST_SECOND);
2663       self->last_upstream_ts = timestamp;
2664     } else {
2665       buf->omx_buf->nTimeStamp = 0;
2666     }
2667
2668     if (duration != GST_CLOCK_TIME_NONE && offset == 0) {
2669       buf->omx_buf->nTickCount =
2670           gst_util_uint64_scale (duration, OMX_TICKS_PER_SECOND, GST_SECOND);
2671       self->last_upstream_ts += duration;
2672     } else {
2673       buf->omx_buf->nTickCount = 0;
2674     }
2675
2676     if (offset == 0 && GST_VIDEO_CODEC_FRAME_IS_SYNC_POINT (frame))
2677       buf->omx_buf->nFlags |= OMX_BUFFERFLAG_SYNCFRAME;
2678
2679     /* TODO: Set flags
2680      *   - OMX_BUFFERFLAG_DECODEONLY for buffers that are outside
2681      *     the segment
2682      */
2683
2684     offset += buf->omx_buf->nFilledLen;
2685
2686     if (offset == size)
2687       buf->omx_buf->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME;
2688
2689     self->started = TRUE;
2690     err = gst_omx_port_release_buffer (port, buf);
2691     if (err != OMX_ErrorNone)
2692       goto release_error;
2693   }
2694
2695   gst_video_codec_frame_unref (frame);
2696
2697   GST_DEBUG_OBJECT (self, "Passed frame to component");
2698
2699   return self->downstream_flow_ret;
2700
2701 full_buffer:
2702   {
2703     gst_video_codec_frame_unref (frame);
2704     GST_ELEMENT_ERROR (self, LIBRARY, FAILED, (NULL),
2705         ("Got OpenMAX buffer with no free space (%p, %u/%u)", buf,
2706             (guint) buf->omx_buf->nOffset, (guint) buf->omx_buf->nAllocLen));
2707     return GST_FLOW_ERROR;
2708   }
2709
2710 flow_error:
2711   {
2712     gst_video_codec_frame_unref (frame);
2713
2714     return self->downstream_flow_ret;
2715   }
2716
2717 too_large_codec_data:
2718   {
2719     gst_video_codec_frame_unref (frame);
2720     GST_ELEMENT_ERROR (self, STREAM, FORMAT, (NULL),
2721         ("codec_data larger than supported by OpenMAX port "
2722             "(%" G_GSIZE_FORMAT " > %u)", gst_buffer_get_size (codec_data),
2723             (guint) self->dec_in_port->port_def.nBufferSize));
2724     return GST_FLOW_ERROR;
2725   }
2726
2727 component_error:
2728   {
2729     gst_video_codec_frame_unref (frame);
2730     GST_ELEMENT_ERROR (self, LIBRARY, FAILED, (NULL),
2731         ("OpenMAX component in error state %s (0x%08x)",
2732             gst_omx_component_get_last_error_string (self->dec),
2733             gst_omx_component_get_last_error (self->dec)));
2734     return GST_FLOW_ERROR;
2735   }
2736
2737 flushing:
2738   {
2739     gst_video_codec_frame_unref (frame);
2740     GST_DEBUG_OBJECT (self, "Flushing -- returning FLUSHING");
2741     return GST_FLOW_FLUSHING;
2742   }
2743 reconfigure_error:
2744   {
2745     gst_video_codec_frame_unref (frame);
2746     GST_ELEMENT_ERROR (self, LIBRARY, SETTINGS, (NULL),
2747         ("Unable to reconfigure input port"));
2748     return GST_FLOW_ERROR;
2749   }
2750 release_error:
2751   {
2752     gst_video_codec_frame_unref (frame);
2753     GST_ELEMENT_ERROR (self, LIBRARY, SETTINGS, (NULL),
2754         ("Failed to relase input buffer to component: %s (0x%08x)",
2755             gst_omx_error_to_string (err), err));
2756     return GST_FLOW_ERROR;
2757   }
2758 }
2759
2760 static GstFlowReturn
2761 gst_omx_video_dec_finish (GstVideoDecoder * decoder)
2762 {
2763   GstOMXVideoDec *self;
2764
2765   self = GST_OMX_VIDEO_DEC (decoder);
2766
2767   return gst_omx_video_dec_drain (self);
2768 }
2769
2770 static GstFlowReturn
2771 gst_omx_video_dec_drain (GstOMXVideoDec * self)
2772 {
2773   GstOMXVideoDecClass *klass;
2774   GstOMXBuffer *buf;
2775   GstOMXAcquireBufferReturn acq_ret;
2776   OMX_ERRORTYPE err;
2777
2778   GST_DEBUG_OBJECT (self, "Draining component");
2779
2780   klass = GST_OMX_VIDEO_DEC_GET_CLASS (self);
2781
2782   if (!self->started) {
2783     GST_DEBUG_OBJECT (self, "Component not started yet");
2784     return GST_FLOW_OK;
2785   }
2786   self->started = FALSE;
2787
2788   if ((klass->cdata.hacks & GST_OMX_HACK_NO_EMPTY_EOS_BUFFER)) {
2789     GST_WARNING_OBJECT (self, "Component does not support empty EOS buffers");
2790     return GST_FLOW_OK;
2791   }
2792
2793   /* Make sure to release the base class stream lock, otherwise
2794    * _loop() can't call _finish_frame() and we might block forever
2795    * because no input buffers are released */
2796   GST_VIDEO_DECODER_STREAM_UNLOCK (self);
2797
2798   /* Send an EOS buffer to the component and let the base
2799    * class drop the EOS event. We will send it later when
2800    * the EOS buffer arrives on the output port. */
2801   acq_ret = gst_omx_port_acquire_buffer (self->dec_in_port, &buf);
2802   if (acq_ret != GST_OMX_ACQUIRE_BUFFER_OK) {
2803     GST_VIDEO_DECODER_STREAM_LOCK (self);
2804     GST_ERROR_OBJECT (self, "Failed to acquire buffer for draining: %d",
2805         acq_ret);
2806     return GST_FLOW_ERROR;
2807   }
2808
2809   g_mutex_lock (&self->drain_lock);
2810   self->draining = TRUE;
2811   buf->omx_buf->nFilledLen = 0;
2812   buf->omx_buf->nTimeStamp =
2813       gst_util_uint64_scale (self->last_upstream_ts, OMX_TICKS_PER_SECOND,
2814       GST_SECOND);
2815   buf->omx_buf->nTickCount = 0;
2816   buf->omx_buf->nFlags |= OMX_BUFFERFLAG_EOS;
2817   err = gst_omx_port_release_buffer (self->dec_in_port, buf);
2818   if (err != OMX_ErrorNone) {
2819     GST_ERROR_OBJECT (self, "Failed to drain component: %s (0x%08x)",
2820         gst_omx_error_to_string (err), err);
2821     g_mutex_unlock (&self->drain_lock);
2822     GST_VIDEO_DECODER_STREAM_LOCK (self);
2823     return GST_FLOW_ERROR;
2824   }
2825
2826   GST_DEBUG_OBJECT (self, "Waiting until component is drained");
2827
2828   if (G_UNLIKELY (self->dec->hacks & GST_OMX_HACK_DRAIN_MAY_NOT_RETURN)) {
2829     gint64 wait_until = g_get_monotonic_time () + G_TIME_SPAN_SECOND / 2;
2830
2831     if (!g_cond_wait_until (&self->drain_cond, &self->drain_lock, wait_until))
2832       GST_WARNING_OBJECT (self, "Drain timed out");
2833     else
2834       GST_DEBUG_OBJECT (self, "Drained component");
2835
2836   } else {
2837     g_cond_wait (&self->drain_cond, &self->drain_lock);
2838     GST_DEBUG_OBJECT (self, "Drained component");
2839   }
2840
2841   g_mutex_unlock (&self->drain_lock);
2842   GST_VIDEO_DECODER_STREAM_LOCK (self);
2843
2844   self->started = FALSE;
2845
2846   return GST_FLOW_OK;
2847 }
2848
2849 static gboolean
2850 gst_omx_video_dec_decide_allocation (GstVideoDecoder * bdec, GstQuery * query)
2851 {
2852   GstBufferPool *pool;
2853   GstStructure *config;
2854
2855 #if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
2856   {
2857     GstCaps *caps;
2858     gint i, n;
2859     GstVideoInfo info;
2860
2861     gst_query_parse_allocation (query, &caps, NULL);
2862     if (caps && gst_video_info_from_caps (&info, caps)
2863         && info.finfo->format == GST_VIDEO_FORMAT_RGBA) {
2864       gboolean found = FALSE;
2865       GstCapsFeatures *feature = gst_caps_get_features (caps, 0);
2866       /* Prefer an EGLImage allocator if available and we want to use it */
2867       n = gst_query_get_n_allocation_params (query);
2868       for (i = 0; i < n; i++) {
2869         GstAllocator *allocator;
2870         GstAllocationParams params;
2871
2872         gst_query_parse_nth_allocation_param (query, i, &allocator, &params);
2873         if (allocator) {
2874           if (g_strcmp0 (allocator->mem_type, GST_EGL_IMAGE_MEMORY_TYPE) == 0) {
2875             found = TRUE;
2876             gst_query_set_nth_allocation_param (query, 0, allocator, &params);
2877             while (gst_query_get_n_allocation_params (query) > 1)
2878               gst_query_remove_nth_allocation_param (query, 1);
2879           }
2880
2881           gst_object_unref (allocator);
2882
2883           if (found)
2884             break;
2885         }
2886       }
2887
2888       /* if try to negotiate with caps feature memory:EGLImage
2889        * and if allocator is not of type memory EGLImage then fails */
2890       if (feature
2891           && gst_caps_features_contains (feature,
2892               GST_CAPS_FEATURE_MEMORY_EGL_IMAGE) && !found) {
2893         return FALSE;
2894       }
2895     }
2896   }
2897 #endif
2898
2899   if (!GST_VIDEO_DECODER_CLASS
2900       (gst_omx_video_dec_parent_class)->decide_allocation (bdec, query))
2901     return FALSE;
2902
2903   g_assert (gst_query_get_n_allocation_pools (query) > 0);
2904   gst_query_parse_nth_allocation_pool (query, 0, &pool, NULL, NULL, NULL);
2905   g_assert (pool != NULL);
2906
2907   config = gst_buffer_pool_get_config (pool);
2908   if (gst_query_find_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL)) {
2909     gst_buffer_pool_config_add_option (config,
2910         GST_BUFFER_POOL_OPTION_VIDEO_META);
2911   }
2912   gst_buffer_pool_set_config (pool, config);
2913   gst_object_unref (pool);
2914
2915   return TRUE;
2916 }
2917
2918 #ifdef TIZEN_FEATURE_OMX
2919 static gboolean
2920 gst_omx_video_dec_acquire_request_flush_buffer (GstOMXVideoDec * self, GstBuffer ** flush_request_buffer)
2921 {
2922   guint8 *dummy_data = NULL;
2923   GstBuffer *buf = NULL;
2924   MMVideoBuffer *mm_vbuffer = NULL;
2925
2926   GST_DEBUG_OBJECT (self, "flush buffer request");
2927
2928   if (self->out_port_pool) {
2929     if (gst_buffer_pool_is_active(self->out_port_pool)) {
2930       dummy_data = g_malloc0(128*128);
2931       buf = gst_buffer_new_wrapped(dummy_data, 128*128);
2932       mm_vbuffer = g_malloc(sizeof(MMVideoBuffer));
2933
2934       mm_vbuffer->type = MM_VIDEO_BUFFER_TYPE_TBM_BO;
2935       mm_vbuffer->size[0] = 0;
2936       mm_vbuffer->flush_request = TRUE;
2937
2938       gst_buffer_append_memory(buf,
2939         gst_memory_new_wrapped(GST_MEMORY_FLAG_READONLY, mm_vbuffer, sizeof(MMVideoBuffer), 0,
2940           sizeof(MMVideoBuffer), mm_vbuffer, g_free));
2941
2942       *flush_request_buffer = buf;
2943
2944       GST_DEBUG_OBJECT (self, "flush buffer requested");
2945       return TRUE;
2946     } else {
2947         GST_DEBUG_OBJECT (self, "the out port pool has not yet been activated");
2948         return FALSE;
2949     }
2950   } else {
2951     GST_DEBUG_OBJECT (self, "the output port has not yet been activated");
2952     return FALSE;
2953   }
2954 }
2955
2956 static gboolean
2957 gst_omx_video_dec_handle_event (GstVideoDecoder * decoder,
2958     GstEvent * event)
2959 {
2960   GstOMXVideoDec *self;
2961
2962   self = GST_OMX_VIDEO_DEC (decoder);
2963
2964   GST_DEBUG_OBJECT (self, "event: %s", GST_EVENT_TYPE_NAME (event));
2965
2966   switch (GST_EVENT_TYPE (event)) {
2967     case GST_EVENT_FLUSH_START:
2968     {
2969       gst_omx_port_flush_start (self->dec_in_port, TRUE);
2970       gst_omx_port_flush_start (self->dec_out_port, TRUE);
2971       break;
2972     }
2973     case GST_EVENT_FLUSH_STOP:
2974     {
2975       gst_omx_port_flush_start (self->dec_in_port, FALSE);
2976       gst_omx_port_flush_start (self->dec_out_port, FALSE);
2977       break;
2978     }
2979     default:
2980       break;
2981   }
2982
2983   return GST_VIDEO_DECODER_CLASS (gst_omx_video_dec_parent_class)->sink_event (decoder, event);
2984 }
2985 #endif