~ubuntu-branches/ubuntu/vivid/gstreamer-vaapi/vivid

« back to all changes in this revision

Viewing changes to ext/codecparsers/gst/videoparsers/gsth264parse.c

  • Committer: Package Import Robot
  • Author(s): Vincent Cheng
  • Date: 2014-08-06 23:56:00 UTC
  • mfrom: (0.1.4 sid) (1.1.3)
  • Revision ID: package-import@ubuntu.com-20140806235600-fg1kcmiu67k315q5
Tags: 0.5.9-2
* Remove spurious build-deps: libva-drm1, libavcodec-dev. (Closes: #757283)
* Drop Build-Depends-Indep and build docs unconditionally on all archs.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* GStreamer H.264 Parser
 
2
 * Copyright (C) <2010> Collabora ltd
 
3
 * Copyright (C) <2010> Nokia Corporation
 
4
 * Copyright (C) <2011> Intel Corporation
 
5
 *
 
6
 * Copyright (C) <2010> Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
 
7
 * Copyright (C) <2011> Thibault Saunier <thibault.saunier@collabora.com>
 
8
 *
 
9
 * This library is free software; you can redistribute it and/or
 
10
 * modify it under the terms of the GNU Library General Public
 
11
 * License as published by the Free Software Foundation; either
 
12
 * version 2 of the License, or (at your option) any later version.
 
13
 *
 
14
 * This library is distributed in the hope that it will be useful,
 
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
17
 * Library General Public License for more details.
 
18
 *
 
19
 * You should have received a copy of the GNU Library General Public
 
20
 * License along with this library; if not, write to the
 
21
 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
 
22
 * Boston, MA 02110-1301, USA.
 
23
 */
 
24
 
 
25
#ifdef HAVE_CONFIG_H
 
26
#  include "config.h"
 
27
#endif
 
28
 
 
29
#include <gst/base/base.h>
 
30
#include <gst/pbutils/pbutils.h>
 
31
#include <gst/video/video.h>
 
32
#include "gsth264parse.h"
 
33
 
 
34
#include <string.h>
 
35
 
 
36
GST_DEBUG_CATEGORY (h264_parse_debug);
 
37
#define GST_CAT_DEFAULT h264_parse_debug
 
38
 
 
39
#define DEFAULT_CONFIG_INTERVAL      (0)
 
40
 
 
41
enum
 
42
{
 
43
  PROP_0,
 
44
  PROP_CONFIG_INTERVAL,
 
45
  PROP_LAST
 
46
};
 
47
 
 
48
enum
 
49
{
 
50
  GST_H264_PARSE_FORMAT_NONE,
 
51
  GST_H264_PARSE_FORMAT_AVC,
 
52
  GST_H264_PARSE_FORMAT_BYTE,
 
53
  GST_H264_PARSE_FORMAT_AVC3
 
54
};
 
55
 
 
56
enum
 
57
{
 
58
  GST_H264_PARSE_ALIGN_NONE = 0,
 
59
  GST_H264_PARSE_ALIGN_NAL,
 
60
  GST_H264_PARSE_ALIGN_AU
 
61
};
 
62
 
 
63
enum
 
64
{
 
65
  GST_H264_PARSE_STATE_GOT_SPS = 1 << 0,
 
66
  GST_H264_PARSE_STATE_GOT_PPS = 1 << 1,
 
67
  GST_H264_PARSE_STATE_GOT_SLICE = 1 << 2,
 
68
 
 
69
  GST_H264_PARSE_STATE_VALID_PICTURE_HEADERS = (GST_H264_PARSE_STATE_GOT_SPS |
 
70
      GST_H264_PARSE_STATE_GOT_PPS),
 
71
  GST_H264_PARSE_STATE_VALID_PICTURE =
 
72
      (GST_H264_PARSE_STATE_VALID_PICTURE_HEADERS |
 
73
      GST_H264_PARSE_STATE_GOT_SLICE)
 
74
};
 
75
 
 
76
#define GST_H264_PARSE_STATE_VALID(parse, expected_state) \
 
77
  (((parse)->state & (expected_state)) == (expected_state))
 
78
 
 
79
static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
 
80
    GST_PAD_SINK,
 
81
    GST_PAD_ALWAYS,
 
82
    GST_STATIC_CAPS ("video/x-h264"));
 
83
 
 
84
static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
 
85
    GST_PAD_SRC,
 
86
    GST_PAD_ALWAYS,
 
87
    GST_STATIC_CAPS ("video/x-h264, parsed = (boolean) true, "
 
88
        "stream-format=(string) { avc, avc3, byte-stream }, "
 
89
        "alignment=(string) { au, nal }"));
 
90
 
 
91
#define parent_class gst_h264_parse_parent_class
 
92
G_DEFINE_TYPE (GstH264Parse, gst_h264_parse, GST_TYPE_BASE_PARSE);
 
93
 
 
94
static void gst_h264_parse_finalize (GObject * object);
 
95
 
 
96
static gboolean gst_h264_parse_start (GstBaseParse * parse);
 
97
static gboolean gst_h264_parse_stop (GstBaseParse * parse);
 
98
static GstFlowReturn gst_h264_parse_handle_frame (GstBaseParse * parse,
 
99
    GstBaseParseFrame * frame, gint * skipsize);
 
100
static GstFlowReturn gst_h264_parse_parse_frame (GstBaseParse * parse,
 
101
    GstBaseParseFrame * frame);
 
102
static GstFlowReturn gst_h264_parse_pre_push_frame (GstBaseParse * parse,
 
103
    GstBaseParseFrame * frame);
 
104
 
 
105
static void gst_h264_parse_set_property (GObject * object, guint prop_id,
 
106
    const GValue * value, GParamSpec * pspec);
 
107
static void gst_h264_parse_get_property (GObject * object, guint prop_id,
 
108
    GValue * value, GParamSpec * pspec);
 
109
 
 
110
static gboolean gst_h264_parse_set_caps (GstBaseParse * parse, GstCaps * caps);
 
111
static GstCaps *gst_h264_parse_get_caps (GstBaseParse * parse,
 
112
    GstCaps * filter);
 
113
static gboolean gst_h264_parse_event (GstBaseParse * parse, GstEvent * event);
 
114
static gboolean gst_h264_parse_src_event (GstBaseParse * parse,
 
115
    GstEvent * event);
 
116
 
 
117
static void
 
118
gst_h264_parse_class_init (GstH264ParseClass * klass)
 
