enabling omx decoder
[platform/upstream/gstreamer.git] / omx / gstomxh264enc.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 "gstomxh264enc.h"
28
29 #ifdef USE_OMX_TARGET_RPI
30 #include <OMX_Broadcom.h>
31 #include <OMX_Index.h>
32 #endif
33
34 GST_DEBUG_CATEGORY_STATIC (gst_omx_h264_enc_debug_category);
35 #define GST_CAT_DEFAULT gst_omx_h264_enc_debug_category
36
37 /* prototypes */
38 static gboolean gst_omx_h264_enc_set_format (GstOMXVideoEnc * enc,
39     GstOMXPort * port, GstVideoCodecState * state);
40 static GstCaps *gst_omx_h264_enc_get_caps (GstOMXVideoEnc * enc,
41     GstOMXPort * port, GstVideoCodecState * state);
42 static GstFlowReturn gst_omx_h264_enc_handle_output_frame (GstOMXVideoEnc *
43     self, GstOMXPort * port, GstOMXBuffer * buf, GstVideoCodecFrame * frame);
44 static gboolean gst_omx_h264_enc_flush (GstVideoEncoder * enc);
45 static gboolean gst_omx_h264_enc_stop (GstVideoEncoder * enc);
46 static void gst_omx_h264_enc_set_property (GObject * object, guint prop_id,
47     const GValue * value, GParamSpec * pspec);
48 static void gst_omx_h264_enc_get_property (GObject * object, guint prop_id,
49     GValue * value, GParamSpec * pspec);
50
51 enum
52 {
53   PROP_0,
54 #ifdef USE_OMX_TARGET_RPI
55   PROP_INLINESPSPPSHEADERS,
56 #endif
57   PROP_PERIODICITYOFIDRFRAMES,
58   PROP_INTERVALOFCODINGINTRAFRAMES
59 };
60
61 #ifdef USE_OMX_TARGET_RPI
62 #define GST_OMX_H264_VIDEO_ENC_INLINE_SPS_PPS_HEADERS_DEFAULT      TRUE
63 #endif
64 #define GST_OMX_H264_VIDEO_ENC_PERIODICITY_OF_IDR_FRAMES_DEFAULT    (0xffffffff)
65 #define GST_OMX_H264_VIDEO_ENC_INTERVAL_OF_CODING_INTRA_FRAMES_DEFAULT (0xffffffff)
66
67
68 /* class initialization */
69
70 #define DEBUG_INIT \
71   GST_DEBUG_CATEGORY_INIT (gst_omx_h264_enc_debug_category, "omxh264enc", 0, \
72       "debug category for gst-omx video encoder base class");
73
74 #define parent_class gst_omx_h264_enc_parent_class
75 G_DEFINE_TYPE_WITH_CODE (GstOMXH264Enc, gst_omx_h264_enc,
76     GST_TYPE_OMX_VIDEO_ENC, DEBUG_INIT);
77
78 static void
79 gst_omx_h264_enc_class_init (GstOMXH264EncClass * klass)
80 {
81   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
82   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
83   GstVideoEncoderClass *basevideoenc_class = GST_VIDEO_ENCODER_CLASS (klass);
84   GstOMXVideoEncClass *videoenc_class = GST_OMX_VIDEO_ENC_CLASS (klass);
85
86   videoenc_class->set_format = GST_DEBUG_FUNCPTR (gst_omx_h264_enc_set_format);
87   videoenc_class->get_caps = GST_DEBUG_FUNCPTR (gst_omx_h264_enc_get_caps);
88
89   gobject_class->set_property = gst_omx_h264_enc_set_property;
90   gobject_class->get_property = gst_omx_h264_enc_get_property;
91
92 #ifdef USE_OMX_TARGET_RPI
93   g_object_class_install_property (gobject_class, PROP_INLINESPSPPSHEADERS,
94       g_param_spec_boolean ("inline-header",
95           "Inline SPS/PPS headers before IDR",
96           "Inline SPS/PPS header before IDR",
97           GST_OMX_H264_VIDEO_ENC_INLINE_SPS_PPS_HEADERS_DEFAULT,
98           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
99           GST_PARAM_MUTABLE_READY));
100 #endif
101
102   g_object_class_install_property (gobject_class, PROP_PERIODICITYOFIDRFRAMES,
103       g_param_spec_uint ("periodicty-idr", "Target Bitrate",
104           "Periodicity of IDR frames (0xffffffff=component default)",
105           0, G_MAXUINT,
106           GST_OMX_H264_VIDEO_ENC_PERIODICITY_OF_IDR_FRAMES_DEFAULT,
107           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
108           GST_PARAM_MUTABLE_READY));
109
110   g_object_class_install_property (gobject_class,
111       PROP_INTERVALOFCODINGINTRAFRAMES,
112       g_param_spec_uint ("interval-intraframes",
113           "Interval of coding Intra frames",
114           "Interval of coding Intra frames (0xffffffff=component default)", 0,
115           G_MAXUINT,
116           GST_OMX_H264_VIDEO_ENC_INTERVAL_OF_CODING_INTRA_FRAMES_DEFAULT,
117           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
118           GST_PARAM_MUTABLE_READY));
119
120   basevideoenc_class->flush = gst_omx_h264_enc_flush;
121   basevideoenc_class->stop = gst_omx_h264_enc_stop;
122
123   videoenc_class->cdata.default_src_template_caps = "video/x-h264, "
124       "width=(int) [ 16, 4096 ], " "height=(int) [ 16, 4096 ]";
125   videoenc_class->handle_output_frame =
126       GST_DEBUG_FUNCPTR (gst_omx_h264_enc_handle_output_frame);
127
128   gst_element_class_set_static_metadata (element_class,
129       "OpenMAX H.264 Video Encoder",
130       "Codec/Encoder/Video",
131       "Encode H.264 video streams",
132       "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
133
134   gst_omx_set_default_role (&videoenc_class->cdata, "video_encoder.avc");
135 }
136
137 static void
138 gst_omx_h264_enc_set_property (GObject * object, guint prop_id,
139     const GValue * value, GParamSpec * pspec)
140 {
141   GstOMXH264Enc *self = GST_OMX_H264_ENC (object);
142
143   switch (prop_id) {
144 #ifdef USE_OMX_TARGET_RPI
145     case PROP_INLINESPSPPSHEADERS:
146       self->inline_sps_pps_headers = g_value_get_boolean (value);
147       break;
148 #endif
149     case PROP_PERIODICITYOFIDRFRAMES:
150       self->periodicty_idr = g_value_get_uint (value);
151       break;
152     case PROP_INTERVALOFCODINGINTRAFRAMES:
153       self->interval_intraframes = g_value_get_uint (value);
154       break;
155     default:
156       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
157       break;
158   }
159 }
160
161 static void
162 gst_omx_h264_enc_get_property (GObject * object, guint prop_id, GValue * value,
163     GParamSpec * pspec)
164 {
165   GstOMXH264Enc *self = GST_OMX_H264_ENC (object);
166
167   switch (prop_id) {
168 #ifdef USE_OMX_TARGET_RPI
169     case PROP_INLINESPSPPSHEADERS:
170       g_value_set_boolean (value, self->inline_sps_pps_headers);
171       break;
172 #endif
173     case PROP_PERIODICITYOFIDRFRAMES:
174       g_value_set_uint (value, self->periodicty_idr);
175       break;
176     case PROP_INTERVALOFCODINGINTRAFRAMES:
177       g_value_set_uint (value, self->interval_intraframes);
178       break;
179     default:
180       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
181       break;
182   }
183 }
184
185 static void
186 gst_omx_h264_enc_init (GstOMXH264Enc * self)
187 {
188 #ifdef USE_OMX_TARGET_RPI
189   self->inline_sps_pps_headers =
190       GST_OMX_H264_VIDEO_ENC_INLINE_SPS_PPS_HEADERS_DEFAULT;
191 #endif
192   self->periodicty_idr =
193       GST_OMX_H264_VIDEO_ENC_PERIODICITY_OF_IDR_FRAMES_DEFAULT;
194   self->interval_intraframes =
195       GST_OMX_H264_VIDEO_ENC_INTERVAL_OF_CODING_INTRA_FRAMES_DEFAULT;
196 }
197
198 static gboolean
199 gst_omx_h264_enc_flush (GstVideoEncoder * enc)
200 {
201   GstOMXH264Enc *self = GST_OMX_H264_ENC (enc);
202
203   g_list_free_full (self->headers, (GDestroyNotify) gst_buffer_unref);
204   self->headers = NULL;
205
206   return GST_VIDEO_ENCODER_CLASS (parent_class)->flush (enc);
207 }
208
209 static gboolean
210 gst_omx_h264_enc_stop (GstVideoEncoder * enc)
211 {
212   GstOMXH264Enc *self = GST_OMX_H264_ENC (enc);
213
214   g_list_free_full (self->headers, (GDestroyNotify) gst_buffer_unref);
215   self->headers = NULL;
216
217   return GST_VIDEO_ENCODER_CLASS (parent_class)->stop (enc);
218 }
219
220 static gboolean
221 gst_omx_h264_enc_set_format (GstOMXVideoEnc * enc, GstOMXPort * port,
222     GstVideoCodecState * state)
223 {
224   GstOMXH264Enc *self = GST_OMX_H264_ENC (enc);
225   GstCaps *peercaps;
226   OMX_PARAM_PORTDEFINITIONTYPE port_def;
227   OMX_VIDEO_PARAM_PROFILELEVELTYPE param;
228   OMX_VIDEO_CONFIG_AVCINTRAPERIOD config_avcintraperiod;
229 #ifdef USE_OMX_TARGET_RPI
230   OMX_CONFIG_PORTBOOLEANTYPE config_inline_header;
231 #endif
232   OMX_ERRORTYPE err;
233   const gchar *profile_string, *level_string;
234
235 #ifdef USE_OMX_TARGET_RPI
236   GST_OMX_INIT_STRUCT (&config_inline_header);
237   config_inline_header.nPortIndex =
238       GST_OMX_VIDEO_ENC (self)->enc_out_port->index;
239   err =
240       gst_omx_component_get_parameter (GST_OMX_VIDEO_ENC (self)->enc,
241       OMX_IndexParamBrcmVideoAVCInlineHeaderEnable, &config_inline_header);
242   if (err != OMX_ErrorNone) {
243     GST_ERROR_OBJECT (self,
244         "can't get OMX_IndexParamBrcmVideoAVCInlineHeaderEnable %s (0x%08x)",
245         gst_omx_error_to_string (err), err);
246     return FALSE;
247   }
248
249   if (self->inline_sps_pps_headers) {
250     config_inline_header.bEnabled = OMX_TRUE;
251   } else {
252     config_inline_header.bEnabled = OMX_FALSE;
253   }
254
255   err =
256       gst_omx_component_set_parameter (GST_OMX_VIDEO_ENC (self)->enc,
257       OMX_IndexParamBrcmVideoAVCInlineHeaderEnable, &config_inline_header);
258   if (err != OMX_ErrorNone) {
259     GST_ERROR_OBJECT (self,
260         "can't set OMX_IndexParamBrcmVideoAVCInlineHeaderEnable %s (0x%08x)",
261         gst_omx_error_to_string (err), err);
262     return FALSE;
263   }
264 #endif
265
266   if (self->periodicty_idr !=
267       GST_OMX_H264_VIDEO_ENC_PERIODICITY_OF_IDR_FRAMES_DEFAULT
268       || self->interval_intraframes !=
269       GST_OMX_H264_VIDEO_ENC_INTERVAL_OF_CODING_INTRA_FRAMES_DEFAULT) {
270
271
272     GST_OMX_INIT_STRUCT (&config_avcintraperiod);
273     config_avcintraperiod.nPortIndex =
274         GST_OMX_VIDEO_ENC (self)->enc_out_port->index;
275     err =
276         gst_omx_component_get_parameter (GST_OMX_VIDEO_ENC (self)->enc,
277         OMX_IndexConfigVideoAVCIntraPeriod, &config_avcintraperiod);
278     if (err != OMX_ErrorNone) {
279       GST_ERROR_OBJECT (self,
280           "can't get OMX_IndexConfigVideoAVCIntraPeriod %s (0x%08x)",
281           gst_omx_error_to_string (err), err);
282       return FALSE;
283     }
284
285     GST_DEBUG_OBJECT (self, "default nPFrames:%u, nIDRPeriod:%u",
286         (guint) config_avcintraperiod.nPFrames,
287         (guint) config_avcintraperiod.nIDRPeriod);
288
289     if (self->periodicty_idr !=
290         GST_OMX_H264_VIDEO_ENC_PERIODICITY_OF_IDR_FRAMES_DEFAULT) {
291       config_avcintraperiod.nIDRPeriod = self->periodicty_idr;
292     }
293
294     if (self->interval_intraframes !=
295         GST_OMX_H264_VIDEO_ENC_INTERVAL_OF_CODING_INTRA_FRAMES_DEFAULT) {
296       config_avcintraperiod.nPFrames = self->interval_intraframes;
297     }
298
299     err =
300         gst_omx_component_set_parameter (GST_OMX_VIDEO_ENC (self)->enc,
301         OMX_IndexConfigVideoAVCIntraPeriod, &config_avcintraperiod);
302     if (err != OMX_ErrorNone) {
303       GST_ERROR_OBJECT (self,
304           "can't set OMX_IndexConfigVideoAVCIntraPeriod %s (0x%08x)",
305           gst_omx_error_to_string (err), err);
306       return FALSE;
307     }
308   }
309
310   gst_omx_port_get_port_definition (GST_OMX_VIDEO_ENC (self)->enc_out_port,
311       &port_def);
312   port_def.format.video.eCompressionFormat = OMX_VIDEO_CodingAVC;
313   err =
314       gst_omx_port_update_port_definition (GST_OMX_VIDEO_ENC
315       (self)->enc_out_port, &port_def);
316   if (err != OMX_ErrorNone)
317     return FALSE;
318
319   GST_OMX_INIT_STRUCT (&param);
320   param.nPortIndex = GST_OMX_VIDEO_ENC (self)->enc_out_port->index;
321
322   err =
323       gst_omx_component_get_parameter (GST_OMX_VIDEO_ENC (self)->enc,
324       OMX_IndexParamVideoProfileLevelCurrent, &param);
325   if (err != OMX_ErrorNone) {
326     GST_WARNING_OBJECT (self,
327         "Setting profile/level not supported by component");
328     return TRUE;
329   }
330
331   peercaps = gst_pad_peer_query_caps (GST_VIDEO_ENCODER_SRC_PAD (enc),
332       gst_pad_get_pad_template_caps (GST_VIDEO_ENCODER_SRC_PAD (enc)));
333   if (peercaps) {
334     GstStructure *s;
335
336     if (gst_caps_is_empty (peercaps)) {
337       gst_caps_unref (peercaps);
338       GST_ERROR_OBJECT (self, "Empty caps");
339       return FALSE;
340     }
341
342     s = gst_caps_get_structure (peercaps, 0);
343     profile_string = gst_structure_get_string (s, "profile");
344     if (profile_string) {
345       if (g_str_equal (profile_string, "baseline")) {
346         param.eProfile = OMX_VIDEO_AVCProfileBaseline;
347       } else if (g_str_equal (profile_string, "main")) {
348         param.eProfile = OMX_VIDEO_AVCProfileMain;
349       } else if (g_str_equal (profile_string, "extended")) {
350         param.eProfile = OMX_VIDEO_AVCProfileExtended;
351       } else if (g_str_equal (profile_string, "high")) {
352         param.eProfile = OMX_VIDEO_AVCProfileHigh;
353       } else if (g_str_equal (profile_string, "high-10")) {
354         param.eProfile = OMX_VIDEO_AVCProfileHigh10;
355       } else if (g_str_equal (profile_string, "high-4:2:2")) {
356         param.eProfile = OMX_VIDEO_AVCProfileHigh422;
357       } else if (g_str_equal (profile_string, "high-4:4:4")) {
358         param.eProfile = OMX_VIDEO_AVCProfileHigh444;
359       } else {
360         goto unsupported_profile;
361       }
362     }
363     level_string = gst_structure_get_string (s, "level");
364     if (level_string) {
365       if (g_str_equal (level_string, "1")) {
366         param.eLevel = OMX_VIDEO_AVCLevel1;
367       } else if (g_str_equal (level_string, "1b")) {
368         param.eLevel = OMX_VIDEO_AVCLevel1b;
369       } else if (g_str_equal (level_string, "1.1")) {
370         param.eLevel = OMX_VIDEO_AVCLevel11;
371       } else if (g_str_equal (level_string, "1.2")) {
372         param.eLevel = OMX_VIDEO_AVCLevel12;
373       } else if (g_str_equal (level_string, "1.3")) {
374         param.eLevel = OMX_VIDEO_AVCLevel13;
375       } else if (g_str_equal (level_string, "2")) {
376         param.eLevel = OMX_VIDEO_AVCLevel2;
377       } else if (g_str_equal (level_string, "2.1")) {
378         param.eLevel = OMX_VIDEO_AVCLevel21;
379       } else if (g_str_equal (level_string, "2.2")) {
380         param.eLevel = OMX_VIDEO_AVCLevel22;
381       } else if (g_str_equal (level_string, "3")) {
382         param.eLevel = OMX_VIDEO_AVCLevel3;
383       } else if (g_str_equal (level_string, "3.1")) {
384         param.eLevel = OMX_VIDEO_AVCLevel31;
385       } else if (g_str_equal (level_string, "3.2")) {
386         param.eLevel = OMX_VIDEO_AVCLevel32;
387       } else if (g_str_equal (level_string, "4")) {
388         param.eLevel = OMX_VIDEO_AVCLevel4;
389       } else if (g_str_equal (level_string, "4.1")) {
390         param.eLevel = OMX_VIDEO_AVCLevel41;
391       } else if (g_str_equal (level_string, "4.2")) {
392         param.eLevel = OMX_VIDEO_AVCLevel42;
393       } else if (g_str_equal (level_string, "5")) {
394         param.eLevel = OMX_VIDEO_AVCLevel5;
395       } else if (g_str_equal (level_string, "5.1")) {
396         param.eLevel = OMX_VIDEO_AVCLevel51;
397       } else {
398         goto unsupported_level;
399       }
400     }
401     gst_caps_unref (peercaps);
402   }
403
404   err =
405       gst_omx_component_set_parameter (GST_OMX_VIDEO_ENC (self)->enc,
406       OMX_IndexParamVideoProfileLevelCurrent, &param);
407   if (err == OMX_ErrorUnsupportedIndex) {
408     GST_WARNING_OBJECT (self,
409         "Setting profile/level not supported by component");
410   } else if (err != OMX_ErrorNone) {
411     GST_ERROR_OBJECT (self,
412         "Error setting profile %u and level %u: %s (0x%08x)",
413         (guint) param.eProfile, (guint) param.eLevel,
414         gst_omx_error_to_string (err), err);
415     return FALSE;
416   }
417
418   return TRUE;
419
420 unsupported_profile:
421   GST_ERROR_OBJECT (self, "Unsupported profile %s", profile_string);
422   gst_caps_unref (peercaps);
423   return FALSE;
424
425 unsupported_level:
426   GST_ERROR_OBJECT (self, "Unsupported level %s", level_string);
427   gst_caps_unref (peercaps);
428   return FALSE;
429 }
430
431 static GstCaps *
432 gst_omx_h264_enc_get_caps (GstOMXVideoEnc * enc, GstOMXPort * port,
433     GstVideoCodecState * state)
434 {
435   GstOMXH264Enc *self = GST_OMX_H264_ENC (enc);
436   GstCaps *caps;
437   OMX_ERRORTYPE err;
438   OMX_VIDEO_PARAM_PROFILELEVELTYPE param;
439   const gchar *profile, *level;
440
441   caps = gst_caps_new_simple ("video/x-h264",
442       "stream-format", G_TYPE_STRING, "byte-stream",
443       "alignment", G_TYPE_STRING, "au", NULL);
444
445   GST_OMX_INIT_STRUCT (&param);
446   param.nPortIndex = GST_OMX_VIDEO_ENC (self)->enc_out_port->index;
447
448   err =
449       gst_omx_component_get_parameter (GST_OMX_VIDEO_ENC (self)->enc,
450       OMX_IndexParamVideoProfileLevelCurrent, &param);
451   if (err != OMX_ErrorNone && err != OMX_ErrorUnsupportedIndex)
452     return NULL;
453
454   if (err == OMX_ErrorNone) {
455     switch (param.eProfile) {
456       case OMX_VIDEO_AVCProfileBaseline:
457         profile = "baseline";
458         break;
459       case OMX_VIDEO_AVCProfileMain:
460         profile = "main";
461         break;
462       case OMX_VIDEO_AVCProfileExtended:
463         profile = "extended";
464         break;
465       case OMX_VIDEO_AVCProfileHigh:
466         profile = "high";
467         break;
468       case OMX_VIDEO_AVCProfileHigh10:
469         profile = "high-10";
470         break;
471       case OMX_VIDEO_AVCProfileHigh422:
472         profile = "high-4:2:2";
473         break;
474       case OMX_VIDEO_AVCProfileHigh444:
475         profile = "high-4:4:4";
476         break;
477       default:
478         g_assert_not_reached ();
479         return NULL;
480     }
481
482     switch (param.eLevel) {
483       case OMX_VIDEO_AVCLevel1:
484         level = "1";
485         break;
486       case OMX_VIDEO_AVCLevel1b:
487         level = "1b";
488         break;
489       case OMX_VIDEO_AVCLevel11:
490         level = "1.1";
491         break;
492       case OMX_VIDEO_AVCLevel12:
493         level = "1.2";
494         break;
495       case OMX_VIDEO_AVCLevel13:
496         level = "1.3";
497         break;
498       case OMX_VIDEO_AVCLevel2:
499         level = "2";
500         break;
501       case OMX_VIDEO_AVCLevel21:
502         level = "2.1";
503         break;
504       case OMX_VIDEO_AVCLevel22:
505         level = "2.2";
506         break;
507       case OMX_VIDEO_AVCLevel3:
508         level = "3";
509         break;
510       case OMX_VIDEO_AVCLevel31:
511         level = "3.1";
512         break;
513       case OMX_VIDEO_AVCLevel32:
514         level = "3.2";
515         break;
516       case OMX_VIDEO_AVCLevel4:
517         level = "4";
518         break;
519       case OMX_VIDEO_AVCLevel41:
520         level = "4.1";
521         break;
522       case OMX_VIDEO_AVCLevel42:
523         level = "4.2";
524         break;
525       case OMX_VIDEO_AVCLevel5:
526         level = "5";
527         break;
528       case OMX_VIDEO_AVCLevel51:
529         level = "5.1";
530         break;
531       default:
532         g_assert_not_reached ();
533         return NULL;
534     }
535     gst_caps_set_simple (caps,
536         "profile", G_TYPE_STRING, profile, "level", G_TYPE_STRING, level, NULL);
537   }
538
539   return caps;
540 }
541
542 static GstFlowReturn
543 gst_omx_h264_enc_handle_output_frame (GstOMXVideoEnc * enc, GstOMXPort * port,
544     GstOMXBuffer * buf, GstVideoCodecFrame * frame)
545 {
546   GstOMXH264Enc *self = GST_OMX_H264_ENC (enc);
547
548   if (buf->omx_buf->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
549     /* The codec data is SPS/PPS with a startcode => bytestream stream format
550      * For bytestream stream format the SPS/PPS is only in-stream and not
551      * in the caps!
552      */
553     if (buf->omx_buf->nFilledLen >= 4 &&
554         GST_READ_UINT32_BE (buf->omx_buf->pBuffer +
555             buf->omx_buf->nOffset) == 0x00000001) {
556       GstBuffer *hdrs;
557       GstMapInfo map = GST_MAP_INFO_INIT;
558
559       GST_DEBUG_OBJECT (self, "got codecconfig in byte-stream format");
560
561       hdrs = gst_buffer_new_and_alloc (buf->omx_buf->nFilledLen);
562
563       gst_buffer_map (hdrs, &map, GST_MAP_WRITE);
564       memcpy (map.data,
565           buf->omx_buf->pBuffer + buf->omx_buf->nOffset,
566           buf->omx_buf->nFilledLen);
567       gst_buffer_unmap (hdrs, &map);
568       self->headers = g_list_append (self->headers, hdrs);
569
570       if (frame)
571         gst_video_codec_frame_unref (frame);
572
573       return GST_FLOW_OK;
574     }
575   } else if (self->headers) {
576     gst_video_encoder_set_headers (GST_VIDEO_ENCODER (self), self->headers);
577     self->headers = NULL;
578   }
579
580   return
581       GST_OMX_VIDEO_ENC_CLASS
582       (gst_omx_h264_enc_parent_class)->handle_output_frame (enc, port, buf,
583       frame);
584 }