• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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