omxvideodec: support interlace-mode=interleaved input
[platform/upstream/gstreamer.git] / omx / gstomxmpeg4videoenc.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 "gstomxmpeg4videoenc.h"
28
29 GST_DEBUG_CATEGORY_STATIC (gst_omx_mpeg4_video_enc_debug_category);
30 #define GST_CAT_DEFAULT gst_omx_mpeg4_video_enc_debug_category
31
32 /* prototypes */
33 static gboolean gst_omx_mpeg4_video_enc_set_format (GstOMXVideoEnc * enc,
34     GstOMXPort * port, GstVideoCodecState * state);
35 static GstCaps *gst_omx_mpeg4_video_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_mpeg4_video_enc_debug_category, "omxmpeg4videoenc", 0, \
47       "debug category for gst-omx video encoder base class");
48
49 G_DEFINE_TYPE_WITH_CODE (GstOMXMPEG4VideoEnc, gst_omx_mpeg4_video_enc,
50     GST_TYPE_OMX_VIDEO_ENC, DEBUG_INIT);
51
52 static void
53 gst_omx_mpeg4_video_enc_class_init (GstOMXMPEG4VideoEncClass * 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 =
59       GST_DEBUG_FUNCPTR (gst_omx_mpeg4_video_enc_set_format);
60   videoenc_class->get_caps =
61       GST_DEBUG_FUNCPTR (gst_omx_mpeg4_video_enc_get_caps);
62
63   videoenc_class->cdata.default_src_template_caps = "video/mpeg, "
64       "mpegversion=(int) 4, "
65       "systemstream=(boolean) false, "
66       "width=(int) [ 16, 4096 ], " "height=(int) [ 16, 4096 ]";
67
68   gst_element_class_set_static_metadata (element_class,
69       "OpenMAX MPEG4 Video Encoder",
70       "Codec/Encoder/Video/Hardware",
71       "Encode MPEG4 video streams",
72       "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
73
74   gst_omx_set_default_role (&videoenc_class->cdata, "video_encoder.mpeg4");
75 }
76
77 static void
78 gst_omx_mpeg4_video_enc_init (GstOMXMPEG4VideoEnc * self)
79 {
80 }
81
82 static gboolean
83 gst_omx_mpeg4_video_enc_set_format (GstOMXVideoEnc * enc, GstOMXPort * port,
84     GstVideoCodecState * state)
85 {
86   GstOMXMPEG4VideoEnc *self = GST_OMX_MPEG4_VIDEO_ENC (enc);
87   GstCaps *peercaps, *intersection;
88   OMX_PARAM_PORTDEFINITIONTYPE port_def;
89   OMX_VIDEO_PARAM_PROFILELEVELTYPE param;
90   OMX_ERRORTYPE err;
91   const gchar *profile_string, *level_string;
92
93   gst_omx_port_get_port_definition (GST_OMX_VIDEO_ENC (self)->enc_out_port,
94       &port_def);
95   port_def.format.video.eCompressionFormat = OMX_VIDEO_CodingMPEG4;
96   err =
97       gst_omx_port_update_port_definition (GST_OMX_VIDEO_ENC
98       (self)->enc_out_port, &port_def);
99   if (err != OMX_ErrorNone)
100     return FALSE;
101
102   GST_OMX_INIT_STRUCT (&param);
103   param.nPortIndex = GST_OMX_VIDEO_ENC (self)->enc_out_port->index;
104
105   err =
106       gst_omx_component_get_parameter (GST_OMX_VIDEO_ENC (self)->enc,
107       OMX_IndexParamVideoProfileLevelCurrent, &param);
108   if (err != OMX_ErrorNone) {
109     GST_WARNING_OBJECT (self,
110         "Getting profile/level not supported by component");
111     return FALSE;
112   }
113
114   peercaps = gst_pad_peer_query_caps (GST_VIDEO_ENCODER_SRC_PAD (enc), NULL);
115   if (peercaps) {
116     GstStructure *s;
117
118     intersection =
119         gst_caps_intersect (peercaps,
120         gst_pad_get_pad_template_caps (GST_VIDEO_ENCODER_SRC_PAD (enc)));
121
122     gst_caps_unref (peercaps);
123     if (gst_caps_is_empty (intersection)) {
124       gst_caps_unref (intersection);
125       GST_ERROR_OBJECT (self, "Empty caps");
126       return FALSE;
127     }
128
129     s = gst_caps_get_structure (intersection, 0);
130     profile_string = gst_structure_get_string (s, "profile");
131     if (profile_string) {
132       if (g_str_equal (profile_string, "simple")) {
133         param.eProfile = OMX_VIDEO_MPEG4ProfileSimple;
134       } else if (g_str_equal (profile_string, "simple-scalable")) {
135         param.eProfile = OMX_VIDEO_MPEG4ProfileSimpleScalable;
136       } else if (g_str_equal (profile_string, "core")) {
137         param.eProfile = OMX_VIDEO_MPEG4ProfileCore;
138       } else if (g_str_equal (profile_string, "main")) {
139         param.eProfile = OMX_VIDEO_MPEG4ProfileMain;
140       } else if (g_str_equal (profile_string, "n-bit")) {
141         param.eProfile = OMX_VIDEO_MPEG4ProfileNbit;
142       } else if (g_str_equal (profile_string, "scalable")) {
143         param.eProfile = OMX_VIDEO_MPEG4ProfileScalableTexture;
144       } else if (g_str_equal (profile_string, "simple-face")) {
145         param.eProfile = OMX_VIDEO_MPEG4ProfileSimpleFace;
146       } else if (g_str_equal (profile_string, "simple-fba")) {
147         param.eProfile = OMX_VIDEO_MPEG4ProfileSimpleFBA;
148       } else if (g_str_equal (profile_string, "basic-animated-texture")) {
149         param.eProfile = OMX_VIDEO_MPEG4ProfileBasicAnimated;
150       } else if (g_str_equal (profile_string, "hybrid")) {
151         param.eProfile = OMX_VIDEO_MPEG4ProfileHybrid;
152       } else if (g_str_equal (profile_string, "advanced-real-time-simple")) {
153         param.eProfile = OMX_VIDEO_MPEG4ProfileAdvancedRealTime;
154       } else if (g_str_equal (profile_string, "core-scalable")) {
155         param.eProfile = OMX_VIDEO_MPEG4ProfileCoreScalable;
156       } else if (g_str_equal (profile_string, "advanced-coding-efficiency")) {
157         param.eProfile = OMX_VIDEO_MPEG4ProfileAdvancedCoding;
158       } else if (g_str_equal (profile_string, "advanced-core")) {
159         param.eProfile = OMX_VIDEO_MPEG4ProfileAdvancedCore;
160       } else if (g_str_equal (profile_string, "advanced-scalable-texture")) {
161         param.eProfile = OMX_VIDEO_MPEG4ProfileAdvancedScalable;
162       } else if (g_str_equal (profile_string, "advanced-simple")) {
163         param.eProfile = OMX_VIDEO_MPEG4ProfileAdvancedSimple;
164       } else {
165         goto unsupported_profile;
166       }
167     }
168     level_string = gst_structure_get_string (s, "level");
169     if (level_string) {
170       if (g_str_equal (level_string, "0")) {
171         param.eLevel = OMX_VIDEO_MPEG4Level0;
172       } else if (g_str_equal (level_string, "0b")) {
173         param.eLevel = OMX_VIDEO_MPEG4Level0b;
174       } else if (g_str_equal (level_string, "1")) {
175         param.eLevel = OMX_VIDEO_MPEG4Level1;
176       } else if (g_str_equal (level_string, "2")) {
177         param.eLevel = OMX_VIDEO_MPEG4Level2;
178       } else if (g_str_equal (level_string, "3")) {
179         param.eLevel = OMX_VIDEO_MPEG4Level3;
180       } else if (g_str_equal (level_string, "4")) {
181         param.eLevel = OMX_VIDEO_MPEG4Level4;
182       } else if (g_str_equal (level_string, "4a")) {
183         param.eLevel = OMX_VIDEO_MPEG4Level4a;
184       } else if (g_str_equal (level_string, "5")) {
185         param.eLevel = OMX_VIDEO_MPEG4Level5;
186       } else {
187         goto unsupported_level;
188       }
189     }
190
191     gst_caps_unref (intersection);
192   }
193
194   err =
195       gst_omx_component_set_parameter (GST_OMX_VIDEO_ENC (self)->enc,
196       OMX_IndexParamVideoProfileLevelCurrent, &param);
197   if (err == OMX_ErrorUnsupportedIndex) {
198     GST_WARNING_OBJECT (self,
199         "Setting profile/level not supported by component");
200   } else if (err != OMX_ErrorNone) {
201     GST_ERROR_OBJECT (self,
202         "Error setting profile %u and level %u: %s (0x%08x)",
203         (guint) param.eProfile, (guint) param.eLevel,
204         gst_omx_error_to_string (err), err);
205     return FALSE;
206   }
207
208   return TRUE;
209
210 unsupported_profile:
211   GST_ERROR_OBJECT (self, "Unsupported profile %s", profile_string);
212   gst_caps_unref (intersection);
213   return FALSE;
214
215 unsupported_level:
216   GST_ERROR_OBJECT (self, "Unsupported level %s", level_string);
217   gst_caps_unref (intersection);
218   return FALSE;
219 }
220
221 static GstCaps *
222 gst_omx_mpeg4_video_enc_get_caps (GstOMXVideoEnc * enc, GstOMXPort * port,
223     GstVideoCodecState * state)
224 {
225   GstOMXMPEG4VideoEnc *self = GST_OMX_MPEG4_VIDEO_ENC (enc);
226   GstCaps *caps;
227   OMX_ERRORTYPE err;
228   OMX_VIDEO_PARAM_PROFILELEVELTYPE param;
229   const gchar *profile, *level;
230
231   caps =
232       gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
233       "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
234
235   GST_OMX_INIT_STRUCT (&param);
236   param.nPortIndex = GST_OMX_VIDEO_ENC (self)->enc_out_port->index;
237
238   err =
239       gst_omx_component_get_parameter (GST_OMX_VIDEO_ENC (self)->enc,
240       OMX_IndexParamVideoProfileLevelCurrent, &param);
241   if (err != OMX_ErrorNone && err != OMX_ErrorUnsupportedIndex) {
242     gst_caps_unref (caps);
243     return NULL;
244   }
245
246   if (err == OMX_ErrorNone) {
247     switch (param.eProfile) {
248       case OMX_VIDEO_MPEG4ProfileSimple:
249         profile = "simple";
250         break;
251       case OMX_VIDEO_MPEG4ProfileSimpleScalable:
252         profile = "simple-scalable";
253         break;
254       case OMX_VIDEO_MPEG4ProfileCore:
255         profile = "core";
256         break;
257       case OMX_VIDEO_MPEG4ProfileMain:
258         profile = "main";
259         break;
260       case OMX_VIDEO_MPEG4ProfileNbit:
261         profile = "n-bit";
262         break;
263       case OMX_VIDEO_MPEG4ProfileScalableTexture:
264         profile = "scalable";
265         break;
266       case OMX_VIDEO_MPEG4ProfileSimpleFace:
267         profile = "simple-face";
268         break;
269       case OMX_VIDEO_MPEG4ProfileSimpleFBA:
270         profile = "simple-fba";
271         break;
272       case OMX_VIDEO_MPEG4ProfileBasicAnimated:
273         profile = "basic-animated-texture";
274         break;
275       case OMX_VIDEO_MPEG4ProfileHybrid:
276         profile = "hybrid";
277         break;
278       case OMX_VIDEO_MPEG4ProfileAdvancedRealTime:
279         profile = "advanced-real-time-simple";
280         break;
281       case OMX_VIDEO_MPEG4ProfileCoreScalable:
282         profile = "core-scalable";
283         break;
284       case OMX_VIDEO_MPEG4ProfileAdvancedCoding:
285         profile = "advanced-coding-efficiency";
286         break;
287       case OMX_VIDEO_MPEG4ProfileAdvancedCore:
288         profile = "advanced-core";
289         break;
290       case OMX_VIDEO_MPEG4ProfileAdvancedScalable:
291         profile = "advanced-scalable-texture";
292         break;
293       case OMX_VIDEO_MPEG4ProfileAdvancedSimple:
294         profile = "advanced-simple";
295         break;
296       default:
297         g_assert_not_reached ();
298         return NULL;
299     }
300
301     switch (param.eLevel) {
302       case OMX_VIDEO_MPEG4Level0:
303         level = "0";
304         break;
305       case OMX_VIDEO_MPEG4Level0b:
306         level = "0b";
307         break;
308       case OMX_VIDEO_MPEG4Level1:
309         level = "1";
310         break;
311       case OMX_VIDEO_MPEG4Level2:
312         level = "2";
313         break;
314       case OMX_VIDEO_MPEG4Level3:
315         level = "3";
316         break;
317       case OMX_VIDEO_MPEG4Level4:
318         level = "4";
319         break;
320       case OMX_VIDEO_MPEG4Level4a:
321         level = "4a";
322         break;
323       case OMX_VIDEO_MPEG4Level5:
324         level = "5";
325         break;
326       default:
327         g_assert_not_reached ();
328         return NULL;
329     }
330
331     gst_caps_set_simple (caps,
332         "profile", G_TYPE_STRING, profile, "level", G_TYPE_STRING, level, NULL);
333   }
334
335   return caps;
336 }