119
{
 
120
  GObjectClass *gobject_class = (GObjectClass *) klass;
 
121
  GstBaseParseClass *parse_class = GST_BASE_PARSE_CLASS (klass);
 
122
  GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
 
123
 
 
124
  GST_DEBUG_CATEGORY_INIT (h264_parse_debug, "h264parse", 0, "h264 parser");
 
125
 
 
126
  gobject_class->finalize = gst_h264_parse_finalize;
 
127
  gobject_class->set_property = gst_h264_parse_set_property;
 
128
  gobject_class->get_property = gst_h264_parse_get_property;
 
129
 
 
130
  g_object_class_install_property (gobject_class, PROP_CONFIG_INTERVAL,
 
131
      g_param_spec_uint ("config-interval",
 
132
          "SPS PPS Send Interval",
 
133
          "Send SPS and PPS Insertion Interval in seconds (sprop parameter sets "
 
134
          "will be multiplexed in the data stream when detected.) (0 = disabled)",
 
135
          0, 3600, DEFAULT_CONFIG_INTERVAL,
 
136
          G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
 
137
 
 
138
  /* Override BaseParse vfuncs */
 
139
  parse_class->start = GST_DEBUG_FUNCPTR (gst_h264_parse_start);
 
140
  parse_class->stop = GST_DEBUG_FUNCPTR (gst_h264_parse_stop);
 
141
  parse_class->handle_frame = GST_DEBUG_FUNCPTR (gst_h264_parse_handle_frame);
 
142
  parse_class->pre_push_frame =
 
143
      GST_DEBUG_FUNCPTR (gst_h264_parse_pre_push_frame);
 
144
  parse_class->set_sink_caps = GST_DEBUG_FUNCPTR (gst_h264_parse_set_caps);
 
145
  parse_class->get_sink_caps = GST_DEBUG_FUNCPTR (gst_h264_parse_get_caps);
 
146
  parse_class->sink_event = GST_DEBUG_FUNCPTR (gst_h264_parse_event);
 
147
  parse_class->src_event = GST_DEBUG_FUNCPTR (gst_h264_parse_src_event);
 
148
 
 
149
  gst_element_class_add_pad_template (gstelement_class,
 
150
      gst_static_pad_template_get (&srctemplate));
 
151
  gst_element_class_add_pad_template (gstelement_class,
 
152
      gst_static_pad_template_get (&sinktemplate));
 
153
 
 
154
  gst_element_class_set_static_metadata (gstelement_class, "H.264 parser",
 
155
      "Codec/Parser/Converter/Video",
 
156
      "Parses H.264 streams",
 
157
      "Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>");
 
158
}
 
159
 
 
160
static void
 
161
gst_h264_parse_init (GstH264Parse * h264parse)
 
162
{
 
163
  h264parse->frame_out = gst_adapter_new ();
 
164
  gst_base_parse_set_pts_interpolation (GST_BASE_PARSE (h264parse), FALSE);
 
165
  GST_PAD_SET_ACCEPT_INTERSECT (GST_BASE_PARSE_SINK_PAD (h264parse));
 
166
}
 
167
 
 
168
 
 
169
static void
 
170
gst_h264_parse_finalize (GObject * object)
 
171
{
 
172
  GstH264Parse *h264parse = GST_H264_PARSE (object);
 
173
 
 
174
  g_object_unref (h264parse->frame_out);
 
175
 
 
176
  G_OBJECT_CLASS (parent_class)->finalize (object);
 
177
}
 
178
 
 
179
static void
 
180
gst_h264_parse_reset_frame (GstH264Parse * h264parse)
 
181
{
 
182
  GST_DEBUG_OBJECT (h264parse, "reset frame");
 
183
 
 
184
  /* done parsing; reset state */
 
185
  h264parse->current_off = -1;
 
186
 
 
187
  h264parse->picture_start = FALSE;
 
188
  h264parse->update_caps = FALSE;
 
189
  h264parse->idr_pos = -1;
 
190
  h264parse->sei_pos = -1;
 
191
  h264parse->keyframe = FALSE;
 
192
  h264parse->frame_start = FALSE;
 
193
  gst_adapter_clear (h264parse->frame_out);
 
194
}
 
195
 
 
196
static void
 
197
gst_h264_parse_reset (GstH264Parse * h264parse)
 
198
{
 
199
  h264parse->width = 0;
 
200
  h264parse->height = 0;
 
201
  h264parse->fps_num = 0;
 
202
  h264parse->fps_den = 0;
 
203
  h264parse->upstream_par_n = -1;
 
204
  h264parse->upstream_par_d = -1;
 
205
  h264parse->parsed_par_n = 0;
 
206
  h264parse->parsed_par_d = 0;
 
207
  gst_buffer_replace (&h264parse->codec_data, NULL);
 
208
  gst_buffer_replace (&h264parse->codec_data_in, NULL);
 
209
  h264parse->nal_length_size = 4;
 
210
  h264parse->packetized = FALSE;
 
211
  h264parse->transform = FALSE;
 
212
 
 
213
  h264parse->align = GST_H264_PARSE_ALIGN_NONE;
 
214
  h264parse->format = GST_H264_PARSE_FORMAT_NONE;
 
215
 
 
216
  h264parse->last_report = GST_CLOCK_TIME_NONE;
 
217
  h264parse->push_codec = FALSE;
 
218
  h264parse->have_pps = FALSE;
 
219
  h264parse->have_sps = FALSE;
 
220
 
 
221
  h264parse->dts = GST_CLOCK_TIME_NONE;
 
222
  h264parse->ts_trn_nb = GST_CLOCK_TIME_NONE;
 
223
  h264parse->do_ts = TRUE;
 
224
 
 
225
  h264parse->sent_codec_tag = FALSE;
 
226
 
 
227
  h264parse->pending_key_unit_ts = GST_CLOCK_TIME_NONE;
 
228
  gst_event_replace (&h264parse->force_key_unit_event, NULL);
 
229
 
 
230
  h264parse->discont = FALSE;
 
231
 
 
232
  gst_h264_parse_reset_frame (h264parse);
 
233
}
 
234
 
 
235
static gboolean
 
236
gst_h264_parse_start (GstBaseParse * parse)
 
237
{
 
238
  GstH264Parse *h264parse = GST_H264_PARSE (parse);
 
239
 
 
240
  GST_DEBUG_OBJECT (parse, "start");
 
241
  gst_h264_parse_reset (h264parse);
 
242
 
 
243
  h264parse->nalparser = gst_h264_nal_parser_new ();
 
244
 
 
245
  h264parse->dts = GST_CLOCK_TIME_NONE;
 
246
  h264parse->ts_trn_nb = GST_CLOCK_TIME_NONE;
 
247
  h264parse->sei_pic_struct_pres_flag = FALSE;
 
248
  h264parse->sei_pic_struct = 0;
 
249
  h264parse->field_pic_flag = 0;
 
250
 
 
251
  gst_base_parse_set_min_frame_size (parse, 6);
 
252
 
 
253
  return TRUE;
 
254
}
 
255
 
 
256
static gboolean
 
257
gst_h264_parse_stop (GstBaseParse * parse)
 
258
{
 
259
  guint i;
 
260
  GstH264Parse *h264parse = GST_H264_PARSE (parse);
 
261
 
 
262
  GST_DEBUG_OBJECT (parse, "stop");
 
263
  gst_h264_parse_reset (h264parse);
 
264
 
 
265
  for (i = 0; i < GST_H264_MAX_SPS_COUNT; i++)
 
266
    gst_buffer_replace (&h264parse->sps_nals[i], NULL);
 
267
  for (i = 0; i < GST_H264_MAX_PPS_COUNT; i++)
 
268
    gst_buffer_replace (&h264parse->pps_nals[i], NULL);
 
269
 
 
270
  gst_h264_nal_parser_free (h264parse->nalparser);
 
271
 
 
272
  return TRUE;
 
273
}
 
274
 
 
275
static const gchar *
 
276
gst_h264_parse_get_string (GstH264Parse * parse, gboolean format, gint code)
 
277
{
 
278
  if (format) {
 
279
    switch (code) {
 
280
      case GST_H264_PARSE_FORMAT_AVC:
 
281
        return "avc";
 
282
      case GST_H264_PARSE_FORMAT_BYTE:
 
283
        return "byte-stream";
 
284
      case GST_H264_PARSE_FORMAT_AVC3:
 
285
        return "avc3";
 
286
      default:
 
287
        return "none";
 
288
    }
 
289
  } else {
 
290
    switch (code) {
 
291
      case GST_H264_PARSE_ALIGN_NAL:
 
292
        return "nal";
 
293
      case GST_H264_PARSE_ALIGN_AU:
 
294
        return "au";
 
295
      default:
 
296
        return "none";
 
297
    }
 
298
  }
 
299
}
 
300
 
 
301
static void
 
302
gst_h264_parse_format_from_caps (GstCaps * caps, guint * format, guint * align)
 
303
{
 
304
  if (format)
 
305
    *format = GST_H264_PARSE_FORMAT_NONE;
 
306
 
 
307
  if (align)
 
308
    *align = GST_H264_PARSE_ALIGN_NONE;
 
309
 
 
310
  g_return_if_fail (gst_caps_is_fixed (caps));
 
311
 
 
312
  GST_DEBUG ("parsing caps: %" GST_PTR_FORMAT, caps);
 
313
 
 
314
  if (caps && gst_caps_get_size (caps) > 0) {
 
315
    GstStructure *s = gst_caps_get_structure (caps, 0);
 
316
    const gchar *str = NULL;
 
317
 
 
318
    if (format) {
 
319
      if ((str = gst_structure_get_string (s, "stream-format"))) {
 
320
        if (strcmp (str, "avc") == 0)
 
321
          *format = GST_H264_PARSE_FORMAT_AVC;
 
322
        else if (strcmp (str, "byte-stream") == 0)
 
323
          *format = GST_H264_PARSE_FORMAT_BYTE;
 
324
        else if (strcmp (str, "avc3") == 0)
 
325
          *format = GST_H264_PARSE_FORMAT_AVC3;
 
326
      }
 
327
    }
 
328
 
 
329
    if (align) {
 
330
      if ((str = gst_structure_get_string (s, "alignment"))) {
 
331
        if (strcmp (str, "au") == 0)
 
332
          *align = GST_H264_PARSE_ALIGN_AU;
 
333
        else if (strcmp (str, "nal") == 0)
 
334
          *align = GST_H264_PARSE_ALIGN_NAL;
 
335
      }
 
336
    }
 
337
  }
 
338
}
 
339
 
 
340
/* check downstream caps to configure format and alignment */
 
341
static void
 
342
gst_h264_parse_negotiate (GstH264Parse * h264parse, gint in_format,
 
343
    GstCaps * in_caps)
 
344
{
 
345
  GstCaps *caps;
 
346
  guint format = GST_H264_PARSE_FORMAT_NONE;
 
347
  guint align = GST_H264_PARSE_ALIGN_NONE;
 
348
 
 
349
  g_return_if_fail ((in_caps == NULL) || gst_caps_is_fixed (in_caps));
 
350
 
 
351
  caps = gst_pad_get_allowed_caps (GST_BASE_PARSE_SRC_PAD (h264parse));
 
352
  GST_DEBUG_OBJECT (h264parse, "allowed caps: %" GST_PTR_FORMAT, caps);
 
353
 
 
354
  /* concentrate on leading structure, since decodebin2 parser
 
355
   * capsfilter always includes parser template caps */
 
356
  if (caps) {
 
357
    caps = gst_caps_truncate (caps);
 
358
    GST_DEBUG_OBJECT (h264parse, "negotiating with caps: %" GST_PTR_FORMAT,
 
359
        caps);
 
360
  }
 
361
 
 
362
  if (in_caps && caps) {
 
363
    if (gst_caps_can_intersect (in_caps, caps)) {
 
364
      GST_DEBUG_OBJECT (h264parse, "downstream accepts upstream caps");
 
365
      gst_h264_parse_format_from_caps (in_caps, &format, &align);
 
366
      gst_caps_unref (caps);
 
367
      caps = NULL;
 
368
    }
 
369
  }
 
370
 
 
371
  if (caps) {
 
372
    /* fixate to avoid ambiguity with lists when parsing */
 
373
    caps = gst_caps_fixate (caps);
 
374
    gst_h264_parse_format_from_caps (caps, &format, &align);
 
375
    gst_caps_unref (caps);
 
376
  }
 
377
 
 
378
  /* default */
 
379
  if (!format)
 
380
    format = GST_H264_PARSE_FORMAT_BYTE;
 
381
  if (!align)
 
382
    align = GST_H264_PARSE_ALIGN_AU;
 
383
 
 
384
  GST_DEBUG_OBJECT (h264parse, "selected format %s, alignment %s",
 
385
      gst_h264_parse_get_string (h264parse, TRUE, format),
 
386
      gst_h264_parse_get_string (h264parse, FALSE, align));
 
387
 
 
388
  h264parse->format = format;
 
389
  h264parse->align = align;
 
390
 
 
391
  h264parse->transform = in_format != h264parse->format ||
 
392
      align == GST_H264_PARSE_ALIGN_AU;
 
393
}
 
394
 
 
395
static GstBuffer *
 
396
gst_h264_parse_wrap_nal (GstH264Parse * h264parse, guint format, guint8 * data,
 
397
    guint size)
 
398
{
 
399
  GstBuffer *buf;
 
400
  guint nl = h264parse->nal_length_size;
 
401
  guint32 tmp;
 
402
 
 
403
  GST_DEBUG_OBJECT (h264parse, "nal length %d", size);
 
404
 
 
405
  buf = gst_buffer_new_allocate (NULL, 4 + size, NULL);
 
406
  if (format == GST_H264_PARSE_FORMAT_AVC
 
407
      || format == GST_H264_PARSE_FORMAT_AVC3) {
 
408
    tmp = GUINT32_TO_BE (size << (32 - 8 * nl));
 
409
  } else {
 
410
    /* HACK: nl should always be 4 here, otherwise this won't work. 
 
411
     * There are legit cases where nl in avc stream is 2, but byte-stream
 
412
     * SC is still always 4 bytes. */
 
413
    nl = 4;
 
414
    tmp = GUINT32_TO_BE (1);
 
415
  }
 
416
 
 
417
  gst_buffer_fill (buf, 0, &tmp, sizeof (guint32));
 
418
  gst_buffer_fill (buf, nl, data, size);
 
419
  gst_buffer_set_size (buf, size + nl);
 
420
 
 
421
  return buf;
 
422
}
 
423
 
 
424
static void
 
425
gst_h264_parser_store_nal (GstH264Parse * h264parse, guint id,
 
426
    GstH264NalUnitType naltype, GstH264NalUnit * nalu)
 
427
{
 
428
  GstBuffer *buf, **store;
 
429
  guint size = nalu->size, store_size;
 
430
 
 
431
  if (naltype == GST_H264_NAL_SPS) {
 
432
    store_size = GST_H264_MAX_SPS_COUNT;
 
433
    store = h264parse->sps_nals;
 
434
    GST_DEBUG_OBJECT (h264parse, "storing sps %u", id);
 
435
  } else if (naltype == GST_H264_NAL_PPS) {
 
436
    store_size = GST_H264_MAX_PPS_COUNT;
 
437
    store = h264parse->pps_nals;
 
438
    GST_DEBUG_OBJECT (h264parse, "storing pps %u", id);
 
439
  } else
 
440
    return;
 
441
 
 
442
  if (id >= store_size) {
 
443
    GST_DEBUG_OBJECT (h264parse, "unable to store nal, id out-of-range %d", id);
 
444
    return;
 
445
  }
 
446
 
 
447
  buf = gst_buffer_new_allocate (NULL, size, NULL);
 
448
  gst_buffer_fill (buf, 0, nalu->data + nalu->offset, size);
 
449
 
 
450
  if (store[id])
 
451
    gst_buffer_unref (store[id]);
 
452
 
 
453
  store[id] = buf;
 
454
}
 
455
 
 
456
#ifndef GST_DISABLE_GST_DEBUG
 
457
static const gchar *nal_names[] = {
 
458
  "Unknown",
 
459
  "Slice",
 
460
  "Slice DPA",
 
461
  "Slice DPB",
 
462
  "Slice DPC",
 
463
  "Slice IDR",
 
464
  "SEI",
 
465
  "SPS",
 
466
  "PPS",
 
467
  "AU delimiter",
 
468
  "Sequence End",
 
469
  "Stream End",
 
470
  "Filler Data"
 
471
};
 
472
 
 
473
static const gchar *
 
474
_nal_name (GstH264NalUnitType nal_type)
 
475
{
 
476
  if (nal_type <= GST_H264_NAL_FILLER_DATA)
 
477
    return nal_names[nal_type];
 
478
  return "Invalid";
 
479
}
 
480
#endif
 
481
 
 
482
static void
 
483
gst_h264_parse_process_sei (GstH264Parse * h264parse, GstH264NalUnit * nalu)
 
484
{
 
485
  GstH264SEIMessage sei;
 
486
  GstH264NalParser *nalparser = h264parse->nalparser;
 
487
  GstH264ParserResult pres;
 
488
  GArray *messages;
 
489
  guint i;
 
490
 
 
491
  pres = gst_h264_parser_parse_sei (nalparser, nalu, &messages);
 
492
  if (pres != GST_H264_PARSER_OK)
 
493
    GST_WARNING_OBJECT (h264parse, "failed to parse one ore more SEI message");
 
494
 
 
495
  /* Even if pres != GST_H264_PARSER_OK, some message could have been parsed and
 
496
   * stored in messages.
 
497
   */
 
498
  for (i = 0; i < messages->len; i++) {
 
499
    sei = g_array_index (messages, GstH264SEIMessage, i);
 
500
    switch (sei.payloadType) {
 
501
      case GST_H264_SEI_PIC_TIMING:
 
502
        h264parse->sei_pic_struct_pres_flag =
 
503
            sei.payload.pic_timing.pic_struct_present_flag;
 
504
        h264parse->sei_cpb_removal_delay =
 
505
            sei.payload.pic_timing.cpb_removal_delay;
 
506
        if (h264parse->sei_pic_struct_pres_flag)
 
507
          h264parse->sei_pic_struct = sei.payload.pic_timing.pic_struct;
 
508
        GST_LOG_OBJECT (h264parse, "pic timing updated");
 
509
        break;
 
510
      case GST_H264_SEI_BUF_PERIOD:
 
511
        if (h264parse->ts_trn_nb == GST_CLOCK_TIME_NONE ||
 
512
            h264parse->dts == GST_CLOCK_TIME_NONE)
 
513
          h264parse->ts_trn_nb = 0;
 
514
        else
 
515
          h264parse->ts_trn_nb = h264parse->dts;
 
516
 
 
517
        GST_LOG_OBJECT (h264parse,
 
518
            "new buffering period; ts_trn_nb updated: %" GST_TIME_FORMAT,
 
519
            GST_TIME_ARGS (h264parse->ts_trn_nb));
 
520
        break;
 
521
 
 
522
        /* Additional messages that are not innerly useful to the
 
523
         * element but for debugging purposes */
 
524
      case GST_H264_SEI_RECOVERY_POINT:
 
525
        GST_LOG_OBJECT (h264parse, "recovery point found: %u %u %u %u",
 
526
            sei.payload.recovery_point.recovery_frame_cnt,
 
527
            sei.payload.recovery_point.exact_match_flag,
 
528
            sei.payload.recovery_point.broken_link_flag,
 
529
            sei.payload.recovery_point.changing_slice_group_idc);
 
530
        break;
 
531
    }
 
532
  }
 
533
  g_array_free (messages, TRUE);
 
534
}
 
535
 
 
536
/* caller guarantees 2 bytes of nal payload */
 
537
static gboolean
 
538
gst_h264_parse_process_nal (GstH264Parse * h264parse, GstH264NalUnit * nalu)
 
539
{
 
540
  guint nal_type;
 
541
  GstH264PPS pps = { 0, };
 
542
  GstH264SPS sps = { 0, };
 
543
  GstH264NalParser *nalparser = h264parse->nalparser;
 
544
  GstH264ParserResult pres;
 
545
 
 
546
  /* nothing to do for broken input */
 
547
  if (G_UNLIKELY (nalu->size < 2)) {
 
548
    GST_DEBUG_OBJECT (h264parse, "not processing nal size %u", nalu->size);
 
549
    return TRUE;
 
550
  }
 
551
 
 
552
  /* we have a peek as well */
 
553
  nal_type = nalu->type;
 
554
 
 
555
  GST_DEBUG_OBJECT (h264parse, "processing nal of type %u %s, size %u",
 
556
      nal_type, _nal_name (nal_type), nalu->size);
 
557
 
 
558
  switch (nal_type) {
 
559
    case GST_H264_NAL_SPS:
 
560
      /* reset state, everything else is obsolete */
 
561
      h264parse->state = 0;
 
562
 
 
563
      pres = gst_h264_parser_parse_sps (nalparser, nalu, &sps, TRUE);
 
564
      /* arranged for a fallback sps.id, so use that one and only warn */
 
565
      if (pres != GST_H264_PARSER_OK) {
 
566
        GST_WARNING_OBJECT (h264parse, "failed to parse SPS:");
 
567
        return FALSE;
 
568
      }
 
569
 
 
570
      GST_DEBUG_OBJECT (h264parse, "triggering src caps check");
 
571
      h264parse->update_caps = TRUE;
 
572
      h264parse->have_sps = TRUE;
 
573
      if (h264parse->push_codec && h264parse->have_pps) {
 
574
        /* SPS and PPS found in stream before the first pre_push_frame, no need
 
575
         * to forcibly push at start */
 
576
        GST_INFO_OBJECT (h264parse, "have SPS/PPS in stream");
 
577
        h264parse->push_codec = FALSE;
 
578
        h264parse->have_sps = FALSE;
 
579
        h264parse->have_pps = FALSE;
 
580
      }
 
581
 
 
582
      gst_h264_parser_store_nal (h264parse, sps.id, nal_type, nalu);
 
583
      h264parse->state |= GST_H264_PARSE_STATE_GOT_SPS;
 
584
      break;
 
585
    case GST_H264_NAL_PPS:
 
586
      /* expected state: got-sps */
 
587
      h264parse->state &= GST_H264_PARSE_STATE_GOT_SPS;
 
588
      if (!GST_H264_PARSE_STATE_VALID (h264parse, GST_H264_PARSE_STATE_GOT_SPS))
 
589
        return FALSE;
 
590
 
 
591
      pres = gst_h264_parser_parse_pps (nalparser, nalu, &pps);
 
592
      /* arranged for a fallback pps.id, so use that one and only warn */
 
593
      if (pres != GST_H264_PARSER_OK) {
 
594
        GST_WARNING_OBJECT (h264parse, "failed to parse PPS:");
 
595
        if (pres != GST_H264_PARSER_BROKEN_LINK)
 
596
          return FALSE;
 
597
      }
 
598
 
 
599
      /* parameters might have changed, force caps check */
 
600
      if (!h264parse->have_pps) {
 
601
        GST_DEBUG_OBJECT (h264parse, "triggering src caps check");
 
602
        h264parse->update_caps = TRUE;
 
603
      }
 
604
      h264parse->have_pps = TRUE;
 
605
      if (h264parse->push_codec && h264parse->have_sps) {
 
606
        /* SPS and PPS found in stream before the first pre_push_frame, no need
 
607
         * to forcibly push at start */
 
608
        GST_INFO_OBJECT (h264parse, "have SPS/PPS in stream");
 
609
        h264parse->push_codec = FALSE;
 
610
        h264parse->have_sps = FALSE;
 
611
        h264parse->have_pps = FALSE;
 
612
      }
 
613
 
 
614
      gst_h264_parser_store_nal (h264parse, pps.id, nal_type, nalu);
 
615
      gst_h264_pps_clear (&pps);
 
616
      h264parse->state |= GST_H264_PARSE_STATE_GOT_PPS;
 
617
      break;
 
618
    case GST_H264_NAL_SEI:
 
619
      /* expected state: got-sps */
 
620
      if (!GST_H264_PARSE_STATE_VALID (h264parse, GST_H264_PARSE_STATE_GOT_SPS))
 
621
        return FALSE;
 
622
 
 
623
      gst_h264_parse_process_sei (h264parse, nalu);
 
624
      /* mark SEI pos */
 
625
      if (h264parse->sei_pos == -1) {
 
626
        if (h264parse->transform)
 
627
          h264parse->sei_pos = gst_adapter_available (h264parse->frame_out);
 
628
        else
 
629
          h264parse->sei_pos = nalu->sc_offset;
 
630
        GST_DEBUG_OBJECT (h264parse, "marking SEI in frame at offset %d",
 
631
            h264parse->sei_pos);
 
632
      }
 
633
      break;
 
634
 
 
635
    case GST_H264_NAL_SLICE:
 
636
    case GST_H264_NAL_SLICE_DPA:
 
637
    case GST_H264_NAL_SLICE_DPB:
 
638
    case GST_H264_NAL_SLICE_DPC:
 
639
    case GST_H264_NAL_SLICE_IDR:
 
640
      /* expected state: got-sps|got-pps (valid picture headers) */
 
641
      h264parse->state &= GST_H264_PARSE_STATE_VALID_PICTURE_HEADERS;
 
642
      if (!GST_H264_PARSE_STATE_VALID (h264parse,
 
643
              GST_H264_PARSE_STATE_VALID_PICTURE_HEADERS))
 
644
        return FALSE;
 
645
 
 
646
      /* don't need to parse the whole slice (header) here */
 
647
      if (*(nalu->data + nalu->offset + 1) & 0x80) {
 
648
        /* means first_mb_in_slice == 0 */
 
649
        /* real frame data */
 
650
        GST_DEBUG_OBJECT (h264parse, "first_mb_in_slice = 0");
 
651
        h264parse->frame_start = TRUE;
 
652
      }
 
653
      GST_DEBUG_OBJECT (h264parse, "frame start: %i", h264parse->frame_start);
 
654
      {
 
655
        GstH264SliceHdr slice;
 
656
 
 
657
        pres = gst_h264_parser_parse_slice_hdr (nalparser, nalu, &slice,
 
658
            FALSE, FALSE);
 
659
        GST_DEBUG_OBJECT (h264parse,
 
660
            "parse result %d, first MB: %u, slice type: %u",
 
661
            pres, slice.first_mb_in_slice, slice.type);
 
662
        if (pres == GST_H264_PARSER_OK) {
 
663
          if (GST_H264_IS_I_SLICE (&slice) || GST_H264_IS_SI_SLICE (&slice))
 
664
            h264parse->keyframe |= TRUE;
 
665
 
 
666
          h264parse->state |= GST_H264_PARSE_STATE_GOT_SLICE;
 
667
          h264parse->field_pic_flag = slice.field_pic_flag;
 
668
        }
 
669
      }
 
670
      if (G_LIKELY (nal_type != GST_H264_NAL_SLICE_IDR &&
 
671
              !h264parse->push_codec))
 
672
        break;
 
673
      /* if we need to sneak codec NALs into the stream,
 
674
       * this is a good place, so fake it as IDR
 
675
       * (which should be at start anyway) */
 
676
      /* mark where config needs to go if interval expired */
 
677
      /* mind replacement buffer if applicable */
 
678
      if (h264parse->idr_pos == -1) {
 
679
        if (h264parse->transform)
 
680
          h264parse->idr_pos = gst_adapter_available (h264parse->frame_out);
 
681
        else
 
682
          h264parse->idr_pos = nalu->sc_offset;
 
683
        GST_DEBUG_OBJECT (h264parse, "marking IDR in frame at offset %d",
 
684
            h264parse->idr_pos);
 
685
      }
 
686
      /* if SEI preceeds (faked) IDR, then we have to insert config there */
 
687
      if (h264parse->sei_pos >= 0 && h264parse->idr_pos > h264parse->sei_pos) {
 
688
        h264parse->idr_pos = h264parse->sei_pos;
 
689
        GST_DEBUG_OBJECT (h264parse, "moved IDR mark to SEI position %d",
 
690
            h264parse->idr_pos);
 
691
      }
 
692
      break;
 
693
    default:
 
694
      /* drop anything before the initial SPS */
 
695
      if (!GST_H264_PARSE_STATE_VALID (h264parse, GST_H264_PARSE_STATE_GOT_SPS))
 
696
        return FALSE;
 
697
 
 
698
      pres = gst_h264_parser_parse_nal (nalparser, nalu);
 
699
      if (pres != GST_H264_PARSER_OK)
 
700
        return FALSE;
 
701
      break;
 
702
  }
 
703
 
 
704
  /* if AVC output needed, collect properly prefixed nal in adapter,
 
705
   * and use that to replace outgoing buffer data later on */
 
706
  if (h264parse->transform) {
 
707
    GstBuffer *buf;
 
708
 
 
709
    GST_LOG_OBJECT (h264parse, "collecting NAL in AVC frame");
 
710
    buf = gst_h264_parse_wrap_nal (h264parse, h264parse->format,
 
711
        nalu->data + nalu->offset, nalu->size);
 
712
    gst_adapter_push (h264parse->frame_out, buf);
 
713
  }
 
714
  return TRUE;
 
715
}
 
716
 
 
717
/* caller guarantees at least 2 bytes of nal payload for each nal
 
718
 * returns TRUE if next_nal indicates that nal terminates an AU */
 
719
static inline gboolean
 
720
gst_h264_parse_collect_nal (GstH264Parse * h264parse, const guint8 * data,
 
721
    guint size, GstH264NalUnit * nalu)
 
722
{
 
723
  gboolean complete;
 
724
  GstH264ParserResult parse_res;
 
725
  GstH264NalUnitType nal_type = nalu->type;
 
726
  GstH264NalUnit nnalu;
 
727
 
 
728
  GST_DEBUG_OBJECT (h264parse, "parsing collected nal");
 
729
  parse_res = gst_h264_parser_identify_nalu_unchecked (h264parse->nalparser,
 
730
      data, nalu->offset + nalu->size, size, &nnalu);
 
731
 
 
732
  if (parse_res != GST_H264_PARSER_OK)
 
733
    return FALSE;
 
734
 
 
735
  /* determine if AU complete */
 
736
  GST_LOG_OBJECT (h264parse, "nal type: %d %s", nal_type, _nal_name (nal_type));
 
737
  /* coded slice NAL starts a picture,
 
738
   * i.e. other types become aggregated in front of it */
 
739
  h264parse->picture_start |= (nal_type == GST_H264_NAL_SLICE ||
 
740
      nal_type == GST_H264_NAL_SLICE_DPA || nal_type == GST_H264_NAL_SLICE_IDR);
 
741
 
 
742
  /* consider a coded slices (IDR or not) to start a picture,
 
743
   * (so ending the previous one) if first_mb_in_slice == 0
 
744
   * (non-0 is part of previous one) */
 
745
  /* NOTE this is not entirely according to Access Unit specs in 7.4.1.2.4,
 
746
   * but in practice it works in sane cases, needs not much parsing,
 
747
   * and also works with broken frame_num in NAL
 
748
   * (where spec-wise would fail) */
 
749
  nal_type = nnalu.type;
 
750
  complete = h264parse->picture_start && (nal_type >= GST_H264_NAL_SEI &&
 
751
      nal_type <= GST_H264_NAL_AU_DELIMITER);
 
752
 
 
753
  GST_LOG_OBJECT (h264parse, "next nal type: %d %s", nal_type,
 
754
      _nal_name (nal_type));
 
755
  complete |= h264parse->picture_start && (nal_type == GST_H264_NAL_SLICE
 
756
      || nal_type == GST_H264_NAL_SLICE_DPA
 
757
      || nal_type == GST_H264_NAL_SLICE_IDR) &&
 
758
      /* first_mb_in_slice == 0 considered start of frame */
 
759
      (nnalu.data[nnalu.offset + 1] & 0x80);
 
760
 
 
761
  GST_LOG_OBJECT (h264parse, "au complete: %d", complete);
 
762
 
 
763
  return complete;
 
764
}
 
765
 
 
766
 
 
767
static GstFlowReturn
 
768
gst_h264_parse_handle_frame_packetized (GstBaseParse * parse,
 
769
    GstBaseParseFrame * frame)
 
770
{
 
771
  GstH264Parse *h264parse = GST_H264_PARSE (parse);
 
772
  GstBuffer *buffer = frame->buffer;
 
773
  GstFlowReturn ret = GST_FLOW_OK;
 
774
  GstH264ParserResult parse_res;
 
775
  GstH264NalUnit nalu;
 
776
  const guint nl = h264parse->nal_length_size;
 
777
  GstMapInfo map;
 
778
  gint left;
 
779
 
 
780
  if (nl < 1 || nl > 4) {
 
781
    GST_DEBUG_OBJECT (h264parse, "insufficient data to split input");
 
782
    return GST_FLOW_NOT_NEGOTIATED;
 
783
  }
 
784
 
 
785
  /* need to save buffer from invalidation upon _finish_frame */
 
786
  if (h264parse->split_packetized)
 
787
    buffer = gst_buffer_copy (frame->buffer);
 
788
 
 
789
  gst_buffer_map (buffer, &map, GST_MAP_READ);
 
790
 
 
791
  left = map.size;
 
792
 
 
793
  GST_LOG_OBJECT (h264parse,
 
794
      "processing packet buffer of size %" G_GSIZE_FORMAT, map.size);
 
795
 
 
796
  parse_res = gst_h264_parser_identify_nalu_avc (h264parse->nalparser,
 
797
      map.data, 0, map.size, nl, &nalu);
 
798
 
 
799
  while (parse_res == GST_H264_PARSER_OK) {
 
800
    GST_DEBUG_OBJECT (h264parse, "AVC nal offset %d", nalu.offset + nalu.size);
 
801
 
 
802
    /* either way, have a look at it */
 
803
    gst_h264_parse_process_nal (h264parse, &nalu);
 
804
 
 
805
    /* dispatch per NALU if needed */
 
806
    if (h264parse->split_packetized) {
 
807
      GstBaseParseFrame tmp_frame;
 
808
 
 
809
      gst_base_parse_frame_init (&tmp_frame);
 
810
      tmp_frame.flags |= frame->flags;
 
811
      tmp_frame.offset = frame->offset;
 
812
      tmp_frame.overhead = frame->overhead;
 
813
      tmp_frame.buffer = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL,
 
814
          nalu.offset, nalu.size);
 
815
 
 
816
      /* note we don't need to come up with a sub-buffer, since
 
817
       * subsequent code only considers input buffer's metadata.
 
818
       * Real data is either taken from input by baseclass or
 
819
       * a replacement output buffer is provided anyway. */
 
820
      gst_h264_parse_parse_frame (parse, &tmp_frame);
 
821
      ret = gst_base_parse_finish_frame (parse, &tmp_frame, nl + nalu.size);
 
822
      left -= nl + nalu.size;
 
823
    }
 
824
 
 
825
    parse_res = gst_h264_parser_identify_nalu_avc (h264parse->nalparser,
 
826
        map.data, nalu.offset + nalu.size, map.size, nl, &nalu);
 
827
  }
 
828
 
 
829
  gst_buffer_unmap (buffer, &map);
 
830
 
 
831
  if (!h264parse->split_packetized) {
 
832
    gst_h264_parse_parse_frame (parse, frame);
 
833
    ret = gst_base_parse_finish_frame (parse, frame, map.size);
 
834
  } else {
 
835
    gst_buffer_unref (buffer);
 
836
    if (G_UNLIKELY (left)) {
 
837
      /* should not be happening for nice AVC */
 
838
      GST_WARNING_OBJECT (parse, "skipping leftover AVC data %d", left);
 
839
      frame->flags |= GST_BASE_PARSE_FRAME_FLAG_DROP;
 
840
      ret = gst_base_parse_finish_frame (parse, frame, map.size);
 
841
    }
 
842
  }
 
843
 
 
844
  if (parse_res == GST_H264_PARSER_NO_NAL_END ||
 
845
      parse_res == GST_H264_PARSER_BROKEN_DATA) {
 
846
 
 
847
    if (h264parse->split_packetized) {
 
848
      GST_ELEMENT_ERROR (h264parse, STREAM, FAILED, (NULL),
 
849
          ("invalid AVC input data"));
 
850
      gst_buffer_unref (buffer);
 
851
 
 
852
      return GST_FLOW_ERROR;
 
853
    } else {
 
854
      /* do not meddle to much in this case */
 
855
      GST_DEBUG_OBJECT (h264parse, "parsing packet failed");
 
856
    }
 
857
  }
 
858
 
 
859
  return ret;
 
860
}
 
861
 
 
862
static GstFlowReturn
 
863
gst_h264_parse_handle_frame (GstBaseParse * parse,
 
864
    GstBaseParseFrame * frame, gint * skipsize)
 
865
{
 
866
  GstH264Parse *h264parse = GST_H264_PARSE (parse);
 
867
  GstBuffer *buffer = frame->buffer;
 
868
  GstMapInfo map;
 
869
  guint8 *data;
 
870
  gsize size;
 
871
  gint current_off = 0;
 
872
  gboolean drain, nonext;
 
873
  GstH264NalParser *nalparser = h264parse->nalparser;
 
874
  GstH264NalUnit nalu;
 
875
  GstH264ParserResult pres;
 
876
  gint framesize;
 
877
 
 
878
  if (G_UNLIKELY (GST_BUFFER_FLAG_IS_SET (frame->buffer,
 
879
              GST_BUFFER_FLAG_DISCONT))) {
 
880
    h264parse->discont = TRUE;
 
881
  }
 
882
 
 
883
  /* delegate in packetized case, no skipping should be needed */
 
884
  if (h264parse->packetized)
 
885
    return gst_h264_parse_handle_frame_packetized (parse, frame);
 
886
 
 
887
  gst_buffer_map (buffer, &map, GST_MAP_READ);
 
888
  data = map.data;
 
889
  size = map.size;
 
890
 
 
891
  /* expect at least 3 bytes startcode == sc, and 2 bytes NALU payload */
 
892
  if (G_UNLIKELY (size < 5)) {
 
893
    gst_buffer_unmap (buffer, &map);
 
894
    *skipsize = 1;
 
895
    return GST_FLOW_OK;
 
896
  }
 
897
 
 
898
  /* need to configure aggregation */
 
899
  if (G_UNLIKELY (h264parse->format == GST_H264_PARSE_FORMAT_NONE))
 
900
    gst_h264_parse_negotiate (h264parse, GST_H264_PARSE_FORMAT_BYTE, NULL);
 
901
 
 
902
  /* avoid stale cached parsing state */
 
903
  if (frame->flags & GST_BASE_PARSE_FRAME_FLAG_NEW_FRAME) {
 
904
    GST_LOG_OBJECT (h264parse, "parsing new frame");
 
905
    gst_h264_parse_reset_frame (h264parse);
 
906
  } else {
 
907
    GST_LOG_OBJECT (h264parse, "resuming frame parsing");
 
908
  }
 
909
 
 
910
  drain = GST_BASE_PARSE_DRAINING (parse);
 
911
  nonext = FALSE;
 
912
 
 
913
  current_off = h264parse->current_off;
 
914
  if (current_off < 0)
 
915
    current_off = 0;
 
916
  g_assert (current_off < size);
 
917
  GST_DEBUG_OBJECT (h264parse, "last parse position %d", current_off);
 
918
 
 
919
  /* check for initial skip */
 
920
  if (h264parse->current_off == -1) {
 
921
    pres =
 
922
        gst_h264_parser_identify_nalu_unchecked (nalparser, data, current_off,
 
923
        size, &nalu);
 
924
    switch (pres) {
 
925
      case GST_H264_PARSER_OK:
 
926
        if (nalu.sc_offset > 0) {
 
927
          *skipsize = nalu.sc_offset;
 
928
          goto skip;
 
929
        }
 
930
        break;
 
931
      case GST_H264_PARSER_NO_NAL:
 
932
        *skipsize = size - 3;
 
933
        goto skip;
 
934
        break;
 
935
      default:
 
936
        g_assert_not_reached ();
 
937
        break;
 
938
    }
 
939
  }
 
940
 
 
941
  while (TRUE) {
 
942
    pres =
 
943
        gst_h264_parser_identify_nalu (nalparser, data, current_off, size,
 
944
        &nalu);
 
945
 
 
946
    switch (pres) {
 
947
      case GST_H264_PARSER_OK:
 
948
        GST_DEBUG_OBJECT (h264parse, "complete nal (offset, size): (%u, %u) ",
 
949
            nalu.offset, nalu.size);
 
950
        break;
 
951
      case GST_H264_PARSER_NO_NAL_END:
 
952
        GST_DEBUG_OBJECT (h264parse, "not a complete nal found at offset %u",
 
953
            nalu.offset);
 
954
        /* if draining, accept it as complete nal */
 
955
        if (drain) {
 
956
          nonext = TRUE;
 
957
          nalu.size = size - nalu.offset;
 
958
          GST_DEBUG_OBJECT (h264parse, "draining, accepting with size %u",
 
959
              nalu.size);
 
960
          /* if it's not too short at least */
 
961
          if (nalu.size < 2)
 
962
            goto broken;
 
963
          break;
 
964
        }
 
965
        /* otherwise need more */
 
966
        goto more;
 
967
      case GST_H264_PARSER_BROKEN_LINK:
 
968
        GST_ELEMENT_ERROR (h264parse, STREAM, FORMAT,
 
969
            ("Error parsing H.264 stream"),
 
970
            ("The link to structure needed for the parsing couldn't be found"));
 
971
        goto invalid_stream;
 
972
      case GST_H264_PARSER_ERROR:
 
973
        /* should not really occur either */
 
974
        GST_ELEMENT_ERROR (h264parse, STREAM, FORMAT,
 
975
            ("Error parsing H.264 stream"), ("Invalid H.264 stream"));
 
976
        goto invalid_stream;
 
977
      case GST_H264_PARSER_NO_NAL:
 
978
        GST_ELEMENT_ERROR (h264parse, STREAM, FORMAT,
 
979
            ("Error parsing H.264 stream"), ("No H.264 NAL unit found"));
 
980
        goto invalid_stream;
 
981
      case GST_H264_PARSER_BROKEN_DATA:
 
982
        GST_WARNING_OBJECT (h264parse, "input stream is corrupt; "
 
983
            "it contains a NAL unit of length %u", nalu.size);
 
984
      broken:
 
985
        /* broken nal at start -> arrange to skip it,
 
986
         * otherwise have it terminate current au
 
987
         * (and so it will be skipped on next frame round) */
 
988
        if (current_off == 0) {
 
989
          GST_DEBUG_OBJECT (h264parse, "skipping broken nal");
 
990
          *skipsize = nalu.offset;
 
991
          goto skip;
 
992
        } else {
 
993
          GST_DEBUG_OBJECT (h264parse, "terminating au");
 
994
          nalu.size = 0;
 
995
          nalu.offset = nalu.sc_offset;
 
996
          goto end;
 
997
        }
 
998
        break;
 
999
      default:
 
1000
        g_assert_not_reached ();
 
1001
        break;
 
1002
    }
 
1003
 
 
1004
    GST_DEBUG_OBJECT (h264parse, "%p complete nal found. Off: %u, Size: %u",
 
1005
        data, nalu.offset, nalu.size);
 
1006
 
 
1007
    /* simulate no next nal if none needed */
 
1008
    nonext = nonext || (h264parse->align == GST_H264_PARSE_ALIGN_NAL);
 
1009
 
 
1010
    if (!nonext) {
 
1011
      if (nalu.offset + nalu.size + 4 + 2 > size) {
 
1012
        GST_DEBUG_OBJECT (h264parse, "not enough data for next NALU");
 
1013
        if (drain) {
 
1014
          GST_DEBUG_OBJECT (h264parse, "but draining anyway");
 
1015
          nonext = TRUE;
 
1016
        } else {
 
1017
          goto more;
 
1018
        }
 
1019
      }
 
1020
    }
 
1021
 
 
1022
    if (!gst_h264_parse_process_nal (h264parse, &nalu)) {
 
1023
      GST_WARNING_OBJECT (h264parse,
 
1024
          "broken/invalid nal Type: %d %s, Size: %u will be dropped",
 
1025
          nalu.type, _nal_name (nalu.type), nalu.size);
 
1026
      *skipsize = nalu.size;
 
1027
      goto skip;
 
1028
    }
 
1029
 
 
1030
    if (nonext)
 
1031
      break;
 
1032
 
 
1033
    /* if no next nal, we know it's complete here */
 
1034
    if (gst_h264_parse_collect_nal (h264parse, data, size, &nalu))
 
1035
      break;
 
1036
 
 
1037
    GST_DEBUG_OBJECT (h264parse, "Looking for more");
 
1038
    current_off = nalu.offset + nalu.size;
 
1039
  }
 
1040
 
 
1041
end:
 
1042
  framesize = nalu.offset + nalu.size;
 
1043
 
 
1044
  gst_buffer_unmap (buffer, &map);
 
1045
 
 
1046
  gst_h264_parse_parse_frame (parse, frame);
 
1047
 
 
1048
  return gst_base_parse_finish_frame (parse, frame, framesize);
 
1049
 
 
1050
more:
 
1051
  *skipsize = 0;
 
1052
 
 
1053
  /* Restart parsing from here next time */
 
1054
  if (current_off > 0)
 
1055
    h264parse->current_off = current_off;
 
1056
 
 
1057
  /* Fall-through. */
 
1058
out:
 
1059
  gst_buffer_unmap (buffer, &map);
 
1060
  return GST_FLOW_OK;
 
1061
 
 
1062
skip:
 
1063
  GST_DEBUG_OBJECT (h264parse, "skipping %d", *skipsize);
 
1064
  /* If we are collecting access units, we need to preserve the initial
 
1065
   * config headers (SPS, PPS et al.) and only reset the frame if another
 
1066
   * slice NAL was received. This means that broken pictures are discarded */
 
1067
  if (h264parse->align != GST_H264_PARSE_ALIGN_AU ||
 
1068
      !(h264parse->state & GST_H264_PARSE_STATE_VALID_PICTURE_HEADERS) ||
 
1069
      (h264parse->state & GST_H264_PARSE_STATE_GOT_SLICE))
 
1070
    gst_h264_parse_reset_frame (h264parse);
 
1071
  goto out;
 
1072
 
 
1073
invalid_stream:
 
1074
  gst_buffer_unmap (buffer, &map);
 
1075
  return GST_FLOW_ERROR;
 
1076
}
 
1077
 
 
1078
/* byte together avc codec data based on collected pps and sps so far */
 
1079
static GstBuffer *
 
1080
gst_h264_parse_make_codec_data (GstH264Parse * h264parse)
 
1081
{
 
1082
  GstBuffer *buf, *nal;
 
1083
  gint i, sps_size = 0, pps_size = 0, num_sps = 0, num_pps = 0;
 
1084
  guint8 profile_idc = 0, profile_comp = 0, level_idc = 0;
 
1085
  gboolean found = FALSE;
 
1086
  GstMapInfo map;
 
1087
  guint8 *data;
 
1088
  gint nl;
 
1089
 
 
1090
  /* only nal payload in stored nals */
 
1091
 
 
1092
  for (i = 0; i < GST_H264_MAX_SPS_COUNT; i++) {
 
1093
    if ((nal = h264parse->sps_nals[i])) {
 
1094
      gsize size = gst_buffer_get_size (nal);
 
1095
      num_sps++;
 
1096
      /* size bytes also count */
 
1097
      sps_size += size + 2;
 
1098
      if (size >= 4) {
 
1099
        guint8 tmp[3];
 
1100
        found = TRUE;
 
1101
        gst_buffer_extract (nal, 1, tmp, 3);
 
1102
        profile_idc = tmp[0];
 
1103
        profile_comp = tmp[1];
 
1104
        level_idc = tmp[2];
 
1105
      }
 
1106
    }
 
1107
  }
 
1108
  for (i = 0; i < GST_H264_MAX_PPS_COUNT; i++) {
 
1109
    if ((nal = h264parse->pps_nals[i])) {
 
1110
      num_pps++;
 
1111
      /* size bytes also count */
 
1112
      pps_size += gst_buffer_get_size (nal) + 2;
 
1113
    }
 
1114
  }
 
1115
 
 
1116
  /* AVC3 has SPS/PPS inside the stream, not in the codec_data */
 
1117
  if (h264parse->format == GST_H264_PARSE_FORMAT_AVC3) {
 
1118
    num_sps = sps_size = 0;
 
1119
    num_pps = pps_size = 0;
 
1120
  }
 
1121
 
 
1122
  GST_DEBUG_OBJECT (h264parse,
 
1123
      "constructing codec_data: num_sps=%d, num_pps=%d", num_sps, num_pps);
 
1124
 
 
1125
  if (!found || (0 == num_pps
 
1126
          && GST_H264_PARSE_FORMAT_AVC3 != h264parse->format))
 
1127
    return NULL;
 
1128
 
 
1129
  buf = gst_buffer_new_allocate (NULL, 5 + 1 + sps_size + 1 + pps_size, NULL);
 
1130
  gst_buffer_map (buf, &map, GST_MAP_WRITE);
 
1131
  data = map.data;
 
1132
  nl = h264parse->nal_length_size;
 
1133
 
 
1134
  data[0] = 1;                  /* AVC Decoder Configuration Record ver. 1 */
 
1135
  data[1] = profile_idc;        /* profile_idc                             */
 
1136
  data[2] = profile_comp;       /* profile_compability                     */
 
1137
  data[3] = level_idc;          /* level_idc                               */
 
1138
  data[4] = 0xfc | (nl - 1);    /* nal_length_size_minus1                  */
 
1139
  data[5] = 0xe0 | num_sps;     /* number of SPSs */
 
1140
 
 
1141
  data += 6;
 
1142
  if (h264parse->format != GST_H264_PARSE_FORMAT_AVC3) {
 
1143
    for (i = 0; i < GST_H264_MAX_SPS_COUNT; i++) {
 
1144
      if ((nal = h264parse->sps_nals[i])) {
 
1145
        gsize nal_size = gst_buffer_get_size (nal);
 
1146
        GST_WRITE_UINT16_BE (data, nal_size);
 
1147
        gst_buffer_extract (nal, 0, data + 2, nal_size);
 
1148
        data += 2 + nal_size;
 
1149
      }
 
1150
    }
 
1151
  }
 
1152
 
 
1153
  data[0] = num_pps;
 
1154
  data++;
 
1155
  if (h264parse->format != GST_H264_PARSE_FORMAT_AVC3) {
 
1156
    for (i = 0; i < GST_H264_MAX_PPS_COUNT; i++) {
 
1157
      if ((nal = h264parse->pps_nals[i])) {
 
1158
        gsize nal_size = gst_buffer_get_size (nal);
 
1159
        GST_WRITE_UINT16_BE (data, nal_size);
 
1160
        gst_buffer_extract (nal, 0, data + 2, nal_size);
 
1161
        data += 2 + nal_size;
 
1162
      }
 
1163
    }
 
1164
  }
 
1165
 
 
1166
  gst_buffer_unmap (buf, &map);
 
1167
 
 
1168
  return buf;
 
1169
}
 
1170
 
 
1171
static void
 
1172
gst_h264_parse_get_par (GstH264Parse * h264parse, gint * num, gint * den)
 
1173
{
 
1174
  if (h264parse->upstream_par_n != -1 && h264parse->upstream_par_d != -1) {
 
1175
    *num = h264parse->upstream_par_n;
 
1176
    *den = h264parse->upstream_par_d;
 
1177
  } else {
 
1178
    *num = h264parse->parsed_par_n;
 
1179
    *den = h264parse->parsed_par_d;
 
1180
  }
 
1181
}
 
1182
 
 
1183
static void
 
1184
gst_h264_parse_update_src_caps (GstH264Parse * h264parse, GstCaps * caps)
 
1185
{
 
1186
  GstH264SPS *sps;
 
1187
  GstCaps *sink_caps, *src_caps;
 
1188
  gboolean modified = FALSE;
 
1189
  GstBuffer *buf = NULL;
 
1190
  GstStructure *s = NULL;
 
1191
 
 
1192
  if (G_UNLIKELY (!gst_pad_has_current_caps (GST_BASE_PARSE_SRC_PAD
 
1193
              (h264parse))))
 
1194
    modified = TRUE;
 
1195
  else if (G_UNLIKELY (!h264parse->update_caps))
 
1196
    return;
 
1197
 
 
1198
  /* if this is being called from the first _setcaps call, caps on the sinkpad
 
1199
   * aren't set yet and so they need to be passed as an argument */
 
1200
  if (caps)
 
1201
    sink_caps = gst_caps_ref (caps);
 
1202
  else
 
1203
    sink_caps = gst_pad_get_current_caps (GST_BASE_PARSE_SINK_PAD (h264parse));
 
1204
 
 
1205
  /* carry over input caps as much as possible; override with our own stuff */
 
1206
  if (!sink_caps)
 
1207
    sink_caps = gst_caps_new_empty_simple ("video/x-h264");
 
1208
  else
 
1209
    s = gst_caps_get_structure (sink_caps, 0);
 
1210
 
 
1211
  sps = h264parse->nalparser->last_sps;
 
1212
  GST_DEBUG_OBJECT (h264parse, "sps: %p", sps);
 
1213
 
 
1214
  /* only codec-data for nice-and-clean au aligned packetized avc format */
 
1215
  if ((h264parse->format == GST_H264_PARSE_FORMAT_AVC
 
1216
          || h264parse->format == GST_H264_PARSE_FORMAT_AVC3)
 
1217
      && h264parse->align == GST_H264_PARSE_ALIGN_AU) {
 
1218
    buf = gst_h264_parse_make_codec_data (h264parse);
 
1219
    if (buf && h264parse->codec_data) {
 
1220
      GstMapInfo map;
 
1221
 
 
1222
      gst_buffer_map (buf, &map, GST_MAP_READ);
 
1223
      if (map.size != gst_buffer_get_size (h264parse->codec_data) ||
 
1224
          gst_buffer_memcmp (h264parse->codec_data, 0, map.data, map.size))
 
1225
        modified = TRUE;
 
1226
 
 
1227
      gst_buffer_unmap (buf, &map);
 
1228
    } else {
 
1229
      if (!buf && h264parse->codec_data_in)
 
1230
        buf = gst_buffer_ref (h264parse->codec_data_in);
 
1231
      modified = TRUE;
 
1232
    }
 
1233
  }
 
1234
 
 
1235
  caps = NULL;
 
1236
  if (G_UNLIKELY (!sps)) {
 
1237
    caps = gst_caps_copy (sink_caps);
 
1238
  } else {
 
1239
    gint crop_width, crop_height;
 
1240
    gint fps_num, fps_den;
 
1241
 
 
1242
    if (sps->frame_cropping_flag) {
 
1243
      crop_width = sps->crop_rect_width;
 
1244
      crop_height = sps->crop_rect_height;
 
1245
    } else {
 
1246
      crop_width = sps->width;
 
1247
      crop_height = sps->height;
 
1248
    }
 
1249
 
 
1250
    if (G_UNLIKELY (h264parse->width != crop_width ||
 
1251
            h264parse->height != crop_height)) {
 
1252
      GST_INFO_OBJECT (h264parse, "resolution changed %dx%d",
 
1253
          crop_width, crop_height);
 
1254
      h264parse->width = crop_width;
 
1255
      h264parse->height = crop_height;
 
1256
      modified = TRUE;
 
1257
    }
 
1258
 
 
1259
    /* 0/1 is set as the default in the codec parser, we will set
 
1260
     * it in case we have no info */
 
1261
    gst_h264_video_calculate_framerate (sps, h264parse->field_pic_flag,
 
1262
        h264parse->sei_pic_struct, &fps_num, &fps_den);
 
1263
    if (G_UNLIKELY (h264parse->fps_num != fps_num
 
1264
            || h264parse->fps_den != fps_den)) {
 
1265
      GST_DEBUG_OBJECT (h264parse, "framerate changed %d/%d", fps_num, fps_den);
 
1266
      h264parse->fps_num = fps_num;
 
1267
      h264parse->fps_den = fps_den;
 
1268
      modified = TRUE;
 
1269
    }
 
1270
 
 
1271
    if (sps->vui_parameters.aspect_ratio_info_present_flag) {
 
1272
      if (G_UNLIKELY ((h264parse->parsed_par_n != sps->vui_parameters.par_n)
 
1273
              || (h264parse->parsed_par_d != sps->vui_parameters.par_d))) {
 
1274
        h264parse->parsed_par_n = sps->vui_parameters.par_n;
 
1275
        h264parse->parsed_par_d = sps->vui_parameters.par_d;
 
1276
        GST_INFO_OBJECT (h264parse, "pixel aspect ratio has been changed %d/%d",
 
1277
            h264parse->parsed_par_n, h264parse->parsed_par_d);
 
1278
      }
 
1279
    }
 
1280
 
 
1281
    if (G_UNLIKELY (modified || h264parse->update_caps)) {
 
1282
      gint width, height;
 
1283
      GstClockTime latency;
 
1284
 
 
1285
      fps_num = h264parse->fps_num;
 
1286
      fps_den = h264parse->fps_den;
 
1287
 
 
1288
      caps = gst_caps_copy (sink_caps);
 
1289
 
 
1290
      /* sps should give this but upstream overrides */
 
1291
      if (s && gst_structure_has_field (s, "width"))
 
1292
        gst_structure_get_int (s, "width", &width);
 
1293
      else
 
1294
        width = h264parse->width;
 
1295
 
 
1296
      if (s && gst_structure_has_field (s, "height"))
 
1297
        gst_structure_get_int (s, "height", &height);
 
1298
      else
 
1299
        height = h264parse->height;
 
1300
 
 
1301
      gst_caps_set_simple (caps, "width", G_TYPE_INT, width,
 
1302
          "height", G_TYPE_INT, height, NULL);
 
1303
 
 
1304
      /* upstream overrides */
 
1305
      if (s && gst_structure_has_field (s, "framerate"))
 
1306
        gst_structure_get_fraction (s, "framerate", &fps_num, &fps_den);
 
1307
 
 
1308
      /* but not necessarily or reliably this */
 
1309
      if (fps_den > 0) {
 
1310
        gst_caps_set_simple (caps, "framerate",
 
1311
            GST_TYPE_FRACTION, fps_num, fps_den, NULL);
 
1312
        gst_base_parse_set_frame_rate (GST_BASE_PARSE (h264parse),
 
1313
            fps_num, fps_den, 0, 0);
 
1314
        if (fps_num > 0) {
 
1315
          latency = gst_util_uint64_scale (GST_SECOND, fps_den, fps_num);
 
1316
          gst_base_parse_set_latency (GST_BASE_PARSE (h264parse), latency,
 
1317
              latency);
 
1318
        }
 
1319
      }
 
1320
    }
 
1321
  }
 
1322
 
 
1323
  if (caps) {
 
1324
    gint par_n, par_d;
 
1325
 
 
1326
    gst_caps_set_simple (caps, "parsed", G_TYPE_BOOLEAN, TRUE,
 
1327
        "stream-format", G_TYPE_STRING,
 
1328
        gst_h264_parse_get_string (h264parse, TRUE, h264parse->format),
 
1329
        "alignment", G_TYPE_STRING,
 
1330
        gst_h264_parse_get_string (h264parse, FALSE, h264parse->align), NULL);
 
1331
 
 
1332
    gst_h264_parse_get_par (h264parse, &par_n, &par_d);
 
1333
    if (par_n != 0 && par_d != 0 &&
 
1334
        (!s || !gst_structure_has_field (s, "pixel-aspect-ratio"))) {
 
1335
      GST_INFO_OBJECT (h264parse, "PAR %d/%d", par_n, par_d);
 
1336
      gst_caps_set_simple (caps, "pixel-aspect-ratio", GST_TYPE_FRACTION,
 
1337
          par_n, par_d, NULL);
 
1338
    }
 
1339
 
 
1340
    src_caps = gst_pad_get_current_caps (GST_BASE_PARSE_SRC_PAD (h264parse));
 
1341
 
 
1342
    if (src_caps
 
1343
        && gst_structure_has_field (gst_caps_get_structure (src_caps, 0),
 
1344
            "codec_data")) {
 
1345
      /* use codec data from old caps for comparison; we don't want to resend caps
 
1346
         if everything is same except codec data; */
 
1347
      gst_caps_set_value (caps, "codec_data",
 
1348
          gst_structure_get_value (gst_caps_get_structure (src_caps, 0),
 
1349
              "codec_data"));
 
1350
    }
 
1351
 
 
1352
    if (!(src_caps && gst_caps_is_strictly_equal (src_caps, caps))) {
 
1353
      /* update codec data to new value */
 
1354
      if (buf) {
 
1355
        gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER, buf, NULL);
 
1356
        gst_buffer_replace (&h264parse->codec_data, buf);
 
1357
        gst_buffer_unref (buf);
 
1358
        buf = NULL;
 
1359
      } else {
 
1360
        GstStructure *s;
 
1361
        /* remove any left-over codec-data hanging around */
 
1362
        s = gst_caps_get_structure (caps, 0);
 
1363
        gst_structure_remove_field (s, "codec_data");
 
1364
        gst_buffer_replace (&h264parse->codec_data, NULL);
 
1365
      }
 
1366
 
 
1367
      gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (h264parse), caps);
 
1368
    }
 
1369
 
 
1370
    if (src_caps)
 
1371
      gst_caps_unref (src_caps);
 
1372
    gst_caps_unref (caps);
 
1373
  }
 
