#include <gst/check/check.h>
#include <gst/app/app.h>
#include <gst/rtp/gstrtpbuffer.h>
+#include <gst/rtp/gstrtph265types.h>
#define ALLOCATOR_CUSTOM_SYSMEM "CustomSysMem"
GST_END_TEST;
+GST_START_TEST (test_rtph265pay_aggregate_verify_nalu_hdr)
+{
+ GstHarness *h = gst_harness_new_parse ("rtph265pay timestamp-offset=123"
+ " name=p");
+ GstFlowReturn ret;
+ GstBuffer *buffer;
+ GstRTPBuffer rtp = GST_RTP_BUFFER_INIT;
+ guint8 *payload = NULL;
+ gint paylen;
+ guint nalu_type;
+ guint nal_hdr_idx = 0;
+ guint nal_size_idx;
+ guint f_bit;
+ guint max_f_bit;
+ guint layer_id;
+ guint layer_id_min;
+ guint tid;
+ guint tid_min;
+ guint i;
+
+ gst_harness_set_src_caps_str (h,
+ "video/x-h265,alignment=nal,stream-format=byte-stream");
+ buffer = wrap_static_buffer_with_pts (h265_vps, sizeof (h265_vps), 0);
+ ret = gst_harness_push (h, buffer);
+ fail_unless_equals_int (ret, GST_FLOW_OK);
+
+ buffer = wrap_static_buffer_with_pts (h265_sps, sizeof (h265_sps), 0);
+ ret = gst_harness_push (h, buffer);
+ fail_unless_equals_int (ret, GST_FLOW_OK);
+
+ buffer = wrap_static_buffer_with_pts (h265_pps, sizeof (h265_pps), 0);
+ ret = gst_harness_push (h, buffer);
+ fail_unless_equals_int (ret, GST_FLOW_OK);
+
+ buffer = wrap_static_buffer_with_pts (h265_idr_slice_1,
+ sizeof (h265_idr_slice_1), 0);
+ ret = gst_harness_push (h, buffer);
+ fail_unless_equals_int (ret, GST_FLOW_OK);
+
+ fail_unless_equals_int (gst_harness_buffers_in_queue (h), 1);
+
+ buffer = gst_harness_pull (h);
+ fail_unless (gst_rtp_buffer_map (buffer, GST_MAP_READ, &rtp));
+ fail_unless_equals_uint64 (GST_BUFFER_PTS (buffer), 0);
+ fail_unless_equals_uint64 (gst_rtp_buffer_get_timestamp (&rtp), 123);
+ /* RTP header = 12, STAP header = 2, 2 bytes length per NAL */
+ fail_unless_equals_int (gst_buffer_get_size (buffer), 12 + 2 +
+ (2 + sizeof (h265_vps) - 4) +
+ (2 + sizeof (h265_sps) - 4) +
+ (2 + sizeof (h265_pps) - 4) + (2 + sizeof (h265_idr_slice_1) - 4));
+
+ paylen = gst_rtp_buffer_get_payload_len (&rtp);
+ payload = gst_rtp_buffer_get_payload (&rtp);
+ fail_unless (payload);
+
+ /* Verify NAL unit type is 48. We need to shift to the rigth to get rid of the
+ * first bit belonging to LayerID */
+ nalu_type = ((0x7e & payload[nal_hdr_idx]) >> 1);
+ fail_unless (nalu_type == 48);
+
+ /* The F bit MUST be cleared if all F bits of the aggregated NAL units
+ * are zero; otherwise, it MUST be set. rfc7798 4.4.2 */
+ f_bit = (0x80 & payload[nal_hdr_idx]);
+ max_f_bit = 0;
+
+ /* The value of LayerId and TID MUST be equal to the lowest value of LayerId
+ * resp TID of all the aggregated NAL units */
+ layer_id = ((0x01 & payload[nal_hdr_idx]) << 5) |
+ ((payload[nal_hdr_idx + 1] >> 3) & 0x1F);
+ tid = payload[nal_hdr_idx + 1] & 0x7;
+
+ nal_hdr_idx = 4;
+ nal_size_idx = 2;
+ layer_id_min = 63;
+ tid_min = 7;
+ i = 0;
+ while (nal_size_idx < paylen) {
+ guint nal_type = ((0x7e & payload[nal_hdr_idx]) >> 1);
+ if (i == 0) {
+ fail_unless (nal_type == GST_H265_NAL_VPS);
+ } else if (i == 1) {
+ fail_unless (nal_type == GST_H265_NAL_SPS);
+ } else if (i == 2) {
+ fail_unless (nal_type == GST_H265_NAL_PPS);
+ } else if (i == 3) {
+ fail_unless (nal_type == GST_H265_NAL_SLICE_IDR_N_LP);
+ }
+
+ if ((0x80 & payload[nal_hdr_idx]) > max_f_bit)
+ max_f_bit = (0x80 & payload[nal_hdr_idx]);
+
+ if ((((0x01 & payload[nal_hdr_idx]) << 5) | ((payload[nal_hdr_idx + 1] >> 3)
+ & 0x1F)) < layer_id_min)
+ layer_id_min =
+ ((0x01 & payload[nal_hdr_idx]) << 5) | ((payload[nal_hdr_idx + 1]
+ >> 3) & 0x1F);
+
+ if ((payload[nal_hdr_idx + 1] & 0x7) < tid_min)
+ tid_min = payload[nal_hdr_idx + 1] & 0x7;
+
+ nal_size_idx =
+ (payload[nal_size_idx] << 8 | payload[nal_size_idx + 1]) +
+ nal_size_idx + 2;
+ nal_hdr_idx = nal_size_idx + 2;
+ i++;
+ }
+
+ fail_unless (nal_size_idx == paylen);
+ fail_unless (max_f_bit == f_bit);
+ fail_unless (layer_id_min == layer_id);
+ fail_unless (tid_min == tid);
+
+ gst_rtp_buffer_unmap (&rtp);
+ gst_buffer_unref (buffer);
+
+ gst_harness_teardown (h);
+}
+
+GST_END_TEST;
static Suite *
rtph265_suite (void)
{
tcase_add_test (tc_chain, test_rtph265pay_aggregate_with_ts_change);
tcase_add_test (tc_chain, test_rtph265pay_aggregate_with_discont);
tcase_add_test (tc_chain, test_rtph265pay_aggregate_until_vcl);
+ tcase_add_test (tc_chain, test_rtph265pay_aggregate_verify_nalu_hdr);
return s;
}