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