1374
 
 
1375
  gst_caps_unref (sink_caps);
 
1376
  if (buf)
 
1377
    gst_buffer_unref (buf);
 
1378
}
 
1379
 
 
1380
static void
 
1381
gst_h264_parse_get_timestamp (GstH264Parse * h264parse,
 
1382
    GstClockTime * out_ts, GstClockTime * out_dur, gboolean frame)
 
1383
{
 
1384
  GstH264SPS *sps = h264parse->nalparser->last_sps;
 
1385
  GstClockTime upstream;
 
1386
  gint duration = 1;
 
1387
 
 
1388
  g_return_if_fail (out_dur != NULL);
 
1389
  g_return_if_fail (out_ts != NULL);
 
1390
 
 
1391
  upstream = *out_ts;
 
1392
 
 
1393
  if (!frame) {
 
1394
    GST_LOG_OBJECT (h264parse, "no frame data ->  0 duration");
 
1395
    *out_dur = 0;
 
1396
    goto exit;
 
1397
  } else {
 
1398
    *out_ts = upstream;
 
1399
  }
 
1400
 
 
1401
  if (!sps) {
 
1402
    GST_DEBUG_OBJECT (h264parse, "referred SPS invalid");
 
1403
    goto exit;
 
1404
  } else if (!sps->vui_parameters_present_flag) {
 
1405
    GST_DEBUG_OBJECT (h264parse,
 
1406
        "unable to compute timestamp: VUI not present");
 
1407
    goto exit;
 
1408
  } else if (!sps->vui_parameters.timing_info_present_flag) {
 
1409
    GST_DEBUG_OBJECT (h264parse,
 
1410
        "unable to compute timestamp: timing info not present");
 
1411
    goto exit;
 
1412
  } else if (sps->vui_parameters.time_scale == 0) {
 
1413
    GST_DEBUG_OBJECT (h264parse,
 
1414
        "unable to compute timestamp: time_scale = 0 "
 
1415
        "(this is forbidden in spec; bitstream probably contains error)");
 
1416
    goto exit;
 
1417
  }
 
1418
 
 
1419
  if (h264parse->sei_pic_struct_pres_flag &&
 
1420
      h264parse->sei_pic_struct != (guint8) - 1) {
 
1421
    /* Note that when h264parse->sei_pic_struct == -1 (unspecified), there
 
1422
     * are ways to infer its value. This is related to computing the
 
1423
     * TopFieldOrderCnt and BottomFieldOrderCnt, which looks
 
1424
     * complicated and thus not implemented for the time being. Yet
 
1425
     * the value we have here is correct for many applications
 
1426
     */
 
1427
    switch (h264parse->sei_pic_struct) {
 
1428
      case GST_H264_SEI_PIC_STRUCT_TOP_FIELD:
 
1429
      case GST_H264_SEI_PIC_STRUCT_BOTTOM_FIELD:
 
1430
        duration = 1;
 
1431
        break;
 
1432
      case GST_H264_SEI_PIC_STRUCT_FRAME:
 
1433
      case GST_H264_SEI_PIC_STRUCT_TOP_BOTTOM:
 
1434
      case GST_H264_SEI_PIC_STRUCT_BOTTOM_TOP:
 
1435
        duration = 2;
 
1436
        break;
 
1437
      case GST_H264_SEI_PIC_STRUCT_TOP_BOTTOM_TOP:
 
1438
      case GST_H264_SEI_PIC_STRUCT_BOTTOM_TOP_BOTTOM:
 
1439
        duration = 3;
 
1440
        break;
 
1441
      case GST_H264_SEI_PIC_STRUCT_FRAME_DOUBLING:
 
1442
        duration = 4;
 
1443
        break;
 
1444
      case GST_H264_SEI_PIC_STRUCT_FRAME_TRIPLING:
 
1445
        duration = 6;
 
1446
        break;
 
1447
      default:
 
1448
        GST_DEBUG_OBJECT (h264parse,
 
1449
            "h264parse->sei_pic_struct of unknown value %d. Not parsed",
 
1450
            h264parse->sei_pic_struct);
 
1451
        break;
 
1452
    }
 
1453
  } else {
 
1454
    duration = h264parse->field_pic_flag ? 1 : 2;
 
1455
  }
 
1456
 
 
1457
  GST_LOG_OBJECT (h264parse, "frame tick duration %d", duration);
 
1458
 
 
1459
  /*
 
1460
   * h264parse.264 C.1.2 Timing of coded picture removal (equivalent to DTS):
 
1461
   * Tr,n(0) = initial_cpb_removal_delay[ SchedSelIdx ] / 90000
 
1462
   * Tr,n(n) = Tr,n(nb) + Tc * cpb_removal_delay(n)
 
1463
   * where
 
1464
   * Tc = num_units_in_tick / time_scale
 
1465
   */
 
1466
 
 
1467
  if (h264parse->ts_trn_nb != GST_CLOCK_TIME_NONE) {
 
1468
    GST_LOG_OBJECT (h264parse, "buffering based ts");
 
1469
    /* buffering period is present */
 
1470
    if (upstream != GST_CLOCK_TIME_NONE) {
 
1471
      /* If upstream timestamp is valid, we respect it and adjust current
 
1472
       * reference point */
 
1473
      h264parse->ts_trn_nb = upstream -
 
1474
          (GstClockTime) gst_util_uint64_scale_int
 
1475
          (h264parse->sei_cpb_removal_delay * GST_SECOND,
 
1476
          sps->vui_parameters.num_units_in_tick,
 
1477
          sps->vui_parameters.time_scale);
 
1478
    } else {
 
1479
      /* If no upstream timestamp is given, we write in new timestamp */
 
1480
      upstream = h264parse->dts = h264parse->ts_trn_nb +
 
1481
          (GstClockTime) gst_util_uint64_scale_int
 
1482
          (h264parse->sei_cpb_removal_delay * GST_SECOND,
 
1483
          sps->vui_parameters.num_units_in_tick,
 
1484
          sps->vui_parameters.time_scale);
 
1485
    }
 
1486
  } else {
 
1487
    GstClockTime dur;
 
1488
 
 
1489
    GST_LOG_OBJECT (h264parse, "duration based ts");
 
1490
    /* naive method: no removal delay specified
 
1491
     * track upstream timestamp and provide best guess frame duration */
 
1492
    dur = gst_util_uint64_scale_int (duration * GST_SECOND,
 
1493
        sps->vui_parameters.num_units_in_tick, sps->vui_parameters.time_scale);
 
1494
    /* sanity check */
 
1495
    if (dur < GST_MSECOND) {
 
1496
      GST_DEBUG_OBJECT (h264parse, "discarding dur %" GST_TIME_FORMAT,
 
1497
          GST_TIME_ARGS (dur));
 
1498
    } else {
 
1499
      *out_dur = dur;
 
1500
    }
 
1501
  }
 
1502
 
 
1503
exit:
 
1504
  if (GST_CLOCK_TIME_IS_VALID (upstream))
 
1505
    *out_ts = h264parse->dts = upstream;
 
1506
 
 
1507
  if (GST_CLOCK_TIME_IS_VALID (*out_dur) &&
 
1508
      GST_CLOCK_TIME_IS_VALID (h264parse->dts))
 
1509
    h264parse->dts += *out_dur;
 
1510
}
 
