mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 04:01:08 +00:00
rtph265pay/depay: Sync against RFC 7798
Handle sprop-vps, sprop-sps and sprop-pps in caps instead of sprop-parameter-sets. rtph265pay works with byte-stream and hvc1 formats but not hev1 yet. It handles profile-id, tier-flag and level-id in caps query. https://bugzilla.gnome.org/show_bug.cgi?id=753760
This commit is contained in:
parent
b3cfbe575c
commit
a06152c40a
4 changed files with 268 additions and 91 deletions
|
@ -131,7 +131,7 @@ gst_rtp_h265_depay_class_init (GstRtpH265DepayClass * klass)
|
|||
|
||||
gst_element_class_set_static_metadata (gstelement_class,
|
||||
"RTP H265 depayloader", "Codec/Depayloader/Network/RTP",
|
||||
"Extracts H265 video from RTP packets (draft-ietf-payload-rtp-h265-03.txt)",
|
||||
"Extracts H265 video from RTP packets (RFC 7798)",
|
||||
"Jurgen Slowack <jurgenslowack@gmail.com>");
|
||||
gstelement_class->change_state = gst_rtp_h265_depay_change_state;
|
||||
|
||||
|
@ -754,8 +754,10 @@ gst_rtp_h265_depay_setcaps (GstRTPBaseDepayload * depayload, GstCaps * caps)
|
|||
gint clock_rate;
|
||||
GstStructure *structure = gst_caps_get_structure (caps, 0);
|
||||
GstRtpH265Depay *rtph265depay;
|
||||
const gchar *ps;
|
||||
GstBuffer *codec_data;
|
||||
const gchar *vps;
|
||||
const gchar *sps;
|
||||
const gchar *pps;
|
||||
gchar *ps;
|
||||
GstMapInfo map;
|
||||
guint8 *ptr;
|
||||
|
||||
|
@ -766,7 +768,14 @@ gst_rtp_h265_depay_setcaps (GstRTPBaseDepayload * depayload, GstCaps * caps)
|
|||
depayload->clock_rate = clock_rate;
|
||||
|
||||
/* Base64 encoded, comma separated config NALs */
|
||||
ps = gst_structure_get_string (structure, "sprop-parameter-sets");
|
||||
vps = gst_structure_get_string (structure, "sprop-vps");
|
||||
sps = gst_structure_get_string (structure, "sprop-sps");
|
||||
pps = gst_structure_get_string (structure, "sprop-pps");
|
||||
if (vps == NULL || sps == NULL || pps == NULL) {
|
||||
ps = NULL;
|
||||
} else {
|
||||
ps = g_strdup_printf ("%s,%s,%s", vps, sps, pps);
|
||||
}
|
||||
|
||||
/* negotiate with downstream w.r.t. output format and alignment */
|
||||
gst_rtp_h265_depay_negotiate (rtph265depay);
|
||||
|
@ -775,6 +784,7 @@ gst_rtp_h265_depay_setcaps (GstRTPBaseDepayload * depayload, GstCaps * caps)
|
|||
/* for bytestream we only need the parameter sets but we don't error out
|
||||
* when they are not there, we assume they are in the stream. */
|
||||
gchar **params;
|
||||
GstBuffer *codec_data;
|
||||
guint len, total;
|
||||
gint i;
|
||||
|
||||
|
@ -855,10 +865,14 @@ gst_rtp_h265_depay_setcaps (GstRTPBaseDepayload * depayload, GstCaps * caps)
|
|||
}
|
||||
g_strfreev (params);
|
||||
|
||||
if (rtph265depay->sps->len == 0 || rtph265depay->pps->len == 0)
|
||||
if (rtph265depay->vps->len == 0 || rtph265depay->sps->len == 0 ||
|
||||
rtph265depay->pps->len == 0) {
|
||||
goto incomplete_caps;
|
||||
}
|
||||
}
|
||||
|
||||
g_free (ps);
|
||||
|
||||
return gst_rtp_h265_set_src_caps (rtph265depay);
|
||||
|
||||
/* ERRORS */
|
||||
|
@ -866,6 +880,7 @@ incomplete_caps:
|
|||
{
|
||||
GST_DEBUG_OBJECT (depayload, "we have incomplete caps,"
|
||||
" doing setcaps later");
|
||||
g_free (ps);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -53,13 +53,12 @@ static GstStaticPadTemplate gst_rtp_h265_pay_sink_template =
|
|||
GST_PAD_SINK,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS (
|
||||
/* Only bytestream format supported for now */
|
||||
/* only hvc1 and byte-stream formats supported for now */
|
||||
"video/x-h265, stream-format = (string) hvc1, alignment = (string) au; "
|
||||
/* "video/x-h265, "
|
||||
"stream-format = (string) hvc1, alignment = (string) au; "
|
||||
"video/x-h265, "
|
||||
"stream-format = (string) hev1, alignment = (string) au; " */
|
||||
"video/x-h265, "
|
||||
"stream-format = (string) byte-stream, alignment = (string) { nal, au }")
|
||||
"video/x-h265, stream-format = (string) byte-stream, "
|
||||
"alignment = (string) { nal, au }")
|
||||
);
|
||||
|
||||
static GstStaticPadTemplate gst_rtp_h265_pay_src_template =
|
||||
|
@ -167,7 +166,7 @@ gst_rtp_h265_pay_class_init (GstRtpH265PayClass * klass)
|
|||
|
||||
gst_element_class_set_static_metadata (gstelement_class, "RTP H265 payloader",
|
||||
"Codec/Payloader/Network/RTP",
|
||||
"Payload-encode H265 video into RTP packets (based on draft-ietf-payload-rtp-h265-03.txt)",
|
||||
"Payload-encode H265 video into RTP packets (RFC 7798)",
|
||||
"Jurgen Slowack <jurgenslowack@gmail.com>");
|
||||
|
||||
gstelement_class->change_state =
|
||||
|
@ -186,7 +185,6 @@ static void
|
|||
gst_rtp_h265_pay_init (GstRtpH265Pay * rtph265pay)
|
||||
{
|
||||
rtph265pay->queue = g_array_new (FALSE, FALSE, sizeof (guint));
|
||||
rtph265pay->profile = 0;
|
||||
rtph265pay->sps = g_ptr_array_new_with_free_func (
|
||||
(GDestroyNotify) gst_buffer_unref);
|
||||
rtph265pay->pps = g_ptr_array_new_with_free_func (
|
||||
|
@ -241,6 +239,32 @@ static const gchar all_levels[][4] = {
|
|||
"6.2"
|
||||
};
|
||||
|
||||
static gboolean
|
||||
parse_field (GstStructure * s, const gchar * field, gulong min, gulong max,
|
||||
guint8 * result)
|
||||
{
|
||||
const gchar *str;
|
||||
|
||||
g_assert (result != NULL);
|
||||
|
||||
str = gst_structure_get_string (s, field);
|
||||
if (str != NULL && *str != '\0') {
|
||||
gulong value;
|
||||
gchar *end;
|
||||
|
||||
value = strtoul (str, &end, 10);
|
||||
if (*end == '\0' && value >= min && value <= max) {
|
||||
*result = (guint8) value;
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static GstCaps *
|
||||
gst_rtp_h265_pay_getcaps (GstRTPBasePayload * payload, GstPad * pad,
|
||||
GstCaps * filter)
|
||||
|
@ -249,7 +273,6 @@ gst_rtp_h265_pay_getcaps (GstRTPBasePayload * payload, GstPad * pad,
|
|||
GstCaps *allowed_caps;
|
||||
GstCaps *caps;
|
||||
GstCaps *icaps;
|
||||
gboolean append_unrestricted;
|
||||
guint i;
|
||||
|
||||
allowed_caps =
|
||||
|
@ -272,54 +295,48 @@ gst_rtp_h265_pay_getcaps (GstRTPBasePayload * payload, GstPad * pad,
|
|||
}
|
||||
|
||||
caps = gst_caps_new_empty ();
|
||||
|
||||
append_unrestricted = FALSE;
|
||||
for (i = 0; i < gst_caps_get_size (allowed_caps); i++) {
|
||||
GstStructure *s = gst_caps_get_structure (allowed_caps, i);
|
||||
GstStructure *new_s = gst_structure_new_empty ("video/x-h265");
|
||||
const gchar *profile_level_id;
|
||||
guint8 ptl[12] = { 0, };
|
||||
guint8 value;
|
||||
|
||||
profile_level_id = gst_structure_get_string (s, "profile-level-id");
|
||||
|
||||
if (profile_level_id && strlen (profile_level_id) == 6) { /* Code taken from gstrtph264pay.c, needs to be revised for H.265 */
|
||||
if (parse_field (s, "profile-id", 0, 31, &value)) {
|
||||
const gchar *profile;
|
||||
|
||||
ptl[0] = value;
|
||||
profile = gst_codec_utils_h265_get_profile (ptl, sizeof (ptl));
|
||||
if (profile != NULL) {
|
||||
GST_DEBUG_OBJECT (payload, "profile %s", profile);
|
||||
gst_structure_set (new_s, "profile", G_TYPE_STRING, profile, NULL);
|
||||
} else {
|
||||
GST_WARNING_OBJECT (payload, "invalid profile-id %d in caps", value);
|
||||
}
|
||||
} else {
|
||||
GST_DEBUG_OBJECT (payload, "no valid profile-id in caps");
|
||||
}
|
||||
|
||||
if (parse_field (s, "tier-flag", 0, 1, &value)) {
|
||||
const gchar *tier;
|
||||
|
||||
ptl[0] |= value << 5;
|
||||
tier = gst_codec_utils_h265_get_tier (ptl, sizeof (ptl));
|
||||
GST_DEBUG_OBJECT (payload, "tier %s", tier);
|
||||
gst_structure_set (new_s, "tier", G_TYPE_STRING, tier, NULL);
|
||||
} else {
|
||||
GST_DEBUG_OBJECT (payload, "no valid tier-flag in caps");
|
||||
}
|
||||
|
||||
if (parse_field (s, "level-id", 0, 255, &value)) {
|
||||
const gchar *level;
|
||||
long int spsint;
|
||||
guint8 sps[3];
|
||||
|
||||
spsint = strtol (profile_level_id, NULL, 16);
|
||||
sps[0] = spsint >> 16;
|
||||
sps[1] = spsint >> 8;
|
||||
sps[2] = spsint;
|
||||
|
||||
profile = gst_codec_utils_h265_get_profile (sps, 3);
|
||||
level = gst_codec_utils_h265_get_level (sps, 3);
|
||||
|
||||
if (profile && level) {
|
||||
GST_LOG_OBJECT (payload, "In caps, have profile %s and level %s",
|
||||
profile, level);
|
||||
|
||||
if (!strcmp (profile, "main"))
|
||||
gst_structure_set (new_s, "profile", G_TYPE_STRING, profile, NULL);
|
||||
else {
|
||||
GValue val = { 0, };
|
||||
GValue profiles = { 0, };
|
||||
|
||||
g_value_init (&profiles, GST_TYPE_LIST);
|
||||
g_value_init (&val, G_TYPE_STRING);
|
||||
|
||||
g_value_set_static_string (&val, profile);
|
||||
gst_value_list_append_value (&profiles, &val);
|
||||
|
||||
g_value_set_static_string (&val, "main");
|
||||
gst_value_list_append_value (&profiles, &val);
|
||||
|
||||
gst_structure_take_value (new_s, "profile", &profiles);
|
||||
}
|
||||
|
||||
if (!strcmp (level, "1"))
|
||||
ptl[11] = value;
|
||||
level = gst_codec_utils_h265_get_level (ptl, sizeof (ptl));
|
||||
if (level != NULL) {
|
||||
GST_DEBUG_OBJECT (payload, "level %s", level);
|
||||
if (strcmp (level, "1") == 0) {
|
||||
gst_structure_set (new_s, "level", G_TYPE_STRING, level, NULL);
|
||||
else {
|
||||
} else {
|
||||
GValue levels = { 0, };
|
||||
GValue val = { 0, };
|
||||
int j;
|
||||
|
@ -336,26 +353,15 @@ gst_rtp_h265_pay_getcaps (GstRTPBasePayload * payload, GstPad * pad,
|
|||
gst_structure_take_value (new_s, "level", &levels);
|
||||
}
|
||||
} else {
|
||||
/* Invalid profile-level-id means main */
|
||||
|
||||
gst_structure_set (new_s, "profile", G_TYPE_STRING, "main", NULL);
|
||||
GST_WARNING_OBJECT (payload, "invalid level-id %d in caps", value);
|
||||
}
|
||||
} else {
|
||||
/* No profile-level-id means main or unrestricted */
|
||||
|
||||
gst_structure_set (new_s, "profile", G_TYPE_STRING, "main", NULL);
|
||||
append_unrestricted = TRUE;
|
||||
GST_DEBUG_OBJECT (payload, "no valid level-id in caps");
|
||||
}
|
||||
|
||||
caps = gst_caps_merge_structure (caps, new_s);
|
||||
}
|
||||
|
||||
if (append_unrestricted) {
|
||||
caps =
|
||||
gst_caps_merge_structure (caps, gst_structure_new ("video/x-h265", NULL,
|
||||
NULL));
|
||||
}
|
||||
|
||||
icaps = gst_caps_intersect (caps, template_caps);
|
||||
gst_caps_unref (caps);
|
||||
caps = icaps;
|
||||
|
@ -369,27 +375,26 @@ done:
|
|||
return caps;
|
||||
}
|
||||
|
||||
/* take the currently configured VPS, SPS and PPS lists and set them on the caps as
|
||||
* sprop-parameter-sets */
|
||||
/* take the currently configured VPS, SPS and PPS lists and set them on the
|
||||
* caps */
|
||||
static gboolean
|
||||
gst_rtp_h265_pay_set_vps_sps_pps (GstRTPBasePayload * basepayload)
|
||||
{
|
||||
GstRtpH265Pay *payloader = GST_RTP_H265_PAY (basepayload);
|
||||
gchar *profile;
|
||||
gchar *set;
|
||||
GString *sprops;
|
||||
GString *vps;
|
||||
GString *sps;
|
||||
GString *pps;
|
||||
guint count;
|
||||
gboolean res;
|
||||
GstMapInfo map;
|
||||
guint i;
|
||||
|
||||
sprops = g_string_new ("");
|
||||
vps = g_string_new ("");
|
||||
sps = g_string_new ("");
|
||||
pps = g_string_new ("");
|
||||
count = 0;
|
||||
|
||||
GST_DEBUG_OBJECT (payloader,
|
||||
"Entering function gst_rtp_h265_pay_set_vps_sps_pps");
|
||||
|
||||
/* build the sprop-parameter-sets */
|
||||
for (i = 0; i < payloader->vps->len; i++) {
|
||||
GstBuffer *vps_buf =
|
||||
GST_BUFFER_CAST (g_ptr_array_index (payloader->vps, i));
|
||||
|
@ -398,7 +403,7 @@ gst_rtp_h265_pay_set_vps_sps_pps (GstRTPBasePayload * basepayload)
|
|||
set = g_base64_encode (map.data, map.size);
|
||||
gst_buffer_unmap (vps_buf, &map);
|
||||
|
||||
g_string_append_printf (sprops, "%s%s", count ? "," : "", set);
|
||||
g_string_append_printf (vps, "%s%s", i ? "," : "", set);
|
||||
g_free (set);
|
||||
count++;
|
||||
}
|
||||
|
@ -410,7 +415,7 @@ gst_rtp_h265_pay_set_vps_sps_pps (GstRTPBasePayload * basepayload)
|
|||
set = g_base64_encode (map.data, map.size);
|
||||
gst_buffer_unmap (sps_buf, &map);
|
||||
|
||||
g_string_append_printf (sprops, "%s%s", count ? "," : "", set);
|
||||
g_string_append_printf (sps, "%s%s", i ? "," : "", set);
|
||||
g_free (set);
|
||||
count++;
|
||||
}
|
||||
|
@ -422,22 +427,23 @@ gst_rtp_h265_pay_set_vps_sps_pps (GstRTPBasePayload * basepayload)
|
|||
set = g_base64_encode (map.data, map.size);
|
||||
gst_buffer_unmap (pps_buf, &map);
|
||||
|
||||
g_string_append_printf (sprops, "%s%s", count ? "," : "", set);
|
||||
g_string_append_printf (pps, "%s%s", i ? "," : "", set);
|
||||
g_free (set);
|
||||
count++;
|
||||
}
|
||||
|
||||
if (G_LIKELY (count)) {
|
||||
/* profile is 24 bit. Force it to respect the limit */
|
||||
profile = g_strdup_printf ("%06x", payloader->profile & 0xffffff);
|
||||
/* combine into output caps */
|
||||
res = gst_rtp_base_payload_set_outcaps (basepayload,
|
||||
"sprop-parameter-sets", G_TYPE_STRING, sprops->str, NULL);
|
||||
g_free (profile);
|
||||
"sprop-vps", G_TYPE_STRING, vps->str,
|
||||
"sprop-sps", G_TYPE_STRING, sps->str,
|
||||
"sprop-pps", G_TYPE_STRING, pps->str, NULL);
|
||||
} else {
|
||||
res = gst_rtp_base_payload_set_outcaps (basepayload, NULL);
|
||||
}
|
||||
g_string_free (sprops, TRUE);
|
||||
g_string_free (vps, TRUE);
|
||||
g_string_free (sps, TRUE);
|
||||
g_string_free (pps, TRUE);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
@ -505,8 +511,7 @@ gst_rtp_h265_pay_setcaps (GstRTPBasePayload * basepayload, GstCaps * caps)
|
|||
goto wrong_version;
|
||||
|
||||
/* profile_space | tier_flag | profile_idc */
|
||||
rtph265pay->profile = data[1];
|
||||
GST_DEBUG_OBJECT (rtph265pay, "profile %06x", rtph265pay->profile);
|
||||
GST_DEBUG_OBJECT (rtph265pay, "profile %06x", data[1]);
|
||||
|
||||
/* profile_compatibility_flags */
|
||||
for (i = 2; i < 6; i++) {
|
||||
|
@ -773,7 +778,7 @@ gst_rtp_h265_pay_decode_nal (GstRtpH265Pay * payloader,
|
|||
/* encode the entire NAL in base64 */
|
||||
GST_DEBUG_OBJECT (payloader, "found %s (type 0x%x), size %u",
|
||||
type == GST_H265_NAL_VPS ? "VPS" : type == GST_H265_NAL_SPS ?
|
||||
"SPS" : "PPS", type, size);
|
||||
"SPS" : "PPS", type, size);
|
||||
|
||||
nal = gst_buffer_new_allocate (NULL, size, NULL);
|
||||
gst_buffer_fill (nal, 0, data, size);
|
||||
|
@ -1189,7 +1194,7 @@ gst_rtp_h265_pay_handle_buffer (GstRTPBasePayload * basepayload,
|
|||
GST_DEBUG_OBJECT (basepayload,
|
||||
"found first start at %u, bytes left %" G_GSIZE_FORMAT, next, size);
|
||||
|
||||
/* first pass to locate NALs and parse SPS/PPS */
|
||||
/* first pass to locate NALs and parse VPS/SPS/PPS */
|
||||
while (size > 4) {
|
||||
/* skip start code */
|
||||
data += 3;
|
||||
|
@ -1217,10 +1222,9 @@ gst_rtp_h265_pay_handle_buffer (GstRTPBasePayload * basepayload,
|
|||
nal_len);
|
||||
|
||||
/* We know our stream is a valid H265 NAL packet,
|
||||
* go parse it for SPS/PPS to enrich the caps */
|
||||
* go parse it for VPS/SPS/PPS to enrich the caps */
|
||||
/* order: make sure to check nal */
|
||||
update =
|
||||
gst_rtp_h265_pay_decode_nal (rtph265pay, data, nal_len, dts, pts)
|
||||
update = gst_rtp_h265_pay_decode_nal (rtph265pay, data, nal_len, dts, pts)
|
||||
|| update;
|
||||
|
||||
/* move to next NAL packet */
|
||||
|
|
|
@ -51,7 +51,6 @@ struct _GstRtpH265Pay
|
|||
{
|
||||
GstRTPBasePayload payload;
|
||||
|
||||
guint profile;
|
||||
GPtrArray *sps, *pps, *vps;
|
||||
|
||||
GstH265StreamFormat stream_format;
|
||||
|
|
|
@ -60,6 +60,7 @@ rtp_pipeline_chain_list (GstPad * pad, GstObject * parent, GstBufferList * list)
|
|||
* Count the size of the payload in the buffer list.
|
||||
*/
|
||||
len = gst_buffer_list_length (list);
|
||||
GST_LOG ("list length %u", len);
|
||||
|
||||
/* Loop through all groups */
|
||||
for (i = 0; i < len; i++) {
|
||||
|
@ -69,12 +70,14 @@ rtp_pipeline_chain_list (GstPad * pad, GstObject * parent, GstBufferList * list)
|
|||
|
||||
paybuf = gst_buffer_list_get (list, i);
|
||||
/* only count real data which is expected in last memory block */
|
||||
GST_LOG ("n_memory %d", gst_buffer_n_memory (paybuf));
|
||||
fail_unless (gst_buffer_n_memory (paybuf) > 1);
|
||||
mem = gst_buffer_get_memory_range (paybuf, gst_buffer_n_memory (paybuf) - 1,
|
||||
1);
|
||||
size = gst_memory_get_sizes (mem, NULL, NULL);
|
||||
gst_memory_unref (mem);
|
||||
chain_list_bytes_received += size;
|
||||
GST_LOG ("size %d, total %u", size, chain_list_bytes_received);
|
||||
}
|
||||
gst_buffer_list_unref (list);
|
||||
|
||||
|
@ -752,6 +755,157 @@ GST_START_TEST (rtp_h264_list_gt_mtu_avc)
|
|||
|
||||
GST_END_TEST;
|
||||
|
||||
static const guint8 rtp_h265_frame_data[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
static int rtp_h265_frame_data_size = 20;
|
||||
|
||||
static int rtp_h265_frame_count = 1;
|
||||
|
||||
GST_START_TEST (rtp_h265)
|
||||
{
|
||||
rtp_pipeline_test (rtp_h265_frame_data, rtp_h265_frame_data_size,
|
||||
rtp_h265_frame_count,
|
||||
"video/x-h265,stream-format=(string)byte-stream,alignment=(string)nal",
|
||||
"rtph265pay", "rtph265depay", 0, 0, FALSE);
|
||||
|
||||
/* config-interval property used to be of uint type, was changed to int,
|
||||
* make sure old GValue stuff still works */
|
||||
{
|
||||
GValue val = G_VALUE_INIT;
|
||||
GstElement *rtph265pay;
|
||||
GParamSpec *pspec;
|
||||
|
||||
|
||||
rtph265pay = gst_element_factory_make ("rtph265pay", NULL);
|
||||
pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (rtph265pay),
|
||||
"config-interval");
|
||||
fail_unless (pspec->value_type == G_TYPE_INT);
|
||||
g_value_init (&val, G_TYPE_UINT);
|
||||
g_value_set_uint (&val, 10);
|
||||
g_object_set_property (G_OBJECT (rtph265pay), "config-interval", &val);
|
||||
g_value_set_uint (&val, 0);
|
||||
g_object_get_property (G_OBJECT (rtph265pay), "config-interval", &val);
|
||||
fail_unless_equals_int (10, g_value_get_uint (&val));
|
||||
g_object_set (G_OBJECT (rtph265pay), "config-interval", -1, NULL);
|
||||
g_object_get_property (G_OBJECT (rtph265pay), "config-interval", &val);
|
||||
fail_unless (g_value_get_uint (&val) == G_MAXUINT);
|
||||
g_value_unset (&val);
|
||||
gst_object_unref (rtph265pay);
|
||||
}
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
static const guint8 rtp_h265_list_lt_mtu_frame_data[] = {
|
||||
/* not packetized, next NALU starts with 0x00000001 */
|
||||
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
|
||||
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x10
|
||||
};
|
||||
|
||||
static int rtp_h265_list_lt_mtu_frame_data_size = 16;
|
||||
|
||||
static int rtp_h265_list_lt_mtu_frame_count = 2;
|
||||
|
||||
/* 3 bytes start code prefixed with one zero byte, NALU header is in payload */
|
||||
static int rtp_h265_list_lt_mtu_bytes_sent = 2 * (16 - 3 - 1);
|
||||
|
||||
static int rtp_h265_list_lt_mtu_mtu_size = 1024;
|
||||
|
||||
GST_START_TEST (rtp_h265_list_lt_mtu)
|
||||
{
|
||||
rtp_pipeline_test (rtp_h265_list_lt_mtu_frame_data,
|
||||
rtp_h265_list_lt_mtu_frame_data_size, rtp_h265_list_lt_mtu_frame_count,
|
||||
"video/x-h265,stream-format=(string)byte-stream,alignment=(string)nal",
|
||||
"rtph265pay", "rtph265depay", rtp_h265_list_lt_mtu_bytes_sent,
|
||||
rtp_h265_list_lt_mtu_mtu_size, TRUE);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
static const guint8 rtp_h265_list_lt_mtu_frame_data_hvc1[] = {
|
||||
/* packetized data */
|
||||
0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
/* length size is 3 bytes */
|
||||
static int rtp_h265_list_lt_mtu_bytes_sent_hvc1 = 2 * (16 - 2 * 3);
|
||||
|
||||
|
||||
GST_START_TEST (rtp_h265_list_lt_mtu_hvc1)
|
||||
{
|
||||
rtp_pipeline_test (rtp_h265_list_lt_mtu_frame_data_hvc1,
|
||||
rtp_h265_list_lt_mtu_frame_data_size, rtp_h265_list_lt_mtu_frame_count,
|
||||
"video/x-h265,stream-format=(string)hvc1,alignment=(string)au,"
|
||||
"codec_data=(buffer)01640032ffe1002a67640032ac1b1a80a03dff016e02020280000"
|
||||
"003008000000a74300018fff5de5c68600031ffebbcb85001000468ee3830",
|
||||
"rtph265pay", "rtph265depay", rtp_h265_list_lt_mtu_bytes_sent_hvc1,
|
||||
rtp_h265_list_lt_mtu_mtu_size, TRUE);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
static const guint8 rtp_h265_list_gt_mtu_frame_data[] = {
|
||||
/* not packetized, next NAL starts with 0x000001 */
|
||||
0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x10
|
||||
};
|
||||
|
||||
static const int const rtp_h265_list_gt_mtu_frame_data_size = 62;
|
||||
|
||||
static const int rtp_h265_list_gt_mtu_frame_count = 1;
|
||||
|
||||
/* start code is 3 bytes, NALU header is 2 bytes */
|
||||
static int rtp_h265_list_gt_mtu_bytes_sent = 1 * (62 - 3 - 2);
|
||||
|
||||
static int rtp_h265_list_gt_mtu_mtu_size = 28;
|
||||
|
||||
GST_START_TEST (rtp_h265_list_gt_mtu)
|
||||
{
|
||||
rtp_pipeline_test (rtp_h265_list_gt_mtu_frame_data,
|
||||
rtp_h265_list_gt_mtu_frame_data_size, rtp_h265_list_gt_mtu_frame_count,
|
||||
"video/x-h265,stream-format=(string)byte-stream,alignment=(string)nal",
|
||||
"rtph265pay", "rtph265depay", rtp_h265_list_gt_mtu_bytes_sent,
|
||||
rtp_h265_list_gt_mtu_mtu_size, TRUE);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
static const guint8 rtp_h265_list_gt_mtu_frame_data_hvc1[] = {
|
||||
/* packetized data */
|
||||
0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
/* length size is 3 bytes, NALU header is 2 bytes */
|
||||
static int rtp_h265_list_gt_mtu_bytes_sent_hvc1 = 1 * (62 - 2 * 3 - 2 * 2);
|
||||
|
||||
GST_START_TEST (rtp_h265_list_gt_mtu_hvc1)
|
||||
{
|
||||
rtp_pipeline_test (rtp_h265_list_gt_mtu_frame_data_hvc1,
|
||||
rtp_h265_list_gt_mtu_frame_data_size, rtp_h265_list_gt_mtu_frame_count,
|
||||
"video/x-h265,stream-format=(string)hvc1,alignment=(string)au,"
|
||||
"codec_data=(buffer)01640032ffe1002a67640032ac1b1a80a03dff016e02020280000"
|
||||
"003008000000a74300018fff5de5c68600031ffebbcb85001000468ee3830",
|
||||
"rtph265pay", "rtph265depay", rtp_h265_list_gt_mtu_bytes_sent_hvc1,
|
||||
rtp_h265_list_gt_mtu_mtu_size, TRUE);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
/* KLV data from Day_Flight.mpg */
|
||||
static const guint8 rtp_KLV_frame_data[] = {
|
||||
0x06, 0x0e, 0x2b, 0x34, 0x02, 0x0b, 0x01, 0x01,
|
||||
|
@ -1200,6 +1354,11 @@ rtp_payloading_suite (void)
|
|||
tcase_add_test (tc_chain, rtp_h264_list_lt_mtu_avc);
|
||||
tcase_add_test (tc_chain, rtp_h264_list_gt_mtu);
|
||||
tcase_add_test (tc_chain, rtp_h264_list_gt_mtu_avc);
|
||||
tcase_add_test (tc_chain, rtp_h265);
|
||||
tcase_add_test (tc_chain, rtp_h265_list_lt_mtu);
|
||||
tcase_add_test (tc_chain, rtp_h265_list_lt_mtu_hvc1);
|
||||
tcase_add_test (tc_chain, rtp_h265_list_gt_mtu);
|
||||
tcase_add_test (tc_chain, rtp_h265_list_gt_mtu_hvc1);
|
||||
tcase_add_test (tc_chain, rtp_klv);
|
||||
tcase_add_test (tc_chain, rtp_klv_fragmented);
|
||||
tcase_add_test (tc_chain, rtp_L16);
|
||||
|
|
Loading…
Reference in a new issue