Merge tizen patch based on 1.12.2
[platform/upstream/gstreamer.git] / omx / gstomxvideo.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  * Copyright 2014 Advanced Micro Devices, Inc.
7  *   Author: Christian König <christian.koenig@amd.com>
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation
12  * version 2.1 of the License.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
22  *
23  */
24
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
28
29 #include "gstomxvideo.h"
30
31 GST_DEBUG_CATEGORY (gst_omx_video_debug_category);
32 #define GST_CAT_DEFAULT gst_omx_video_debug_category
33
34 GstVideoFormat
35 gst_omx_video_get_format_from_omx (OMX_COLOR_FORMATTYPE omx_colorformat)
36 {
37   GstVideoFormat format;
38
39   switch (omx_colorformat) {
40     case OMX_COLOR_FormatL8:
41       format = GST_VIDEO_FORMAT_GRAY8;
42       break;
43     case OMX_COLOR_FormatYUV420Planar:
44     case OMX_COLOR_FormatYUV420PackedPlanar:
45       format = GST_VIDEO_FORMAT_I420;
46       break;
47     case OMX_COLOR_FormatYUV420SemiPlanar:
48 #ifdef TIZEN_FEATURE_OMX
49       format = GST_VIDEO_FORMAT_SN12;
50 #else
51       format = GST_VIDEO_FORMAT_NV12;
52 #endif
53       break;
54     case OMX_COLOR_FormatYUV422SemiPlanar:
55       format = GST_VIDEO_FORMAT_NV16;
56       break;
57     case OMX_COLOR_FormatYCbYCr:
58       format = GST_VIDEO_FORMAT_YUY2;
59       break;
60     case OMX_COLOR_FormatYCrYCb:
61       format = GST_VIDEO_FORMAT_YVYU;
62       break;
63     case OMX_COLOR_FormatCbYCrY:
64       format = GST_VIDEO_FORMAT_UYVY;
65       break;
66     case OMX_COLOR_Format32bitARGB8888:
67       /* There is a mismatch in omxil specification 4.2.1 between
68        * OMX_COLOR_Format32bitARGB8888 and its description
69        * Follow the description */
70       format = GST_VIDEO_FORMAT_ABGR;
71       break;
72     case OMX_COLOR_Format32bitBGRA8888:
73       /* Same issue as OMX_COLOR_Format32bitARGB8888 */
74       format = GST_VIDEO_FORMAT_ARGB;
75       break;
76     case OMX_COLOR_Format16bitRGB565:
77       format = GST_VIDEO_FORMAT_RGB16;
78       break;
79     case OMX_COLOR_Format16bitBGR565:
80       format = GST_VIDEO_FORMAT_BGR16;
81       break;
82 #ifdef TIZEN_FEATURE_OMX
83     case OMX_EXT_COLOR_FormatNV12LPhysicalAddress:
84       format = GST_VIDEO_FORMAT_SN12;
85       break;
86     case OMX_EXT_COLOR_FormatNV12TPhysicalAddress:
87       format = GST_VIDEO_FORMAT_ST12;
88       break;
89 #endif
90     default:
91       format = GST_VIDEO_FORMAT_UNKNOWN;
92       break;
93   }
94
95   return format;
96 }
97
98 GList *
99 gst_omx_video_get_supported_colorformats (GstOMXPort * port,
100     GstVideoCodecState * state)
101 {
102   GstOMXComponent *comp = port->comp;
103   OMX_VIDEO_PARAM_PORTFORMATTYPE param;
104   OMX_ERRORTYPE err;
105   GList *negotiation_map = NULL;
106   gint old_index;
107   GstOMXVideoNegotiationMap *m;
108   GstVideoFormat f;
109
110   GST_OMX_INIT_STRUCT (&param);
111   param.nPortIndex = port->index;
112   param.nIndex = 0;
113   if (!state || state->info.fps_n == 0)
114     param.xFramerate = 0;
115   else
116     param.xFramerate = (state->info.fps_n << 16) / (state->info.fps_d);
117
118   old_index = -1;
119   do {
120     err =
121         gst_omx_component_get_parameter (comp,
122         OMX_IndexParamVideoPortFormat, &param);
123
124     /* FIXME: Workaround for Bellagio that simply always
125      * returns the same value regardless of nIndex and
126      * never returns OMX_ErrorNoMore
127      */
128     if (old_index == param.nIndex)
129       break;
130
131     if (err == OMX_ErrorNone || err == OMX_ErrorNoMore) {
132       f = gst_omx_video_get_format_from_omx (param.eColorFormat);
133
134       if (f != GST_VIDEO_FORMAT_UNKNOWN) {
135         m = g_slice_new (GstOMXVideoNegotiationMap);
136         m->format = f;
137         m->type = param.eColorFormat;
138         negotiation_map = g_list_append (negotiation_map, m);
139         GST_DEBUG_OBJECT (comp->parent,
140             "Component supports %s (%x) at index %u",
141             gst_video_format_to_string (f), param.eColorFormat,
142             (guint) param.nIndex);
143       } else {
144         GST_DEBUG_OBJECT (comp->parent,
145             "Component supports unsupported color format %x at index %u",
146             param.eColorFormat, (guint) param.nIndex);
147       }
148     }
149     old_index = param.nIndex++;
150   } while (err == OMX_ErrorNone);
151
152   return negotiation_map;
153 }
154
155 GstCaps *
156 gst_omx_video_get_caps_for_map (GList * map)
157 {
158   GstCaps *caps = gst_caps_new_empty ();
159   GList *l;
160
161   for (l = map; l; l = l->next) {
162     GstOMXVideoNegotiationMap *entry = l->data;
163
164     gst_caps_append_structure (caps,
165         gst_structure_new ("video/x-raw",
166             "format", G_TYPE_STRING,
167             gst_video_format_to_string (entry->format), NULL));
168   }
169   return caps;
170 }
171
172 void
173 gst_omx_video_negotiation_map_free (GstOMXVideoNegotiationMap * m)
174 {
175   g_slice_free (GstOMXVideoNegotiationMap, m);
176 }
177
178 GstVideoCodecFrame *
179 gst_omx_video_find_nearest_frame (GstOMXBuffer * buf, GList * frames)
180 {
181   GstVideoCodecFrame *best = NULL;
182   GstClockTimeDiff best_diff = G_MAXINT64;
183   GstClockTime timestamp;
184   GList *l;
185
186   timestamp =
187       gst_util_uint64_scale (buf->omx_buf->nTimeStamp, GST_SECOND,
188       OMX_TICKS_PER_SECOND);
189
190   for (l = frames; l; l = l->next) {
191     GstVideoCodecFrame *tmp = l->data;
192     GstClockTimeDiff diff = ABS (GST_CLOCK_DIFF (timestamp, tmp->pts));
193
194     if (diff < best_diff) {
195       best = tmp;
196       best_diff = diff;
197
198       if (diff == 0)
199         break;
200     }
201   }
202
203   if (best)
204     gst_video_codec_frame_ref (best);
205
206   g_list_foreach (frames, (GFunc) gst_video_codec_frame_unref, NULL);
207   g_list_free (frames);
208
209   return best;
210 }