#include #include #include #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);