1511
 
 
1512
static GstFlowReturn
 
1513
gst_h264_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
 
1514
{
 
1515
  GstH264Parse *h264parse;
 
1516
  GstBuffer *buffer;
 
1517
  guint av;
 
1518
 
 
1519
  h264parse = GST_H264_PARSE (parse);
 
1520
  buffer = frame->buffer;
 
1521
 
 
1522
  gst_h264_parse_update_src_caps (h264parse, NULL);
 
1523
 
 
1524
  /* don't mess with timestamps if provided by upstream,
 
1525
   * particularly since our ts not that good they handle seeking etc */
 
1526
  if (h264parse->do_ts)
 
1527
    gst_h264_parse_get_timestamp (h264parse,
 
1528
        &GST_BUFFER_TIMESTAMP (buffer), &GST_BUFFER_DURATION (buffer),
 
1529
        h264parse->frame_start);
 
1530
 
 
1531
  if (h264parse->keyframe)
 
1532
    GST_BUFFER_FLAG_UNSET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);
 
1533
  else
 
1534
    GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);
 
1535
 
 
1536
  if (h264parse->discont) {
 
1537
    GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
 
1538
    h264parse->discont = FALSE;
 
1539
  }
 
1540
 
 
1541
  /* replace with transformed AVC output if applicable */
 
