| #include <gst/check/check.h> |
| #include <gst/check/gstharness.h> |
| #include <gst/rtp/gstrtpbuffer.h> |
| |
| #define H261_RTP_CAPS_STR \ |
| "application/x-rtp,media=video,encoding-name=H261,clock-rate=90000,payload=31" |
| |
| typedef struct _GstRtpH261PayHeader |
| { |
| #if G_BYTE_ORDER == G_LITTLE_ENDIAN |
| unsigned int v:1; /* Motion vector flag */ |
| unsigned int i:1; /* Intra encoded data */ |
| unsigned int ebit:3; /* End position */ |
| unsigned int sbit:3; /* Start position */ |
| |
| unsigned int mbap1:4; /* MB address predictor - part1 */ |
| unsigned int gobn:4; /* GOB number */ |
| |
| unsigned int hmvd1:2; /* Horizontal motion vector data - part1 */ |
| unsigned int quant:5; /* Quantizer */ |
| unsigned int mbap2:1; /* MB address predictor - part2 */ |
| |
| unsigned int vmvd:5; /* Horizontal motion vector data - part1 */ |
| unsigned int hmvd2:3; /* Vertical motion vector data */ |
| #elif G_BYTE_ORDER == G_BIG_ENDIAN |
| unsigned int sbit:3; /* Start position */ |
| unsigned int ebit:3; /* End position */ |
| unsigned int i:1; /* Intra encoded data */ |
| unsigned int v:1; /* Motion vector flag */ |
| |
| unsigned int gobn:4; /* GOB number */ |
| unsigned int mbap1:4; /* MB address predictor - part1 */ |
| |
| unsigned int mbap2:1; /* MB address predictor - part2 */ |
| unsigned int quant:5; /* Quantizer */ |
| unsigned int hmvd1:2; /* Horizontal motion vector data - part1 */ |
| |
| unsigned int hmvd2:3; /* Vertical motion vector data */ |
| unsigned int vmvd:5; /* Horizontal motion vector data - part1 */ |
| #else |
| #error "G_BYTE_ORDER should be big or little endian." |
| #endif |
| } GstRtpH261PayHeader; |
| |
| #define GST_RTP_H261_PAYLOAD_HEADER_LEN 4 |
| |
| static guint8 * |
| create_h261_payload (gint sbit, gint ebit, gint psc, gsize size) |
| { |
| GstRtpH261PayHeader header; |
| const gint header_len = 4; |
| guint8 *data = g_malloc0 (size); |
| |
| memset (&header, 0x00, sizeof (header)); |
| |
| header.sbit = sbit; |
| header.ebit = ebit; |
| |
| memset (data, 0xff, size); |
| memcpy (data, &header, header_len); |
| |
| if (psc) { |
| guint32 word = 0x000100ff >> sbit; |
| data[header_len + 0] = (word >> 24) & 0xff; |
| data[header_len + 1] = (word >> 16) & 0xff; |
| data[header_len + 2] = (word >> 8) & 0xff; |
| data[header_len + 3] = (word >> 0) & 0xff; |
| } |
| |
| return data; |
| } |
| |
| static GstBuffer * |
| create_rtp_copy_payload (const guint8 * data, gsize size, guint ts, guint16 seq, |
| gboolean marker, guint csrcs) |
| { |
| GstBuffer *buf = gst_rtp_buffer_new_allocate (size, 0, csrcs); |
| GstRTPBuffer rtp = GST_RTP_BUFFER_INIT; |
| |
| gst_rtp_buffer_map (buf, GST_MAP_WRITE, &rtp); |
| |
| gst_rtp_buffer_set_seq (&rtp, seq); |
| gst_rtp_buffer_set_marker (&rtp, marker); |
| memcpy (gst_rtp_buffer_get_payload (&rtp), data, size); |
| |
| GST_BUFFER_PTS (buf) = (ts) * (GST_SECOND / 30); |
| GST_BUFFER_DURATION (buf) = (GST_SECOND / 30); |
| |
| gst_rtp_buffer_unmap (&rtp); |
| |
| return buf; |
| } |
| |
| GST_START_TEST (test_h263depay_empty_payload) |
| { |
| GstHarness *h = gst_harness_new ("rtph261depay"); |
| gint sbit = 4; |
| gint ebit = 4; |
| gsize size; |
| guint8 *payload; |
| guint seq = 0; |
| |
| gst_harness_set_src_caps_str (h, H261_RTP_CAPS_STR); |
| |
| /* First send a proper packet with picture start code */ |
| size = 100; |
| payload = create_h261_payload (sbit, ebit, TRUE, size); |
| gst_harness_push (h, create_rtp_copy_payload (payload, size, 0, seq++, FALSE, |
| 0)); |
| g_free (payload); |
| |
| /* Not a complete frame */ |
| fail_unless_equals_int (gst_harness_buffers_received (h), 0); |
| |
| /* Second buffer has invalid empty payload */ |
| size = GST_RTP_H261_PAYLOAD_HEADER_LEN; |
| payload = create_h261_payload (sbit, ebit, FALSE, size); |
| gst_harness_push (h, create_rtp_copy_payload (payload, size, 0, seq++, TRUE, |
| 0)); |
| g_free (payload); |
| |
| /* Invalid payload should be dropped */ |
| fail_unless_equals_int (gst_harness_buffers_received (h), 0); |
| |
| gst_harness_teardown (h); |
| } |
| |
| GST_END_TEST; |
| |
| static Suite * |
| rtph261_suite (void) |
| { |
| Suite *s = suite_create ("rtph261"); |
| TCase *tc_chain; |
| |
| suite_add_tcase (s, (tc_chain = tcase_create ("h261depay"))); |
| tcase_add_test (tc_chain, test_h263depay_empty_payload); |
| |
| return s; |
| } |
| |
| GST_CHECK_MAIN (rtph261); |