1 /* GStreamer H.265 Parser
2 * Copyright (C) 2013 Intel Corporation
3 * Contact:Sreerenj Balachandran <sreerenj.balachandran@intel.com>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 */
20
21 #ifdef HAVE_CONFIG_H
22 # include "config.h"
23 #endif
24
25 #include <gst/base/base.h>
26 #include <gst/pbutils/pbutils.h>
27 #include <gst/video/video.h>
28 #include "gsth265parse.h"
29
30 #include <string.h>
31
32 GST_DEBUG_CATEGORY (h265_parse_debug);
33 #define GST_CAT_DEFAULT h265_parse_debug
34
35 #define DEFAULT_CONFIG_INTERVAL (0)
36
37 enum
38 {
39 PROP_0,
40 PROP_CONFIG_INTERVAL
41 };
42
43 enum
44 {
45 GST_H265_PARSE_FORMAT_NONE,
46 GST_H265_PARSE_FORMAT_HVC1,
47 GST_H265_PARSE_FORMAT_HEV1,
48 GST_H265_PARSE_FORMAT_BYTE
49 };
50
51 enum
52 {
53 GST_H265_PARSE_ALIGN_NONE = 0,
54 GST_H265_PARSE_ALIGN_NAL,
55 GST_H265_PARSE_ALIGN_AU
56 };
57
58 enum
59 {
60 GST_H265_PARSE_STATE_GOT_SPS = 1 << 0,
61 GST_H265_PARSE_STATE_GOT_PPS = 1 << 1,
62 GST_H265_PARSE_STATE_GOT_SLICE = 1 << 2,
63
64 GST_H265_PARSE_STATE_VALID_PICTURE_HEADERS = (GST_H265_PARSE_STATE_GOT_SPS |
65 GST_H265_PARSE_STATE_GOT_PPS),
66 GST_H265_PARSE_STATE_VALID_PICTURE =
67 (GST_H265_PARSE_STATE_VALID_PICTURE_HEADERS |
68 GST_H265_PARSE_STATE_GOT_SLICE)
69 };
70
71 #define GST_H265_PARSE_STATE_VALID(parse, expected_state) \
72 (((parse)->state & (expected_state)) == (expected_state))
73
74 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
75 GST_PAD_SINK,
76 GST_PAD_ALWAYS,
77 GST_STATIC_CAPS ("video/x-h265"));
78
79 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
80 GST_PAD_SRC,
81 GST_PAD_ALWAYS,
82 GST_STATIC_CAPS ("video/x-h265, parsed = (boolean) true, "
83 "stream-format=(string) { hvc1, hev1, byte-stream }, "
84 "alignment=(string) { au, nal }"));
85
86 #define parent_class gst_h265_parse_parent_class
87 G_DEFINE_TYPE (GstH265Parse, gst_h265_parse, GST_TYPE_BASE_PARSE);
88
89 static void gst_h265_parse_finalize (GObject * object);
90
91 static gboolean gst_h265_parse_start (GstBaseParse * parse);
92 static gboolean gst_h265_parse_stop (GstBaseParse * parse);
93 static GstFlowReturn gst_h265_parse_handle_frame (GstBaseParse * parse,
94 GstBaseParseFrame * frame, gint * skipsize);
95 static GstFlowReturn gst_h265_parse_parse_frame (GstBaseParse * parse,
96 GstBaseParseFrame * frame);
97 static GstFlowReturn gst_h265_parse_pre_push_frame (GstBaseParse * parse,
98 GstBaseParseFrame * frame);
99
100 static void gst_h265_parse_set_property (GObject * object, guint prop_id,
101 const GValue * value, GParamSpec * pspec);
102 static void gst_h265_parse_get_property (GObject * object, guint prop_id,
103 GValue * value, GParamSpec * pspec);
104
105 static gboolean gst_h265_parse_set_caps (GstBaseParse * parse, GstCaps * caps);
106 static GstCaps *gst_h265_parse_get_caps (GstBaseParse * parse,
107 GstCaps * filter);
108 static gboolean gst_h265_parse_event (GstBaseParse * parse, GstEvent * event);
109 static gboolean gst_h265_parse_src_event (GstBaseParse * parse,
110 GstEvent * event);
111
112 static void
gst_h265_parse_class_init(GstH265ParseClass * klass)113 gst_h265_parse_class_init (GstH265ParseClass * klass)
114 {
115 GObjectClass *gobject_class = (GObjectClass *) klass;
116 GstBaseParseClass *parse_class = GST_BASE_PARSE_CLASS (klass);
117 GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
118
119 GST_DEBUG_CATEGORY_INIT (h265_parse_debug, "h265parse", 0, "h265 parser");
120
121 gobject_class->finalize = gst_h265_parse_finalize;
122 gobject_class->set_property = gst_h265_parse_set_property;
123 gobject_class->get_property = gst_h265_parse_get_property;
124
125 g_object_class_install_property (gobject_class, PROP_CONFIG_INTERVAL,
126 g_param_spec_int ("config-interval",
127 "VPS SPS PPS Send Interval",
128 "Send VPS, SPS and PPS Insertion Interval in seconds (sprop parameter sets "
129 "will be multiplexed in the data stream when detected.) "
130 "(0 = disabled, -1 = send with every IDR frame)",
131 -1, 3600, DEFAULT_CONFIG_INTERVAL,
132 G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
133 /* Override BaseParse vfuncs */
134 parse_class->start = GST_DEBUG_FUNCPTR (gst_h265_parse_start);
135 parse_class->stop = GST_DEBUG_FUNCPTR (gst_h265_parse_stop);
136 parse_class->handle_frame = GST_DEBUG_FUNCPTR (gst_h265_parse_handle_frame);
137 parse_class->pre_push_frame =
138 GST_DEBUG_FUNCPTR (gst_h265_parse_pre_push_frame);
139 parse_class->set_sink_caps = GST_DEBUG_FUNCPTR (gst_h265_parse_set_caps);
140 parse_class->get_sink_caps = GST_DEBUG_FUNCPTR (gst_h265_parse_get_caps);
141 parse_class->sink_event = GST_DEBUG_FUNCPTR (gst_h265_parse_event);
142 parse_class->src_event = GST_DEBUG_FUNCPTR (gst_h265_parse_src_event);
143
144 gst_element_class_add_static_pad_template (gstelement_class, &srctemplate);
145 gst_element_class_add_static_pad_template (gstelement_class, &sinktemplate);
146
147 gst_element_class_set_static_metadata (gstelement_class, "H.265 parser",
148 "Codec/Parser/Converter/Video",
149 "Parses H.265 streams",
150 "Sreerenj Balachandran <sreerenj.balachandran@intel.com>");
151 }
152
153 static void
gst_h265_parse_init(GstH265Parse * h265parse)154 gst_h265_parse_init (GstH265Parse * h265parse)
155 {
156 h265parse->frame_out = gst_adapter_new ();
157 gst_base_parse_set_pts_interpolation (GST_BASE_PARSE (h265parse), FALSE);
158 GST_PAD_SET_ACCEPT_INTERSECT (GST_BASE_PARSE_SINK_PAD (h265parse));
159 GST_PAD_SET_ACCEPT_TEMPLATE (GST_BASE_PARSE_SINK_PAD (h265parse));
160 }
161
162
163 static void
gst_h265_parse_finalize(GObject * object)164 gst_h265_parse_finalize (GObject * object)
165 {
166 GstH265Parse *h265parse = GST_H265_PARSE (object);
167
168 g_object_unref (h265parse->frame_out);
169
170 G_OBJECT_CLASS (parent_class)->finalize (object);
171 }
172
173 static void
gst_h265_parse_reset_frame(GstH265Parse * h265parse)174 gst_h265_parse_reset_frame (GstH265Parse * h265parse)
175 {
176 GST_DEBUG_OBJECT (h265parse, "reset frame");
177
178 /* done parsing; reset state */
179 h265parse->current_off = -1;
180
181 h265parse->picture_start = FALSE;
182 h265parse->update_caps = FALSE;
183 h265parse->idr_pos = -1;
184 h265parse->sei_pos = -1;
185 h265parse->keyframe = FALSE;
186 h265parse->header = FALSE;
187 h265parse->have_vps_in_frame = FALSE;
188 h265parse->have_sps_in_frame = FALSE;
189 h265parse->have_pps_in_frame = FALSE;
190 gst_adapter_clear (h265parse->frame_out);
191 }
192
193 static void
gst_h265_parse_reset_stream_info(GstH265Parse * h265parse)194 gst_h265_parse_reset_stream_info (GstH265Parse * h265parse)
195 {
196 gint i;
197
198 h265parse->width = 0;
199 h265parse->height = 0;
200 h265parse->fps_num = 0;
201 h265parse->fps_den = 0;
202 h265parse->upstream_par_n = -1;
203 h265parse->upstream_par_d = -1;
204 h265parse->parsed_par_n = 0;
205 h265parse->parsed_par_n = 0;
206 h265parse->have_pps = FALSE;
207 h265parse->have_sps = FALSE;
208 h265parse->have_vps = FALSE;
209
210 h265parse->align = GST_H265_PARSE_ALIGN_NONE;
211 h265parse->format = GST_H265_PARSE_FORMAT_NONE;
212
213 h265parse->transform = FALSE;
214 h265parse->nal_length_size = 4;
215 h265parse->packetized = FALSE;
216 h265parse->push_codec = FALSE;
217
218 gst_buffer_replace (&h265parse->codec_data, NULL);
219 gst_buffer_replace (&h265parse->codec_data_in, NULL);
220
221 gst_h265_parse_reset_frame (h265parse);
222
223 for (i = 0; i < GST_H265_MAX_VPS_COUNT; i++)
224 gst_buffer_replace (&h265parse->vps_nals[i], NULL);
225 for (i = 0; i < GST_H265_MAX_SPS_COUNT; i++)
226 gst_buffer_replace (&h265parse->sps_nals[i], NULL);
227 for (i = 0; i < GST_H265_MAX_PPS_COUNT; i++)
228 gst_buffer_replace (&h265parse->pps_nals[i], NULL);
229 }
230
231 static void
gst_h265_parse_reset(GstH265Parse * h265parse)232 gst_h265_parse_reset (GstH265Parse * h265parse)
233 {
234 h265parse->last_report = GST_CLOCK_TIME_NONE;
235
236 h265parse->sent_codec_tag = FALSE;
237
238 h265parse->pending_key_unit_ts = GST_CLOCK_TIME_NONE;
239 gst_event_replace (&h265parse->force_key_unit_event, NULL);
240
241 h265parse->discont = FALSE;
242
243 gst_h265_parse_reset_stream_info (h265parse);
244 }
245
246 static gboolean
gst_h265_parse_start(GstBaseParse * parse)247 gst_h265_parse_start (GstBaseParse * parse)
248 {
249 GstH265Parse *h265parse = GST_H265_PARSE (parse);
250
251 GST_DEBUG_OBJECT (parse, "start");
252 gst_h265_parse_reset (h265parse);
253
254 h265parse->nalparser = gst_h265_parser_new ();
255 h265parse->state = 0;
256
257 gst_base_parse_set_min_frame_size (parse, 7);
258
259 return TRUE;
260 }
261
262 static gboolean
gst_h265_parse_stop(GstBaseParse * parse)263 gst_h265_parse_stop (GstBaseParse * parse)
264 {
265 GstH265Parse *h265parse = GST_H265_PARSE (parse);
266
267 GST_DEBUG_OBJECT (parse, "stop");
268 gst_h265_parse_reset (h265parse);
269
270 gst_h265_parser_free (h265parse->nalparser);
271
272 return TRUE;
273 }
274
275 static const gchar *
gst_h265_parse_get_string(GstH265Parse * parse,gboolean format,gint code)276 gst_h265_parse_get_string (GstH265Parse * parse, gboolean format, gint code)
277 {
278 if (format) {
279 switch (code) {
280 case GST_H265_PARSE_FORMAT_HVC1:
281 return "hvc1";
282 case GST_H265_PARSE_FORMAT_HEV1:
283 return "hev1";
284 case GST_H265_PARSE_FORMAT_BYTE:
285 return "byte-stream";
286 default:
287 return "none";
288 }
289 } else {
290 switch (code) {
291 case GST_H265_PARSE_ALIGN_NAL:
292 return "nal";
293 case GST_H265_PARSE_ALIGN_AU:
294 return "au";
295 default:
296 return "none";
297 }
298 }
299 }
300
301 static void
gst_h265_parse_format_from_caps(GstCaps * caps,guint * format,guint * align)302 gst_h265_parse_format_from_caps (GstCaps * caps, guint * format, guint * align)
303 {
304 g_return_if_fail (gst_caps_is_fixed (caps));
305
306 GST_DEBUG ("parsing caps: %" GST_PTR_FORMAT, caps);
307
308 if (format)
309 *format = GST_H265_PARSE_FORMAT_NONE;
310
311 if (align)
312 *align = GST_H265_PARSE_ALIGN_NONE;
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, "hvc1") == 0)
321 *format = GST_H265_PARSE_FORMAT_HVC1;
322 else if (strcmp (str, "hev1") == 0)
323 *format = GST_H265_PARSE_FORMAT_HEV1;
324 else if (strcmp (str, "byte-stream") == 0)
325 *format = GST_H265_PARSE_FORMAT_BYTE;
326 }
327 }
328
329 if (align) {
330 if ((str = gst_structure_get_string (s, "alignment"))) {
331 if (strcmp (str, "au") == 0)
332 *align = GST_H265_PARSE_ALIGN_AU;
333 else if (strcmp (str, "nal") == 0)
334 *align = GST_H265_PARSE_ALIGN_NAL;
335 }
336 }
337 }
338 }
339
340 /* check downstream caps to configure format and alignment */
341 static void
gst_h265_parse_negotiate(GstH265Parse * h265parse,gint in_format,GstCaps * in_caps)342 gst_h265_parse_negotiate (GstH265Parse * h265parse, gint in_format,
343 GstCaps * in_caps)
344 {
345 GstCaps *caps;
346 guint format = GST_H265_PARSE_FORMAT_NONE;
347 guint align = GST_H265_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 (h265parse));
352 GST_DEBUG_OBJECT (h265parse, "allowed caps: %" GST_PTR_FORMAT, caps);
353
354 /* concentrate on leading structure, since decodebin parser
355 * capsfilter always includes parser template caps */
356 if (caps) {
357 caps = gst_caps_truncate (caps);
358 GST_DEBUG_OBJECT (h265parse, "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 (h265parse, "downstream accepts upstream caps");
365 gst_h265_parse_format_from_caps (in_caps, &format, &align);
366 gst_caps_unref (caps);
367 caps = NULL;
368 }
369 }
370
371 /* FIXME We could fail the negotiation immediatly if caps are empty */
372 if (caps && !gst_caps_is_empty (caps)) {
373 /* fixate to avoid ambiguity with lists when parsing */
374 caps = gst_caps_fixate (caps);
375 gst_h265_parse_format_from_caps (caps, &format, &align);
376 }
377
378 /* default */
379 if (!format)
380 format = GST_H265_PARSE_FORMAT_BYTE;
381 if (!align)
382 align = GST_H265_PARSE_ALIGN_AU;
383
384 GST_DEBUG_OBJECT (h265parse, "selected format %s, alignment %s",
385 gst_h265_parse_get_string (h265parse, TRUE, format),
386 gst_h265_parse_get_string (h265parse, FALSE, align));
387
388 h265parse->format = format;
389 h265parse->align = align;
390
391 h265parse->transform = in_format != h265parse->format ||
392 align == GST_H265_PARSE_ALIGN_AU;
393
394 if (caps)
395 gst_caps_unref (caps);
396 }
397
398 static GstBuffer *
gst_h265_parse_wrap_nal(GstH265Parse * h265parse,guint format,guint8 * data,guint size)399 gst_h265_parse_wrap_nal (GstH265Parse * h265parse, guint format, guint8 * data,
400 guint size)
401 {
402 GstBuffer *buf;
403 guint nl = h265parse->nal_length_size;
404 guint32 tmp;
405
406 GST_DEBUG_OBJECT (h265parse, "nal length %d", size);
407
408 buf = gst_buffer_new_allocate (NULL, 4 + size, NULL);
409 if (format == GST_H265_PARSE_FORMAT_HVC1
410 || format == GST_H265_PARSE_FORMAT_HEV1) {
411 tmp = GUINT32_TO_BE (size << (32 - 8 * nl));
412 } else {
413 /* HACK: nl should always be 4 here, otherwise this won't work.
414 * There are legit cases where nl in hevc stream is 2, but byte-stream
415 * SC is still always 4 bytes. */
416 nl = 4;
417 tmp = GUINT32_TO_BE (1);
418 }
419
420 gst_buffer_fill (buf, 0, &tmp, sizeof (guint32));
421 gst_buffer_fill (buf, nl, data, size);
422 gst_buffer_set_size (buf, size + nl);
423
424 return buf;
425 }
426
427 static void
gst_h265_parser_store_nal(GstH265Parse * h265parse,guint id,GstH265NalUnitType naltype,GstH265NalUnit * nalu)428 gst_h265_parser_store_nal (GstH265Parse * h265parse, guint id,
429 GstH265NalUnitType naltype, GstH265NalUnit * nalu)
430 {
431 GstBuffer *buf, **store;
432 guint size = nalu->size, store_size;
433
434 if (naltype == GST_H265_NAL_VPS) {
435 store_size = GST_H265_MAX_VPS_COUNT;
436 store = h265parse->vps_nals;
437 GST_DEBUG_OBJECT (h265parse, "storing vps %u", id);
438 } else if (naltype == GST_H265_NAL_SPS) {
439 store_size = GST_H265_MAX_SPS_COUNT;
440 store = h265parse->sps_nals;
441 GST_DEBUG_OBJECT (h265parse, "storing sps %u", id);
442 } else if (naltype == GST_H265_NAL_PPS) {
443 store_size = GST_H265_MAX_PPS_COUNT;
444 store = h265parse->pps_nals;
445 GST_DEBUG_OBJECT (h265parse, "storing pps %u", id);
446 } else
447 return;
448
449 if (id >= store_size) {
450 GST_DEBUG_OBJECT (h265parse, "unable to store nal, id out-of-range %d", id);
451 return;
452 }
453
454 buf = gst_buffer_new_allocate (NULL, size, NULL);
455 gst_buffer_fill (buf, 0, nalu->data + nalu->offset, size);
456
457 /* Indicate that buffer contain a header needed for decoding */
458 if (naltype >= GST_H265_NAL_VPS && naltype <= GST_H265_NAL_PPS)
459 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_HEADER);
460
461 if (store[id])
462 gst_buffer_unref (store[id]);
463
464 store[id] = buf;
465 }
466
467 #ifndef GST_DISABLE_GST_DEBUG
468 static const gchar *nal_names[] = {
469 "Slice_TRAIL_N",
470 "Slice_TRAIL_R",
471 "Slice_TSA_N",
472 "Slice_TSA_R",
473 "Slice_STSA_N",
474 "Slice_STSA_R",
475 "Slice_RADL_N",
476 "Slice_RADL_R",
477 "SLICE_RASL_N",
478 "SLICE_RASL_R",
479 "Invalid (10)",
480 "Invalid (11)",
481 "Invalid (12)",
482 "Invalid (13)",
483 "Invalid (14)",
484 "Invalid (15)",
485 "SLICE_BLA_W_LP",
486 "SLICE_BLA_W_RADL",
487 "SLICE_BLA_N_LP",
488 "SLICE_IDR_W_RADL",
489 "SLICE_IDR_N_LP",
490 "SLICE_CRA_NUT",
491 "Invalid (22)",
492 "Invalid (23)",
493 "Invalid (24)",
494 "Invalid (25)",
495 "Invalid (26)",
496 "Invalid (27)",
497 "Invalid (28)",
498 "Invalid (29)",
499 "Invalid (30)",
500 "Invalid (31)",
501 "VPS",
502 "SPS",
503 "PPS",
504 "AUD",
505 "EOS",
506 "EOB",
507 "FD",
508 "PREFIX_SEI",
509 "SUFFIX_SEI"
510 };
511
512 static const gchar *
_nal_name(GstH265NalUnitType nal_type)513 _nal_name (GstH265NalUnitType nal_type)
514 {
515 if (nal_type <= GST_H265_NAL_SUFFIX_SEI)
516 return nal_names[nal_type];
517 return "Invalid";
518 }
519 #endif
520
521 static void
gst_h265_parse_process_sei(GstH265Parse * h265parse,GstH265NalUnit * nalu)522 gst_h265_parse_process_sei (GstH265Parse * h265parse, GstH265NalUnit * nalu)
523 {
524 GstH265SEIMessage sei;
525 GstH265Parser *nalparser = h265parse->nalparser;
526 GstH265ParserResult pres;
527 GArray *messages;
528 guint i;
529
530 pres = gst_h265_parser_parse_sei (nalparser, nalu, &messages);
531 if (pres != GST_H265_PARSER_OK)
532 GST_WARNING_OBJECT (h265parse, "failed to parse one or more SEI message");
533
534 /* Even if pres != GST_H265_PARSER_OK, some message could have been parsed and
535 * stored in messages.
536 */
537 for (i = 0; i < messages->len; i++) {
538 sei = g_array_index (messages, GstH265SEIMessage, i);
539 switch (sei.payloadType) {
540 case GST_H265_SEI_RECOVERY_POINT:
541 GST_LOG_OBJECT (h265parse, "recovery point found: %u %u %u",
542 sei.payload.recovery_point.recovery_poc_cnt,
543 sei.payload.recovery_point.exact_match_flag,
544 sei.payload.recovery_point.broken_link_flag);
545 h265parse->keyframe = TRUE;
546 break;
547 case GST_H265_SEI_TIME_CODE:
548 memcpy (&h265parse->time_code, &sei.payload.time_code,
549 sizeof (GstH265TimeCode));
550 break;
551 case GST_H265_SEI_PIC_TIMING:
552 h265parse->sei_pic_struct = sei.payload.pic_timing.pic_struct;
553 break;
554 case GST_H265_SEI_BUF_PERIOD:
555 /* FIXME */
556 break;
557 }
558 }
559 g_array_free (messages, TRUE);
560 }
561
562 /* caller guarantees 2 bytes of nal payload */
563 static gboolean
gst_h265_parse_process_nal(GstH265Parse * h265parse,GstH265NalUnit * nalu)564 gst_h265_parse_process_nal (GstH265Parse * h265parse, GstH265NalUnit * nalu)
565 {
566 GstH265PPS pps = { 0, };
567 GstH265SPS sps = { 0, };
568 GstH265VPS vps = { 0, };
569 gboolean is_irap;
570 guint nal_type;
571 GstH265Parser *nalparser = h265parse->nalparser;
572 GstH265ParserResult pres = GST_H265_PARSER_ERROR;
573
574 /* nothing to do for broken input */
575 if (G_UNLIKELY (nalu->size < 2)) {
576 GST_DEBUG_OBJECT (h265parse, "not processing nal size %u", nalu->size);
577 return TRUE;
578 }
579
580 /* we have a peek as well */
581 nal_type = nalu->type;
582
583 GST_DEBUG_OBJECT (h265parse, "processing nal of type %u %s, size %u",
584 nal_type, _nal_name (nal_type), nalu->size);
585 switch (nal_type) {
586 case GST_H265_NAL_VPS:
587 /* It is not mandatory to have VPS in the stream. But it might
588 * be needed for other extensions like svc */
589 pres = gst_h265_parser_parse_vps (nalparser, nalu, &vps);
590 if (pres != GST_H265_PARSER_OK) {
591 GST_WARNING_OBJECT (h265parse, "failed to parse VPS");
592 return FALSE;
593 }
594
595 GST_DEBUG_OBJECT (h265parse, "triggering src caps check");
596 h265parse->update_caps = TRUE;
597 h265parse->have_vps = TRUE;
598 h265parse->have_vps_in_frame = TRUE;
599 if (h265parse->push_codec && h265parse->have_pps) {
600 /* VPS/SPS/PPS found in stream before the first pre_push_frame, no need
601 * to forcibly push at start */
602 GST_INFO_OBJECT (h265parse, "have VPS/SPS/PPS in stream");
603 h265parse->push_codec = FALSE;
604 h265parse->have_vps = FALSE;
605 h265parse->have_sps = FALSE;
606 h265parse->have_pps = FALSE;
607 }
608
609 gst_h265_parser_store_nal (h265parse, vps.id, nal_type, nalu);
610 h265parse->header |= TRUE;
611 break;
612 case GST_H265_NAL_SPS:
613 /* reset state, everything else is obsolete */
614 h265parse->state = 0;
615
616 pres = gst_h265_parser_parse_sps (nalparser, nalu, &sps, TRUE);
617
618
619 /* arranged for a fallback sps.id, so use that one and only warn */
620 if (pres != GST_H265_PARSER_OK) {
621 /* try to not parse VUI */
622 pres = gst_h265_parser_parse_sps (nalparser, nalu, &sps, FALSE);
623 if (pres != GST_H265_PARSER_OK) {
624 GST_WARNING_OBJECT (h265parse, "failed to parse SPS:");
625 return FALSE;
626 }
627 GST_WARNING_OBJECT (h265parse,
628 "failed to parse VUI of SPS, ignore VUI");
629 }
630
631 GST_DEBUG_OBJECT (h265parse, "triggering src caps check");
632 h265parse->update_caps = TRUE;
633 h265parse->have_sps = TRUE;
634 h265parse->have_sps_in_frame = TRUE;
635 if (h265parse->push_codec && h265parse->have_pps) {
636 /* SPS and PPS found in stream before the first pre_push_frame, no need
637 * to forcibly push at start */
638 GST_INFO_OBJECT (h265parse, "have SPS/PPS in stream");
639 h265parse->push_codec = FALSE;
640 h265parse->have_sps = FALSE;
641 h265parse->have_pps = FALSE;
642 }
643
644 gst_h265_parser_store_nal (h265parse, sps.id, nal_type, nalu);
645 h265parse->header |= TRUE;
646 h265parse->state |= GST_H265_PARSE_STATE_GOT_SPS;
647 break;
648 case GST_H265_NAL_PPS:
649 /* expected state: got-sps */
650 h265parse->state &= GST_H265_PARSE_STATE_GOT_SPS;
651 if (!GST_H265_PARSE_STATE_VALID (h265parse, GST_H265_PARSE_STATE_GOT_SPS))
652 return FALSE;
653
654 pres = gst_h265_parser_parse_pps (nalparser, nalu, &pps);
655
656
657 /* arranged for a fallback pps.id, so use that one and only warn */
658 if (pres != GST_H265_PARSER_OK) {
659 GST_WARNING_OBJECT (h265parse, "failed to parse PPS:");
660 if (pres != GST_H265_PARSER_BROKEN_LINK)
661 return FALSE;
662 }
663
664 /* parameters might have changed, force caps check */
665 if (!h265parse->have_pps) {
666 GST_DEBUG_OBJECT (h265parse, "triggering src caps check");
667 h265parse->update_caps = TRUE;
668 }
669 h265parse->have_pps = TRUE;
670 h265parse->have_pps_in_frame = TRUE;
671 if (h265parse->push_codec && h265parse->have_sps) {
672 /* SPS and PPS found in stream before the first pre_push_frame, no need
673 * to forcibly push at start */
674 GST_INFO_OBJECT (h265parse, "have SPS/PPS in stream");
675 h265parse->push_codec = FALSE;
676 h265parse->have_sps = FALSE;
677 h265parse->have_pps = FALSE;
678 }
679
680 gst_h265_parser_store_nal (h265parse, pps.id, nal_type, nalu);
681 h265parse->header |= TRUE;
682 h265parse->state |= GST_H265_PARSE_STATE_GOT_PPS;
683 break;
684 case GST_H265_NAL_PREFIX_SEI:
685 case GST_H265_NAL_SUFFIX_SEI:
686 /* expected state: got-sps */
687 if (!GST_H265_PARSE_STATE_VALID (h265parse, GST_H265_PARSE_STATE_GOT_SPS))
688 return FALSE;
689
690 h265parse->header |= TRUE;
691
692 gst_h265_parse_process_sei (h265parse, nalu);
693
694 /* mark SEI pos */
695 if (h265parse->sei_pos == -1) {
696 if (h265parse->transform)
697 h265parse->sei_pos = gst_adapter_available (h265parse->frame_out);
698 else
699 h265parse->sei_pos = nalu->sc_offset;
700 GST_DEBUG_OBJECT (h265parse, "marking SEI in frame at offset %d",
701 h265parse->sei_pos);
702 }
703 break;
704
705 case GST_H265_NAL_SLICE_TRAIL_N:
706 case GST_H265_NAL_SLICE_TRAIL_R:
707 case GST_H265_NAL_SLICE_TSA_N:
708 case GST_H265_NAL_SLICE_TSA_R:
709 case GST_H265_NAL_SLICE_STSA_N:
710 case GST_H265_NAL_SLICE_STSA_R:
711 case GST_H265_NAL_SLICE_RADL_N:
712 case GST_H265_NAL_SLICE_RADL_R:
713 case GST_H265_NAL_SLICE_RASL_N:
714 case GST_H265_NAL_SLICE_RASL_R:
715 case GST_H265_NAL_SLICE_BLA_W_LP:
716 case GST_H265_NAL_SLICE_BLA_W_RADL:
717 case GST_H265_NAL_SLICE_BLA_N_LP:
718 case GST_H265_NAL_SLICE_IDR_W_RADL:
719 case GST_H265_NAL_SLICE_IDR_N_LP:
720 case GST_H265_NAL_SLICE_CRA_NUT:
721 {
722 GstH265SliceHdr slice;
723
724 /* expected state: got-sps|got-pps (valid picture headers) */
725 h265parse->state &= GST_H265_PARSE_STATE_VALID_PICTURE_HEADERS;
726 if (!GST_H265_PARSE_STATE_VALID (h265parse,
727 GST_H265_PARSE_STATE_VALID_PICTURE_HEADERS))
728 return FALSE;
729
730 pres = gst_h265_parser_parse_slice_hdr (nalparser, nalu, &slice);
731
732 if (pres == GST_H265_PARSER_OK) {
733 if (GST_H265_IS_I_SLICE (&slice))
734 h265parse->keyframe |= TRUE;
735
736 h265parse->state |= GST_H265_PARSE_STATE_GOT_SLICE;
737 }
738 if (slice.first_slice_segment_in_pic_flag == 1)
739 GST_DEBUG_OBJECT (h265parse,
740 "frame start, first_slice_segment_in_pic_flag = 1");
741
742 GST_DEBUG_OBJECT (h265parse,
743 "parse result %d, first slice_segment: %u, slice type: %u",
744 pres, slice.first_slice_segment_in_pic_flag, slice.type);
745
746 gst_h265_slice_hdr_free (&slice);
747 }
748
749 is_irap = ((nal_type >= GST_H265_NAL_SLICE_BLA_W_LP)
750 && (nal_type <= GST_H265_NAL_SLICE_CRA_NUT)) ? TRUE : FALSE;
751 if (G_LIKELY (!is_irap && !h265parse->push_codec))
752 break;
753
754 /* if we need to sneak codec NALs into the stream,
755 * this is a good place, so fake it as IDR
756 * (which should be at start anyway) */
757 /* mark where config needs to go if interval expired */
758 /* mind replacement buffer if applicable */
759 if (h265parse->idr_pos == -1) {
760 if (h265parse->transform)
761 h265parse->idr_pos = gst_adapter_available (h265parse->frame_out);
762 else
763 h265parse->idr_pos = nalu->sc_offset;
764 GST_DEBUG_OBJECT (h265parse, "marking IDR in frame at offset %d",
765 h265parse->idr_pos);
766 }
767 /* if SEI preceeds (faked) IDR, then we have to insert config there */
768 if (h265parse->sei_pos >= 0 && h265parse->idr_pos > h265parse->sei_pos) {
769 h265parse->idr_pos = h265parse->sei_pos;
770 GST_DEBUG_OBJECT (h265parse, "moved IDR mark to SEI position %d",
771 h265parse->idr_pos);
772 }
773 break;
774 case GST_H265_NAL_AUD:
775 /* Just accumulate AU Delimiter, whether it's before SPS or not */
776 pres = gst_h265_parser_parse_nal (nalparser, nalu);
777 if (pres != GST_H265_PARSER_OK)
778 return FALSE;
779 break;
780 default:
781 /* drop anything before the initial SPS */
782 if (!GST_H265_PARSE_STATE_VALID (h265parse, GST_H265_PARSE_STATE_GOT_SPS))
783 return FALSE;
784
785 pres = gst_h265_parser_parse_nal (nalparser, nalu);
786 if (pres != GST_H265_PARSER_OK)
787 return FALSE;
788 break;
789 }
790
791 /* if HEVC output needed, collect properly prefixed nal in adapter,
792 * and use that to replace outgoing buffer data later on */
793 if (h265parse->transform) {
794 GstBuffer *buf;
795
796 GST_LOG_OBJECT (h265parse, "collecting NAL in HEVC frame");
797 buf = gst_h265_parse_wrap_nal (h265parse, h265parse->format,
798 nalu->data + nalu->offset, nalu->size);
799 gst_adapter_push (h265parse->frame_out, buf);
800 }
801
802 return TRUE;
803 }
804
805 /* caller guarantees at least 3 bytes of nal payload for each nal
806 * returns TRUE if next_nal indicates that nal terminates an AU */
807 static inline gboolean
gst_h265_parse_collect_nal(GstH265Parse * h265parse,const guint8 * data,guint size,GstH265NalUnit * nalu)808 gst_h265_parse_collect_nal (GstH265Parse * h265parse, const guint8 * data,
809 guint size, GstH265NalUnit * nalu)
810 {
811 gboolean complete;
812 GstH265ParserResult parse_res;
813 GstH265NalUnitType nal_type = nalu->type;
814 GstH265NalUnit nnalu;
815
816 GST_DEBUG_OBJECT (h265parse, "parsing collected nal");
817 parse_res = gst_h265_parser_identify_nalu_unchecked (h265parse->nalparser,
818 data, nalu->offset + nalu->size, size, &nnalu);
819
820 if (parse_res != GST_H265_PARSER_OK)
821 return FALSE;
822
823 /* determine if AU complete */
824 GST_LOG_OBJECT (h265parse, "nal type: %d %s", nal_type, _nal_name (nal_type));
825 /* coded slice NAL starts a picture,
826 * i.e. other types become aggregated in front of it */
827 h265parse->picture_start |= ((nal_type >= GST_H265_NAL_SLICE_TRAIL_N
828 && nal_type <= GST_H265_NAL_SLICE_RASL_R)
829 || (nal_type >= GST_H265_NAL_SLICE_BLA_W_LP
830 && nal_type <= RESERVED_IRAP_NAL_TYPE_MAX));
831
832 /* consider a coded slices (IRAP or not) to start a picture,
833 * (so ending the previous one) if first_slice_segment_in_pic_flag == 1*/
834 nal_type = nnalu.type;
835 complete = h265parse->picture_start && ((nal_type >= GST_H265_NAL_VPS
836 && nal_type <= GST_H265_NAL_AUD)
837 || nal_type == GST_H265_NAL_PREFIX_SEI || (nal_type >= 41
838 && nal_type <= 44) || (nal_type >= 48 && nal_type <= 55));
839
840 GST_LOG_OBJECT (h265parse, "next nal type: %d %s", nal_type,
841 _nal_name (nal_type));
842
843 /* Any VCL Nal unit with first_slice_segment_in_pic_flag == 1 considered start of frame */
844 complete |= h265parse->picture_start
845 && (((nal_type >= GST_H265_NAL_SLICE_TRAIL_N
846 && nal_type <= GST_H265_NAL_SLICE_RASL_R)
847 || (nal_type >= GST_H265_NAL_SLICE_BLA_W_LP
848 && nal_type <= RESERVED_IRAP_NAL_TYPE_MAX))
849 && (nnalu.data[nnalu.offset + 2] & 0x80));
850
851 GST_LOG_OBJECT (h265parse, "au complete: %d", complete);
852 return complete;
853 }
854
855 static GstFlowReturn
gst_h265_parse_handle_frame_packetized(GstBaseParse * parse,GstBaseParseFrame * frame)856 gst_h265_parse_handle_frame_packetized (GstBaseParse * parse,
857 GstBaseParseFrame * frame)
858 {
859 GstH265Parse *h265parse = GST_H265_PARSE (parse);
860 GstBuffer *buffer = frame->buffer;
861 GstFlowReturn ret = GST_FLOW_OK;
862 GstH265ParserResult parse_res;
863 GstH265NalUnit nalu;
864 const guint nl = h265parse->nal_length_size;
865 GstMapInfo map;
866 gint left;
867
868 if (nl < 1 || nl > 4) {
869 GST_DEBUG_OBJECT (h265parse, "insufficient data to split input");
870 return GST_FLOW_NOT_NEGOTIATED;
871 }
872
873 /* need to save buffer from invalidation upon _finish_frame */
874 if (h265parse->split_packetized)
875 buffer = gst_buffer_copy (frame->buffer);
876
877 gst_buffer_map (buffer, &map, GST_MAP_READ);
878
879 left = map.size;
880
881 GST_LOG_OBJECT (h265parse,
882 "processing packet buffer of size %" G_GSIZE_FORMAT, map.size);
883
884 parse_res = gst_h265_parser_identify_nalu_hevc (h265parse->nalparser,
885 map.data, 0, map.size, nl, &nalu);
886
887 while (parse_res == GST_H265_PARSER_OK) {
888 GST_DEBUG_OBJECT (h265parse, "HEVC nal offset %d", nalu.offset + nalu.size);
889
890 /* either way, have a look at it */
891 gst_h265_parse_process_nal (h265parse, &nalu);
892
893 /* dispatch per NALU if needed */
894 if (h265parse->split_packetized) {
895 GstBaseParseFrame tmp_frame;
896
897 gst_base_parse_frame_init (&tmp_frame);
898 tmp_frame.flags |= frame->flags;
899 tmp_frame.offset = frame->offset;
900 tmp_frame.overhead = frame->overhead;
901 tmp_frame.buffer = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL,
902 nalu.offset, nalu.size);
903
904 /* note we don't need to come up with a sub-buffer, since
905 * subsequent code only considers input buffer's metadata.
906 * Real data is either taken from input by baseclass or
907 * a replacement output buffer is provided anyway. */
908 gst_h265_parse_parse_frame (parse, &tmp_frame);
909 ret = gst_base_parse_finish_frame (parse, &tmp_frame, nl + nalu.size);
910 left -= nl + nalu.size;
911 }
912
913 parse_res = gst_h265_parser_identify_nalu_hevc (h265parse->nalparser,
914 map.data, nalu.offset + nalu.size, map.size, nl, &nalu);
915 }
916
917 gst_buffer_unmap (buffer, &map);
918
919 if (!h265parse->split_packetized) {
920 gst_h265_parse_parse_frame (parse, frame);
921 ret = gst_base_parse_finish_frame (parse, frame, map.size);
922 } else {
923 gst_buffer_unref (buffer);
924 if (G_UNLIKELY (left)) {
925 /* should not be happening for nice HEVC */
926 GST_WARNING_OBJECT (parse, "skipping leftover HEVC data %d", left);
927 frame->flags |= GST_BASE_PARSE_FRAME_FLAG_DROP;
928 ret = gst_base_parse_finish_frame (parse, frame, map.size);
929 }
930 }
931
932 if (parse_res == GST_H265_PARSER_NO_NAL_END ||
933 parse_res == GST_H265_PARSER_BROKEN_DATA) {
934
935 if (h265parse->split_packetized) {
936 GST_ELEMENT_ERROR (h265parse, STREAM, FAILED, (NULL),
937 ("invalid HEVC input data"));
938
939 return GST_FLOW_ERROR;
940 } else {
941 /* do not meddle to much in this case */
942 GST_DEBUG_OBJECT (h265parse, "parsing packet failed");
943 }
944 }
945
946 return ret;
947 }
948
949 static GstFlowReturn
gst_h265_parse_handle_frame(GstBaseParse * parse,GstBaseParseFrame * frame,gint * skipsize)950 gst_h265_parse_handle_frame (GstBaseParse * parse,
951 GstBaseParseFrame * frame, gint * skipsize)
952 {
953 GstH265Parse *h265parse = GST_H265_PARSE (parse);
954 GstBuffer *buffer = frame->buffer;
955 GstMapInfo map;
956 guint8 *data;
957 gsize size;
958 gint current_off = 0;
959 gboolean drain, nonext;
960 GstH265Parser *nalparser = h265parse->nalparser;
961 GstH265NalUnit nalu;
962 GstH265ParserResult pres;
963 gint framesize;
964
965 if (G_UNLIKELY (GST_BUFFER_FLAG_IS_SET (frame->buffer,
966 GST_BUFFER_FLAG_DISCONT))) {
967 h265parse->discont = TRUE;
968 }
969
970 /* delegate in packetized case, no skipping should be needed */
971 if (h265parse->packetized)
972 return gst_h265_parse_handle_frame_packetized (parse, frame);
973
974 gst_buffer_map (buffer, &map, GST_MAP_READ);
975 data = map.data;
976 size = map.size;
977
978 /* expect at least 3 bytes startcode == sc, and 3 bytes NALU payload */
979 if (G_UNLIKELY (size < 6)) {
980 gst_buffer_unmap (buffer, &map);
981 *skipsize = 1;
982 return GST_FLOW_OK;
983 }
984
985 /* need to configure aggregation */
986 if (G_UNLIKELY (h265parse->format == GST_H265_PARSE_FORMAT_NONE))
987 gst_h265_parse_negotiate (h265parse, GST_H265_PARSE_FORMAT_BYTE, NULL);
988
989 /* avoid stale cached parsing state */
990 if (frame->flags & GST_BASE_PARSE_FRAME_FLAG_NEW_FRAME) {
991 GST_LOG_OBJECT (h265parse, "parsing new frame");
992 gst_h265_parse_reset_frame (h265parse);
993 } else {
994 GST_LOG_OBJECT (h265parse, "resuming frame parsing");
995 }
996
997 drain = GST_BASE_PARSE_DRAINING (parse);
998 nonext = FALSE;
999
1000 current_off = h265parse->current_off;
1001 if (current_off < 0)
1002 current_off = 0;
1003 g_assert (current_off < size);
1004 GST_DEBUG_OBJECT (h265parse, "last parse position %d", current_off);
1005
1006 /* check for initial skip */
1007 if (h265parse->current_off == -1) {
1008 pres =
1009 gst_h265_parser_identify_nalu_unchecked (nalparser, data, current_off,
1010 size, &nalu);
1011 switch (pres) {
1012 case GST_H265_PARSER_OK:
1013 if (nalu.sc_offset > 0) {
1014 *skipsize = nalu.sc_offset;
1015 goto skip;
1016 }
1017 break;
1018 case GST_H265_PARSER_NO_NAL:
1019 *skipsize = size - 3;
1020 goto skip;
1021 default:
1022 /* should not really occur either */
1023 GST_ELEMENT_ERROR (h265parse, STREAM, FORMAT,
1024 ("Error parsing H.265 stream"), ("Invalid H.265 stream"));
1025 goto invalid_stream;
1026 }
1027 }
1028
1029 while (TRUE) {
1030 pres =
1031 gst_h265_parser_identify_nalu (nalparser, data, current_off, size,
1032 &nalu);
1033
1034 switch (pres) {
1035 case GST_H265_PARSER_OK:
1036 GST_DEBUG_OBJECT (h265parse, "complete nal (offset, size): (%u, %u) ",
1037 nalu.offset, nalu.size);
1038 break;
1039 case GST_H265_PARSER_NO_NAL_END:
1040 GST_DEBUG_OBJECT (h265parse, "not a complete nal found at offset %u",
1041 nalu.offset);
1042 /* if draining, accept it as complete nal */
1043 if (drain) {
1044 nonext = TRUE;
1045 nalu.size = size - nalu.offset;
1046 GST_DEBUG_OBJECT (h265parse, "draining, accepting with size %u",
1047 nalu.size);
1048 /* if it's not too short at least */
1049 if (nalu.size < 3)
1050 goto broken;
1051 break;
1052 }
1053 /* otherwise need more */
1054 goto more;
1055 case GST_H265_PARSER_BROKEN_LINK:
1056 GST_ELEMENT_ERROR (h265parse, STREAM, FORMAT,
1057 ("Error parsing H.265 stream"),
1058 ("The link to structure needed for the parsing couldn't be found"));
1059 goto invalid_stream;
1060 case GST_H265_PARSER_ERROR:
1061 /* should not really occur either */
1062 GST_ELEMENT_ERROR (h265parse, STREAM, FORMAT,
1063 ("Error parsing H.265 stream"), ("Invalid H.265 stream"));
1064 goto invalid_stream;
1065 case GST_H265_PARSER_NO_NAL:
1066 GST_ELEMENT_ERROR (h265parse, STREAM, FORMAT,
1067 ("Error parsing H.265 stream"), ("No H.265 NAL unit found"));
1068 goto invalid_stream;
1069 case GST_H265_PARSER_BROKEN_DATA:
1070 GST_WARNING_OBJECT (h265parse, "input stream is corrupt; "
1071 "it contains a NAL unit of length %u", nalu.size);
1072 broken:
1073 /* broken nal at start -> arrange to skip it,
1074 * otherwise have it terminate current au
1075 * (and so it will be skipped on next frame round) */
1076 if (current_off == 0) {
1077 GST_DEBUG_OBJECT (h265parse, "skipping broken nal");
1078 *skipsize = nalu.offset;
1079 goto skip;
1080 } else {
1081 GST_DEBUG_OBJECT (h265parse, "terminating au");
1082 nalu.size = 0;
1083 nalu.offset = nalu.sc_offset;
1084 goto end;
1085 }
1086 default:
1087 g_assert_not_reached ();
1088 break;
1089 }
1090
1091 GST_DEBUG_OBJECT (h265parse, "%p complete nal found. Off: %u, Size: %u",
1092 data, nalu.offset, nalu.size);
1093
1094 /* simulate no next nal if none needed */
1095 nonext = nonext || (h265parse->align == GST_H265_PARSE_ALIGN_NAL);
1096
1097 if (!nonext) {
1098 if (nalu.offset + nalu.size + 5 + 2 > size) {
1099 GST_DEBUG_OBJECT (h265parse, "not enough data for next NALU");
1100 if (drain) {
1101 GST_DEBUG_OBJECT (h265parse, "but draining anyway");
1102 nonext = TRUE;
1103 } else {
1104 goto more;
1105 }
1106 }
1107 }
1108
1109 if (!gst_h265_parse_process_nal (h265parse, &nalu)) {
1110 GST_WARNING_OBJECT (h265parse,
1111 "broken/invalid nal Type: %d %s, Size: %u will be dropped",
1112 nalu.type, _nal_name (nalu.type), nalu.size);
1113 *skipsize = nalu.size;
1114 goto skip;
1115 }
1116
1117 if (nonext)
1118 break;
1119
1120 /* if no next nal, we know it's complete here */
1121 if (gst_h265_parse_collect_nal (h265parse, data, size, &nalu))
1122 break;
1123
1124 GST_DEBUG_OBJECT (h265parse, "Looking for more");
1125 current_off = nalu.offset + nalu.size;
1126 }
1127
1128 end:
1129 framesize = nalu.offset + nalu.size;
1130
1131 gst_buffer_unmap (buffer, &map);
1132
1133 gst_h265_parse_parse_frame (parse, frame);
1134
1135 return gst_base_parse_finish_frame (parse, frame, framesize);
1136
1137 more:
1138 *skipsize = 0;
1139
1140 /* Restart parsing from here next time */
1141 if (current_off > 0)
1142 h265parse->current_off = current_off;
1143
1144 /* Fall-through. */
1145 out:
1146 gst_buffer_unmap (buffer, &map);
1147 return GST_FLOW_OK;
1148
1149 skip:
1150 GST_DEBUG_OBJECT (h265parse, "skipping %d", *skipsize);
1151 /* If we are collecting access units, we need to preserve the initial
1152 * config headers (SPS, PPS et al.) and only reset the frame if another
1153 * slice NAL was received. This means that broken pictures are discarded */
1154 if (h265parse->align != GST_H265_PARSE_ALIGN_AU ||
1155 !(h265parse->state & GST_H265_PARSE_STATE_VALID_PICTURE_HEADERS) ||
1156 (h265parse->state & GST_H265_PARSE_STATE_GOT_SLICE))
1157 gst_h265_parse_reset_frame (h265parse);
1158 goto out;
1159
1160 invalid_stream:
1161 gst_buffer_unmap (buffer, &map);
1162 return GST_FLOW_ERROR;
1163 }
1164
1165 /* byte together hevc codec data based on collected pps and sps so far */
1166 static GstBuffer *
gst_h265_parse_make_codec_data(GstH265Parse * h265parse)1167 gst_h265_parse_make_codec_data (GstH265Parse * h265parse)
1168 {
1169 GstBuffer *buf, *nal;
1170 gint i, j, k = 0;
1171 guint vps_size = 0, sps_size = 0, pps_size = 0;
1172 guint num_vps = 0, num_sps = 0, num_pps = 0;
1173 gboolean found = FALSE;
1174 GstMapInfo map;
1175 guint8 *data;
1176 gint nl;
1177 guint8 num_arrays = 0;
1178 GstH265SPS *sps = NULL;
1179 guint16 min_spatial_segmentation_idc = 0;
1180 GstH265ProfileTierLevel *pft;
1181
1182 /* only nal payload in stored nals */
1183 /* Fixme: Current implementation is not embedding SEI in codec_data */
1184 for (i = 0; i < GST_H265_MAX_VPS_COUNT; i++) {
1185 if ((nal = h265parse->vps_nals[i])) {
1186 num_vps++;
1187 /* size bytes also count */
1188 vps_size += gst_buffer_get_size (nal) + 2;
1189 }
1190 }
1191 if (num_vps > 0)
1192 num_arrays++;
1193
1194 for (i = 0; i < GST_H265_MAX_SPS_COUNT; i++) {
1195 if ((nal = h265parse->sps_nals[i])) {
1196 num_sps++;
1197 /* size bytes also count */
1198 sps_size += gst_buffer_get_size (nal) + 2;
1199 found = TRUE;
1200 }
1201 }
1202 if (num_sps > 0)
1203 num_arrays++;
1204
1205 for (i = 0; i < GST_H265_MAX_PPS_COUNT; i++) {
1206 if ((nal = h265parse->pps_nals[i])) {
1207 num_pps++;
1208 /* size bytes also count */
1209 pps_size += gst_buffer_get_size (nal) + 2;
1210 }
1211 }
1212 if (num_pps > 0)
1213 num_arrays++;
1214
1215 GST_DEBUG_OBJECT (h265parse,
1216 "constructing codec_data: num_vps =%d num_sps=%d, num_pps=%d", num_vps,
1217 num_sps, num_pps);
1218
1219 if (!found)
1220 return NULL;
1221
1222 sps = h265parse->nalparser->last_sps;
1223 if (!sps)
1224 return NULL;
1225
1226 buf =
1227 gst_buffer_new_allocate (NULL,
1228 23 + (3 * num_arrays) + vps_size + sps_size + pps_size, NULL);
1229 gst_buffer_map (buf, &map, GST_MAP_WRITE);
1230 data = map.data;
1231 memset (data, 0, map.size);
1232 nl = h265parse->nal_length_size;
1233
1234 pft = &sps->profile_tier_level;
1235 if (sps->vui_parameters_present_flag)
1236 min_spatial_segmentation_idc = sps->vui_params.min_spatial_segmentation_idc;
1237
1238 /* HEVCDecoderConfigurationVersion = 1
1239 * profile_space | tier_flat | profile_idc |
1240 * profile_compatibility_flags | constraint_indicator_flags |
1241 * level_idc */
1242 data[0] = 1;
1243 data[1] =
1244 (pft->profile_space << 5) | (pft->tier_flag << 5) | pft->profile_idc;
1245 for (i = 2; i < 6; i++) {
1246 for (j = 7; j >= 0; j--) {
1247 data[i] |= (pft->profile_compatibility_flag[k] << j);
1248 k++;
1249 }
1250 }
1251 data[6] |=
1252 (pft->progressive_source_flag << 7) | (pft->interlaced_source_flag << 6) |
1253 (pft->non_packed_constraint_flag << 5) | (pft->
1254 frame_only_constraint_flag << 4);
1255 data[12] = pft->level_idc;
1256 /* min_spatial_segmentation_idc */
1257 GST_WRITE_UINT16_BE (data + 13, min_spatial_segmentation_idc);
1258 data[13] |= 0xf0;
1259 data[15] = 0xfc; /* keeping parrallelismType as zero (unknown) */
1260 data[16] = 0xfc | sps->chroma_format_idc;
1261 data[17] = 0xf8 | sps->bit_depth_luma_minus8;
1262 data[18] = 0xf8 | sps->bit_depth_chroma_minus8;
1263 data[19] = 0x00; /* keep avgFrameRate as unspecified */
1264 data[20] = 0x00; /* keep avgFrameRate as unspecified */
1265 /* constFrameRate(2 bits): 0, stream may or may not be of constant framerate
1266 * numTemporalLayers (3 bits): number of temporal layers, value from SPS
1267 * TemporalIdNested (1 bit): sps_temporal_id_nesting_flag from SPS
1268 * lengthSizeMinusOne (2 bits): plus 1 indicates the length of the NALUnitLength */
1269 data[21] =
1270 0x00 | ((sps->max_sub_layers_minus1 +
1271 1) << 3) | (sps->temporal_id_nesting_flag << 2) | (nl - 1);
1272 GST_WRITE_UINT8 (data + 22, num_arrays); /* numOfArrays */
1273
1274 data += 23;
1275
1276 /* VPS */
1277 if (num_vps > 0) {
1278 /* array_completeness | reserved_zero bit | nal_unit_type */
1279 data[0] = 0x00 | 0x20;
1280 data++;
1281
1282 GST_WRITE_UINT16_BE (data, num_vps);
1283 data += 2;
1284
1285 for (i = 0; i < GST_H265_MAX_VPS_COUNT; i++) {
1286 if ((nal = h265parse->vps_nals[i])) {
1287 gsize nal_size = gst_buffer_get_size (nal);
1288 GST_WRITE_UINT16_BE (data, nal_size);
1289 gst_buffer_extract (nal, 0, data + 2, nal_size);
1290 data += 2 + nal_size;
1291 }
1292 }
1293 }
1294
1295 /* SPS */
1296 if (num_sps > 0) {
1297 /* array_completeness | reserved_zero bit | nal_unit_type */
1298 data[0] = 0x00 | 0x21;
1299 data++;
1300
1301 GST_WRITE_UINT16_BE (data, num_sps);
1302 data += 2;
1303
1304 for (i = 0; i < GST_H265_MAX_SPS_COUNT; i++) {
1305 if ((nal = h265parse->sps_nals[i])) {
1306 gsize nal_size = gst_buffer_get_size (nal);
1307 GST_WRITE_UINT16_BE (data, nal_size);
1308 gst_buffer_extract (nal, 0, data + 2, nal_size);
1309 data += 2 + nal_size;
1310 }
1311 }
1312 }
1313
1314 /* PPS */
1315 if (num_pps > 0) {
1316 /* array_completeness | reserved_zero bit | nal_unit_type */
1317 data[0] = 0x00 | 0x22;
1318 data++;
1319
1320 GST_WRITE_UINT16_BE (data, num_pps);
1321 data += 2;
1322
1323 for (i = 0; i < GST_H265_MAX_PPS_COUNT; i++) {
1324 if ((nal = h265parse->pps_nals[i])) {
1325 gsize nal_size = gst_buffer_get_size (nal);
1326 GST_WRITE_UINT16_BE (data, nal_size);
1327 gst_buffer_extract (nal, 0, data + 2, nal_size);
1328 data += 2 + nal_size;
1329 }
1330 }
1331 }
1332 gst_buffer_unmap (buf, &map);
1333
1334 return buf;
1335 }
1336
1337 static void
gst_h265_parse_get_par(GstH265Parse * h265parse,gint * num,gint * den)1338 gst_h265_parse_get_par (GstH265Parse * h265parse, gint * num, gint * den)
1339 {
1340 if (h265parse->upstream_par_n != -1 && h265parse->upstream_par_d != -1) {
1341 *num = h265parse->upstream_par_n;
1342 *den = h265parse->upstream_par_d;
1343 } else {
1344 *num = h265parse->parsed_par_n;
1345 *den = h265parse->parsed_par_d;
1346 }
1347 }
1348
1349 static const gchar *
digit_to_string(guint digit)1350 digit_to_string (guint digit)
1351 {
1352 static const char itoa[][2] = {
1353 "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"
1354 };
1355
1356 if (G_LIKELY (digit < 10))
1357 return itoa[digit];
1358 else
1359 return NULL;
1360 }
1361
1362 static const gchar *
get_profile_string(GstH265Profile profile)1363 get_profile_string (GstH265Profile profile)
1364 {
1365 switch (profile) {
1366 case GST_H265_PROFILE_MAIN:
1367 return "main";
1368 case GST_H265_PROFILE_MAIN_10:
1369 return "main-10";
1370 case GST_H265_PROFILE_MAIN_STILL_PICTURE:
1371 return "main-still-picture";
1372 case GST_H265_PROFILE_MONOCHROME:
1373 return "monochrome";
1374 case GST_H265_PROFILE_MONOCHROME_12:
1375 return "monochrome-12";
1376 case GST_H265_PROFILE_MONOCHROME_16:
1377 return "monochrome-16";
1378 case GST_H265_PROFILE_MAIN_12:
1379 return "main-12";
1380 case GST_H265_PROFILE_MAIN_422_10:
1381 return "main-422-10";
1382 case GST_H265_PROFILE_MAIN_422_12:
1383 return "main-422-12";
1384 case GST_H265_PROFILE_MAIN_444:
1385 return "main-444";
1386 case GST_H265_PROFILE_MAIN_444_10:
1387 return "main-444-10";
1388 case GST_H265_PROFILE_MAIN_444_12:
1389 return "main-444-12";
1390 case GST_H265_PROFILE_MAIN_INTRA:
1391 return "main-intra";
1392 case GST_H265_PROFILE_MAIN_10_INTRA:
1393 return "main-10-intra";
1394 case GST_H265_PROFILE_MAIN_12_INTRA:
1395 return "main-12-intra";
1396 case GST_H265_PROFILE_MAIN_422_10_INTRA:
1397 return "main-422-10-intra";
1398 case GST_H265_PROFILE_MAIN_422_12_INTRA:
1399 return "main-422-12-intra";
1400 case GST_H265_PROFILE_MAIN_444_INTRA:
1401 return "main-444-intra";
1402 case GST_H265_PROFILE_MAIN_444_10_INTRA:
1403 return "main-444-10-intra";
1404 case GST_H265_PROFILE_MAIN_444_12_INTRA:
1405 return "main-444-12-intra";
1406 case GST_H265_PROFILE_MAIN_444_16_INTRA:
1407 return "main-444-16-intra";
1408 case GST_H265_PROFILE_MAIN_444_STILL_PICTURE:
1409 return "main-444-still-picture";
1410 case GST_H265_PROFILE_MAIN_444_16_STILL_PICTURE:
1411 return "main-444-16-still-picture";
1412 default:
1413 break;
1414 }
1415
1416 return NULL;
1417 }
1418
1419 static const gchar *
get_tier_string(guint8 tier_flag)1420 get_tier_string (guint8 tier_flag)
1421 {
1422 const gchar *tier = NULL;
1423
1424 if (tier_flag)
1425 tier = "high";
1426 else
1427 tier = "main";
1428
1429 return tier;
1430 }
1431
1432 static const gchar *
get_level_string(guint8 level_idc)1433 get_level_string (guint8 level_idc)
1434 {
1435 if (level_idc == 0)
1436 return NULL;
1437 else if (level_idc % 30 == 0)
1438 return digit_to_string (level_idc / 30);
1439 else {
1440 switch (level_idc) {
1441 case 63:
1442 return "2.1";
1443 break;
1444 case 93:
1445 return "3.1";
1446 break;
1447 case 123:
1448 return "4.1";
1449 break;
1450 case 153:
1451 return "5.1";
1452 break;
1453 case 156:
1454 return "5.2";
1455 break;
1456 case 183:
1457 return "6.1";
1458 break;
1459 case 186:
1460 return "6.2";
1461 break;
1462 default:
1463 return NULL;
1464 }
1465 }
1466 }
1467
1468 static GstCaps *
get_compatible_profile_caps(GstH265SPS * sps)1469 get_compatible_profile_caps (GstH265SPS * sps)
1470 {
1471 GstCaps *caps = NULL;
1472 const gchar **profiles = NULL;
1473 gint i;
1474 GValue compat_profiles = G_VALUE_INIT;
1475 g_value_init (&compat_profiles, GST_TYPE_LIST);
1476
1477 switch (sps->profile_tier_level.profile_idc) {
1478 case GST_H265_PROFILE_IDC_MAIN_10:
1479 if (sps->profile_tier_level.profile_compatibility_flag[1]) {
1480 if (sps->profile_tier_level.profile_compatibility_flag[3]) {
1481 static const gchar *profile_array[] =
1482 { "main", "main-still-picture", NULL };
1483 profiles = profile_array;
1484 } else {
1485 static const gchar *profile_array[] = { "main", NULL };
1486 profiles = profile_array;
1487 }
1488 }
1489 break;
1490 case GST_H265_PROFILE_IDC_MAIN:
1491 if (sps->profile_tier_level.profile_compatibility_flag[3]) {
1492 static const gchar *profile_array[] =
1493 { "main-still-picture", "main-10", NULL
1494 };
1495 profiles = profile_array;
1496 } else {
1497 static const gchar *profile_array[] = { "main-10", NULL };
1498 profiles = profile_array;
1499 }
1500 break;
1501 case GST_H265_PROFILE_IDC_MAIN_STILL_PICTURE:
1502 {
1503 static const gchar *profile_array[] = { "main", "main-10", NULL
1504 };
1505 profiles = profile_array;
1506 }
1507 break;
1508 default:
1509 break;
1510 }
1511
1512 if (profiles) {
1513 GValue value = G_VALUE_INIT;
1514 caps = gst_caps_new_empty_simple ("video/x-h265");
1515 for (i = 0; profiles[i]; i++) {
1516 g_value_init (&value, G_TYPE_STRING);
1517 g_value_set_string (&value, profiles[i]);
1518 gst_value_list_append_value (&compat_profiles, &value);
1519 g_value_unset (&value);
1520 }
1521 gst_caps_set_value (caps, "profile", &compat_profiles);
1522 g_value_unset (&compat_profiles);
1523 }
1524
1525 return caps;
1526 }
1527
1528 /* if downstream didn't support the exact profile indicated in sps header,
1529 * check for the compatible profiles also */
1530 static void
ensure_caps_profile(GstH265Parse * h265parse,GstCaps * caps,GstH265SPS * sps)1531 ensure_caps_profile (GstH265Parse * h265parse, GstCaps * caps, GstH265SPS * sps)
1532 {
1533 GstCaps *peer_caps, *compat_caps;
1534
1535 peer_caps = gst_pad_get_current_caps (GST_BASE_PARSE_SRC_PAD (h265parse));
1536 if (!peer_caps || !gst_caps_can_intersect (caps, peer_caps)) {
1537 GstCaps *filter_caps = gst_caps_new_empty_simple ("video/x-h265");
1538
1539 if (peer_caps)
1540 gst_caps_unref (peer_caps);
1541 peer_caps =
1542 gst_pad_peer_query_caps (GST_BASE_PARSE_SRC_PAD (h265parse),
1543 filter_caps);
1544
1545 gst_caps_unref (filter_caps);
1546 }
1547
1548 if (peer_caps && !gst_caps_can_intersect (caps, peer_caps)) {
1549 GstStructure *structure;
1550
1551 compat_caps = get_compatible_profile_caps (sps);
1552 if (compat_caps != NULL) {
1553 GstCaps *res_caps = NULL;
1554
1555 res_caps = gst_caps_intersect (peer_caps, compat_caps);
1556
1557 if (res_caps && !gst_caps_is_empty (res_caps)) {
1558 const gchar *profile_str = NULL;
1559
1560 res_caps = gst_caps_fixate (res_caps);
1561 structure = gst_caps_get_structure (res_caps, 0);
1562 profile_str = gst_structure_get_string (structure, "profile");
1563 if (profile_str) {
1564 gst_caps_set_simple (caps, "profile", G_TYPE_STRING, profile_str,
1565 NULL);
1566 GST_DEBUG_OBJECT (h265parse,
1567 "Setting compatible profile %s to the caps", profile_str);
1568 }
1569 }
1570 if (res_caps)
1571 gst_caps_unref (res_caps);
1572 gst_caps_unref (compat_caps);
1573 }
1574 }
1575 if (peer_caps)
1576 gst_caps_unref (peer_caps);
1577 }
1578
1579 static void
gst_h265_parse_update_src_caps(GstH265Parse * h265parse,GstCaps * caps)1580 gst_h265_parse_update_src_caps (GstH265Parse * h265parse, GstCaps * caps)
1581 {
1582 GstH265SPS *sps;
1583 GstCaps *sink_caps, *src_caps;
1584 gboolean modified = FALSE;
1585 GstBuffer *buf = NULL;
1586 GstStructure *s = NULL;
1587
1588 if (G_UNLIKELY (!gst_pad_has_current_caps (GST_BASE_PARSE_SRC_PAD
1589 (h265parse))))
1590 modified = TRUE;
1591 else if (G_UNLIKELY (!h265parse->update_caps))
1592 return;
1593
1594 /* if this is being called from the first _setcaps call, caps on the sinkpad
1595 * aren't set yet and so they need to be passed as an argument */
1596 if (caps)
1597 sink_caps = gst_caps_ref (caps);
1598 else
1599 sink_caps = gst_pad_get_current_caps (GST_BASE_PARSE_SINK_PAD (h265parse));
1600
1601 /* carry over input caps as much as possible; override with our own stuff */
1602 if (!sink_caps)
1603 sink_caps = gst_caps_new_empty_simple ("video/x-h265");
1604 else
1605 s = gst_caps_get_structure (sink_caps, 0);
1606
1607 sps = h265parse->nalparser->last_sps;
1608 GST_DEBUG_OBJECT (h265parse, "sps: %p", sps);
1609
1610 /* only codec-data for nice-and-clean au aligned packetized hevc format */
1611 if ((h265parse->format == GST_H265_PARSE_FORMAT_HVC1
1612 || h265parse->format == GST_H265_PARSE_FORMAT_HEV1)
1613 && h265parse->align == GST_H265_PARSE_ALIGN_AU) {
1614 buf = gst_h265_parse_make_codec_data (h265parse);
1615 if (buf && h265parse->codec_data) {
1616 GstMapInfo map;
1617
1618 gst_buffer_map (buf, &map, GST_MAP_READ);
1619 if (map.size != gst_buffer_get_size (h265parse->codec_data) ||
1620 gst_buffer_memcmp (h265parse->codec_data, 0, map.data, map.size))
1621 modified = TRUE;
1622
1623 gst_buffer_unmap (buf, &map);
1624 } else {
1625 if (!buf && h265parse->codec_data_in)
1626 buf = gst_buffer_ref (h265parse->codec_data_in);
1627 modified = TRUE;
1628 }
1629 }
1630
1631 caps = NULL;
1632 if (G_UNLIKELY (!sps)) {
1633 caps = gst_caps_copy (sink_caps);
1634 } else {
1635 gint crop_width, crop_height;
1636 const gchar *chroma_format = NULL;
1637 guint bit_depth_chroma;
1638
1639 if (sps->conformance_window_flag) {
1640 crop_width = sps->crop_rect_width;
1641 crop_height = sps->crop_rect_height;
1642 } else {
1643 crop_width = sps->width;
1644 crop_height = sps->height;
1645 }
1646
1647 if (G_UNLIKELY (h265parse->width != crop_width ||
1648 h265parse->height != crop_height)) {
1649 GST_INFO_OBJECT (h265parse, "resolution changed %dx%d",
1650 crop_width, crop_height);
1651 h265parse->width = crop_width;
1652 h265parse->height = crop_height;
1653 modified = TRUE;
1654 }
1655
1656 /* 0/1 is set as the default in the codec parser */
1657 if (sps->vui_params.timing_info_present_flag &&
1658 !(sps->fps_num == 0 && sps->fps_den == 1)) {
1659 if (G_UNLIKELY (h265parse->fps_num != sps->fps_num
1660 || h265parse->fps_den != sps->fps_den)) {
1661 GST_INFO_OBJECT (h265parse, "framerate changed %d/%d",
1662 sps->fps_num, sps->fps_den);
1663 h265parse->fps_num = sps->fps_num;
1664 h265parse->fps_den = sps->fps_den;
1665 modified = TRUE;
1666 }
1667 }
1668
1669 if (sps->vui_params.aspect_ratio_info_present_flag) {
1670 if (G_UNLIKELY ((h265parse->parsed_par_n != sps->vui_params.par_n)
1671 && (h265parse->parsed_par_d != sps->vui_params.par_d))) {
1672 h265parse->parsed_par_n = sps->vui_params.par_n;
1673 h265parse->parsed_par_d = sps->vui_params.par_d;
1674 GST_INFO_OBJECT (h265parse, "pixel aspect ratio has been changed %d/%d",
1675 h265parse->parsed_par_n, h265parse->parsed_par_d);
1676 modified = TRUE;
1677 }
1678
1679 }
1680
1681 if (G_UNLIKELY (modified || h265parse->update_caps)) {
1682 gint fps_num = h265parse->fps_num;
1683 gint fps_den = h265parse->fps_den;
1684 gint width, height;
1685 GstClockTime latency;
1686
1687 caps = gst_caps_copy (sink_caps);
1688
1689 /* sps should give this but upstream overrides */
1690 if (s && gst_structure_has_field (s, "width"))
1691 gst_structure_get_int (s, "width", &width);
1692 else
1693 width = h265parse->width;
1694
1695 if (s && gst_structure_has_field (s, "height"))
1696 gst_structure_get_int (s, "height", &height);
1697 else
1698 height = h265parse->height;
1699
1700 gst_caps_set_simple (caps, "width", G_TYPE_INT, width,
1701 "height", G_TYPE_INT, height, NULL);
1702
1703 /* upstream overrides */
1704 if (s && gst_structure_has_field (s, "framerate"))
1705 gst_structure_get_fraction (s, "framerate", &fps_num, &fps_den);
1706
1707 /* but not necessarily or reliably this */
1708 if (fps_num > 0 && fps_den > 0) {
1709 GstStructure *s2;
1710 GST_INFO_OBJECT (h265parse, "setting framerate in caps");
1711 gst_caps_set_simple (caps, "framerate",
1712 GST_TYPE_FRACTION, fps_num, fps_den, NULL);
1713 s2 = gst_caps_get_structure (caps, 0);
1714 gst_structure_get_fraction (s2, "framerate", &h265parse->parsed_fps_n,
1715 &h265parse->parsed_fps_d);
1716 gst_base_parse_set_frame_rate (GST_BASE_PARSE (h265parse),
1717 fps_num, fps_den, 0, 0);
1718 latency = gst_util_uint64_scale (GST_SECOND, fps_den, fps_num);
1719 gst_base_parse_set_latency (GST_BASE_PARSE (h265parse), latency,
1720 latency);
1721 }
1722
1723 bit_depth_chroma = sps->bit_depth_chroma_minus8 + 8;
1724
1725 switch (sps->chroma_format_idc) {
1726 case 0:
1727 chroma_format = "4:0:0";
1728 bit_depth_chroma = 0;
1729 break;
1730 case 1:
1731 chroma_format = "4:2:0";
1732 break;
1733 case 2:
1734 chroma_format = "4:2:2";
1735 break;
1736 case 3:
1737 chroma_format = "4:4:4";
1738 break;
1739 default:
1740 break;
1741 }
1742
1743 if (chroma_format)
1744 gst_caps_set_simple (caps, "chroma-format", G_TYPE_STRING,
1745 chroma_format, "bit-depth-luma", G_TYPE_UINT,
1746 sps->bit_depth_luma_minus8 + 8, "bit-depth-chroma", G_TYPE_UINT,
1747 bit_depth_chroma, NULL);
1748 }
1749 }
1750
1751 if (caps) {
1752 gint par_n, par_d;
1753
1754 gst_caps_set_simple (caps, "parsed", G_TYPE_BOOLEAN, TRUE,
1755 "stream-format", G_TYPE_STRING,
1756 gst_h265_parse_get_string (h265parse, TRUE, h265parse->format),
1757 "alignment", G_TYPE_STRING,
1758 gst_h265_parse_get_string (h265parse, FALSE, h265parse->align), NULL);
1759
1760 gst_h265_parse_get_par (h265parse, &par_n, &par_d);
1761 if (par_n != 0 && par_d != 0 &&
1762 (!s || !gst_structure_has_field (s, "pixel-aspect-ratio"))) {
1763 GST_INFO_OBJECT (h265parse, "PAR %d/%d", par_n, par_d);
1764 gst_caps_set_simple (caps, "pixel-aspect-ratio", GST_TYPE_FRACTION,
1765 par_n, par_d, NULL);
1766 }
1767
1768 /* set profile and level in caps */
1769 if (sps) {
1770 const gchar *profile, *tier, *level;
1771 GstH265Profile p;
1772
1773 p = gst_h265_profile_tier_level_get_profile (&sps->profile_tier_level);
1774 profile = get_profile_string (p);
1775 if (profile != NULL)
1776 gst_caps_set_simple (caps, "profile", G_TYPE_STRING, profile, NULL);
1777
1778 tier = get_tier_string (sps->profile_tier_level.tier_flag);
1779 if (tier != NULL)
1780 gst_caps_set_simple (caps, "tier", G_TYPE_STRING, tier, NULL);
1781
1782 level = get_level_string (sps->profile_tier_level.level_idc);
1783 if (level != NULL)
1784 gst_caps_set_simple (caps, "level", G_TYPE_STRING, level, NULL);
1785
1786 /* relax the profile constraint to find a suitable decoder */
1787 ensure_caps_profile (h265parse, caps, sps);
1788 }
1789
1790 src_caps = gst_pad_get_current_caps (GST_BASE_PARSE_SRC_PAD (h265parse));
1791
1792 if (src_caps) {
1793 /* use codec data from old caps for comparison; we don't want to resend caps
1794 if everything is same except codec data; */
1795 if (gst_structure_has_field (gst_caps_get_structure (src_caps, 0),
1796 "codec_data")) {
1797 gst_caps_set_value (caps, "codec_data",
1798 gst_structure_get_value (gst_caps_get_structure (src_caps, 0),
1799 "codec_data"));
1800 } else if (!buf) {
1801 GstStructure *s;
1802 /* remove any left-over codec-data hanging around */
1803 s = gst_caps_get_structure (caps, 0);
1804 gst_structure_remove_field (s, "codec_data");
1805 }
1806 }
1807
1808 if (!(src_caps && gst_caps_is_strictly_equal (src_caps, caps))) {
1809 /* update codec data to new value */
1810 if (buf) {
1811 gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER, buf, NULL);
1812 gst_buffer_replace (&h265parse->codec_data, buf);
1813 gst_buffer_unref (buf);
1814 buf = NULL;
1815 } else {
1816 GstStructure *s;
1817 /* remove any left-over codec-data hanging around */
1818 s = gst_caps_get_structure (caps, 0);
1819 gst_structure_remove_field (s, "codec_data");
1820 gst_buffer_replace (&h265parse->codec_data, NULL);
1821 }
1822
1823 gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (h265parse), caps);
1824 }
1825
1826 if (src_caps)
1827 gst_caps_unref (src_caps);
1828 gst_caps_unref (caps);
1829 }
1830
1831 gst_caps_unref (sink_caps);
1832 if (buf)
1833 gst_buffer_unref (buf);
1834
1835 }
1836
1837 static GstFlowReturn
gst_h265_parse_parse_frame(GstBaseParse * parse,GstBaseParseFrame * frame)1838 gst_h265_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
1839 {
1840 GstH265Parse *h265parse;
1841 GstBuffer *buffer;
1842 guint av;
1843
1844 h265parse = GST_H265_PARSE (parse);
1845 buffer = frame->buffer;
1846
1847 gst_h265_parse_update_src_caps (h265parse, NULL);
1848
1849 /* Fixme: Implement timestamp interpolation based on SEI Messagses */
1850 GST_FIXME_OBJECT (h265parse,
1851 "Implement timestamp/duration interpolation based on SEI message");
1852
1853 if (h265parse->keyframe)
1854 GST_BUFFER_FLAG_UNSET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);
1855 else
1856 GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);
1857
1858 if (h265parse->header)
1859 GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_HEADER);
1860 else
1861 GST_BUFFER_FLAG_UNSET (buffer, GST_BUFFER_FLAG_HEADER);
1862
1863 if (h265parse->discont) {
1864 GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
1865 h265parse->discont = FALSE;
1866 }
1867
1868 /* replace with transformed HEVC output if applicable */
1869 av = gst_adapter_available (h265parse->frame_out);
1870 if (av) {
1871 GstBuffer *buf;
1872
1873 buf = gst_adapter_take_buffer (h265parse->frame_out, av);
1874 gst_buffer_copy_into (buf, buffer, GST_BUFFER_COPY_METADATA, 0, -1);
1875 gst_buffer_replace (&frame->out_buffer, buf);
1876 gst_buffer_unref (buf);
1877 }
1878
1879 return GST_FLOW_OK;
1880 }
1881
1882 /* sends a codec NAL downstream, decorating and transforming as needed.
1883 * No ownership is taken of @nal */
1884 static GstFlowReturn
gst_h265_parse_push_codec_buffer(GstH265Parse * h265parse,GstBuffer * nal,GstClockTime ts)1885 gst_h265_parse_push_codec_buffer (GstH265Parse * h265parse, GstBuffer * nal,
1886 GstClockTime ts)
1887 {
1888 GstMapInfo map;
1889
1890 gst_buffer_map (nal, &map, GST_MAP_READ);
1891 nal = gst_h265_parse_wrap_nal (h265parse, h265parse->format,
1892 map.data, map.size);
1893 gst_buffer_unmap (nal, &map);
1894
1895 GST_BUFFER_TIMESTAMP (nal) = ts;
1896 GST_BUFFER_DURATION (nal) = 0;
1897
1898 return gst_pad_push (GST_BASE_PARSE_SRC_PAD (h265parse), nal);
1899 }
1900
1901 static GstEvent *
check_pending_key_unit_event(GstEvent * pending_event,GstSegment * segment,GstClockTime timestamp,guint flags,GstClockTime pending_key_unit_ts)1902 check_pending_key_unit_event (GstEvent * pending_event, GstSegment * segment,
1903 GstClockTime timestamp, guint flags, GstClockTime pending_key_unit_ts)
1904 {
1905 GstClockTime running_time, stream_time;
1906 gboolean all_headers;
1907 guint count;
1908 GstEvent *event = NULL;
1909
1910 g_return_val_if_fail (segment != NULL, NULL);
1911
1912 if (pending_event == NULL)
1913 goto out;
1914
1915 if (GST_CLOCK_TIME_IS_VALID (pending_key_unit_ts) &&
1916 timestamp == GST_CLOCK_TIME_NONE)
1917 goto out;
1918
1919 running_time = gst_segment_to_running_time (segment,
1920 GST_FORMAT_TIME, timestamp);
1921
1922 GST_INFO ("now %" GST_TIME_FORMAT " wanted %" GST_TIME_FORMAT,
1923 GST_TIME_ARGS (running_time), GST_TIME_ARGS (pending_key_unit_ts));
1924 if (GST_CLOCK_TIME_IS_VALID (pending_key_unit_ts) &&
1925 running_time < pending_key_unit_ts)
1926 goto out;
1927
1928 if (flags & GST_BUFFER_FLAG_DELTA_UNIT) {
1929 GST_DEBUG ("pending force key unit, waiting for keyframe");
1930 goto out;
1931 }
1932
1933 stream_time = gst_segment_to_stream_time (segment,
1934 GST_FORMAT_TIME, timestamp);
1935
1936 if (!gst_video_event_parse_upstream_force_key_unit (pending_event,
1937 NULL, &all_headers, &count)) {
1938 gst_video_event_parse_downstream_force_key_unit (pending_event, NULL,
1939 NULL, NULL, &all_headers, &count);
1940 }
1941
1942 event =
1943 gst_video_event_new_downstream_force_key_unit (timestamp, stream_time,
1944 running_time, all_headers, count);
1945 gst_event_set_seqnum (event, gst_event_get_seqnum (pending_event));
1946
1947 out:
1948 return event;
1949 }
1950
1951 static void
gst_h265_parse_prepare_key_unit(GstH265Parse * parse,GstEvent * event)1952 gst_h265_parse_prepare_key_unit (GstH265Parse * parse, GstEvent * event)
1953 {
1954 GstClockTime running_time;
1955 guint count;
1956 #ifndef GST_DISABLE_GST_DEBUG
1957 gboolean have_vps, have_sps, have_pps;
1958 gint i;
1959 #endif
1960
1961 parse->pending_key_unit_ts = GST_CLOCK_TIME_NONE;
1962 gst_event_replace (&parse->force_key_unit_event, NULL);
1963
1964 gst_video_event_parse_downstream_force_key_unit (event,
1965 NULL, NULL, &running_time, NULL, &count);
1966
1967 GST_INFO_OBJECT (parse, "pushing downstream force-key-unit event %d "
1968 "%" GST_TIME_FORMAT " count %d", gst_event_get_seqnum (event),
1969 GST_TIME_ARGS (running_time), count);
1970 gst_pad_push_event (GST_BASE_PARSE_SRC_PAD (parse), event);
1971
1972 #ifndef GST_DISABLE_GST_DEBUG
1973 have_vps = have_sps = have_pps = FALSE;
1974 for (i = 0; i < GST_H265_MAX_VPS_COUNT; i++) {
1975 if (parse->vps_nals[i] != NULL) {
1976 have_vps = TRUE;
1977 break;
1978 }
1979 }
1980 for (i = 0; i < GST_H265_MAX_SPS_COUNT; i++) {
1981 if (parse->sps_nals[i] != NULL) {
1982 have_sps = TRUE;
1983 break;
1984 }
1985 }
1986 for (i = 0; i < GST_H265_MAX_PPS_COUNT; i++) {
1987 if (parse->pps_nals[i] != NULL) {
1988 have_pps = TRUE;
1989 break;
1990 }
1991 }
1992
1993 GST_INFO_OBJECT (parse,
1994 "preparing key unit, have vps %d have sps %d have pps %d", have_vps,
1995 have_sps, have_pps);
1996 #endif
1997
1998 /* set push_codec to TRUE so that pre_push_frame sends VPS/SPS/PPS again */
1999 parse->push_codec = TRUE;
2000 }
2001
2002 static gboolean
gst_h265_parse_handle_vps_sps_pps_nals(GstH265Parse * h265parse,GstBuffer * buffer,GstBaseParseFrame * frame)2003 gst_h265_parse_handle_vps_sps_pps_nals (GstH265Parse * h265parse,
2004 GstBuffer * buffer, GstBaseParseFrame * frame)
2005 {
2006 GstBuffer *codec_nal;
2007 gint i;
2008 gboolean send_done = FALSE;
2009 GstClockTime timestamp = GST_BUFFER_TIMESTAMP (buffer);
2010
2011 if (h265parse->have_vps_in_frame && h265parse->have_sps_in_frame
2012 && h265parse->have_pps_in_frame) {
2013 GST_DEBUG_OBJECT (h265parse, "VPS/SPS/PPS exist in frame, will not insert");
2014 return TRUE;
2015 }
2016
2017 if (h265parse->align == GST_H265_PARSE_ALIGN_NAL) {
2018 /* send separate config NAL buffers */
2019 GST_DEBUG_OBJECT (h265parse, "- sending VPS/SPS/PPS");
2020 for (i = 0; i < GST_H265_MAX_VPS_COUNT; i++) {
2021 if ((codec_nal = h265parse->vps_nals[i])) {
2022 GST_DEBUG_OBJECT (h265parse, "sending VPS nal");
2023 gst_h265_parse_push_codec_buffer (h265parse, codec_nal, timestamp);
2024 send_done = TRUE;
2025 }
2026 }
2027 for (i = 0; i < GST_H265_MAX_SPS_COUNT; i++) {
2028 if ((codec_nal = h265parse->sps_nals[i])) {
2029 GST_DEBUG_OBJECT (h265parse, "sending SPS nal");
2030 gst_h265_parse_push_codec_buffer (h265parse, codec_nal, timestamp);
2031 send_done = TRUE;
2032 }
2033 }
2034 for (i = 0; i < GST_H265_MAX_PPS_COUNT; i++) {
2035 if ((codec_nal = h265parse->pps_nals[i])) {
2036 GST_DEBUG_OBJECT (h265parse, "sending PPS nal");
2037 gst_h265_parse_push_codec_buffer (h265parse, codec_nal, timestamp);
2038 send_done = TRUE;
2039 }
2040 }
2041 } else {
2042 /* insert config NALs into AU */
2043 GstByteWriter bw;
2044 GstBuffer *new_buf;
2045 const gboolean bs = h265parse->format == GST_H265_PARSE_FORMAT_BYTE;
2046 const gint nls = 4 - h265parse->nal_length_size;
2047 gboolean ok;
2048
2049 gst_byte_writer_init_with_size (&bw, gst_buffer_get_size (buffer), FALSE);
2050 ok = gst_byte_writer_put_buffer (&bw, buffer, 0, h265parse->idr_pos);
2051 GST_DEBUG_OBJECT (h265parse, "- inserting VPS/SPS/PPS");
2052 for (i = 0; i < GST_H265_MAX_VPS_COUNT; i++) {
2053 if ((codec_nal = h265parse->vps_nals[i])) {
2054 gsize nal_size = gst_buffer_get_size (codec_nal);
2055 GST_DEBUG_OBJECT (h265parse, "inserting VPS nal");
2056 if (bs) {
2057 ok &= gst_byte_writer_put_uint32_be (&bw, 1);
2058 } else {
2059 ok &= gst_byte_writer_put_uint32_be (&bw, (nal_size << (nls * 8)));
2060 ok &= gst_byte_writer_set_pos (&bw,
2061 gst_byte_writer_get_pos (&bw) - nls);
2062 }
2063
2064 ok &= gst_byte_writer_put_buffer (&bw, codec_nal, 0, nal_size);
2065 send_done = TRUE;
2066 }
2067 }
2068 for (i = 0; i < GST_H265_MAX_SPS_COUNT; i++) {
2069 if ((codec_nal = h265parse->sps_nals[i])) {
2070 gsize nal_size = gst_buffer_get_size (codec_nal);
2071 GST_DEBUG_OBJECT (h265parse, "inserting SPS nal");
2072 if (bs) {
2073 ok &= gst_byte_writer_put_uint32_be (&bw, 1);
2074 } else {
2075 ok &= gst_byte_writer_put_uint32_be (&bw, (nal_size << (nls * 8)));
2076 ok &= gst_byte_writer_set_pos (&bw,
2077 gst_byte_writer_get_pos (&bw) - nls);
2078 }
2079
2080 ok &= gst_byte_writer_put_buffer (&bw, codec_nal, 0, nal_size);
2081 send_done = TRUE;
2082 }
2083 }
2084 for (i = 0; i < GST_H265_MAX_PPS_COUNT; i++) {
2085 if ((codec_nal = h265parse->pps_nals[i])) {
2086 gsize nal_size = gst_buffer_get_size (codec_nal);
2087 GST_DEBUG_OBJECT (h265parse, "inserting PPS nal");
2088 if (bs) {
2089 ok &= gst_byte_writer_put_uint32_be (&bw, 1);
2090 } else {
2091 ok &= gst_byte_writer_put_uint32_be (&bw, (nal_size << (nls * 8)));
2092 ok &= gst_byte_writer_set_pos (&bw,
2093 gst_byte_writer_get_pos (&bw) - nls);
2094 }
2095 ok &= gst_byte_writer_put_buffer (&bw, codec_nal, 0, nal_size);
2096 send_done = TRUE;
2097 }
2098 }
2099 ok &= gst_byte_writer_put_buffer (&bw, buffer, h265parse->idr_pos, -1);
2100 /* collect result and push */
2101 new_buf = gst_byte_writer_reset_and_get_buffer (&bw);
2102 gst_buffer_copy_into (new_buf, buffer, GST_BUFFER_COPY_METADATA, 0, -1);
2103 /* should already be keyframe/IDR, but it may not have been,
2104 * so mark it as such to avoid being discarded by picky decoder */
2105 GST_BUFFER_FLAG_UNSET (new_buf, GST_BUFFER_FLAG_DELTA_UNIT);
2106 gst_buffer_replace (&frame->out_buffer, new_buf);
2107 gst_buffer_unref (new_buf);
2108 /* some result checking seems to make some compilers happy */
2109 if (G_UNLIKELY (!ok)) {
2110 GST_ERROR_OBJECT (h265parse, "failed to insert SPS/PPS");
2111 }
2112 }
2113
2114 return send_done;
2115 }
2116
2117 static GstFlowReturn
gst_h265_parse_pre_push_frame(GstBaseParse * parse,GstBaseParseFrame * frame)2118 gst_h265_parse_pre_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
2119 {
2120 GstH265Parse *h265parse;
2121 GstBuffer *buffer;
2122 GstEvent *event;
2123
2124 h265parse = GST_H265_PARSE (parse);
2125
2126 if (!h265parse->sent_codec_tag) {
2127 GstTagList *taglist;
2128 GstCaps *caps;
2129
2130 /* codec tag */
2131 caps = gst_pad_get_current_caps (GST_BASE_PARSE_SRC_PAD (parse));
2132 if (G_UNLIKELY (caps == NULL)) {
2133 if (GST_PAD_IS_FLUSHING (GST_BASE_PARSE_SRC_PAD (parse))) {
2134 GST_INFO_OBJECT (parse, "Src pad is flushing");
2135 return GST_FLOW_FLUSHING;
2136 } else {
2137 GST_INFO_OBJECT (parse, "Src pad is not negotiated!");
2138 return GST_FLOW_NOT_NEGOTIATED;
2139 }
2140 }
2141
2142 taglist = gst_tag_list_new_empty ();
2143 gst_pb_utils_add_codec_description_to_tag_list (taglist,
2144 GST_TAG_VIDEO_CODEC, caps);
2145 gst_caps_unref (caps);
2146
2147 gst_base_parse_merge_tags (parse, taglist, GST_TAG_MERGE_REPLACE);
2148 gst_tag_list_unref (taglist);
2149
2150 /* also signals the end of first-frame processing */
2151 h265parse->sent_codec_tag = TRUE;
2152 }
2153
2154 buffer = frame->buffer;
2155
2156 if ((event = check_pending_key_unit_event (h265parse->force_key_unit_event,
2157 &parse->segment, GST_BUFFER_TIMESTAMP (buffer),
2158 GST_BUFFER_FLAGS (buffer), h265parse->pending_key_unit_ts))) {
2159 gst_h265_parse_prepare_key_unit (h265parse, event);
2160 }
2161
2162 /* periodic VPS/SPS/PPS sending */
2163 if (h265parse->interval > 0 || h265parse->push_codec) {
2164 GstClockTime timestamp = GST_BUFFER_TIMESTAMP (buffer);
2165 guint64 diff;
2166 gboolean initial_frame = FALSE;
2167
2168 /* init */
2169 if (!GST_CLOCK_TIME_IS_VALID (h265parse->last_report)) {
2170 h265parse->last_report = timestamp;
2171 initial_frame = TRUE;
2172 }
2173
2174 if (h265parse->idr_pos >= 0) {
2175 GST_LOG_OBJECT (h265parse, "IDR nal at offset %d", h265parse->idr_pos);
2176
2177 if (timestamp > h265parse->last_report)
2178 diff = timestamp - h265parse->last_report;
2179 else
2180 diff = 0;
2181
2182 GST_LOG_OBJECT (h265parse,
2183 "now %" GST_TIME_FORMAT ", last VPS/SPS/PPS %" GST_TIME_FORMAT,
2184 GST_TIME_ARGS (timestamp), GST_TIME_ARGS (h265parse->last_report));
2185
2186 GST_DEBUG_OBJECT (h265parse,
2187 "interval since last VPS/SPS/PPS %" GST_TIME_FORMAT,
2188 GST_TIME_ARGS (diff));
2189
2190 if (GST_TIME_AS_SECONDS (diff) >= h265parse->interval ||
2191 initial_frame || h265parse->push_codec) {
2192 GstClockTime new_ts;
2193
2194 /* avoid overwriting a perfectly fine timestamp */
2195 new_ts = GST_CLOCK_TIME_IS_VALID (timestamp) ? timestamp :
2196 h265parse->last_report;
2197
2198 if (gst_h265_parse_handle_vps_sps_pps_nals (h265parse, buffer, frame)) {
2199 h265parse->last_report = new_ts;
2200 }
2201 }
2202
2203 /* we pushed whatever we had */
2204 h265parse->push_codec = FALSE;
2205 h265parse->have_vps = FALSE;
2206 h265parse->have_sps = FALSE;
2207 h265parse->have_pps = FALSE;
2208 h265parse->state &= GST_H265_PARSE_STATE_VALID_PICTURE_HEADERS;
2209 }
2210 } else if (h265parse->interval == -1) {
2211 if (h265parse->idr_pos >= 0) {
2212 GST_LOG_OBJECT (h265parse, "IDR nal at offset %d", h265parse->idr_pos);
2213
2214 gst_h265_parse_handle_vps_sps_pps_nals (h265parse, buffer, frame);
2215
2216 /* we pushed whatever we had */
2217 h265parse->push_codec = FALSE;
2218 h265parse->have_vps = FALSE;
2219 h265parse->have_sps = FALSE;
2220 h265parse->have_pps = FALSE;
2221 h265parse->state &= GST_H265_PARSE_STATE_VALID_PICTURE_HEADERS;
2222 }
2223 }
2224
2225 {
2226 guint i = 0;
2227
2228 for (i = 0; i < h265parse->time_code.num_clock_ts; i++) {
2229 GstVideoTimeCodeFlags flags = 0;
2230 gint field_count = -1;
2231 guint n_frames;
2232
2233 if (!h265parse->time_code.clock_timestamp_flag[i])
2234 break;
2235
2236 h265parse->time_code.clock_timestamp_flag[i] = 0;
2237
2238 /* Table D.2 */
2239 switch (h265parse->sei_pic_struct) {
2240 case GST_H265_SEI_PIC_STRUCT_FRAME:
2241 case GST_H265_SEI_PIC_STRUCT_TOP_FIELD:
2242 case GST_H265_SEI_PIC_STRUCT_BOTTOM_FIELD:
2243 field_count = h265parse->sei_pic_struct;
2244 break;
2245 case GST_H265_SEI_PIC_STRUCT_TOP_BOTTOM:
2246 case GST_H265_SEI_PIC_STRUCT_TOP_PAIRED_PREVIOUS_BOTTOM:
2247 case GST_H265_SEI_PIC_STRUCT_TOP_PAIRED_NEXT_BOTTOM:
2248 field_count = i + 1;
2249 break;
2250 case GST_H265_SEI_PIC_STRUCT_BOTTOM_TOP:
2251 case GST_H265_SEI_PIC_STRUCT_BOTTOM_PAIRED_PREVIOUS_TOP:
2252 case GST_H265_SEI_PIC_STRUCT_BOTTOM_PAIRED_NEXT_TOP:
2253 field_count = 2 - i;
2254 break;
2255 case GST_H265_SEI_PIC_STRUCT_TOP_BOTTOM_TOP:
2256 field_count = i % 2 ? 2 : 1;
2257 break;
2258 case GST_H265_SEI_PIC_STRUCT_BOTTOM_TOP_BOTTOM:
2259 field_count = i % 2 ? 1 : 2;
2260 break;
2261 case GST_H265_SEI_PIC_STRUCT_FRAME_DOUBLING:
2262 case GST_H265_SEI_PIC_STRUCT_FRAME_TRIPLING:
2263 field_count = 0;
2264 break;
2265 }
2266
2267 if (field_count == -1) {
2268 GST_WARNING_OBJECT (parse,
2269 "failed to determine field count for timecode");
2270 field_count = 0;
2271 }
2272
2273 /* Dropping of the two lowest (value 0 and 1) n_frames[ i ] counts when
2274 * seconds_value[ i ] is equal to 0 and minutes_value[ i ] is not an integer
2275 * multiple of 10 */
2276 if (h265parse->time_code.counting_type[i] == 4)
2277 flags |= GST_VIDEO_TIME_CODE_FLAGS_DROP_FRAME;
2278
2279 if (h265parse->sei_pic_struct != GST_H265_SEI_PIC_STRUCT_FRAME)
2280 flags |= GST_VIDEO_TIME_CODE_FLAGS_INTERLACED;
2281
2282 n_frames =
2283 gst_util_uint64_scale_int (h265parse->time_code.n_frames[i], 1,
2284 2 - h265parse->time_code.units_field_based_flag[i]);
2285
2286 gst_buffer_add_video_time_code_meta_full (buffer,
2287 h265parse->parsed_fps_n,
2288 h265parse->parsed_fps_d,
2289 NULL,
2290 flags,
2291 h265parse->time_code.hours_flag[i] ? h265parse->
2292 time_code.hours_value[i] : 0,
2293 h265parse->time_code.minutes_flag[i] ? h265parse->
2294 time_code.minutes_value[i] : 0,
2295 h265parse->time_code.seconds_flag[i] ? h265parse->
2296 time_code.seconds_value[i] : 0, n_frames, field_count);
2297 }
2298 }
2299
2300 gst_h265_parse_reset_frame (h265parse);
2301
2302 return GST_FLOW_OK;
2303 }
2304
2305 static gboolean
gst_h265_parse_set_caps(GstBaseParse * parse,GstCaps * caps)2306 gst_h265_parse_set_caps (GstBaseParse * parse, GstCaps * caps)
2307 {
2308 GstH265Parse *h265parse;
2309 GstStructure *str;
2310 const GValue *value;
2311 GstBuffer *codec_data = NULL;
2312 gsize off, size;
2313 guint format, align;
2314 guint num_nals, i, j;
2315 GstH265NalUnit nalu;
2316 GstH265ParserResult parseres;
2317 GstCaps *old_caps;
2318
2319 h265parse = GST_H265_PARSE (parse);
2320
2321 /* reset */
2322 h265parse->push_codec = FALSE;
2323
2324 old_caps = gst_pad_get_current_caps (GST_BASE_PARSE_SINK_PAD (parse));
2325 if (old_caps) {
2326 if (!gst_caps_is_equal (old_caps, caps))
2327 gst_h265_parse_reset_stream_info (h265parse);
2328 gst_caps_unref (old_caps);
2329 }
2330
2331 str = gst_caps_get_structure (caps, 0);
2332
2333 /* accept upstream info if provided */
2334 gst_structure_get_int (str, "width", &h265parse->width);
2335 gst_structure_get_int (str, "height", &h265parse->height);
2336 gst_structure_get_fraction (str, "framerate", &h265parse->fps_num,
2337 &h265parse->fps_den);
2338 gst_structure_get_fraction (str, "pixel-aspect-ratio",
2339 &h265parse->upstream_par_n, &h265parse->upstream_par_d);
2340
2341 /* get upstream format and align from caps */
2342 gst_h265_parse_format_from_caps (caps, &format, &align);
2343
2344 /* packetized video has a codec_data */
2345 if (format != GST_H265_PARSE_FORMAT_BYTE &&
2346 (value = gst_structure_get_value (str, "codec_data"))) {
2347 GstMapInfo map;
2348 guint8 *data;
2349 guint num_nal_arrays;
2350
2351 GST_DEBUG_OBJECT (h265parse, "have packetized h265");
2352 /* make note for optional split processing */
2353 h265parse->packetized = TRUE;
2354
2355 codec_data = gst_value_get_buffer (value);
2356 if (!codec_data)
2357 goto wrong_type;
2358 gst_buffer_map (codec_data, &map, GST_MAP_READ);
2359 data = map.data;
2360 size = map.size;
2361
2362 /* parse the hvcC data */
2363 if (size < 23) {
2364 gst_buffer_unmap (codec_data, &map);
2365 goto hvcc_too_small;
2366 }
2367 /* parse the version, this must be one but
2368 * is zero until the spec is finalized */
2369 if (data[0] != 0 && data[0] != 1) {
2370 gst_buffer_unmap (codec_data, &map);
2371 goto wrong_version;
2372 }
2373
2374 h265parse->nal_length_size = (data[21] & 0x03) + 1;
2375 GST_DEBUG_OBJECT (h265parse, "nal length size %u",
2376 h265parse->nal_length_size);
2377
2378 num_nal_arrays = data[22];
2379 off = 23;
2380
2381 for (i = 0; i < num_nal_arrays; i++) {
2382 if (off + 3 >= size) {
2383 gst_buffer_unmap (codec_data, &map);
2384 goto hvcc_too_small;
2385 }
2386
2387 num_nals = GST_READ_UINT16_BE (data + off + 1);
2388 off += 3;
2389 for (j = 0; j < num_nals; j++) {
2390 parseres = gst_h265_parser_identify_nalu_hevc (h265parse->nalparser,
2391 data, off, size, 2, &nalu);
2392
2393 if (parseres != GST_H265_PARSER_OK) {
2394 gst_buffer_unmap (codec_data, &map);
2395 goto hvcc_too_small;
2396 }
2397
2398 gst_h265_parse_process_nal (h265parse, &nalu);
2399 off = nalu.offset + nalu.size;
2400 }
2401 }
2402 gst_buffer_unmap (codec_data, &map);
2403
2404 /* don't confuse codec_data with inband vps/sps/pps */
2405 h265parse->have_vps_in_frame = FALSE;
2406 h265parse->have_sps_in_frame = FALSE;
2407 h265parse->have_pps_in_frame = FALSE;
2408 } else {
2409 GST_DEBUG_OBJECT (h265parse, "have bytestream h265");
2410 /* nothing to pre-process */
2411 h265parse->packetized = FALSE;
2412 /* we have 4 sync bytes */
2413 h265parse->nal_length_size = 4;
2414
2415 if (format == GST_H265_PARSE_FORMAT_NONE) {
2416 format = GST_H265_PARSE_FORMAT_BYTE;
2417 align = GST_H265_PARSE_ALIGN_AU;
2418 }
2419 }
2420
2421 {
2422 GstCaps *in_caps;
2423
2424 /* prefer input type determined above */
2425 in_caps = gst_caps_new_simple ("video/x-h265",
2426 "parsed", G_TYPE_BOOLEAN, TRUE,
2427 "stream-format", G_TYPE_STRING,
2428 gst_h265_parse_get_string (h265parse, TRUE, format),
2429 "alignment", G_TYPE_STRING,
2430 gst_h265_parse_get_string (h265parse, FALSE, align), NULL);
2431 /* negotiate with downstream, sets ->format and ->align */
2432 gst_h265_parse_negotiate (h265parse, format, in_caps);
2433 gst_caps_unref (in_caps);
2434 }
2435
2436 if (format == h265parse->format && align == h265parse->align) {
2437 /* do not set CAPS and passthrough mode if SPS/PPS have not been parsed */
2438 if (h265parse->have_sps && h265parse->have_pps) {
2439 gst_base_parse_set_passthrough (parse, TRUE);
2440
2441 /* we did parse codec-data and might supplement src caps */
2442 gst_h265_parse_update_src_caps (h265parse, caps);
2443 }
2444 } else if (format == GST_H265_PARSE_FORMAT_HVC1
2445 || format == GST_H265_PARSE_FORMAT_HEV1) {
2446 /* if input != output, and input is hevc, must split before anything else */
2447 /* arrange to insert codec-data in-stream if needed.
2448 * src caps are only arranged for later on */
2449 h265parse->push_codec = TRUE;
2450 h265parse->have_vps = FALSE;
2451 h265parse->have_sps = FALSE;
2452 h265parse->have_pps = FALSE;
2453 if (h265parse->align == GST_H265_PARSE_ALIGN_NAL)
2454 h265parse->split_packetized = TRUE;
2455 h265parse->packetized = TRUE;
2456 }
2457
2458 return TRUE;
2459
2460 /* ERRORS */
2461 hvcc_too_small:
2462 {
2463 GST_DEBUG_OBJECT (h265parse, "hvcC size %" G_GSIZE_FORMAT " < 23", size);
2464 goto refuse_caps;
2465 }
2466 wrong_version:
2467 {
2468 GST_DEBUG_OBJECT (h265parse, "wrong hvcC version");
2469 goto refuse_caps;
2470 }
2471 wrong_type:
2472 {
2473 GST_DEBUG_OBJECT (h265parse, "wrong codec-data type");
2474 goto refuse_caps;
2475 }
2476 refuse_caps:
2477 {
2478 GST_WARNING_OBJECT (h265parse, "refused caps %" GST_PTR_FORMAT, caps);
2479 return FALSE;
2480 }
2481 }
2482
2483 static void
remove_fields(GstCaps * caps,gboolean all)2484 remove_fields (GstCaps * caps, gboolean all)
2485 {
2486 guint i, n;
2487
2488 n = gst_caps_get_size (caps);
2489 for (i = 0; i < n; i++) {
2490 GstStructure *s = gst_caps_get_structure (caps, i);
2491
2492 if (all) {
2493 gst_structure_remove_field (s, "alignment");
2494 gst_structure_remove_field (s, "stream-format");
2495 }
2496 gst_structure_remove_field (s, "parsed");
2497 }
2498 }
2499
2500 static GstCaps *
gst_h265_parse_get_caps(GstBaseParse * parse,GstCaps * filter)2501 gst_h265_parse_get_caps (GstBaseParse * parse, GstCaps * filter)
2502 {
2503 GstCaps *peercaps, *templ;
2504 GstCaps *res, *tmp, *pcopy;
2505
2506 templ = gst_pad_get_pad_template_caps (GST_BASE_PARSE_SINK_PAD (parse));
2507 if (filter) {
2508 GstCaps *fcopy = gst_caps_copy (filter);
2509 /* Remove the fields we convert */
2510 remove_fields (fcopy, TRUE);
2511 peercaps = gst_pad_peer_query_caps (GST_BASE_PARSE_SRC_PAD (parse), fcopy);
2512 gst_caps_unref (fcopy);
2513 } else
2514 peercaps = gst_pad_peer_query_caps (GST_BASE_PARSE_SRC_PAD (parse), NULL);
2515
2516 pcopy = gst_caps_copy (peercaps);
2517 remove_fields (pcopy, TRUE);
2518
2519 res = gst_caps_intersect_full (pcopy, templ, GST_CAPS_INTERSECT_FIRST);
2520 gst_caps_unref (pcopy);
2521 gst_caps_unref (templ);
2522
2523 if (filter) {
2524 GstCaps *tmp = gst_caps_intersect_full (res, filter,
2525 GST_CAPS_INTERSECT_FIRST);
2526 gst_caps_unref (res);
2527 res = tmp;
2528 }
2529
2530 /* Try if we can put the downstream caps first */
2531 pcopy = gst_caps_copy (peercaps);
2532 remove_fields (pcopy, FALSE);
2533 tmp = gst_caps_intersect_full (pcopy, res, GST_CAPS_INTERSECT_FIRST);
2534 gst_caps_unref (pcopy);
2535 if (!gst_caps_is_empty (tmp))
2536 res = gst_caps_merge (tmp, res);
2537 else
2538 gst_caps_unref (tmp);
2539
2540 gst_caps_unref (peercaps);
2541 return res;
2542 }
2543
2544 static gboolean
gst_h265_parse_event(GstBaseParse * parse,GstEvent * event)2545 gst_h265_parse_event (GstBaseParse * parse, GstEvent * event)
2546 {
2547 gboolean res;
2548 GstH265Parse *h265parse = GST_H265_PARSE (parse);
2549
2550 switch (GST_EVENT_TYPE (event)) {
2551 case GST_EVENT_CUSTOM_DOWNSTREAM:
2552 {
2553 GstClockTime timestamp, stream_time, running_time;
2554 gboolean all_headers;
2555 guint count;
2556
2557 if (gst_video_event_is_force_key_unit (event)) {
2558 gst_video_event_parse_downstream_force_key_unit (event,
2559 ×tamp, &stream_time, &running_time, &all_headers, &count);
2560
2561 GST_INFO_OBJECT (h265parse, "received downstream force key unit event, "
2562 "seqnum %d running_time %" GST_TIME_FORMAT
2563 " all_headers %d count %d", gst_event_get_seqnum (event),
2564 GST_TIME_ARGS (running_time), all_headers, count);
2565 if (h265parse->force_key_unit_event) {
2566 GST_INFO_OBJECT (h265parse, "ignoring force key unit event "
2567 "as one is already queued");
2568 } else {
2569 h265parse->pending_key_unit_ts = running_time;
2570 gst_event_replace (&h265parse->force_key_unit_event, event);
2571 }
2572 gst_event_unref (event);
2573 res = TRUE;
2574 } else {
2575 res = GST_BASE_PARSE_CLASS (parent_class)->sink_event (parse, event);
2576 break;
2577 }
2578 break;
2579 }
2580 case GST_EVENT_FLUSH_STOP:
2581 h265parse->push_codec = TRUE;
2582 res = GST_BASE_PARSE_CLASS (parent_class)->sink_event (parse, event);
2583 break;
2584 case GST_EVENT_SEGMENT:
2585 {
2586 h265parse->last_report = GST_CLOCK_TIME_NONE;
2587
2588 res = GST_BASE_PARSE_CLASS (parent_class)->sink_event (parse, event);
2589 break;
2590 }
2591 default:
2592 res = GST_BASE_PARSE_CLASS (parent_class)->sink_event (parse, event);
2593 break;
2594 }
2595 return res;
2596 }
2597
2598 static gboolean
gst_h265_parse_src_event(GstBaseParse * parse,GstEvent * event)2599 gst_h265_parse_src_event (GstBaseParse * parse, GstEvent * event)
2600 {
2601 gboolean res;
2602 GstH265Parse *h265parse = GST_H265_PARSE (parse);
2603
2604 switch (GST_EVENT_TYPE (event)) {
2605 case GST_EVENT_CUSTOM_UPSTREAM:
2606 {
2607 GstClockTime running_time;
2608 gboolean all_headers;
2609 guint count;
2610
2611 if (gst_video_event_is_force_key_unit (event)) {
2612 gst_video_event_parse_upstream_force_key_unit (event,
2613 &running_time, &all_headers, &count);
2614
2615 GST_INFO_OBJECT (h265parse, "received upstream force-key-unit event, "
2616 "seqnum %d running_time %" GST_TIME_FORMAT
2617 " all_headers %d count %d", gst_event_get_seqnum (event),
2618 GST_TIME_ARGS (running_time), all_headers, count);
2619
2620 if (all_headers) {
2621 h265parse->pending_key_unit_ts = running_time;
2622 gst_event_replace (&h265parse->force_key_unit_event, event);
2623 }
2624 }
2625 res = GST_BASE_PARSE_CLASS (parent_class)->src_event (parse, event);
2626 break;
2627 }
2628 default:
2629 res = GST_BASE_PARSE_CLASS (parent_class)->src_event (parse, event);
2630 break;
2631 }
2632
2633 return res;
2634 }
2635
2636 static void
gst_h265_parse_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)2637 gst_h265_parse_set_property (GObject * object, guint prop_id,
2638 const GValue * value, GParamSpec * pspec)
2639 {
2640 GstH265Parse *parse;
2641 parse = GST_H265_PARSE (object);
2642
2643 switch (prop_id) {
2644 case PROP_CONFIG_INTERVAL:
2645 parse->interval = g_value_get_int (value);
2646 break;
2647 default:
2648 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
2649 break;
2650 }
2651 }
2652
2653 static void
gst_h265_parse_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)2654 gst_h265_parse_get_property (GObject * object, guint prop_id, GValue * value,
2655 GParamSpec * pspec)
2656 {
2657 GstH265Parse *parse;
2658 parse = GST_H265_PARSE (object);
2659
2660 switch (prop_id) {
2661 case PROP_CONFIG_INTERVAL:
2662 g_value_set_int (value, parse->interval);
2663 break;
2664 default:
2665 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
2666 break;
2667 }
2668 }
2669