1542
  av = gst_adapter_available (h264parse->frame_out);
 
1543
  if (av) {
 
1544
    GstBuffer *buf;
 
1545
 
 
1546
    buf = gst_adapter_take_buffer (h264parse->frame_out, av);
 
1547
    gst_buffer_copy_into (buf, buffer, GST_BUFFER_COPY_METADATA, 0, -1);
 
1548
    gst_buffer_replace (&frame->out_buffer, buf);
 
1549
    gst_buffer_unref (buf);
 
1550
  }
 
1551
 
 
1552
  return GST_FLOW_OK;
 
1553
}
 
1554
 
 
1555
/* sends a codec NAL downstream, decorating and transforming as needed.
 
1556
 * No ownership is taken of @nal */
 
1557
static GstFlowReturn
 
1558
gst_h264_parse_push_codec_buffer (GstH264Parse * h264parse,
 
1559
    GstBuffer * nal, GstClockTime ts)
 
1560
{
 
1561
  GstMapInfo map;
 
1562
 
 
1563
  gst_buffer_map (nal, &map, GST_MAP_READ);
 
1564
  nal = gst_h264_parse_wrap_nal (h264parse, h264parse->format,
 
1565
      map.data, map.size);
 
1566
  gst_buffer_unmap (nal, &map);
 
1567
 
 
1568
  GST_BUFFER_TIMESTAMP (nal) = ts;
 
1569
  GST_BUFFER_DURATION (nal) = 0;
 
1570
 
 
1571
  return gst_pad_push (GST_BASE_PARSE_SRC_PAD (h264parse), nal);
 
1572
}
 
