videoparsers: add h264parse
[gstreamer-omap:gst-plugins-bad.git] / gst / videoparsers / gsth264parse.c
1 /* GStreamer H.264 Parser
2  * Copyright (C) <2010> Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
3  * Copyright (C) <2010> Collabora Multimedia
4  * Copyright (C) <2010> Nokia Corporation
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #  include "config.h"
24 #endif
25
26 #include <gst/base/gstbytereader.h>
27 #include <gst/base/gstbytewriter.h>
28 #include "gsth264parse.h"
29
30 #include <string.h>
31
32 GST_DEBUG_CATEGORY (h264_parse_debug);
33 #define GST_CAT_DEFAULT h264_parse_debug
34
35 #define DEFAULT_SPLIT_PACKETIZED     FALSE
36 #define DEFAULT_CONFIG_INTERVAL      (0)
37
38 enum
39 {
40   PROP_0,
41   PROP_SPLIT_PACKETIZED,
42   PROP_CONFIG_INTERVAL,
43   PROP_LAST
44 };
45
46 enum
47 {
48   GST_H264_PARSE_FORMAT_NONE,
49   GST_H264_PARSE_FORMAT_AVC,
50   GST_H264_PARSE_FORMAT_BYTE
51 };
52
53 enum
54 {
55   GST_H264_PARSE_ALIGN_NONE = 0,
56   GST_H264_PARSE_ALIGN_NAL,
57   GST_H264_PARSE_ALIGN_AU
58 };
59
60 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
61     GST_PAD_SINK,
62     GST_PAD_ALWAYS,
63     GST_STATIC_CAPS ("video/x-h264, parsed = (boolean) false"));
64
65 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
66     GST_PAD_SRC,
67     GST_PAD_ALWAYS,
68     GST_STATIC_CAPS ("video/x-h264, parsed = (boolean) true"));
69
70 GST_BOILERPLATE (GstH264Parse, gst_h264_parse, GstElement, GST_TYPE_BASE_PARSE);
71
72 static void gst_h264_parse_finalize (GObject * object);
73
74 static gboolean gst_h264_parse_start (GstBaseParse * parse);
75 static gboolean gst_h264_parse_stop (GstBaseParse * parse);
76 static gboolean gst_h264_parse_check_valid_frame (GstBaseParse * parse,
77     GstBaseParseFrame * frame, guint * framesize, gint * skipsize);
78 static GstFlowReturn gst_h264_parse_parse_frame (GstBaseParse * parse,
79     GstBaseParseFrame * frame);
80 static GstFlowReturn gst_h264_parse_pre_push_frame (GstBaseParse * parse,
81     GstBaseParseFrame * frame);
82
83 static void gst_h264_parse_set_property (GObject * object, guint prop_id,
84     const GValue * value, GParamSpec * pspec);
85 static void gst_h264_parse_get_property (GObject * object, guint prop_id,
86     GValue * value, GParamSpec * pspec);
87
88 static gboolean gst_h264_parse_set_caps (GstBaseParse * parse, GstCaps * caps);
89 static GstFlowReturn gst_h264_parse_chain (GstPad * pad, GstBuffer * buffer);
90
91 static void
92 gst_h264_parse_base_init (gpointer g_class)
93 {
94   GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
95
96   gst_element_class_add_pad_template (gstelement_class,
97       gst_static_pad_template_get (&srctemplate));
98   gst_element_class_add_pad_template (gstelement_class,
99       gst_static_pad_template_get (&sinktemplate));
100
101   gst_element_class_set_details_simple (gstelement_class, "H.264 parser",
102       "Codec/Parser/Video",
103       "Parses H.264 streams",
104       "Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>");
105
106   GST_DEBUG_CATEGORY_INIT (h264_parse_debug, "h264parse", 0, "h264 parser");
107 }
108
109 static void
110 gst_h264_parse_class_init (GstH264ParseClass * klass)
111 {
112   GObjectClass *gobject_class = (GObjectClass *) klass;
113   GstBaseParseClass *parse_class = GST_BASE_PARSE_CLASS (klass);
114
115   gobject_class->finalize = gst_h264_parse_finalize;
116   gobject_class->set_property = gst_h264_parse_set_property;
117   gobject_class->get_property = gst_h264_parse_get_property;
118
119   g_object_class_install_property (gobject_class, PROP_SPLIT_PACKETIZED,
120       g_param_spec_boolean ("split-packetized", "Split packetized",
121           "Split NAL units of packetized streams", DEFAULT_SPLIT_PACKETIZED,
122           G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
123   g_object_class_install_property (gobject_class, PROP_CONFIG_INTERVAL,
124       g_param_spec_uint ("config-interval",
125           "SPS PPS Send Interval",
126           "Send SPS and PPS Insertion Interval in seconds (sprop parameter sets "
127           "will be multiplexed in the data stream when detected.) (0 = disabled)",
128           0, 3600, DEFAULT_CONFIG_INTERVAL,
129           G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
130
131   /* Override BaseParse vfuncs */
132   parse_class->start = GST_DEBUG_FUNCPTR (gst_h264_parse_start);
133   parse_class->stop = GST_DEBUG_FUNCPTR (gst_h264_parse_stop);
134   parse_class->check_valid_frame =
135       GST_DEBUG_FUNCPTR (gst_h264_parse_check_valid_frame);
136   parse_class->parse_frame = GST_DEBUG_FUNCPTR (gst_h264_parse_parse_frame);
137   parse_class->pre_push_frame =
138       GST_DEBUG_FUNCPTR (gst_h264_parse_pre_push_frame);
139   parse_class->set_sink_caps = GST_DEBUG_FUNCPTR (gst_h264_parse_set_caps);
140 }
141
142 static void
143 gst_h264_parse_init (GstH264Parse * h264parse, GstH264ParseClass * g_class)
144 {
145   h264parse->frame_out = gst_adapter_new ();
146
147   /* retrieve and intercept baseparse.
148    * Quite HACKish, but fairly OK since it is needed to perform avc packet
149    * splitting, which is the penultimate de-parsing */
150   h264parse->parse_chain =
151       GST_PAD_CHAINFUNC (GST_BASE_PARSE_SINK_PAD (h264parse));
152   gst_pad_set_chain_function (GST_BASE_PARSE_SINK_PAD (h264parse),
153       gst_h264_parse_chain);
154 }
155
156
157 static void
158 gst_h264_parse_finalize (GObject * object)
159 {
160   GstH264Parse *h264parse = GST_H264_PARSE (object);
161
162   g_object_unref (h264parse->frame_out);
163 }
164
165 static void
166 gst_h264_parse_reset_frame (GstH264Parse * h264parse)
167 {
168   /* done parsing; reset state */
169   h264parse->last_nal_pos = 0;
170   h264parse->next_sc_pos = 0;
171   h264parse->picture_start = FALSE;
172   h264parse->update_caps = FALSE;
173   h264parse->idr_pos = -1;
174   h264parse->keyframe = FALSE;
175   h264parse->frame_start = FALSE;
176 }
177
178 static void
179 gst_h264_parse_reset (GstH264Parse * h264parse)
180 {
181   h264parse->width = 0;
182   h264parse->height = 0;
183   h264parse->fps_num = 0;
184   h264parse->fps_den = 0;
185   gst_buffer_replace (&h264parse->codec_data, NULL);
186   h264parse->nal_length_size = 4;
187   h264parse->packetized = FALSE;
188
189   h264parse->align = GST_H264_PARSE_ALIGN_NONE;
190   h264parse->format = GST_H264_PARSE_FORMAT_NONE;
191
192   h264parse->last_report = GST_CLOCK_TIME_NONE;
193   h264parse->push_codec = FALSE;
194
195   gst_h264_parse_reset_frame (h264parse);
196 }
197
198 static gboolean
199 gst_h264_parse_start (GstBaseParse * parse)
200 {
201   GstH264Parse *h264parse = GST_H264_PARSE (parse);
202
203   GST_DEBUG ("Start");
204   gst_h264_parse_reset (h264parse);
205
206   gst_h264_params_create (&h264parse->params, GST_ELEMENT (h264parse));
207
208   gst_base_parse_set_min_frame_size (parse, 512);
209
210   return TRUE;
211 }
212
213 static gboolean
214 gst_h264_parse_stop (GstBaseParse * parse)
215 {
216   GstH264Parse *h264parse = GST_H264_PARSE (parse);
217
218   GST_DEBUG ("Stop");
219   gst_h264_parse_reset (h264parse);
220
221   gst_h264_params_free (h264parse->params);
222   h264parse->params = NULL;
223
224   return TRUE;
225 }
226
227 static const gchar *
228 gst_h264_parse_get_string (GstH264Parse * parse, gboolean format, gint code)
229 {
230   if (format) {
231     switch (code) {
232       case GST_H264_PARSE_FORMAT_AVC:
233         return "avc";
234       case GST_H264_PARSE_FORMAT_BYTE:
235         return "byte-stream";
236       default:
237         return "none";
238     }
239   } else {
240     switch (code) {
241       case GST_H264_PARSE_ALIGN_NAL:
242         return "nal";
243       case GST_H264_PARSE_ALIGN_AU:
244         return "au";
245       default:
246         return "none";
247     }
248   }
249 }
250
251 /* check downstream caps to configure format and alignment */
252 static void
253 gst_h264_parse_negotiate (GstH264Parse * h264parse)
254 {
255   GstCaps *caps;
256   guint format = GST_H264_PARSE_FORMAT_NONE;
257   guint align = GST_H264_PARSE_ALIGN_NONE;
258
259   caps = gst_pad_get_allowed_caps (GST_BASE_PARSE_SRC_PAD (h264parse));
260   GST_DEBUG_OBJECT (h264parse, "allowed caps: %" GST_PTR_FORMAT, caps);
261
262   if (caps && gst_caps_get_size (caps) > 0) {
263     GstStructure *s = gst_caps_get_structure (caps, 0);
264     const gchar *str = NULL;
265
266     if ((str = gst_structure_get_string (s, "stream-format"))) {
267       if (strcmp (str, "avc") == 0) {
268         format = GST_H264_PARSE_FORMAT_AVC;
269       } else if (strcmp (str, "byte-stream") == 0) {
270         format = GST_H264_PARSE_FORMAT_BYTE;
271       } else {
272         GST_DEBUG_OBJECT (h264parse, "unknown stream-format: %s", str);
273       }
274     }
275
276     if ((str = gst_structure_get_string (s, "alignment"))) {
277       if (strcmp (str, "au") == 0) {
278         align = GST_H264_PARSE_ALIGN_AU;
279       } else if (strcmp (str, "nal") == 0) {
280         align = GST_H264_PARSE_ALIGN_NAL;
281       } else {
282         GST_DEBUG_OBJECT (h264parse, "unknown alignment: %s", str);
283       }
284     }
285   }
286
287   if (caps)
288     gst_caps_unref (caps);
289
290   /* default */
291   if (!format)
292     format = GST_H264_PARSE_FORMAT_BYTE;
293   if (!align)
294     align = GST_H264_PARSE_ALIGN_AU;
295
296   GST_DEBUG_OBJECT (h264parse, "selected format %s, alignment %s",
297       gst_h264_parse_get_string (h264parse, TRUE, format),
298       gst_h264_parse_get_string (h264parse, FALSE, align));
299
300   h264parse->format = format;
301   h264parse->align = align;
302 }
303
304 static GstBuffer *
305 gst_h264_parse_wrap_nal (GstH264Parse * h264parse, guint format, guint8 * data,
306     guint size)
307 {
308   GstBuffer *buf;
309   const guint nl = h264parse->nal_length_size;
310
311   buf = gst_buffer_new_and_alloc (size + nl + 4);
312   if (format == GST_H264_PARSE_FORMAT_AVC) {
313     GST_WRITE_UINT32_BE (GST_BUFFER_DATA (buf), size << (32 - 8 * nl));
314   } else {
315     g_assert (nl == 4);
316     GST_WRITE_UINT32_BE (GST_BUFFER_DATA (buf), 1);
317   }
318
319   GST_BUFFER_SIZE (buf) = size + nl;
320   memcpy (GST_BUFFER_DATA (buf) + nl, data, size);
321
322   return buf;
323 }
324
325 /* SPS/PPS/IDR considered key, all others DELTA;
326  * so downstream waiting for keyframe can pick up at SPS/PPS/IDR */
327 #define NAL_TYPE_IS_KEY(nt) (((nt) == 5) || ((nt) == 7) || ((nt) == 8))
328
329 /* caller guarantees 2 bytes of nal payload */
330 static void
331 gst_h264_parse_process_nal (GstH264Parse * h264parse, guint8 * data,
332     gint sc_pos, gint nal_pos, guint nal_size)
333 {
334   guint nal_type;
335
336   g_return_if_fail (nal_size >= 2);
337   g_return_if_fail (nal_pos - sc_pos > 0 && nal_pos - sc_pos <= 4);
338
339   /* lower layer collects params */
340   gst_h264_params_parse_nal (h264parse->params, data + nal_pos, nal_size);
341
342   /* we have a peek as well */
343   nal_type = data[nal_pos] & 0x1f;
344   h264parse->keyframe |= NAL_TYPE_IS_KEY (nal_type);
345
346   switch (nal_type) {
347     case NAL_SPS:
348     case NAL_PPS:
349       /* parameters might have changed, force caps check */
350       GST_DEBUG_OBJECT (h264parse, "triggering src caps check");
351       h264parse->update_caps = TRUE;
352       /* found in stream, no need to forcibly push at start */
353       h264parse->push_codec = FALSE;
354       break;
355     case NAL_SLICE:
356     case NAL_SLICE_DPA:
357     case NAL_SLICE_DPB:
358     case NAL_SLICE_DPC:
359       /* real frame data */
360       h264parse->frame_start |= (h264parse->params->first_mb_in_slice == 0);
361       /* if we need to sneak codec NALs into the stream,
362        * this is a good place, so fake it as IDR
363        * (which should be at start anyway) */
364       if (G_LIKELY (!h264parse->push_codec))
365         break;
366       /* fall-through */
367     case NAL_SLICE_IDR:
368       /* real frame data */
369       h264parse->frame_start |= (h264parse->params->first_mb_in_slice == 0);
370       /* mark where config needs to go if interval expired */
371       /* mind replacement buffer if applicable */
372       if (h264parse->format == GST_H264_PARSE_FORMAT_AVC)
373         h264parse->idr_pos = gst_adapter_available (h264parse->frame_out);
374       else
375         h264parse->idr_pos = sc_pos;
376       GST_DEBUG_OBJECT (h264parse, "marking IDR in frame at offset %d",
377           h264parse->idr_pos);
378       break;
379   }
380
381   /* if AVC output needed, collect properly prefixed nal in adapter,
382    * and use that to replace outgoing buffer data later on */
383   if (h264parse->format == GST_H264_PARSE_FORMAT_AVC) {
384     GstBuffer *buf;
385
386     GST_LOG_OBJECT (h264parse, "collecting NAL in AVC frame");
387     buf = gst_h264_parse_wrap_nal (h264parse, h264parse->format,
388         data + nal_pos, nal_size);
389     gst_adapter_push (h264parse->frame_out, buf);
390   }
391 }
392
393 /* caller guarantees at least 2 bytes of nal payload for each nal
394  * returns TRUE if next_nal indicates that nal terminates an AU */
395 static inline gboolean
396 gst_h264_parse_collect_nal (GstH264Parse * h264parse, guint8 * nal,
397     guint8 * next_nal)
398 {
399   gint nal_type;
400   gboolean complete;
401
402   if (h264parse->align == GST_H264_PARSE_ALIGN_NAL)
403     return TRUE;
404
405   /* determine if AU complete */
406   nal_type = nal[0] & 0x1f;
407   GST_LOG_OBJECT (h264parse, "nal type: %d", nal_type);
408   /* coded slice NAL starts a picture,
409    * i.e. other types become aggregated in front of it */
410   h264parse->picture_start |= (nal_type == 1 || nal_type == 2 || nal_type == 5);
411
412   /* consider a coded slices (IDR or not) to start a picture,
413    * (so ending the previous one) if first_mb_in_slice == 0
414    * (non-0 is part of previous one) */
415   /* NOTE this is not entirely according to Access Unit specs in 7.4.1.2.4,
416    * but in practice it works in sane cases, needs not much parsing,
417    * and also works with broken frame_num in NAL
418    * (where spec-wise would fail) */
419   nal_type = next_nal[0] & 0x1f;
420   GST_LOG_OBJECT (h264parse, "next nal type: %d", nal_type);
421   complete = h264parse->picture_start && (nal_type >= 6 && nal_type <= 9);
422   complete |= h264parse->picture_start &&
423       (nal_type == 1 || nal_type == 2 || nal_type == 5) &&
424       /* first_mb_in_slice == 0 considered start of frame */
425       (next_nal[1] & 0x80);
426
427   GST_LOG_OBJECT (h264parse, "au complete: %d", complete);
428
429   return complete;
430 }
431
432 /* finds next startcode == 00 00 01, along with a subsequent byte */
433 static guint
434 gst_h264_parse_find_sc (GstBuffer * buffer, guint skip)
435 {
436   GstByteReader br;
437   guint sc_pos = -1;
438
439   gst_byte_reader_init_from_buffer (&br, buffer);
440
441   /* NALU not empty, so we can at least expect 1 (even 2) bytes following sc */
442   sc_pos = gst_byte_reader_masked_scan_uint32 (&br, 0xffffff00, 0x00000100,
443       skip, gst_byte_reader_get_remaining (&br) - skip);
444
445   return sc_pos;
446 }
447
448 static gboolean
449 gst_h264_parse_check_valid_frame (GstBaseParse * parse,
450     GstBaseParseFrame * frame, guint * framesize, gint * skipsize)
451 {
452   GstH264Parse *h264parse = GST_H264_PARSE (parse);
453   GstBuffer *buffer = frame->buffer;
454   gint sc_pos, nal_pos, next_sc_pos, next_nal_pos;
455   guint8 *data;
456   guint size;
457   gboolean drain;
458
459   /* expect at least 3 bytes startcode == sc, and 2 bytes NALU payload */
460   if (G_UNLIKELY (GST_BUFFER_SIZE (buffer) < 5))
461     return FALSE;
462
463   /* need to configure aggregation */
464   if (G_UNLIKELY (h264parse->format == GST_H264_PARSE_FORMAT_NONE))
465     gst_h264_parse_negotiate (h264parse);
466
467   data = GST_BUFFER_DATA (buffer);
468   size = GST_BUFFER_SIZE (buffer);
469
470   GST_LOG_OBJECT (h264parse, "last_nal_pos: %d, last_scan_pos %d",
471       h264parse->last_nal_pos, h264parse->next_sc_pos);
472
473   nal_pos = h264parse->last_nal_pos;
474   next_sc_pos = h264parse->next_sc_pos;
475
476   if (!next_sc_pos) {
477     sc_pos = gst_h264_parse_find_sc (buffer, 0);
478
479     if (sc_pos == -1) {
480       /* SC not found, need more data */
481       sc_pos = GST_BUFFER_SIZE (buffer) - 3;
482       goto more;
483     }
484
485     nal_pos = sc_pos + 3;
486     next_sc_pos = nal_pos;
487     /* sc might have 2 or 3 0-bytes */
488     if (sc_pos > 0 && data[sc_pos - 1] == 00)
489       sc_pos--;
490     GST_LOG_OBJECT (h264parse, "found sc at offset %d", sc_pos);
491   } else {
492     /* previous checks already arrange sc at start */
493     sc_pos = 0;
494   }
495
496   drain = GST_BASE_PARSE_FRAME_DRAIN (frame);
497   while (TRUE) {
498     gint prev_sc_pos;
499
500     next_sc_pos = gst_h264_parse_find_sc (buffer, next_sc_pos);
501     if (next_sc_pos == -1) {
502       GST_LOG_OBJECT (h264parse, "no next sc");
503       if (drain) {
504         /* FLUSH/EOS, it's okay if we can't find the next frame */
505         next_sc_pos = size;
506         next_nal_pos = size;
507       } else {
508         next_sc_pos = size - 3;
509         goto more;
510       }
511     } else {
512       next_nal_pos = next_sc_pos + 3;
513       if (data[next_sc_pos - 1] == 00)
514         next_sc_pos--;
515       GST_LOG_OBJECT (h264parse, "found next sc at offset %d", next_sc_pos);
516       /* need at least 1 more byte of next NAL */
517       if (!drain && (next_nal_pos == size - 1))
518         goto more;
519     }
520
521     /* determine nal's sc position */
522     prev_sc_pos = nal_pos - 3;
523     g_assert (prev_sc_pos >= 0);
524     if (prev_sc_pos > 0 && data[prev_sc_pos - 1] == 0)
525       prev_sc_pos--;
526
527     /* already consume and gather info from NAL */
528     gst_h264_parse_process_nal (h264parse, data, prev_sc_pos, nal_pos,
529         next_sc_pos - nal_pos);
530     if (next_nal_pos >= size - 1 ||
531         gst_h264_parse_collect_nal (h264parse, data + nal_pos,
532             data + next_nal_pos))
533       break;
534
535     /* move along */
536     next_sc_pos = nal_pos = next_nal_pos;
537   }
538
539   *skipsize = sc_pos;
540   *framesize = next_sc_pos - sc_pos;
541
542   return TRUE;
543
544 more:
545   /* Ask for 1024 bytes more - this is an arbitrary choice */
546   gst_base_parse_set_min_frame_size (parse, GST_BUFFER_SIZE (buffer) + 1024);
547
548   /* skip up to initial startcode */
549   *skipsize = sc_pos;
550   /* resume scanning here next time */
551   h264parse->last_nal_pos = nal_pos;
552   h264parse->next_sc_pos = next_sc_pos;
553
554   return FALSE;
555 }
556
557 /* byte together avc codec data based on collected pps and sps so far */
558 static GstBuffer *
559 gst_h264_parse_make_codec_data (GstH264Parse * h264parse)
560 {
561   GstBuffer *buf, *nal;
562   gint i, sps_size = 0, pps_size = 0, num_sps = 0, num_pps = 0;
563   guint8 profile_idc = 0, profile_comp = 0, level_idc = 0;
564   gboolean found = FALSE;
565   guint8 *data;
566
567   /* only nal payload in stored nals */
568
569   for (i = 0; i < MAX_SPS_COUNT; i++) {
570     if ((nal = h264parse->params->sps_nals[i])) {
571       num_sps++;
572       /* size bytes also count */
573       sps_size += GST_BUFFER_SIZE (nal) + 2;
574       if (GST_BUFFER_SIZE (nal) >= 4) {
575         found = TRUE;
576         profile_idc = (GST_BUFFER_DATA (nal))[1];
577         profile_comp = (GST_BUFFER_DATA (nal))[2];
578         level_idc = (GST_BUFFER_DATA (nal))[3];
579       }
580     }
581   }
582   for (i = 0; i < MAX_PPS_COUNT; i++) {
583     if ((nal = h264parse->params->pps_nals[i])) {
584       num_pps++;
585       /* size bytes also count */
586       pps_size += GST_BUFFER_SIZE (nal) + 2;
587     }
588   }
589
590   GST_DEBUG_OBJECT (h264parse,
591       "constructing codec_data: num_sps=%d, num_pps=%d", num_sps, num_pps);
592
593   if (!found || !num_pps)
594     return NULL;
595
596   buf = gst_buffer_new_and_alloc (5 + 1 + sps_size + 1 + pps_size);
597   data = GST_BUFFER_DATA (buf);
598
599   data[0] = 1;                  /* AVC Decoder Configuration Record ver. 1 */
600   data[1] = profile_idc;        /* profile_idc                             */
601   data[2] = profile_comp;       /* profile_compability                     */
602   data[3] = level_idc;          /* level_idc                               */
603   data[4] = 0xfc | (4 - 1);     /* nal_length_size_minus1                  */
604   data[5] = 0xe0 | num_sps;     /* number of SPSs */
605
606   data += 6;
607   for (i = 0; i < MAX_SPS_COUNT; i++) {
608     if ((nal = h264parse->params->sps_nals[i])) {
609       GST_WRITE_UINT16_BE (data, GST_BUFFER_SIZE (nal));
610       memcpy (data + 2, GST_BUFFER_DATA (nal), GST_BUFFER_SIZE (nal));
611       data += 2 + GST_BUFFER_SIZE (nal);
612     }
613   }
614
615   data[0] = num_pps;
616   data++;
617   for (i = 0; i < MAX_PPS_COUNT; i++) {
618     if ((nal = h264parse->params->pps_nals[i])) {
619       GST_WRITE_UINT16_BE (data, GST_BUFFER_SIZE (nal));
620       memcpy (data + 2, GST_BUFFER_DATA (nal), GST_BUFFER_SIZE (nal));
621       data += 2 + GST_BUFFER_SIZE (nal);
622     }
623   }
624
625   return buf;
626 }
627
628 static void
629 gst_h264_parse_update_src_caps (GstH264Parse * h264parse)
630 {
631   GstH264ParamsSPS *sps;
632   GstCaps *caps = NULL, *sink_caps;
633   gboolean modified = FALSE;
634   GstBuffer *buf = NULL;
635
636   if (G_UNLIKELY (!GST_PAD_CAPS (GST_BASE_PARSE_SRC_PAD (h264parse))))
637     modified = TRUE;
638   else if (G_UNLIKELY (!h264parse->update_caps))
639     return;
640
641   /* carry over input caps as much as possible; override with our own stuff */
642   sink_caps = GST_PAD_CAPS (GST_BASE_PARSE_SINK_PAD (h264parse));
643   if (sink_caps)
644     gst_caps_ref (sink_caps);
645   else
646     sink_caps = gst_caps_new_simple ("video/x-h264", NULL);
647
648   sps = h264parse->params->sps;
649   GST_DEBUG_OBJECT (h264parse, "sps: %p", sps);
650
651   /* only codec-data for nice-and-clean au aligned packetized avc format */
652   if (h264parse->format == GST_H264_PARSE_FORMAT_AVC &&
653       h264parse->align == GST_H264_PARSE_ALIGN_AU) {
654     buf = gst_h264_parse_make_codec_data (h264parse);
655     if (buf && h264parse->codec_data) {
656       if (GST_BUFFER_SIZE (buf) != GST_BUFFER_SIZE (h264parse->codec_data) ||
657           memcmp (GST_BUFFER_DATA (buf),
658               GST_BUFFER_DATA (h264parse->codec_data), GST_BUFFER_SIZE (buf)))
659         modified = TRUE;
660     } else {
661       if (h264parse->codec_data)
662         buf = gst_buffer_ref (h264parse->codec_data);
663       modified = TRUE;
664     }
665   }
666
667   if (G_UNLIKELY (!sps)) {
668     caps = gst_caps_copy (sink_caps);
669   } else if (G_UNLIKELY (h264parse->width != sps->width ||
670           h264parse->height != sps->height || h264parse->fps_num != sps->fps_num
671           || h264parse->fps_den != sps->fps_den || modified)) {
672     caps = gst_caps_copy (sink_caps);
673     /* sps should give this */
674     gst_caps_set_simple (caps, "width", G_TYPE_INT, sps->width,
675         "height", G_TYPE_INT, sps->height, NULL);
676     h264parse->height = sps->height;
677     h264parse->width = sps->width;
678     /* but not necessarily or reliably this */
679     if ((!h264parse->fps_num || !h264parse->fps_den) &&
680         sps->fps_num > 0 && sps->fps_den > 0) {
681       gst_caps_set_simple (caps, "framerate",
682           GST_TYPE_FRACTION, sps->fps_num, sps->fps_den, NULL);
683       h264parse->fps_num = sps->fps_num;
684       h264parse->fps_den = sps->fps_den;
685       gst_base_parse_set_frame_props (GST_BASE_PARSE (h264parse),
686           h264parse->fps_num, h264parse->fps_den, 0, 0);
687     }
688   }
689
690   if (caps) {
691     gst_caps_set_simple (caps, "stream-format", G_TYPE_STRING,
692         gst_h264_parse_get_string (h264parse, TRUE, h264parse->format),
693         "alignment", G_TYPE_STRING,
694         gst_h264_parse_get_string (h264parse, FALSE, h264parse->align), NULL);
695     if (buf) {
696       gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER, buf, NULL);
697       gst_buffer_replace (&h264parse->codec_data, buf);
698       gst_buffer_unref (buf);
699       buf = NULL;
700     } else {
701       GstStructure *s;
702       /* remove any left-over codec-data hanging around */
703       s = gst_caps_get_structure (caps, 0);
704       gst_structure_remove_field (s, "codec_data");
705     }
706     gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (h264parse), caps);
707     gst_caps_unref (caps);
708   }
709
710   gst_caps_unref (sink_caps);
711   if (buf)
712     gst_buffer_unref (buf);
713 }
714
715 static GstFlowReturn
716 gst_h264_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
717 {
718   GstH264Parse *h264parse;
719   GstBuffer *buffer;
720   guint av;
721
722   h264parse = GST_H264_PARSE (parse);
723   buffer = frame->buffer;
724
725   gst_h264_parse_update_src_caps (h264parse);
726
727   gst_h264_params_get_timestamp (h264parse->params,
728       &GST_BUFFER_TIMESTAMP (buffer), &GST_BUFFER_DURATION (buffer),
729       h264parse->frame_start);
730
731   if (h264parse->keyframe)
732     GST_BUFFER_FLAG_UNSET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);
733   else
734     GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);
735
736   /* replace with transformed AVC output if applicable */
737   av = gst_adapter_available (h264parse->frame_out);
738   if (av) {
739     GstBuffer *buf;
740
741     buf = gst_adapter_take_buffer (h264parse->frame_out, av);
742     gst_buffer_copy_metadata (buf, buffer, GST_BUFFER_COPY_ALL);
743     gst_buffer_replace (&frame->buffer, buf);
744   }
745
746   return GST_FLOW_OK;
747 }
748
749 /* sends a codec NAL downstream, decorating and transforming as needed.
750  * No ownership is taken of @nal */
751 static GstFlowReturn
752 gst_h264_parse_push_codec_buffer (GstH264Parse * h264parse, GstBuffer * nal,
753     GstClockTime ts)
754 {
755   nal = gst_h264_parse_wrap_nal (h264parse, h264parse->format,
756       GST_BUFFER_DATA (nal), GST_BUFFER_SIZE (nal));
757
758   GST_BUFFER_TIMESTAMP (nal) = ts;
759   GST_BUFFER_DURATION (nal) = 0;
760
761   gst_buffer_set_caps (nal, GST_PAD_CAPS (GST_BASE_PARSE_SRC_PAD (h264parse)));
762
763   return gst_pad_push (GST_BASE_PARSE_SRC_PAD (h264parse), nal);
764 }
765
766 static GstFlowReturn
767 gst_h264_parse_pre_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
768 {
769   GstH264Parse *h264parse;
770   GstBuffer *buffer;
771
772   h264parse = GST_H264_PARSE (parse);
773   buffer = frame->buffer;
774
775   /* periodic SPS/PPS sending */
776   if (h264parse->interval > 0 || h264parse->push_codec) {
777     GstClockTime timestamp = GST_BUFFER_TIMESTAMP (buffer);
778     guint64 diff;
779
780     /* init */
781     if (!GST_CLOCK_TIME_IS_VALID (h264parse->last_report)) {
782       h264parse->last_report = timestamp;
783     }
784
785     if (h264parse->idr_pos >= 0) {
786       GST_LOG_OBJECT (h264parse, "IDR nal at offset %d", h264parse->idr_pos);
787
788       if (timestamp > h264parse->last_report)
789         diff = timestamp - h264parse->last_report;
790       else
791         diff = 0;
792
793       GST_LOG_OBJECT (h264parse,
794           "now %" GST_TIME_FORMAT ", last SPS/PPS %" GST_TIME_FORMAT,
795           GST_TIME_ARGS (timestamp), GST_TIME_ARGS (h264parse->last_report));
796
797       GST_DEBUG_OBJECT (h264parse,
798           "interval since last SPS/PPS %" GST_TIME_FORMAT,
799           GST_TIME_ARGS (diff));
800
801       if (GST_TIME_AS_SECONDS (diff) >= h264parse->interval ||
802           h264parse->push_codec) {
803         GstBuffer *codec_nal;
804         gint i;
805         GstClockTime new_ts;
806
807         /* avoid overwriting a perfectly fine timestamp */
808         new_ts = GST_CLOCK_TIME_IS_VALID (timestamp) ? timestamp :
809             h264parse->last_report;
810
811         if (h264parse->align == GST_H264_PARSE_ALIGN_NAL) {
812           /* send separate config NAL buffers */
813           GST_DEBUG_OBJECT (h264parse, "- sending SPS/PPS");
814           for (i = 0; i < MAX_SPS_COUNT; i++) {
815             if ((codec_nal = h264parse->params->sps_nals[i])) {
816               GST_DEBUG_OBJECT (h264parse, "sending SPS nal");
817               gst_h264_parse_push_codec_buffer (h264parse, codec_nal,
818                   timestamp);
819               h264parse->last_report = new_ts;
820             }
821           }
822           for (i = 0; i < MAX_PPS_COUNT; i++) {
823             if ((codec_nal = h264parse->params->pps_nals[i])) {
824               GST_DEBUG_OBJECT (h264parse, "sending PPS nal");
825               gst_h264_parse_push_codec_buffer (h264parse, codec_nal,
826                   timestamp);
827               h264parse->last_report = new_ts;
828             }
829           }
830         } else {
831           /* insert config NALs into AU */
832           GstByteWriter bw;
833           GstBuffer *new_buf;
834           const gboolean bs = h264parse->format == GST_H264_PARSE_FORMAT_BYTE;
835
836           gst_byte_writer_init_with_size (&bw, GST_BUFFER_SIZE (buffer), FALSE);
837           gst_byte_writer_put_data (&bw, GST_BUFFER_DATA (buffer),
838               h264parse->idr_pos);
839           GST_DEBUG_OBJECT (h264parse, "- inserting SPS/PPS");
840           for (i = 0; i < MAX_SPS_COUNT; i++) {
841             if ((codec_nal = h264parse->params->sps_nals[i])) {
842               GST_DEBUG_OBJECT (h264parse, "inserting SPS nal");
843               gst_byte_writer_put_uint32_be (&bw,
844                   bs ? 1 : GST_BUFFER_SIZE (codec_nal));
845               gst_byte_writer_put_data (&bw, GST_BUFFER_DATA (codec_nal),
846                   GST_BUFFER_SIZE (codec_nal));
847               h264parse->last_report = new_ts;
848             }
849           }
850           for (i = 0; i < MAX_PPS_COUNT; i++) {
851             if ((codec_nal = h264parse->params->pps_nals[i])) {
852               GST_DEBUG_OBJECT (h264parse, "inserting PPS nal");
853               gst_byte_writer_put_uint32_be (&bw,
854                   bs ? 1 : GST_BUFFER_SIZE (codec_nal));
855               gst_byte_writer_put_data (&bw, GST_BUFFER_DATA (codec_nal),
856                   GST_BUFFER_SIZE (codec_nal));
857               h264parse->last_report = new_ts;
858             }
859           }
860           gst_byte_writer_put_data (&bw,
861               GST_BUFFER_DATA (buffer) + h264parse->idr_pos,
862               GST_BUFFER_SIZE (buffer) - h264parse->idr_pos);
863           /* collect result and push */
864           new_buf = gst_byte_writer_reset_and_get_buffer (&bw);
865           gst_buffer_copy_metadata (new_buf, buffer, GST_BUFFER_COPY_ALL);
866           gst_buffer_replace (&frame->buffer, new_buf);
867         }
868       }
869       /* we pushed whatever we had */
870       h264parse->push_codec = FALSE;
871     }
872   }
873
874   gst_h264_parse_reset_frame (h264parse);
875
876   return GST_FLOW_OK;
877 }
878
879 static gboolean
880 gst_h264_parse_set_caps (GstBaseParse * parse, GstCaps * caps)
881 {
882   GstH264Parse *h264parse;
883   GstStructure *str;
884   const GValue *value;
885   GstBuffer *buffer = NULL;
886   guint size;
887
888   h264parse = GST_H264_PARSE (parse);
889
890   /* reset */
891   h264parse->push_codec = FALSE;
892
893   str = gst_caps_get_structure (caps, 0);
894
895   /* accept upstream info if provided */
896   gst_structure_get_int (str, "width", &h264parse->width);
897   gst_structure_get_int (str, "height", &h264parse->height);
898   gst_structure_get_fraction (str, "framerate", &h264parse->fps_num,
899       &h264parse->fps_den);
900
901   /* packetized video has a codec_data */
902   if ((value = gst_structure_get_value (str, "codec_data"))) {
903     guint8 *data;
904     guint num_sps, num_pps, profile, len;
905     gint i;
906
907     GST_DEBUG_OBJECT (h264parse, "have packetized h264");
908     /* make note for optional split processing */
909     h264parse->packetized = TRUE;
910
911     buffer = gst_value_get_buffer (value);
912     if (!buffer)
913       goto wrong_type;
914     data = GST_BUFFER_DATA (buffer);
915     size = GST_BUFFER_SIZE (buffer);
916
917     /* parse the avcC data */
918     if (size < 7)
919       goto avcc_too_small;
920     /* parse the version, this must be 1 */
921     if (data[0] != 1)
922       goto wrong_version;
923
924     /* AVCProfileIndication */
925     /* profile_compat */
926     /* AVCLevelIndication */
927     profile = (data[1] << 16) | (data[2] << 8) | data[3];
928     GST_DEBUG_OBJECT (h264parse, "profile %06x", profile);
929
930     /* 6 bits reserved | 2 bits lengthSizeMinusOne */
931     /* this is the number of bytes in front of the NAL units to mark their
932      * length */
933     h264parse->nal_length_size = (data[4] & 0x03) + 1;
934     GST_DEBUG_OBJECT (h264parse, "nal length %u", h264parse->nal_length_size);
935
936     num_sps = data[5] & 0x1f;
937     data += 6;
938     size -= 6;
939     for (i = 0; i < num_sps; i++) {
940       len = GST_READ_UINT16_BE (data);
941       if (size < len + 2 || len < 2)
942         goto avcc_too_small;
943       /* digest for later reference */
944       gst_h264_parse_process_nal (h264parse, data, 0, 2, len);
945       data += len + 2;
946       size -= len + 2;
947     }
948     num_pps = data[0];
949     data++;
950     size++;
951     for (i = 0; i < num_pps; i++) {
952       len = GST_READ_UINT16_BE (data);
953       if (size < len + 2 || len < 2)
954         goto avcc_too_small;
955       /* digest for later reference */
956       gst_h264_parse_process_nal (h264parse, data, 0, 2, len);
957       data += len + 2;
958       size -= len + 2;
959     }
960   } else {
961     GST_DEBUG_OBJECT (h264parse, "have bytestream h264");
962     /* nothing to pre-process */
963     h264parse->packetized = FALSE;
964     /* we have 4 sync bytes */
965     h264parse->nal_length_size = 4;
966   }
967
968   if (h264parse->packetized) {
969     if (h264parse->split_packetized) {
970       GST_DEBUG_OBJECT (h264parse,
971           "converting AVC to nal bytestream prior to parsing");
972       /* negotiate behaviour with upstream */
973       gst_h264_parse_negotiate (h264parse);
974       if (h264parse->format == GST_H264_PARSE_FORMAT_BYTE) {
975         /* arrange to insert codec-data in-stream if needed */
976         h264parse->push_codec = h264parse->packetized;
977       }
978     } else {
979       GST_DEBUG_OBJECT (h264parse, "passing on packetized AVC");
980       /* no choice to negotiate */
981       h264parse->format = GST_H264_PARSE_FORMAT_AVC;
982       h264parse->align = GST_H264_PARSE_ALIGN_AU;
983       /* fallback codec-data */
984       h264parse->codec_data = gst_buffer_ref (buffer);
985       /* pass through unharmed, though _chain will parse a bit */
986       gst_base_parse_set_format (parse,
987           GST_BASE_PARSE_FORMAT_PASSTHROUGH, TRUE);
988       /* we did parse codec-data and might supplement src caps */
989       gst_h264_parse_update_src_caps (h264parse);
990     }
991   }
992
993   /* src caps are only arranged for later on */
994   return TRUE;
995
996   /* ERRORS */
997 avcc_too_small:
998   {
999     GST_DEBUG_OBJECT (h264parse, "avcC size %u < 7", size);
1000     goto refuse_caps;
1001   }
1002 wrong_version:
1003   {
1004     GST_DEBUG_OBJECT (h264parse, "wrong avcC version");
1005     goto refuse_caps;
1006   }
1007 wrong_type:
1008   {
1009     GST_DEBUG_OBJECT (h264parse, "wrong codec-data type");
1010     goto refuse_caps;
1011   }
1012 refuse_caps:
1013   {
1014     GST_WARNING_OBJECT (h264parse, "refused caps %" GST_PTR_FORMAT, caps);
1015     return FALSE;
1016   }
1017 }
1018
1019 static GstFlowReturn
1020 gst_h264_parse_chain (GstPad * pad, GstBuffer * buffer)
1021 {
1022   GstH264Parse *h264parse = GST_H264_PARSE (GST_PAD_PARENT (pad));
1023
1024   if (h264parse->packetized && buffer) {
1025     GstByteReader br;
1026     GstBuffer *sub;
1027     GstFlowReturn ret = GST_FLOW_OK;
1028     guint32 len;
1029     const guint nl = h264parse->nal_length_size;
1030
1031     GST_LOG_OBJECT (h264parse, "processing packet buffer of size %d",
1032         GST_BUFFER_SIZE (buffer));
1033     gst_byte_reader_init_from_buffer (&br, buffer);
1034     while (ret == GST_FLOW_OK && gst_byte_reader_get_remaining (&br)) {
1035       GST_DEBUG_OBJECT (h264parse, "AVC nal offset %d",
1036           gst_byte_reader_get_pos (&br));
1037       if (gst_byte_reader_get_remaining (&br) < nl)
1038         goto parse_failed;
1039       switch (nl) {
1040         case 4:
1041           len = gst_byte_reader_get_uint32_be_unchecked (&br);
1042           break;
1043         case 3:
1044           len = gst_byte_reader_get_uint24_be_unchecked (&br);
1045           break;
1046         case 2:
1047           len = gst_byte_reader_get_uint16_be_unchecked (&br);
1048           break;
1049         case 1:
1050           len = gst_byte_reader_get_uint8_unchecked (&br);
1051           break;
1052         default:
1053           goto not_negotiated;
1054           break;
1055       }
1056       GST_DEBUG_OBJECT (h264parse, "AVC nal size %d", len);
1057       if (gst_byte_reader_get_remaining (&br) < len)
1058         goto parse_failed;
1059       if (h264parse->split_packetized) {
1060         /* convert to NAL aligned byte stream input */
1061         sub = gst_h264_parse_wrap_nal (h264parse, GST_H264_PARSE_FORMAT_BYTE,
1062             (guint8 *) gst_byte_reader_get_data_unchecked (&br, len), len);
1063         /* at least this should make sense */
1064         GST_BUFFER_TIMESTAMP (sub) = GST_BUFFER_TIMESTAMP (buffer);
1065         GST_LOG_OBJECT (h264parse, "pushing NAL of size %d", len);
1066         ret = h264parse->parse_chain (pad, sub);
1067       } else {
1068         /* pass-through: no looking for frames (and nal processing),
1069          * so need to parse to collect data here */
1070         /* NOTE: so if it is really configured to do so,
1071          * pre_push can/will still insert codec-data at intervals,
1072          * which is not really pure pass-through, but anyway ... */
1073         gst_h264_parse_process_nal (h264parse,
1074             GST_BUFFER_DATA (buffer), gst_byte_reader_get_pos (&br) - nl,
1075             gst_byte_reader_get_pos (&br), len);
1076         gst_byte_reader_skip_unchecked (&br, len);
1077       }
1078     }
1079     if (h264parse->split_packetized)
1080       return ret;
1081   }
1082
1083 exit:
1084   /* nal processing in pass-through might have collected stuff;
1085    * ensure nothing happens with this later on */
1086   gst_adapter_clear (h264parse->frame_out);
1087
1088   return h264parse->parse_chain (pad, buffer);
1089
1090   /* ERRORS */
1091 not_negotiated:
1092   {
1093     GST_DEBUG_OBJECT (h264parse, "insufficient data to split input");
1094     return GST_FLOW_NOT_NEGOTIATED;
1095   }
1096 parse_failed:
1097   {
1098     if (h264parse->split_packetized) {
1099       GST_ELEMENT_ERROR (h264parse, STREAM, FAILED, (NULL),
1100           ("invalid AVC input data"));
1101       return GST_FLOW_ERROR;
1102     } else {
1103       /* do not meddle to much in this case */
1104       GST_DEBUG_OBJECT (h264parse, "parsing packet failed");
1105       goto exit;
1106     }
1107   }
1108 }
1109
1110 static void
1111 gst_h264_parse_set_property (GObject * object, guint prop_id,
1112     const GValue * value, GParamSpec * pspec)
1113 {
1114   GstH264Parse *parse;
1115
1116   parse = GST_H264_PARSE (object);
1117
1118   switch (prop_id) {
1119     case PROP_SPLIT_PACKETIZED:
1120       parse->split_packetized = g_value_get_boolean (value);
1121       break;
1122     case PROP_CONFIG_INTERVAL:
1123       parse->interval = g_value_get_uint (value);
1124       break;
1125     default:
1126       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1127       break;
1128   }
1129 }
1130
1131 static void
1132 gst_h264_parse_get_property (GObject * object, guint prop_id, GValue * value,
1133     GParamSpec * pspec)
1134 {
1135   GstH264Parse *parse;
1136
1137   parse = GST_H264_PARSE (object);
1138
1139   switch (prop_id) {
1140     case PROP_SPLIT_PACKETIZED:
1141       g_value_set_boolean (value, parse->split_packetized);
1142       break;
1143     case PROP_CONFIG_INTERVAL:
1144       g_value_set_uint (value, parse->interval);
1145       break;
1146     default:
1147       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1148       break;
1149   }
1150 }