1 #include <gst/check/check.h>
2 #include <gst/check/gstharness.h>
3 #include <gst/rtp/gstrtpbuffer.h>
4 
5 #define H261_RTP_CAPS_STR                                               \
6   "application/x-rtp,media=video,encoding-name=H261,clock-rate=90000,payload=31"
7 
8 typedef struct _GstRtpH261PayHeader
9 {
10 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
11   unsigned int v:1;             /* Motion vector flag */
12   unsigned int i:1;             /* Intra encoded data */
13   unsigned int ebit:3;          /* End position */
14   unsigned int sbit:3;          /* Start position */
15 
16   unsigned int mbap1:4;         /* MB address predictor - part1 */
17   unsigned int gobn:4;          /* GOB number */
18 
19   unsigned int hmvd1:2;         /* Horizontal motion vector data - part1 */
20   unsigned int quant:5;         /* Quantizer */
21   unsigned int mbap2:1;         /* MB address predictor - part2 */
22 
23   unsigned int vmvd:5;          /* Horizontal motion vector data - part1 */
24   unsigned int hmvd2:3;         /* Vertical motion vector data */
25 #elif G_BYTE_ORDER == G_BIG_ENDIAN
26   unsigned int sbit:3;          /* Start position */
27   unsigned int ebit:3;          /* End position */
28   unsigned int i:1;             /* Intra encoded data */
29   unsigned int v:1;             /* Motion vector flag */
30 
31   unsigned int gobn:4;          /* GOB number */
32   unsigned int mbap1:4;         /* MB address predictor - part1 */
33 
34   unsigned int mbap2:1;         /* MB address predictor - part2 */
35   unsigned int quant:5;         /* Quantizer */
36   unsigned int hmvd1:2;         /* Horizontal motion vector data - part1 */
37 
38   unsigned int hmvd2:3;         /* Vertical motion vector data */
39   unsigned int vmvd:5;          /* Horizontal motion vector data - part1 */
40 #else
41 #error "G_BYTE_ORDER should be big or little endian."
42 #endif
43 } GstRtpH261PayHeader;
44 
45 #define GST_RTP_H261_PAYLOAD_HEADER_LEN 4
46 
47 static guint8 *
create_h261_payload(gint sbit,gint ebit,gint psc,gsize size)48 create_h261_payload (gint sbit, gint ebit, gint psc, gsize size)
49 {
50   GstRtpH261PayHeader header;
51   const gint header_len = 4;
52   guint8 *data = g_malloc0 (size);
53 
54   memset (&header, 0x00, sizeof (header));
55 
56   header.sbit = sbit;
57   header.ebit = ebit;
58 
59   memset (data, 0xff, size);
60   memcpy (data, &header, header_len);
61 
62   if (psc) {
63     guint32 word = 0x000100ff >> sbit;
64     data[header_len + 0] = (word >> 24) & 0xff;
65     data[header_len + 1] = (word >> 16) & 0xff;
66     data[header_len + 2] = (word >> 8) & 0xff;
67     data[header_len + 3] = (word >> 0) & 0xff;
68   }
69 
70   return data;
71 }
72 
73 static GstBuffer *
create_rtp_copy_payload(const guint8 * data,gsize size,guint ts,guint16 seq,gboolean marker,guint csrcs)74 create_rtp_copy_payload (const guint8 * data, gsize size, guint ts, guint16 seq,
75     gboolean marker, guint csrcs)
76 {
77   GstBuffer *buf = gst_rtp_buffer_new_allocate (size, 0, csrcs);
78   GstRTPBuffer rtp = GST_RTP_BUFFER_INIT;
79 
80   gst_rtp_buffer_map (buf, GST_MAP_WRITE, &rtp);
81 
82   gst_rtp_buffer_set_seq (&rtp, seq);
83   gst_rtp_buffer_set_marker (&rtp, marker);
84   memcpy (gst_rtp_buffer_get_payload (&rtp), data, size);
85 
86   GST_BUFFER_PTS (buf) = (ts) * (GST_SECOND / 30);
87   GST_BUFFER_DURATION (buf) = (GST_SECOND / 30);
88 
89   gst_rtp_buffer_unmap (&rtp);
90 
91   return buf;
92 }
93 
GST_START_TEST(test_h263depay_empty_payload)94 GST_START_TEST (test_h263depay_empty_payload)
95 {
96   GstHarness *h = gst_harness_new ("rtph261depay");
97   gint sbit = 4;
98   gint ebit = 4;
99   gsize size;
100   guint8 *payload;
101   guint seq = 0;
102 
103   gst_harness_set_src_caps_str (h, H261_RTP_CAPS_STR);
104 
105   /* First send a proper packet with picture start code */
106   size = 100;
107   payload = create_h261_payload (sbit, ebit, TRUE, size);
108   gst_harness_push (h, create_rtp_copy_payload (payload, size, 0, seq++, FALSE,
109           0));
110   g_free (payload);
111 
112   /* Not a complete frame */
113   fail_unless_equals_int (gst_harness_buffers_received (h), 0);
114 
115   /* Second buffer has invalid empty payload */
116   size = GST_RTP_H261_PAYLOAD_HEADER_LEN;
117   payload = create_h261_payload (sbit, ebit, FALSE, size);
118   gst_harness_push (h, create_rtp_copy_payload (payload, size, 0, seq++, TRUE,
119           0));
120   g_free (payload);
121 
122   /* Invalid payload should be dropped */
123   fail_unless_equals_int (gst_harness_buffers_received (h), 0);
124 
125   gst_harness_teardown (h);
126 }
127 
128 GST_END_TEST;
129 
130 static Suite *
rtph261_suite(void)131 rtph261_suite (void)
132 {
133   Suite *s = suite_create ("rtph261");
134   TCase *tc_chain;
135 
136   suite_add_tcase (s, (tc_chain = tcase_create ("h261depay")));
137   tcase_add_test (tc_chain, test_h263depay_empty_payload);
138 
139   return s;
140 }
141 
142 GST_CHECK_MAIN (rtph261);
143