1573
 
 
1574
static GstEvent *
 
1575
check_pending_key_unit_event (GstEvent * pending_event,
 
1576
    GstSegment * segment, GstClockTime timestamp, guint flags,
 
1577
    GstClockTime pending_key_unit_ts)
 
1578
{
 
1579
  GstClockTime running_time, stream_time;
 
1580
  gboolean all_headers;
 
1581
  guint count;
 
1582
  GstEvent *event = NULL;
 
1583
 
 
1584
  g_return_val_if_fail (segment != NULL, NULL);
 
1585
 
 
1586
  if (pending_event == NULL)
 
1587
    goto out;
 
1588
 
 
1589
  if (GST_CLOCK_TIME_IS_VALID (pending_key_unit_ts) &&
 
1590
      timestamp == GST_CLOCK_TIME_NONE)
 
1591
    goto out;
 
1592
 
 
1593
  running_time = gst_segment_to_running_time (segment,
 
1594
      GST_FORMAT_TIME, timestamp);
 
1595
 
 
1596
  GST_INFO ("now %" GST_TIME_FORMAT " wanted %" GST_TIME_FORMAT,
 
1597
      GST_TIME_ARGS (running_time), GST_TIME_ARGS (pending_key_unit_ts));
 
1598
  if (GST_CLOCK_TIME_IS_VALID (pending_key_unit_ts) &&
 
1599
      running_time < pending_key_unit_ts)
 
1600
    goto out;
 
1601
 
 
1602
  if (flags & GST_BUFFER_FLAG_DELTA_UNIT) {
 
1603
    GST_DEBUG ("pending force key unit, waiting for keyframe");
 
1604
    goto out;
 
1605
  }
 
1606
 
 
1607
  stream_time = gst_segment_to_stream_time (segment,
 
1608
      GST_FORMAT_TIME, timestamp);
 
1609
 
 
1610
  gst_video_event_parse_upstream_force_key_unit (pending_event,
 
1611
      NULL, &all_headers, &count);
 
1612
 
 
1613
  event =
 
1614
      gst_video_event_new_downstream_force_key_unit (timestamp, stream_time,
 
1615
      running_time, all_headers, count);
 
1616
  gst_event_set_seqnum (event, gst_event_get_seqnum (pending_event));
 
1617
 
 
1618
out:
 
1619
  return event;
 
1620
}
 
1621
 
 
1622
static void
 
1623
gst_h264_parse_prepare_key_unit (GstH264Parse * parse, GstEvent * event)
 
1624
{
 
1625
  GstClockTime running_time;
 
1626
  guint count;
 
1627
#ifndef GST_DISABLE_GST_DEBUG
 
1628
  gboolean have_sps, have_pps;
 
1629
  gint i;
 
1630
#endif
 
1631
 
 
1632
  parse->pending_key_unit_ts = GST_CLOCK_TIME_NONE;
 
1633
  gst_event_replace (&parse->force_key_unit_event, NULL);
 
1634
 
 
1635
  gst_video_event_parse_downstream_force_key_unit (event,
 
1636
      NULL, NULL, &running_time, NULL, &count);
 
1637
 
 
1638
  GST_INFO_OBJECT (parse, "pushing downstream force-key-unit event %d "
 
1639
      "%" GST_TIME_FORMAT " count %d", gst_event_get_seqnum (event),
 
1640
      GST_TIME_ARGS (running_time), count);
 
1641
  gst_pad_push_event (GST_BASE_PARSE_SRC_PAD (parse), event);
 
1642
 
 
1643
#ifndef GST_DISABLE_GST_DEBUG
 
1644
  have_sps = have_pps = FALSE;
 
1645
  for (i = 0; i < GST_H264_MAX_SPS_COUNT; i++) {
 
1646
    if (parse->sps_nals[i] != NULL) {
 
1647
      have_sps = TRUE;
 
1648
      break;
 
1649
    }
 
1650
  }
 
1651
  for (i = 0; i < GST_H264_MAX_PPS_COUNT; i++) {
 
1652
    if (parse->pps_nals[i] != NULL) {
 
1653
      have_pps = TRUE;
 
1654
      break;
 
1655
    }
 
1656
  }
 
1657
 
 
1658
  GST_INFO_OBJECT (parse, "preparing key unit, have sps %d have pps %d",
 
1659
      have_sps, have_pps);
 
1660
#endif
 
1661
 
 
1662
  /* set push_codec to TRUE so that pre_push_frame sends SPS/PPS again */
 
1663
  parse->push_codec = TRUE;
 
1664
}
 
