omxvideodec: support interlace-mode=interleaved input
[platform/upstream/gstreamer.git] / omx / gstomxh263enc.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  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation
8  * version 2.1 of the License.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
18  *
19  */
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include <gst/gst.h>
26
27 #include "gstomxh263enc.h"
28
29 GST_DEBUG_CATEGORY_STATIC (gst_omx_h263_enc_debug_category);
30 #define GST_CAT_DEFAULT gst_omx_h263_enc_debug_category
31
32 /* prototypes */
33 static gboolean gst_omx_h263_enc_set_format (GstOMXVideoEnc * enc,
34     GstOMXPort * port, GstVideoCodecState * state);
35 static GstCaps *gst_omx_h263_enc_get_caps (GstOMXVideoEnc * enc,
36     GstOMXPort * port, GstVideoCodecState * state);
37
38 enum
39 {
40   PROP_0
41 };
42
43 /* class initialization */
44
45 #define DEBUG_INIT \
46   GST_DEBUG_CATEGORY_INIT (gst_omx_h263_enc_debug_category, "omxh263enc", 0, \
47       "debug category for gst-omx video encoder base class");
48
49 G_DEFINE_TYPE_WITH_CODE (GstOMXH263Enc, gst_omx_h263_enc,
50     GST_TYPE_OMX_VIDEO_ENC, DEBUG_INIT);
51
52 static void
53 gst_omx_h263_enc_class_init (GstOMXH263EncClass * klass)
54 {
55   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
56   GstOMXVideoEncClass *videoenc_class = GST_OMX_VIDEO_ENC_CLASS (klass);
57
58   videoenc_class->set_format = GST_DEBUG_FUNCPTR (gst_omx_h263_enc_set_format);
59   videoenc_class->get_caps = GST_DEBUG_FUNCPTR (gst_omx_h263_enc_get_caps);
60
61   videoenc_class->cdata.default_src_template_caps = "video/x-h263, "
62       "width=(int) [ 16, 4096 ], " "height=(int) [ 16, 4096 ]";
63
64   gst_element_class_set_static_metadata (element_class,
65       "OpenMAX H.263 Video Encoder",
66       "Codec/Encoder/Video/Hardware",
67       "Encode H.263 video streams",
68       "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
69
70   gst_omx_set_default_role (&videoenc_class->cdata, "video_encoder.h263");
71 }
72
73 static void
74 gst_omx_h263_enc_init (GstOMXH263Enc * self)
75 {
76 }
77
78 static gboolean
79 gst_omx_h263_enc_set_format (GstOMXVideoEnc * enc, GstOMXPort * port,
80     GstVideoCodecState * state)
81 {
82   GstOMXH263Enc *self = GST_OMX_H263_ENC (enc);
83   GstCaps *peercaps;
84   OMX_PARAM_PORTDEFINITIONTYPE port_def;
85   OMX_VIDEO_PARAM_PROFILELEVELTYPE param;
86   OMX_ERRORTYPE err;
87   guint profile_id, level_id;
88
89   gst_omx_port_get_port_definition (GST_OMX_VIDEO_ENC (self)->enc_out_port,
90       &port_def);
91   port_def.format.video.eCompressionFormat = OMX_VIDEO_CodingH263;
92   err =
93       gst_omx_port_update_port_definition (GST_OMX_VIDEO_ENC
94       (self)->enc_out_port, &port_def);
95   if (err != OMX_ErrorNone)
96     return FALSE;
97
98   GST_OMX_INIT_STRUCT (&param);
99   param.nPortIndex = GST_OMX_VIDEO_ENC (self)->enc_out_port->index;
100   err =
101       gst_omx_component_get_parameter (GST_OMX_VIDEO_ENC (self)->enc,
102       OMX_IndexParamVideoProfileLevelCurrent, &param);
103   if (err != OMX_ErrorNone) {
104     GST_WARNING_OBJECT (self,
105         "Getting profile/level not supported by component");
106     return TRUE;
107   }
108
109   peercaps = gst_pad_peer_query_caps (GST_VIDEO_ENCODER_SRC_PAD (enc),
110       gst_pad_get_pad_template_caps (GST_VIDEO_ENCODER_SRC_PAD (enc)));
111   if (peercaps) {
112     GstStructure *s;
113
114     if (gst_caps_is_empty (peercaps)) {
115       gst_caps_unref (peercaps);
116       GST_ERROR_OBJECT (self, "Empty caps");
117       return FALSE;
118     }
119
120     s = gst_caps_get_structure (peercaps, 0);
121     if (gst_structure_get_uint (s, "profile", &profile_id)) {
122       switch (profile_id) {
123         case 0:
124           param.eProfile = OMX_VIDEO_H263ProfileBaseline;
125           break;
126         case 1:
127           param.eProfile = OMX_VIDEO_H263ProfileH320Coding;
128           break;
129         case 2:
130           param.eProfile = OMX_VIDEO_H263ProfileBackwardCompatible;
131           break;
132         case 3:
133           param.eProfile = OMX_VIDEO_H263ProfileISWV2;
134           break;
135         case 4:
136           param.eProfile = OMX_VIDEO_H263ProfileISWV3;
137           break;
138         case 5:
139           param.eProfile = OMX_VIDEO_H263ProfileHighCompression;
140           break;
141         case 6:
142           param.eProfile = OMX_VIDEO_H263ProfileInternet;
143           break;
144         case 7:
145           param.eProfile = OMX_VIDEO_H263ProfileInterlace;
146           break;
147         case 8:
148           param.eProfile = OMX_VIDEO_H263ProfileHighLatency;
149           break;
150         default:
151           goto unsupported_profile;
152       }
153     }
154     if (gst_structure_get_uint (s, "level", &level_id)) {
155       switch (level_id) {
156         case 10:
157           param.eLevel = OMX_VIDEO_H263Level10;
158           break;
159         case 20:
160           param.eLevel = OMX_VIDEO_H263Level20;
161           break;
162         case 30:
163           param.eLevel = OMX_VIDEO_H263Level30;
164           break;
165         case 40:
166           param.eLevel = OMX_VIDEO_H263Level40;
167           break;
168         case 50:
169           param.eLevel = OMX_VIDEO_H263Level50;
170           break;
171         case 60:
172           param.eLevel = OMX_VIDEO_H263Level60;
173           break;
174         case 70:
175           param.eLevel = OMX_VIDEO_H263Level70;
176           break;
177         default:
178           goto unsupported_level;
179       }
180     }
181     gst_caps_unref (peercaps);
182   }
183
184   err =
185       gst_omx_component_set_parameter (GST_OMX_VIDEO_ENC (self)->enc,
186       OMX_IndexParamVideoProfileLevelCurrent, &param);
187   if (err == OMX_ErrorUnsupportedIndex) {
188     GST_WARNING_OBJECT (self,
189         "Setting profile/level not supported by component");
190   } else if (err != OMX_ErrorNone) {
191     GST_ERROR_OBJECT (self,
192         "Error setting profile %u and level %u: %s (0x%08x)",
193         (guint) param.eProfile, (guint) param.eLevel,
194         gst_omx_error_to_string (err), err);
195     return FALSE;
196   }
197
198   return TRUE;
199
200 unsupported_profile:
201   GST_ERROR_OBJECT (self, "Unsupported profile %u", profile_id);
202   gst_caps_unref (peercaps);
203   return FALSE;
204
205 unsupported_level:
206   GST_ERROR_OBJECT (self, "Unsupported level %u", level_id);
207   gst_caps_unref (peercaps);
208   return FALSE;
209 }
210
211 static GstCaps *
212 gst_omx_h263_enc_get_caps (GstOMXVideoEnc * enc, GstOMXPort * port,
213     GstVideoCodecState * state)
214 {
215   GstOMXH263Enc *self = GST_OMX_H263_ENC (enc);
216   GstCaps *caps;
217   OMX_ERRORTYPE err;
218   OMX_VIDEO_PARAM_PROFILELEVELTYPE param;
219   guint profile, level;
220
221   caps = gst_caps_new_empty_simple ("video/x-h263");
222
223   GST_OMX_INIT_STRUCT (&param);
224   param.nPortIndex = GST_OMX_VIDEO_ENC (self)->enc_out_port->index;
225
226   err =
227       gst_omx_component_get_parameter (GST_OMX_VIDEO_ENC (self)->enc,
228       OMX_IndexParamVideoProfileLevelCurrent, &param);
229   if (err != OMX_ErrorNone && err != OMX_ErrorUnsupportedIndex) {
230     gst_caps_unref (caps);
231     return NULL;
232   }
233
234   if (err == OMX_ErrorNone) {
235     switch (param.eProfile) {
236       case OMX_VIDEO_H263ProfileBaseline:
237         profile = 0;
238         break;
239       case OMX_VIDEO_H263ProfileH320Coding:
240         profile = 1;
241         break;
242       case OMX_VIDEO_H263ProfileBackwardCompatible:
243         profile = 2;
244         break;
245       case OMX_VIDEO_H263ProfileISWV2:
246         profile = 3;
247         break;
248       case OMX_VIDEO_H263ProfileISWV3:
249         profile = 4;
250         break;
251       case OMX_VIDEO_H263ProfileHighCompression:
252         profile = 5;
253         break;
254       case OMX_VIDEO_H263ProfileInternet:
255         profile = 6;
256         break;
257       case OMX_VIDEO_H263ProfileInterlace:
258         profile = 7;
259         break;
260       case OMX_VIDEO_H263ProfileHighLatency:
261         profile = 8;
262         break;
263       default:
264         g_assert_not_reached ();
265         gst_caps_unref (caps);
266         return NULL;
267     }
268
269     switch (param.eLevel) {
270       case OMX_VIDEO_H263Level10:
271         level = 10;
272         break;
273       case OMX_VIDEO_H263Level20:
274         level = 20;
275         break;
276       case OMX_VIDEO_H263Level30:
277         level = 30;
278         break;
279       case OMX_VIDEO_H263Level40:
280         level = 40;
281         break;
282       case OMX_VIDEO_H263Level50:
283         level = 50;
284         break;
285       case OMX_VIDEO_H263Level60:
286         level = 60;
287         break;
288       case OMX_VIDEO_H263Level70:
289         level = 70;
290         break;
291       default:
292         g_assert_not_reached ();
293         gst_caps_unref (caps);
294         return NULL;
295     }
296
297     gst_caps_set_simple (caps,
298         "profile", G_TYPE_UINT, profile, "level", G_TYPE_UINT, level, NULL);
299   }
300
301   return caps;
302 }