1 /*
2 * GStreamer AVTP Plugin
3 * Copyright (C) 2019 Intel Corporation
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later
9 * version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301 USA
20 */
21
22 /**
23 * SECTION:element-avtpcvfdepay
24 * @see_also: avtpcvfpay
25 *
26 * De-payload CVF AVTPDUs into compressed video (currently, only H.264) according
27 * to IEEE 1722-2016. For detailed information see
28 * https://standards.ieee.org/standard/1722-2016.html.
29 *
30 * <refsect2>
31 * <title>Example pipeline</title>
32 * |[
33 * gst-launch-1.0 avtpsrc ! avtpcvfdepay ! decodebin ! videoconvert ! autovideosink
34 * ]| This example pipeline will de-payload H.264 video from the AVTPDUs, decode
35 * and play them. Refer to the avtpcvfpay example to payload H.264 and send the
36 * AVTP stream.
37 * </refsect2>
38 */
39
40 #include <avtp.h>
41 #include <avtp_cvf.h>
42 #include <gst/audio/audio-format.h>
43 #include <arpa/inet.h>
44
45 #include "gstavtpcvfdepay.h"
46
47 GST_DEBUG_CATEGORY_STATIC (avtpcvfdepay_debug);
48 #define GST_CAT_DEFAULT avtpcvfdepay_debug
49
50 /* prototypes */
51
52 static GstFlowReturn gst_avtp_cvf_depay_chain (GstPad * pad, GstObject * parent,
53 GstBuffer * buffer);
54 static GstStateChangeReturn gst_avtp_cvf_depay_change_state (GstElement *
55 element, GstStateChange transition);
56
57 #define AVTP_CVF_H264_HEADER_SIZE (sizeof(struct avtp_stream_pdu) + sizeof(guint32))
58 #define FU_A_HEADER_SIZE (sizeof(guint16))
59 #define STAP_A_TYPE 24
60 #define STAP_B_TYPE 25
61 #define MTAP16_TYPE 26
62 #define MTAP24_TYPE 27
63 #define FU_A_TYPE 28
64 #define FU_B_TYPE 29
65
66 #define NRI_MASK 0x60
67 #define NRI_SHIFT 5
68 #define START_MASK 0x80
69 #define START_SHIFT 7
70 #define END_MASK 0x40
71 #define END_SHIFT 6
72 #define NAL_TYPE_MASK 0x1f
73
74 /* pad templates */
75
76 static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
77 GST_PAD_SRC,
78 GST_PAD_ALWAYS,
79 GST_STATIC_CAPS ("video/x-h264,"
80 " stream-format = (string) avc, alignment = (string) au")
81 );
82
83 #define gst_avtp_cvf_depay_parent_class parent_class
84 G_DEFINE_TYPE (GstAvtpCvfDepay, gst_avtp_cvf_depay,
85 GST_TYPE_AVTP_BASE_DEPAYLOAD);
86 GST_ELEMENT_REGISTER_DEFINE (avtpcvfdepay, "avtpcvfdepay", GST_RANK_NONE,
87 GST_TYPE_AVTP_CVF_DEPAY);
88
89 static void
gst_avtp_cvf_depay_class_init(GstAvtpCvfDepayClass * klass)90 gst_avtp_cvf_depay_class_init (GstAvtpCvfDepayClass * klass)
91 {
92 GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
93 GstAvtpBaseDepayloadClass *avtpbasedepayload_class =
94 GST_AVTP_BASE_DEPAYLOAD_CLASS (klass);
95
96 gst_element_class_add_static_pad_template (element_class, &src_template);
97
98 gst_element_class_set_static_metadata (element_class,
99 "AVTP Compressed Video Format (CVF) depayloader",
100 "Codec/Depayloader/Network/AVTP",
101 "Extracts compressed video from CVF AVTPDUs",
102 "Ederson de Souza <ederson.desouza@intel.com>");
103
104 element_class->change_state =
105 GST_DEBUG_FUNCPTR (gst_avtp_cvf_depay_change_state);
106
107 avtpbasedepayload_class->chain = GST_DEBUG_FUNCPTR (gst_avtp_cvf_depay_chain);
108
109 GST_DEBUG_CATEGORY_INIT (avtpcvfdepay_debug, "avtpcvfdepay",
110 0, "debug category for avtpcvfdepay element");
111 }
112
113 static void
gst_avtp_cvf_depay_init(GstAvtpCvfDepay * avtpcvfdepay)114 gst_avtp_cvf_depay_init (GstAvtpCvfDepay * avtpcvfdepay)
115 {
116 avtpcvfdepay->out_buffer = NULL;
117 avtpcvfdepay->fragments = NULL;
118 avtpcvfdepay->seqnum = 0;
119 }
120
121 static GstStateChangeReturn
gst_avtp_cvf_depay_change_state(GstElement * element,GstStateChange transition)122 gst_avtp_cvf_depay_change_state (GstElement *
123 element, GstStateChange transition)
124 {
125 GstAvtpCvfDepay *avtpcvfdepay = GST_AVTP_CVF_DEPAY (element);
126 GstStateChangeReturn ret;
127
128 ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
129 if (ret == GST_STATE_CHANGE_FAILURE) {
130 return ret;
131 }
132
133 if (transition == GST_STATE_CHANGE_READY_TO_NULL) {
134 if (avtpcvfdepay->out_buffer) {
135 gst_buffer_unref (avtpcvfdepay->out_buffer);
136 avtpcvfdepay->out_buffer = NULL;
137 }
138 }
139
140 return ret;
141 }
142
143 static gboolean
gst_avtp_cvf_depay_push_caps(GstAvtpCvfDepay * avtpcvfdepay)144 gst_avtp_cvf_depay_push_caps (GstAvtpCvfDepay * avtpcvfdepay)
145 {
146 GstAvtpBaseDepayload *avtpbasedepayload =
147 GST_AVTP_BASE_DEPAYLOAD (avtpcvfdepay);
148 GstBuffer *codec_data;
149 GstEvent *event;
150 GstMapInfo map;
151 GstCaps *caps;
152
153 GST_DEBUG_OBJECT (avtpcvfdepay, "Setting src pad caps");
154
155 /* Send simple codec data, with only the NAL size len, no SPS/PPS.
156 * Below, 7 is the minimal codec_data size, when no SPS/PPS is sent */
157 codec_data = gst_buffer_new_allocate (NULL, 7, NULL);
158 gst_buffer_map (codec_data, &map, GST_MAP_READWRITE);
159
160 memset (map.data, 0, map.size);
161 map.data[0] = 1; /* version */
162 map.data[4] = 0x03 | 0xfc; /* nal len size (4) - 1. Other 6 bits are 1 */
163 map.data[5] = 0xe0; /* first 3 bits are 1 */
164 gst_buffer_unmap (codec_data, &map);
165
166 caps = gst_pad_get_pad_template_caps (avtpbasedepayload->srcpad);
167 caps = gst_caps_make_writable (caps);
168 gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER, codec_data, NULL);
169
170 event = gst_event_new_caps (caps);
171
172 gst_buffer_unref (codec_data);
173 gst_caps_unref (caps);
174
175 return gst_pad_push_event (avtpbasedepayload->srcpad, event);
176 }
177
178 static GstFlowReturn
gst_avtp_cvf_depay_push(GstAvtpCvfDepay * avtpcvfdepay)179 gst_avtp_cvf_depay_push (GstAvtpCvfDepay * avtpcvfdepay)
180 {
181 GstAvtpBaseDepayload *avtpbasedepayload =
182 GST_AVTP_BASE_DEPAYLOAD (avtpcvfdepay);
183 GstFlowReturn ret;
184
185 if (G_UNLIKELY (!gst_pad_has_current_caps (avtpbasedepayload->srcpad))) {
186 guint64 pts_m;
187 guint32 dts, pts;
188
189 if (gst_debug_category_get_threshold (GST_CAT_DEFAULT) >= GST_LEVEL_DEBUG) {
190 GstClock *clock = gst_element_get_clock (GST_ELEMENT_CAST (avtpcvfdepay));
191 if (clock == NULL) {
192 GST_DEBUG_OBJECT (avtpcvfdepay,
193 "Sending initial CAPS and SEGMENT, no pipeline time.");
194 } else {
195 GST_DEBUG_OBJECT (avtpcvfdepay,
196 "Sending initial CAPS and SEGMENT, pipeline time: %"
197 GST_TIME_FORMAT, GST_TIME_ARGS (gst_clock_get_time (clock)));
198 }
199 }
200
201 if (!gst_avtp_cvf_depay_push_caps (avtpcvfdepay)) {
202 GST_ELEMENT_ERROR (avtpcvfdepay, CORE, CAPS, (NULL), (NULL));
203 return GST_FLOW_ERROR;
204 }
205
206 if (!gst_avtp_base_depayload_push_segment_event (avtpbasedepayload,
207 GST_BUFFER_PTS (avtpcvfdepay->out_buffer))) {
208 GST_ELEMENT_ERROR (avtpcvfdepay, CORE, EVENT,
209 ("Could not send SEGMENT event"), (NULL));
210 }
211
212 /* Now that we sent our segment starting on the first Presentation
213 * time available, `avtpbasedepayload->prev_ptime` saves that value,
214 * to be a reference for calculating future buffer timestamps from
215 * the AVTP timestamps (avtp_ts and h264_ts).
216 *
217 * However, decode timestamps can be smaller than presentation
218 * timestamps. So we can't use `avtpbasedepayload->prev_time` as
219 * reference to calculate them. Instead, here, we calculate the
220 * first decode timestamp and save it on `avtpcvfdepay->prev_ptime`.
221 *
222 * The method used to calculate the "absolute" decode timestamp (DTS)
223 * from presentation timestamp is as follows:
224 *
225 * DTS = dts > pts ? (PTSm - 1) | dts : PTSm | dts
226 *
227 * Where:
228 * dts: 32 bits gPTP decode timestamp
229 * pts: 32 bits gPTP presentation timestamp
230 * PTSm: 32 most signifactive bits of the "absolute" presentation
231 * timestamp
232 *
233 * This allow us to handle cases where the pts ends up being smaller
234 * than dts due pts falling after an AVTP timestamp wrapping.
235 */
236
237 pts = GST_BUFFER_PTS (avtpcvfdepay->out_buffer);
238 dts = GST_BUFFER_DTS (avtpcvfdepay->out_buffer);
239 pts_m = avtpbasedepayload->prev_ptime & 0xFFFFFFFF00000000ULL;
240
241 avtpbasedepayload->prev_ptime = dts > pts ? (pts_m -=
242 (1ULL << 32)) | dts : pts_m | dts;
243 GST_DEBUG_OBJECT (avtpcvfdepay, "prev_ptime set to %" GST_TIME_FORMAT,
244 GST_TIME_ARGS (avtpbasedepayload->prev_ptime));
245 }
246
247 /* At this point, we're sure segment was sent, so we can properly calc
248 * buffer timestamps */
249 GST_DEBUG_OBJECT (avtpcvfdepay, "Converting %" GST_TIME_FORMAT " to PTS",
250 GST_TIME_ARGS (GST_BUFFER_PTS (avtpcvfdepay->out_buffer)));
251 GST_BUFFER_PTS (avtpcvfdepay->out_buffer) =
252 gst_avtp_base_depayload_tstamp_to_ptime (avtpbasedepayload, GST_BUFFER_PTS
253 (avtpcvfdepay->out_buffer), avtpbasedepayload->prev_ptime);
254
255 GST_DEBUG_OBJECT (avtpcvfdepay, "Converting %" GST_TIME_FORMAT " to DTS",
256 GST_TIME_ARGS (GST_BUFFER_DTS (avtpcvfdepay->out_buffer)));
257 GST_BUFFER_DTS (avtpcvfdepay->out_buffer) =
258 gst_avtp_base_depayload_tstamp_to_ptime (avtpbasedepayload, GST_BUFFER_DTS
259 (avtpcvfdepay->out_buffer), avtpbasedepayload->prev_ptime);
260
261 /* Use DTS as prev_ptime as it is smaller or equal to PTS, so that
262 * next calculations of PTS/DTS won't wrap too early */
263 avtpbasedepayload->prev_ptime = GST_BUFFER_DTS (avtpcvfdepay->out_buffer);
264
265 ret = gst_pad_push (GST_AVTP_BASE_DEPAYLOAD (avtpcvfdepay)->srcpad,
266 avtpcvfdepay->out_buffer);
267 avtpcvfdepay->out_buffer = NULL;
268
269 return ret;
270 }
271
272 static GstFlowReturn
gst_avtp_cvf_depay_push_and_discard(GstAvtpCvfDepay * avtpcvfdepay)273 gst_avtp_cvf_depay_push_and_discard (GstAvtpCvfDepay * avtpcvfdepay)
274 {
275 GstFlowReturn ret = GST_FLOW_OK;
276
277 /* Push everything we have, hopefully decoder can handle it */
278 if (avtpcvfdepay->out_buffer != NULL) {
279 GST_DEBUG_OBJECT (avtpcvfdepay, "Pushing incomplete buffers");
280
281 ret = gst_avtp_cvf_depay_push (avtpcvfdepay);
282 }
283
284 /* Discard any incomplete fragments */
285 if (avtpcvfdepay->fragments != NULL) {
286 GST_DEBUG_OBJECT (avtpcvfdepay, "Discarding incomplete fragments");
287 gst_buffer_unref (avtpcvfdepay->fragments);
288 avtpcvfdepay->fragments = NULL;
289 }
290
291 return ret;
292 }
293
294 static gboolean
gst_avtp_cvf_depay_validate_avtpdu(GstAvtpCvfDepay * avtpcvfdepay,GstMapInfo * map,gboolean * lost_packet)295 gst_avtp_cvf_depay_validate_avtpdu (GstAvtpCvfDepay * avtpcvfdepay,
296 GstMapInfo * map, gboolean * lost_packet)
297 {
298 GstAvtpBaseDepayload *avtpbasedepayload =
299 GST_AVTP_BASE_DEPAYLOAD (avtpcvfdepay);
300 struct avtp_stream_pdu *pdu;
301 gboolean result = FALSE;
302 guint64 val;
303 guint val32;
304 gint r;
305
306 if (G_UNLIKELY (map->size < AVTP_CVF_H264_HEADER_SIZE)) {
307 GST_DEBUG_OBJECT (avtpcvfdepay,
308 "Incomplete AVTP header, expected it to have size of %zd, got %zd",
309 AVTP_CVF_H264_HEADER_SIZE, map->size);
310 goto end;
311 }
312
313 pdu = (struct avtp_stream_pdu *) map->data;
314
315 r = avtp_pdu_get ((struct avtp_common_pdu *) pdu, AVTP_FIELD_SUBTYPE, &val32);
316 g_assert (r == 0);
317 if (val32 != AVTP_SUBTYPE_CVF) {
318 GST_DEBUG_OBJECT (avtpcvfdepay,
319 "Unexpected AVTP header subtype %d, expected %d", val32,
320 AVTP_SUBTYPE_CVF);
321 goto end;
322 }
323
324 r = avtp_pdu_get ((struct avtp_common_pdu *) pdu, AVTP_FIELD_VERSION, &val32);
325 g_assert (r == 0);
326 if (G_UNLIKELY (val32 != 0)) {
327 GST_DEBUG_OBJECT (avtpcvfdepay,
328 "Unexpected AVTP header version %d, expected %d", val32, 0);
329 goto end;
330 }
331
332 r = avtp_cvf_pdu_get (pdu, AVTP_CVF_FIELD_SV, &val);
333 g_assert (r == 0);
334 if (G_UNLIKELY (val != 1)) {
335 GST_DEBUG_OBJECT (avtpcvfdepay,
336 "Unexpected AVTP header stream valid %" G_GUINT64_FORMAT
337 ", expected %d", val, 1);
338 goto end;
339 }
340
341 r = avtp_cvf_pdu_get (pdu, AVTP_CVF_FIELD_STREAM_ID, &val);
342 g_assert (r == 0);
343 if (val != avtpbasedepayload->streamid) {
344 GST_DEBUG_OBJECT (avtpcvfdepay,
345 "Unexpected AVTP header stream id 0x%" G_GINT64_MODIFIER
346 "x, expected 0x%" G_GINT64_MODIFIER "x", val,
347 avtpbasedepayload->streamid);
348 goto end;
349 }
350
351 r = avtp_cvf_pdu_get (pdu, AVTP_CVF_FIELD_FORMAT, &val);
352 g_assert (r == 0);
353 if (G_UNLIKELY (val != AVTP_CVF_FORMAT_RFC)) {
354 GST_DEBUG_OBJECT (avtpcvfdepay,
355 "Unexpected AVTP header format %" G_GUINT64_FORMAT ", expected %d", val,
356 AVTP_CVF_FORMAT_RFC);
357 goto end;
358 }
359
360 r = avtp_cvf_pdu_get (pdu, AVTP_CVF_FIELD_FORMAT_SUBTYPE, &val);
361 g_assert (r == 0);
362 if (G_UNLIKELY (val != AVTP_CVF_FORMAT_SUBTYPE_H264)) {
363 GST_DEBUG_OBJECT (avtpcvfdepay,
364 "Unsupported AVTP header format subtype %" G_GUINT64_FORMAT, val);
365 goto end;
366 }
367
368 r = avtp_cvf_pdu_get (pdu, AVTP_CVF_FIELD_STREAM_DATA_LEN, &val);
369 g_assert (r == 0);
370 if (G_UNLIKELY (map->size < sizeof (*pdu) + val)) {
371 GST_DEBUG_OBJECT (avtpcvfdepay,
372 "AVTP packet size %" G_GSIZE_FORMAT " too small, expected at least %"
373 G_GUINT64_FORMAT, map->size - AVTP_CVF_H264_HEADER_SIZE,
374 sizeof (*pdu) + val);
375 goto end;
376 }
377
378 *lost_packet = FALSE;
379 r = avtp_cvf_pdu_get (pdu, AVTP_CVF_FIELD_SEQ_NUM, &val);
380 g_assert (r == 0);
381 if (G_UNLIKELY (val != avtpcvfdepay->seqnum)) {
382 GST_INFO_OBJECT (avtpcvfdepay,
383 "Unexpected AVTP header seq num %" G_GUINT64_FORMAT ", expected %u",
384 val, avtpcvfdepay->seqnum);
385
386 avtpcvfdepay->seqnum = val;
387 /* This is not a reason to drop the packet, but it may be a good moment
388 * to push everything we have - maybe we lost the M packet? */
389 *lost_packet = TRUE;
390 }
391 avtpcvfdepay->seqnum++;
392
393 result = TRUE;
394
395 end:
396 return result;
397 }
398
399 static guint8
gst_avtp_cvf_depay_get_nal_type(GstMapInfo * map)400 gst_avtp_cvf_depay_get_nal_type (GstMapInfo * map)
401 {
402 struct avtp_stream_pdu *pdu;
403 struct avtp_cvf_h264_payload *pay;
404 guint8 nal_header, nal_type;
405
406 pdu = (struct avtp_stream_pdu *) map->data;
407 pay = (struct avtp_cvf_h264_payload *) pdu->avtp_payload;
408 nal_header = pay->h264_data[0];
409 nal_type = nal_header & NAL_TYPE_MASK;
410
411 return nal_type;
412 }
413
414 static void
gst_avtp_cvf_depay_get_avtp_timestamps(GstAvtpCvfDepay * avtpcvfdepay,GstMapInfo * map,GstClockTime * pts,GstClockTime * dts)415 gst_avtp_cvf_depay_get_avtp_timestamps (GstAvtpCvfDepay * avtpcvfdepay,
416 GstMapInfo * map, GstClockTime * pts, GstClockTime * dts)
417 {
418 struct avtp_stream_pdu *pdu;
419 guint64 avtp_time, h264_time, tv, ptv;
420 gint res;
421
422 *pts = GST_CLOCK_TIME_NONE;
423 *dts = GST_CLOCK_TIME_NONE;
424
425 pdu = (struct avtp_stream_pdu *) map->data;
426
427 res = avtp_cvf_pdu_get (pdu, AVTP_CVF_FIELD_TV, &tv);
428 g_assert (res == 0);
429
430 if (tv == 1) {
431 res = avtp_cvf_pdu_get (pdu, AVTP_CVF_FIELD_TIMESTAMP, &avtp_time);
432 g_assert (res == 0);
433
434 *dts = avtp_time;
435 }
436
437 res = avtp_cvf_pdu_get (pdu, AVTP_CVF_FIELD_H264_PTV, &ptv);
438 g_assert (res == 0);
439
440 if (ptv == 1) {
441 res = avtp_cvf_pdu_get (pdu, AVTP_CVF_FIELD_H264_TIMESTAMP, &h264_time);
442 g_assert (res == 0);
443
444 *pts = h264_time;
445 }
446 }
447
448 static GstFlowReturn
gst_avtp_cvf_depay_internal_push(GstAvtpCvfDepay * avtpcvfdepay,GstBuffer * buffer,gboolean M)449 gst_avtp_cvf_depay_internal_push (GstAvtpCvfDepay * avtpcvfdepay,
450 GstBuffer * buffer, gboolean M)
451 {
452 GstFlowReturn ret = GST_FLOW_OK;
453
454 GST_LOG_OBJECT (avtpcvfdepay,
455 "Adding buffer of size %" G_GSIZE_FORMAT " (nalu size %"
456 G_GSIZE_FORMAT ") to out_buffer", gst_buffer_get_size (buffer),
457 gst_buffer_get_size (buffer) - sizeof (guint32));
458
459 if (avtpcvfdepay->out_buffer) {
460 avtpcvfdepay->out_buffer =
461 gst_buffer_append (avtpcvfdepay->out_buffer, buffer);
462 } else {
463 avtpcvfdepay->out_buffer = buffer;
464 }
465
466 /* We only truly push to decoder when we get the last video buffer */
467 if (M) {
468 ret = gst_avtp_cvf_depay_push (avtpcvfdepay);
469 }
470
471 return ret;
472 }
473
474 static void
gst_avtp_cvf_depay_get_M(GstAvtpCvfDepay * avtpcvfdepay,GstMapInfo * map,gboolean * M)475 gst_avtp_cvf_depay_get_M (GstAvtpCvfDepay * avtpcvfdepay, GstMapInfo * map,
476 gboolean * M)
477 {
478 struct avtp_stream_pdu *pdu;
479 guint64 val;
480 gint res;
481
482 pdu = (struct avtp_stream_pdu *) map->data;
483
484 res = avtp_cvf_pdu_get (pdu, AVTP_CVF_FIELD_M, &val);
485 g_assert (res == 0);
486
487 *M = val;
488 }
489
490 static void
gst_avtp_cvf_depay_get_nalu_size(GstAvtpCvfDepay * avtpcvfdepay,GstMapInfo * map,guint16 * nalu_size)491 gst_avtp_cvf_depay_get_nalu_size (GstAvtpCvfDepay * avtpcvfdepay,
492 GstMapInfo * map, guint16 * nalu_size)
493 {
494 struct avtp_stream_pdu *pdu;
495 guint64 val;
496 gint res;
497
498 pdu = (struct avtp_stream_pdu *) map->data;
499
500 res = avtp_cvf_pdu_get (pdu, AVTP_CVF_FIELD_STREAM_DATA_LEN, &val);
501 g_assert (res == 0);
502
503 /* We need to discount the H.264 header field */
504 *nalu_size = val - sizeof (guint32);
505 }
506
507 static GstFlowReturn
gst_avtp_cvf_depay_process_last_fragment(GstAvtpCvfDepay * avtpcvfdepay,GstBuffer * avtpdu,GstMapInfo * map,gsize offset,gsize nalu_size,guint8 nri,guint8 nal_type)508 gst_avtp_cvf_depay_process_last_fragment (GstAvtpCvfDepay * avtpcvfdepay,
509 GstBuffer * avtpdu, GstMapInfo * map, gsize offset, gsize nalu_size,
510 guint8 nri, guint8 nal_type)
511 {
512 GstBuffer *nal;
513 GstMapInfo map_nal;
514 GstClockTime pts, dts;
515 gboolean M;
516 GstFlowReturn ret = GST_FLOW_OK;
517
518 if (G_UNLIKELY (avtpcvfdepay->fragments == NULL)) {
519 GST_DEBUG_OBJECT (avtpcvfdepay,
520 "Received final fragment, but no start fragment received. Dropping it.");
521 goto end;
522 }
523
524 gst_buffer_copy_into (avtpcvfdepay->fragments, avtpdu,
525 GST_BUFFER_COPY_MEMORY, offset, nalu_size);
526
527 /* Allocate buffer to keep the nal_header (1 byte) and the NALu size (4 bytes) */
528 nal = gst_buffer_new_allocate (NULL, 4 + 1, NULL);
529 if (G_UNLIKELY (nal == NULL)) {
530 GST_ERROR_OBJECT (avtpcvfdepay, "Could not allocate buffer");
531 ret = GST_FLOW_ERROR;
532 goto end;
533 }
534
535 gst_buffer_map (nal, &map_nal, GST_MAP_READWRITE);
536 /* Add NAL size. Extra 1 counts the nal_header */
537 nalu_size = gst_buffer_get_size (avtpcvfdepay->fragments) + 1;
538 map_nal.data[0] = nalu_size >> 24;
539 map_nal.data[1] = nalu_size >> 16;
540 map_nal.data[2] = nalu_size >> 8;
541 map_nal.data[3] = nalu_size;
542
543 /* Finally, add the nal_header */
544 map_nal.data[4] = (nri << 5) | nal_type;
545
546 gst_buffer_unmap (nal, &map_nal);
547
548 nal = gst_buffer_append (nal, avtpcvfdepay->fragments);
549
550 gst_avtp_cvf_depay_get_avtp_timestamps (avtpcvfdepay, map, &pts, &dts);
551 GST_BUFFER_PTS (nal) = pts;
552 GST_BUFFER_DTS (nal) = dts;
553
554 gst_avtp_cvf_depay_get_M (avtpcvfdepay, map, &M);
555 ret = gst_avtp_cvf_depay_internal_push (avtpcvfdepay, nal, M);
556
557 avtpcvfdepay->fragments = NULL;
558
559 end:
560 return ret;
561 }
562
563 static GstFlowReturn
gst_avtp_cvf_depay_handle_fu_a(GstAvtpCvfDepay * avtpcvfdepay,GstBuffer * avtpdu,GstMapInfo * map)564 gst_avtp_cvf_depay_handle_fu_a (GstAvtpCvfDepay * avtpcvfdepay,
565 GstBuffer * avtpdu, GstMapInfo * map)
566 {
567 GstFlowReturn ret = GST_FLOW_OK;
568 struct avtp_stream_pdu *pdu;
569 struct avtp_cvf_h264_payload *pay;
570 guint8 fu_header, fu_indicator, nal_type, start, end, nri;
571 guint16 nalu_size;
572 gsize offset;
573
574 if (G_UNLIKELY (map->size - AVTP_CVF_H264_HEADER_SIZE < 2)) {
575 GST_ERROR_OBJECT (avtpcvfdepay,
576 "Buffer too small to contain fragment headers, size: %"
577 G_GSIZE_FORMAT, map->size - AVTP_CVF_H264_HEADER_SIZE);
578 ret = gst_avtp_cvf_depay_push_and_discard (avtpcvfdepay);
579 goto end;
580 }
581
582 pdu = (struct avtp_stream_pdu *) map->data;
583 pay = (struct avtp_cvf_h264_payload *) pdu->avtp_payload;
584 fu_indicator = pay->h264_data[0];
585 nri = (fu_indicator & NRI_MASK) >> NRI_SHIFT;
586
587 GST_DEBUG_OBJECT (avtpcvfdepay, "Fragment indicator - NRI: %u", nri);
588
589 fu_header = pay->h264_data[1];
590 nal_type = fu_header & NAL_TYPE_MASK;
591 start = (fu_header & START_MASK) >> START_SHIFT;
592 end = (fu_header & END_MASK) >> END_SHIFT;
593
594 GST_DEBUG_OBJECT (avtpcvfdepay,
595 "Fragment header - type: %u start: %u end: %u", nal_type, start, end);
596
597 if (G_UNLIKELY (start && end)) {
598 GST_ERROR_OBJECT (avtpcvfdepay,
599 "Invalid fragment header - 'start' and 'end' bits set");
600 ret = gst_avtp_cvf_depay_push_and_discard (avtpcvfdepay);
601 goto end;
602 }
603
604 /* Size and offset also ignores the FU_HEADER and FU_INDICATOR fields,
605 * hence the "sizeof(guint8) * 2" */
606 offset = AVTP_CVF_H264_HEADER_SIZE + sizeof (guint8) * 2;
607 gst_avtp_cvf_depay_get_nalu_size (avtpcvfdepay, map, &nalu_size);
608 nalu_size -= sizeof (guint8) * 2;
609
610 if (start) {
611 if (G_UNLIKELY (avtpcvfdepay->fragments != NULL)) {
612 GST_DEBUG_OBJECT (avtpcvfdepay,
613 "Received starting fragment, but previous one is not complete. Dropping old fragment");
614 ret = gst_avtp_cvf_depay_push_and_discard (avtpcvfdepay);
615 if (ret != GST_FLOW_OK)
616 goto end;
617 }
618
619 avtpcvfdepay->fragments =
620 gst_buffer_copy_region (avtpdu, GST_BUFFER_COPY_MEMORY, offset,
621 nalu_size);
622 }
623
624 if (!start && !end) {
625 if (G_UNLIKELY (avtpcvfdepay->fragments == NULL)) {
626 GST_DEBUG_OBJECT (avtpcvfdepay,
627 "Received intermediate fragment, but no start fragment received. Dropping it.");
628 ret = gst_avtp_cvf_depay_push_and_discard (avtpcvfdepay);
629 goto end;
630 }
631 gst_buffer_copy_into (avtpcvfdepay->fragments, avtpdu,
632 GST_BUFFER_COPY_MEMORY, offset, nalu_size);
633 }
634
635 if (end) {
636 ret =
637 gst_avtp_cvf_depay_process_last_fragment (avtpcvfdepay, avtpdu, map,
638 offset, nalu_size, nri, nal_type);
639 }
640
641 end:
642 return ret;
643 }
644
645 static GstFlowReturn
gst_avtp_cvf_depay_handle_single_nal(GstAvtpCvfDepay * avtpcvfdepay,GstBuffer * avtpdu,GstMapInfo * map)646 gst_avtp_cvf_depay_handle_single_nal (GstAvtpCvfDepay * avtpcvfdepay,
647 GstBuffer * avtpdu, GstMapInfo * map)
648 {
649 GstClockTime pts, dts;
650 GstMapInfo map_nal;
651 guint16 nalu_size;
652 GstBuffer *nal;
653 gboolean M;
654
655 GST_DEBUG_OBJECT (avtpcvfdepay, "Handling single NAL unit");
656
657 if (avtpcvfdepay->fragments != NULL) {
658 GstFlowReturn ret;
659
660 GST_DEBUG_OBJECT (avtpcvfdepay,
661 "Received single NAL unit, but previous fragment is incomplete. Dropping fragment.");
662 ret = gst_avtp_cvf_depay_push_and_discard (avtpcvfdepay);
663 if (ret != GST_FLOW_OK)
664 return ret;
665 }
666
667 gst_avtp_cvf_depay_get_avtp_timestamps (avtpcvfdepay, map, &pts, &dts);
668 gst_avtp_cvf_depay_get_nalu_size (avtpcvfdepay, map, &nalu_size);
669 gst_avtp_cvf_depay_get_M (avtpcvfdepay, map, &M);
670
671 /* Four is the number of bytes containing NALu size just before the NALu */
672 nal = gst_buffer_new_allocate (NULL, 4, NULL);
673 gst_buffer_map (nal, &map_nal, GST_MAP_READWRITE);
674
675 /* Add NAL size just before the NAL itself (4 bytes before it) */
676 map_nal.data[0] = map_nal.data[1] = 0;
677 map_nal.data[2] = nalu_size >> 8;
678 map_nal.data[3] = nalu_size & 0xff;
679 gst_buffer_unmap (nal, &map_nal);
680
681 gst_buffer_copy_into (nal, avtpdu, GST_BUFFER_COPY_MEMORY,
682 AVTP_CVF_H264_HEADER_SIZE, nalu_size);
683 GST_BUFFER_PTS (nal) = pts;
684 GST_BUFFER_DTS (nal) = dts;
685
686 return gst_avtp_cvf_depay_internal_push (avtpcvfdepay, nal, M);
687 }
688
689 static GstFlowReturn
gst_avtp_cvf_depay_chain(GstPad * pad,GstObject * parent,GstBuffer * buffer)690 gst_avtp_cvf_depay_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
691 {
692 GstAvtpCvfDepay *avtpcvfdepay = GST_AVTP_CVF_DEPAY (parent);
693 GstFlowReturn ret = GST_FLOW_OK;
694 gboolean lost_packet;
695 GstMapInfo map;
696
697 gst_buffer_map (buffer, &map, GST_MAP_READ);
698
699 if (!gst_avtp_cvf_depay_validate_avtpdu (avtpcvfdepay, &map, &lost_packet)) {
700 GST_DEBUG_OBJECT (avtpcvfdepay, "Invalid AVTPDU buffer, dropping it");
701 goto end;
702 }
703 if (lost_packet) {
704 ret = gst_avtp_cvf_depay_push_and_discard (avtpcvfdepay);
705 if (ret != GST_FLOW_OK)
706 goto end;
707 }
708
709 switch (gst_avtp_cvf_depay_get_nal_type (&map)) {
710 case STAP_A_TYPE:
711 case STAP_B_TYPE:
712 case MTAP16_TYPE:
713 case MTAP24_TYPE:
714 GST_DEBUG_OBJECT (avtpcvfdepay,
715 "AVTP aggregation packets not supported, dropping it");
716 break;
717 case FU_A_TYPE:
718 ret = gst_avtp_cvf_depay_handle_fu_a (avtpcvfdepay, buffer, &map);
719 break;
720 case FU_B_TYPE:
721 GST_DEBUG_OBJECT (avtpcvfdepay,
722 "AVTP fragmentation FU-B packets not supported, dropping it");
723 break;
724 default:
725 ret = gst_avtp_cvf_depay_handle_single_nal (avtpcvfdepay, buffer, &map);
726 break;
727 }
728
729 end:
730 gst_buffer_unmap (buffer, &map);
731 gst_buffer_unref (buffer);
732
733 return ret;
734 }
735