1665
 
 
1666
static GstFlowReturn
 
1667
gst_h264_parse_pre_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
 
1668
{
 
1669
  GstH264Parse *h264parse;
 
1670
  GstBuffer *buffer;
 
1671
  GstEvent *event;
 
1672
 
 
1673
  h264parse = GST_H264_PARSE (parse);
 
1674
 
 
1675
  if (!h264parse->sent_codec_tag) {
 
1676
    GstTagList *taglist;
 
1677
    GstCaps *caps;
 
1678
 
 
1679
    taglist = gst_tag_list_new_empty ();
 
1680
 
 
1681
    /* codec tag */
 
1682
    caps = gst_pad_get_current_caps (GST_BASE_PARSE_SRC_PAD (parse));
 
1683
    gst_pb_utils_add_codec_description_to_tag_list (taglist,
 
1684
        GST_TAG_VIDEO_CODEC, caps);
 
1685
    gst_caps_unref (caps);
 
1686
 
 
1687
    gst_pad_push_event (GST_BASE_PARSE_SRC_PAD (h264parse),
 
1688
        gst_event_new_tag (taglist));
 
1689
 
 
1690
    /* also signals the end of first-frame processing */
 
1691
    h264parse->sent_codec_tag = TRUE;
 
1692
  }
 
1693
 
 
1694
  buffer = frame->buffer;
 
1695
 
 
1696
  if ((event = check_pending_key_unit_event (h264parse->force_key_unit_event,
 
1697
              &parse->segment, GST_BUFFER_TIMESTAMP (buffer),
 
1698
              GST_BUFFER_FLAGS (buffer), h264parse->pending_key_unit_ts))) {
 
1699
    gst_h264_parse_prepare_key_unit (h264parse, event);
 
1700
  }
 
1701
 
 
1702
  /* periodic SPS/PPS sending */
 
1703
  if (h264parse->interval > 0 || h264parse->push_codec) {
 
1704
    GstClockTime timestamp = GST_BUFFER_TIMESTAMP (buffer);
 
1705
    guint64 diff;
 
1706
 
 
1707
    /* init */
 
1708
    if (!GST_CLOCK_TIME_IS_VALID (h264parse->last_report)) {
 
1709
      h264parse->last_report = timestamp;
 
1710
    }
 
1711
 
 
1712
    if (h264parse->idr_pos >= 0) {
 
1713
      GST_LOG_OBJECT (h264parse, "IDR nal at offset %d", h264parse->idr_pos);
 
1714
 
 
1715
      if (timestamp > h264parse->last_report)
 
1716
        diff = timestamp - h264parse->last_report;
 
1717
      else
 
1718
        diff = 0;
 
1719
 
 
1720
      GST_LOG_OBJECT (h264parse,
 
1721
          "now %" GST_TIME_FORMAT ", last SPS/PPS %" GST_TIME_FORMAT,
 
1722
          GST_TIME_ARGS (timestamp), GST_TIME_ARGS (h264parse->last_report));
 
1723
 
 
1724
      GST_DEBUG_OBJECT (h264parse,
 
1725
          "interval since last SPS/PPS %" GST_TIME_FORMAT,
 
1726
          GST_TIME_ARGS (diff));
 
1727
 
 
1728
      if (GST_TIME_AS_SECONDS (diff) >= h264parse->interval ||
 
1729
          h264parse->push_codec) {
 
1730
        GstBuffer *codec_nal;
 
1731
        gint i;
 
1732
        GstClockTime new_ts;
 
1733
 
 
1734
        /* avoid overwriting a perfectly fine timestamp */
 
1735
        new_ts = GST_CLOCK_TIME_IS_VALID (timestamp) ? timestamp :
 
1736
            h264parse->last_report;
 
1737
 
 
1738
        if (h264parse->align == GST_H264_PARSE_ALIGN_NAL) {
 
1739
          /* send separate config NAL buffers */
 
1740
          GST_DEBUG_OBJECT (h264parse, "- sending SPS/PPS");
 
1741
          for (i = 0; i < GST_H264_MAX_SPS_COUNT; i++) {
 
1742
            if ((codec_nal = h264parse->sps_nals[i])) {
 
1743
              GST_DEBUG_OBJECT (h264parse, "sending SPS nal");
 
1744
              gst_h264_parse_push_codec_buffer (h264parse, codec_nal,
 
1745
                  timestamp);
 
1746
              h264parse->last_report = new_ts;
 
1747
            }
 
1748
          }
 
1749
          for (i = 0; i < GST_H264_MAX_PPS_COUNT; i++) {
 
1750
            if ((codec_nal = h264parse->pps_nals[i])) {
 
1751
              GST_DEBUG_OBJECT (h264parse, "sending PPS nal");
 
1752
              gst_h264_parse_push_codec_buffer (h264parse, codec_nal,
 
1753
                  timestamp);
 
1754
              h264parse->last_report = new_ts;
 
1755
            }
 
1756
          }
 
1757
        } else {
 
1758
          /* insert config NALs into AU */
 
1759
          GstByteWriter bw;
 
1760
          GstBuffer *new_buf;
 
1761
          const gboolean bs = h264parse->format == GST_H264_PARSE_FORMAT_BYTE;
 
1762
          const gint nls = 4 - h264parse->nal_length_size;
 
1763
          gboolean ok;
 
1764
 
 
1765
          gst_byte_writer_init_with_size (&bw, gst_buffer_get_size (buffer),
 
1766
              FALSE);
 
1767
          ok = gst_byte_writer_put_buffer (&bw, buffer, 0, h264parse->idr_pos);
 
1768
          GST_DEBUG_OBJECT (h264parse, "- inserting SPS/PPS");
 
1769
          for (i = 0; i < GST_H264_MAX_SPS_COUNT; i++) {
 
1770
            if ((codec_nal = h264parse->sps_nals[i])) {
 
1771
              gsize nal_size = gst_buffer_get_size (codec_nal);
 
1772
              GST_DEBUG_OBJECT (h264parse, "inserting SPS nal");
 
1773
              if (bs) {
 
1774
                ok &= gst_byte_writer_put_uint32_be (&bw, 1);
 
1775
              } else {
 
1776
                ok &= gst_byte_writer_put_uint32_be (&bw,
 
1777
                    (nal_size << (nls * 8)));
 
1778
                ok &= gst_byte_writer_set_pos (&bw,
 
1779
                    gst_byte_writer_get_pos (&bw) - nls);
 
1780
              }
 
1781
 
 
1782
              ok &= gst_byte_writer_put_buffer (&bw, codec_nal, 0, nal_size);
 
1783
              h264parse->last_report = new_ts;
 
1784
            }
 
1785
          }
 
1786
          for (i = 0; i < GST_H264_MAX_PPS_COUNT; i++) {
 
1787
            if ((codec_nal = h264parse->pps_nals[i])) {
 
1788
              gsize nal_size = gst_buffer_get_size (codec_nal);
 
1789
              GST_DEBUG_OBJECT (h264parse, "inserting PPS nal");
 
1790
              if (bs) {
 
1791
                ok &= gst_byte_writer_put_uint32_be (&bw, 1);
 
1792
              } else {
 
1793
                ok &= gst_byte_writer_put_uint32_be (&bw,
 
1794
                    (nal_size << (nls * 8)));
 
1795
                ok &= gst_byte_writer_set_pos (&bw,
 
1796
                    gst_byte_writer_get_pos (&bw) - nls);
 
1797
              }
 
1798
              ok &= gst_byte_writer_put_buffer (&bw, codec_nal, 0, nal_size);
 
1799
              h264parse->last_report = new_ts;
 
1800
            }
 
1801
          }
 
1802
          ok &=
 
1803
              gst_byte_writer_put_buffer (&bw, buffer, h264parse->idr_pos, -1);
 
1804
          /* collect result and push */
 
1805
          new_buf = gst_byte_writer_reset_and_get_buffer (&bw);
 
1806
          gst_buffer_copy_into (new_buf, buffer, GST_BUFFER_COPY_METADATA, 0,
 
1807
              -1);
 
1808
          /* should already be keyframe/IDR, but it may not have been,
 
1809
           * so mark it as such to avoid being discarded by picky decoder */
 
1810
          GST_BUFFER_FLAG_UNSET (new_buf, GST_BUFFER_FLAG_DELTA_UNIT);
 
1811
          gst_buffer_replace (&frame->out_buffer, new_buf);
 
1812
          gst_buffer_unref (new_buf);
 
1813
          /* some result checking seems to make some compilers happy */
 
1814
          if (G_UNLIKELY (!ok)) {
 
1815
            GST_ERROR_OBJECT (h264parse, "failed to insert SPS/PPS");
 
1816
          }
 
1817
        }
 
1818
      }
 
1819
      /* we pushed whatever we had */
 
1820
      h264parse->push_codec = FALSE;
 
1821
      h264parse->have_sps = FALSE;
 
1822
      h264parse->have_pps = FALSE;
 
1823
      h264parse->state &= GST_H264_PARSE_STATE_VALID_PICTURE_HEADERS;
 
1824
    }
 
1825
  }
 
1826
 
 
1827
  gst_h264_parse_reset_frame (h264parse);
 
1828
 
 
1829
  return GST_FLOW_OK;
 
1830
}
 
1831
 
 
1832
static gboolean
 
1833
gst_h264_parse_set_caps (GstBaseParse * parse, GstCaps * caps)
 
