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