enabling omx decoder
[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       format = GST_VIDEO_FORMAT_NV12;
49       break;
50     case OMX_COLOR_FormatYUV422SemiPlanar:
51       format = GST_VIDEO_FORMAT_NV16;
52       break;
53     case OMX_COLOR_FormatYCbYCr:
54       format = GST_VIDEO_FORMAT_YUY2;
55       break;
56     case OMX_COLOR_FormatYCrYCb:
57       format = GST_VIDEO_FORMAT_YVYU;
58       break;
59     case OMX_COLOR_FormatCbYCrY:
60       format = GST_VIDEO_FORMAT_UYVY;
61       break;
62     case OMX_COLOR_Format32bitARGB8888:
63       /* There is a mismatch in omxil specification 4.2.1 between
64        * OMX_COLOR_Format32bitARGB8888 and its description
65        * Follow the description */
66       format = GST_VIDEO_FORMAT_ABGR;
67       break;
68     case OMX_COLOR_Format32bitBGRA8888:
69       /* Same issue as OMX_COLOR_Format32bitARGB8888 */
70       format = GST_VIDEO_FORMAT_ARGB;
71       break;
72     case OMX_COLOR_Format16bitRGB565:
73       format = GST_VIDEO_FORMAT_RGB16;
74       break;
75     case OMX_COLOR_Format16bitBGR565:
76       format = GST_VIDEO_FORMAT_BGR16;
77       break;
78 #ifdef GST_TIZEN_MODIFICATION
79     case OMX_EXT_COLOR_FormatNV12TPhysicalAddress:
80       format = GST_VIDEO_FORMAT_SN12;
81       break;
82 #endif
83     default:
84       format = GST_VIDEO_FORMAT_UNKNOWN;
85       break;
86   }
87
88   return format;
89 }
90
91 GList *
92 gst_omx_video_get_supported_colorformats (GstOMXPort * port,
93     GstVideoCodecState * state)
94 {
95   GstOMXComponent *comp = port->comp;
96   OMX_VIDEO_PARAM_PORTFORMATTYPE param;
97   OMX_ERRORTYPE err;
98   GList *negotiation_map = NULL;
99   gint old_index;
100   GstOMXVideoNegotiationMap *m;
101   GstVideoFormat f;
102
103   GST_OMX_INIT_STRUCT (&param);
104   param.nPortIndex = port->index;
105   param.nIndex = 0;
106   if (!state || state->info.fps_n == 0)
107     param.xFramerate = 0;
108   else
109     param.xFramerate = (state->info.fps_n << 16) / (state->info.fps_d);
110
111   old_index = -1;
112   do {
113     err =
114         gst_omx_component_get_parameter (comp,
115         OMX_IndexParamVideoPortFormat, &param);
116
117     /* FIXME: Workaround for Bellagio that simply always
118      * returns the same value regardless of nIndex and
119      * never returns OMX_ErrorNoMore
120      */
121     if (old_index == param.nIndex)
122       break;
123
124     if (err == OMX_ErrorNone || err == OMX_ErrorNoMore) {
125       f = gst_omx_video_get_format_from_omx (param.eColorFormat);
126
127       if (f != GST_VIDEO_FORMAT_UNKNOWN) {
128         m = g_slice_new (GstOMXVideoNegotiationMap);
129         m->format = f;
130         m->type = param.eColorFormat;
131         negotiation_map = g_list_append (negotiation_map, m);
132         GST_DEBUG_OBJECT (comp->parent,
133             "Component supports %s (%x) at index %u",
134             gst_video_format_to_string (f), param.eColorFormat,
135             (guint) param.nIndex);
136       } else {
137         GST_DEBUG_OBJECT (comp->parent,
138             "Component supports unsupported color format %x at index %u",
139             param.eColorFormat, (guint) param.nIndex);
140       }
141     }
142     old_index = param.nIndex++;
143   } while (err == OMX_ErrorNone);
144
145   return negotiation_map;
146 }
147
148 GstCaps *
149 gst_omx_video_get_caps_for_map (GList * map)
150 {
151   GstCaps *caps = gst_caps_new_empty ();
152   GList *l;
153
154   for (l = map; l; l = l->next) {
155     GstOMXVideoNegotiationMap *entry = l->data;
156
157     gst_caps_append_structure (caps,
158         gst_structure_new ("video/x-raw",
159             "format", G_TYPE_STRING,
160             gst_video_format_to_string (entry->format), NULL));
161   }
162   return caps;
163 }
164
165 void
166 gst_omx_video_negotiation_map_free (GstOMXVideoNegotiationMap * m)
167 {
168   g_slice_free (GstOMXVideoNegotiationMap, m);
169 }
170
171 GstVideoCodecFrame *
172 gst_omx_video_find_nearest_frame (GstOMXBuffer * buf, GList * frames)
173 {
174   GstVideoCodecFrame *best = NULL;
175   GstClockTimeDiff best_diff = G_MAXINT64;
176   GstClockTime timestamp;
177   GList *l;
178
179   timestamp =
180       gst_util_uint64_scale (buf->omx_buf->nTimeStamp, GST_SECOND,
181       OMX_TICKS_PER_SECOND);
182
183   for (l = frames; l; l = l->next) {
184     GstVideoCodecFrame *tmp = l->data;
185     GstClockTimeDiff diff = ABS (GST_CLOCK_DIFF (timestamp, tmp->pts));
186
187     if (diff < best_diff) {
188       best = tmp;
189       best_diff = diff;
190
191       if (diff == 0)
192         break;
193     }
194   }
195
196   if (best)
197     gst_video_codec_frame_ref (best);
198
199   g_list_foreach (frames, (GFunc) gst_video_codec_frame_unref, NULL);
200   g_list_free (frames);
201
202   return best;
203 }