1834
{
 
1835
  GstH264Parse *h264parse;
 
1836
  GstStructure *str;
 
1837
  const GValue *value;
 
1838
  GstBuffer *codec_data = NULL;
 
1839
  gsize size;
 
1840
  guint format, align, off;
 
1841
  GstH264NalUnit nalu;
 
1842
  GstH264ParserResult parseres;
 
1843
 
 
1844
  h264parse = GST_H264_PARSE (parse);
 
1845
 
 
1846
  /* reset */
 
1847
  h264parse->push_codec = FALSE;
 
1848
 
 
1849
  str = gst_caps_get_structure (caps, 0);
 
1850
 
 
1851
  /* accept upstream info if provided */
 
1852
  gst_structure_get_int (str, "width", &h264parse->width);
 
1853
  gst_structure_get_int (str, "height", &h264parse->height);
 
1854
  gst_structure_get_fraction (str, "framerate", &h264parse->fps_num,
 
1855
      &h264parse->fps_den);
 
1856
  gst_structure_get_fraction (str, "pixel-aspect-ratio",
 
1857
      &h264parse->upstream_par_n, &h264parse->upstream_par_d);
 
1858
 
 
1859
  /* get upstream format and align from caps */
 
1860
  gst_h264_parse_format_from_caps (caps, &format, &align);
 
1861
 
 
1862
  /* packetized video has a codec_data */
 
1863
  if (format != GST_H264_PARSE_FORMAT_BYTE &&
 
1864
      (value = gst_structure_get_value (str, "codec_data"))) {
 
1865
    GstMapInfo map;
 
1866
    guint8 *data;
 
1867
    guint num_sps, num_pps;
 
1868
#ifndef GST_DISABLE_GST_DEBUG
 
1869
    guint profile;
 
1870
#endif
 
1871
    gint i;
 
1872
 
 
1873
    GST_DEBUG_OBJECT (h264parse, "have packetized h264");
 
1874
    /* make note for optional split processing */
 
1875
    h264parse->packetized = TRUE;
 
1876
 
 
1877
    codec_data = gst_value_get_buffer (value);
 
1878
    if (!codec_data)
 
1879
      goto wrong_type;
 
1880
    gst_buffer_map (codec_data, &map, GST_MAP_READ);
 
1881
    data = map.data;
 
1882
    size = map.size;
 
1883
 
 
1884
    /* parse the avcC data */
 
1885
    if (size < 7) {             /* when numSPS==0 and numPPS==0, length is 7 bytes */
 
1886
      gst_buffer_unmap (codec_data, &map);
 
1887
      goto avcc_too_small;
 
1888
    }
 
1889
    /* parse the version, this must be 1 */
 
1890
    if (data[0] != 1) {
 
1891
      gst_buffer_unmap (codec_data, &map);
 
1892
      goto wrong_version;
 
1893
    }
 
1894
#ifndef GST_DISABLE_GST_DEBUG
 
1895
    /* AVCProfileIndication */
 
1896
    /* profile_compat */
 
1897
    /* AVCLevelIndication */
 
1898
    profile = (data[1] << 16) | (data[2] << 8) | data[3];
 
1899
    GST_DEBUG_OBJECT (h264parse, "profile %06x", profile);
 
1900
#endif
 
1901
 
 
1902
    /* 6 bits reserved | 2 bits lengthSizeMinusOne */
 
1903
    /* this is the number of bytes in front of the NAL units to mark their
 
1904
     * length */
 
1905
    h264parse->nal_length_size = (data[4] & 0x03) + 1;
 
1906
    GST_DEBUG_OBJECT (h264parse, "nal length size %u",
 
1907
        h264parse->nal_length_size);
 
1908
 
 
1909
    num_sps = data[5] & 0x1f;
 
1910
    off = 6;
 
1911
    for (i = 0; i < num_sps; i++) {
 
1912
      parseres = gst_h264_parser_identify_nalu_avc (h264parse->nalparser,
 
1913
          data, off, size, 2, &nalu);
 
1914
      if (parseres != GST_H264_PARSER_OK) {
 
1915
        gst_buffer_unmap (codec_data, &map);
 
1916
        goto avcc_too_small;
 
1917
      }
 
1918
 
 
1919
      gst_h264_parse_process_nal (h264parse, &nalu);
 
1920
      off = nalu.offset + nalu.size;
 
1921
    }
 
1922
 
 
1923
    num_pps = data[off];
 
1924
    off++;
 
1925
 
 
1926
    for (i = 0; i < num_pps; i++) {
 
1927
      parseres = gst_h264_parser_identify_nalu_avc (h264parse->nalparser,
 
1928
          data, off, size, 2, &nalu);
 
1929
      if (parseres != GST_H264_PARSER_OK) {
 
1930
        gst_buffer_unmap (codec_data, &map);
 
1931
        goto avcc_too_small;
 
1932
      }
 
1933
 
 
1934
      gst_h264_parse_process_nal (h264parse, &nalu);
 
1935
      off = nalu.offset + nalu.size;
 
1936
    }
 
1937
 
 
1938
    gst_buffer_unmap (codec_data, &map);
 
1939
 
 
1940
    gst_buffer_replace (&h264parse->codec_data_in, codec_data);
 
1941
 
 
1942
    /* if upstream sets codec_data without setting stream-format and alignment, we
 
1943
     * assume stream-format=avc,alignment=au */
 
1944
    if (format == GST_H264_PARSE_FORMAT_NONE)
 
1945
      format = GST_H264_PARSE_FORMAT_AVC;
 
1946
    if (align == GST_H264_PARSE_ALIGN_NONE)
 
1947
      align = GST_H264_PARSE_ALIGN_AU;
 
1948
  } else {
 
1949
    GST_DEBUG_OBJECT (h264parse, "have bytestream h264");
 
1950
    /* nothing to pre-process */
 
1951
    h264parse->packetized = FALSE;
 
1952
    /* we have 4 sync bytes */
 
1953
    h264parse->nal_length_size = 4;
 
1954
 
 
1955
    if (format == GST_H264_PARSE_FORMAT_NONE) {
 
1956
      format = GST_H264_PARSE_FORMAT_BYTE;
 
1957
      align = GST_H264_PARSE_ALIGN_AU;
 
1958
    }
 
1959
  }
 
1960
 
 
1961
  {
 
1962
    GstCaps *in_caps;
 
1963
 
 
1964
    /* prefer input type determined above */
 
1965
    in_caps = gst_caps_new_simple ("video/x-h264",
 
1966
        "parsed", G_TYPE_BOOLEAN, TRUE,
 
1967
        "stream-format", G_TYPE_STRING,
 
1968
        gst_h264_parse_get_string (h264parse, TRUE, format),
 
1969
        "alignment", G_TYPE_STRING,
 
1970
        gst_h264_parse_get_string (h264parse, FALSE, align), NULL);
 
1971
    /* negotiate with downstream, sets ->format and ->align */
 
1972
    gst_h264_parse_negotiate (h264parse, format, in_caps);
 
1973
    gst_caps_unref (in_caps);
 
1974
  }
 
1975
 
 
1976
  if (format == h264parse->format && align == h264parse->align) {
 
1977
    /* do not set CAPS and passthrough mode if SPS/PPS have not been parsed */
 
1978
    if (h264parse->have_sps && h264parse->have_pps) {
 
1979
      gst_base_parse_set_passthrough (parse, TRUE);
 
1980
 
 
1981
      /* we did parse codec-data and might supplement src caps */
 
1982
      gst_h264_parse_update_src_caps (h264parse, caps);
 
1983
    }
 
1984
  } else if (format == GST_H264_PARSE_FORMAT_AVC
 
1985
      || format == GST_H264_PARSE_FORMAT_AVC3) {
 
1986
    /* if input != output, and input is avc, must split before anything else */
 
1987
    /* arrange to insert codec-data in-stream if needed.
 
1988
     * src caps are only arranged for later on */
 
1989
    h264parse->push_codec = TRUE;
 
1990
    h264parse->have_sps = FALSE;
 
1991
    h264parse->have_pps = FALSE;
 
1992
    if (h264parse->align == GST_H264_PARSE_ALIGN_NAL)
 
1993
      h264parse->split_packetized = TRUE;
 
1994
    h264parse->packetized = TRUE;
 
1995
  }
 
1996
 
 
1997
  return TRUE;
 
1998
 
 
1999
  /* ERRORS */
 
2000
avcc_too_small:
 
2001
  {
 
2002
    GST_DEBUG_OBJECT (h264parse, "avcC size %" G_GSIZE_FORMAT " < 8", size);
 
2003
    goto refuse_caps;
 
2004
  }
 
2005
wrong_version:
 
2006
  {
 
2007
    GST_DEBUG_OBJECT (h264parse, "wrong avcC version");
 
2008
    goto refuse_caps;
 
2009
  }
 
2010
wrong_type:
 
2011
  {
 
2012
    GST_DEBUG_OBJECT (h264parse, "wrong codec-data type");
 
2013
    goto refuse_caps;
 
2014
  }
 
2015
refuse_caps:
 
2016
  {
 
2017
    GST_WARNING_OBJECT (h264parse, "refused caps %" GST_PTR_FORMAT, caps);
 
2018
    return FALSE;
 
2019
  }
 
2020
}
 
2021
 
 
2022
static void
 
2023
remove_fields (GstCaps * caps)
 
2024
{
 
2025
  guint i, n;
 
2026
 
 
2027
  n = gst_caps_get_size (caps);
 
2028
  for (i = 0; i < n; i++) {
 
2029
    GstStructure *s = gst_caps_get_structure (caps, i);
 
2030
 
 
2031
    gst_structure_remove_field (s, "alignment");
 
2032
    gst_structure_remove_field (s, "stream-format");
 
2033
    gst_structure_remove_field (s, "parsed");
 
2034
  }
 
2035
}
 
2036
 
 
2037
static GstCaps *
 
2038
gst_h264_parse_get_caps (GstBaseParse * parse, GstCaps * filter)
 
2039
{
 
2040
  GstCaps *peercaps, *templ;
 
2041
  GstCaps *res;
 
2042
 
 
2043
  templ = gst_pad_get_pad_template_caps (GST_BASE_PARSE_SINK_PAD (parse));
 
2044
  if (filter) {
 
2045
    GstCaps *fcopy = gst_caps_copy (filter);
 
2046
    /* Remove the fields we convert */
 
2047
    remove_fields (fcopy);
 
2048
    peercaps = gst_pad_peer_query_caps (GST_BASE_PARSE_SRC_PAD (parse), fcopy);
 
2049
    gst_caps_unref (fcopy);
 
2050
  } else
 
2051
    peercaps = gst_pad_peer_query_caps (GST_BASE_PARSE_SRC_PAD (parse), NULL);
 
2052
 
 
2053
  if (peercaps) {
 
2054
    peercaps = gst_caps_make_writable (peercaps);
 
2055
    remove_fields (peercaps);
 
2056
 
 
2057
    res = gst_caps_intersect_full (peercaps, templ, GST_CAPS_INTERSECT_FIRST);
 
2058
    gst_caps_unref (peercaps);
 
2059
    gst_caps_unref (templ);
 
2060
  } else {
 
2061
    res = templ;
 
2062
  }
 
2063
 
 
2064
  if (filter) {
 
2065
    GstCaps *tmp = gst_caps_intersect_full (res, filter,
 
2066
        GST_CAPS_INTERSECT_FIRST);
 
2067
    gst_caps_unref (res);
 
2068
    res = tmp;
 
2069
  }
 
2070
 
 
2071
  return res;
 
2072
}
 
2073
 
 
2074
static gboolean
 
2075
gst_h264_parse_event (GstBaseParse * parse, GstEvent * event)
 
2076
{
 
2077
  gboolean res;
 
2078
  GstH264Parse *h264parse = GST_H264_PARSE (parse);
 
2079
 
 
2080
  switch (GST_EVENT_TYPE (event)) {
 
2081
    case GST_EVENT_CUSTOM_DOWNSTREAM:
 
2082
    {
 
2083
      GstClockTime timestamp, stream_time, running_time;
 
2084
      gboolean all_headers;
 
2085
      guint count;
 
2086
 
 
2087
      if (gst_video_event_is_force_key_unit (event)) {
 
2088
        gst_video_event_parse_downstream_force_key_unit (event,
 
2089
            &timestamp, &stream_time, &running_time, &all_headers, &count);
 
2090
 
 
2091
        GST_INFO_OBJECT (h264parse,
 
2092
            "received downstream force key unit event, "
 
2093
            "seqnum %d running_time %" GST_TIME_FORMAT
 
2094
            " all_headers %d count %d", gst_event_get_seqnum (event),
 
2095
            GST_TIME_ARGS (running_time), all_headers, count);
 
2096
        if (h264parse->force_key_unit_event) {
 
2097
          GST_INFO_OBJECT (h264parse, "ignoring force key unit event "
 
2098
              "as one is already queued");
 
2099
        } else {
 
2100
          h264parse->pending_key_unit_ts = running_time;
 
2101
          gst_event_replace (&h264parse->force_key_unit_event, event);
 
2102
        }
 
2103
        gst_event_unref (event);
 
2104
        res = TRUE;
 
2105
      } else {
 
2106
        res = GST_BASE_PARSE_CLASS (parent_class)->sink_event (parse, event);
 
2107
        break;
 
2108
      }
 
2109
      break;
 
2110
    }
 
2111
    case GST_EVENT_FLUSH_STOP:
 
2112
      h264parse->dts = GST_CLOCK_TIME_NONE;
 
2113
      h264parse->ts_trn_nb = GST_CLOCK_TIME_NONE;
 
2114
 
 
2115
      res = GST_BASE_PARSE_CLASS (parent_class)->sink_event (parse, event);
 
2116
      break;
 
2117
    case GST_EVENT_SEGMENT:
 
2118
    {
 
2119
      const GstSegment *segment;
 
2120
 
 
2121
      gst_event_parse_segment (event, &segment);
 
2122
      /* don't try to mess with more subtle cases (e.g. seek) */
 
2123
      if (segment->format == GST_FORMAT_TIME &&
 
2124
          (segment->start != 0 || segment->rate != 1.0
 
2125
              || segment->applied_rate != 1.0))
 
2126
        h264parse->do_ts = FALSE;
 
2127
 
 
2128
      res = GST_BASE_PARSE_CLASS (parent_class)->sink_event (parse, event);
 
2129
      break;
 
2130
    }
 
2131
    default:
 
2132
      res = GST_BASE_PARSE_CLASS (parent_class)->sink_event (parse, event);
 
2133
      break;
 
2134
  }
 
2135
  return res;
 
2136
}
 
2137
 
 
2138
static gboolean
 
2139
gst_h264_parse_src_event (GstBaseParse * parse, GstEvent * event)
 
2140
{
 
2141
  gboolean res;
 
2142
  GstH264Parse *h264parse = GST_H264_PARSE (parse);
 
2143
 
 
2144
  switch (GST_EVENT_TYPE (event)) {
 
2145
    case GST_EVENT_CUSTOM_UPSTREAM:
 
2146
    {
 
2147
      GstClockTime running_time;
 
2148
      gboolean all_headers;
 
2149
      guint count;
 
2150
 
 
2151
      if (gst_video_event_is_force_key_unit (event)) {
 
2152
        gst_video_event_parse_upstream_force_key_unit (event,
 
2153
            &running_time, &all_headers, &count);
 
2154
 
 
2155
        GST_INFO_OBJECT (h264parse, "received upstream force-key-unit event, "
 
2156
            "seqnum %d running_time %" GST_TIME_FORMAT
 
2157
            " all_headers %d count %d", gst_event_get_seqnum (event),
 
2158
            GST_TIME_ARGS (running_time), all_headers, count);
 
2159
 
 
2160
        if (all_headers) {
 
2161
          h264parse->pending_key_unit_ts = running_time;
 
2162
          gst_event_replace (&h264parse->force_key_unit_event, event);
 
2163
        }
 
2164
      }
 
2165
      res = GST_BASE_PARSE_CLASS (parent_class)->src_event (parse, event);
 
2166
      break;
 
2167
    }
 
2168
    default:
 
2169
      res = GST_BASE_PARSE_CLASS (parent_class)->src_event (parse, event);
 
2170
      break;
 
2171
  }
 
2172
 
 
2173
  return res;
 
2174
}
 
2175
 
 
2176
static void
 
2177
gst_h264_parse_set_property (GObject * object, guint prop_id,
 
2178
    const GValue * value, GParamSpec * pspec)
 
2179
{
 
2180
  GstH264Parse *parse;
 
2181
 
 
2182
  parse = GST_H264_PARSE (object);
 
2183
 
 
2184
  switch (prop_id) {
 
2185
    case PROP_CONFIG_INTERVAL:
 
2186
      parse->interval = g_value_get_uint (value);
 
2187
      break;
 
2188
    default:
 
2189
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 
2190
      break;
 
2191
  }
 
2192
}
 
2193
 
 
2194
static void
 
2195
gst_h264_parse_get_property (GObject * object, guint prop_id,
 
2196
    GValue * value, GParamSpec * pspec)
 
2197
{
 
2198
  GstH264Parse *parse;
 
2199
 
 
2200
  parse = GST_H264_PARSE (object);
 
2201
 
 
2202
  switch (prop_id) {
 
2203
    case PROP_CONFIG_INTERVAL:
 
2204
      g_value_set_uint (value, parse->interval);
 
2205
      break;
 
2206
    default:
 
2207
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 
2208
      break;
 
2209
  }
 
2210
}