rtph264pay/depay: Add frame dimensions a payloaded caps

This allows for applications to format SDP attributes and still do SDP
offer/answer based on caps negotiation.

Fixes https://bugzilla.gnome.org/show_bug.cgi?id=700749
This commit is contained in:
Sebastian Rasmussen 2013-05-22 03:09:44 +02:00 committed by Sebastian Dröge
parent 61666898cf
commit 3dca756a5d
4 changed files with 75 additions and 19 deletions

View file

@ -45,8 +45,14 @@ static GstStaticPadTemplate gst_rtp_h264_depay_src_template =
GST_PAD_ALWAYS, GST_PAD_ALWAYS,
GST_STATIC_CAPS ("video/x-h264, " GST_STATIC_CAPS ("video/x-h264, "
"stream-format = (string) avc, alignment = (string) au; " "stream-format = (string) avc, alignment = (string) au; "
/** optional parameters **/
/* "width = (int) [ 1, MAX ], " */
/* "height = (int) [ 1, MAX ], " */
"video/x-h264, " "video/x-h264, "
"stream-format = (string) byte-stream, alignment = (string) { nal, au }") "stream-format = (string) byte-stream, alignment = (string) { nal, au }")
/** optional parameters **/
/* "width = (int) [ 1, MAX ], " */
/* "height = (int) [ 1, MAX ], " */
); );
static GstStaticPadTemplate gst_rtp_h264_depay_sink_template = static GstStaticPadTemplate gst_rtp_h264_depay_sink_template =
@ -55,7 +61,8 @@ GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_ALWAYS, GST_PAD_ALWAYS,
GST_STATIC_CAPS ("application/x-rtp, " GST_STATIC_CAPS ("application/x-rtp, "
"media = (string) \"video\", " "media = (string) \"video\", "
"clock-rate = (int) 90000, " "encoding-name = (string) \"H264\"") "clock-rate = (int) 90000, "
"encoding-name = (string) \"H264\"")
/** optional parameters **/ /** optional parameters **/
/* "profile-level-id = (string) ANY, " */ /* "profile-level-id = (string) ANY, " */
/* "max-mbps = (string) ANY, " */ /* "max-mbps = (string) ANY, " */
@ -72,7 +79,9 @@ GST_STATIC_PAD_TEMPLATE ("sink",
/* "deint-buf-cap = (string) ANY, " */ /* "deint-buf-cap = (string) ANY, " */
/* "sprop-init-buf-time = (string) ANY, " */ /* "sprop-init-buf-time = (string) ANY, " */
/* "sprop-max-don-diff = (string) ANY, " */ /* "sprop-max-don-diff = (string) ANY, " */
/* "max-rcmd-nalu-size = (string) ANY " */ /* "max-rcmd-nalu-size = (string) ANY, " */
/* "width = (int) [ 1, MAX ], " */
/* "height = (int) [ 1, MAX ], " */
); );
#define gst_rtp_h264_depay_parent_class parent_class #define gst_rtp_h264_depay_parent_class parent_class
@ -147,6 +156,8 @@ gst_rtp_h264_depay_reset (GstRtpH264Depay * rtph264depay)
rtph264depay->last_ts = 0; rtph264depay->last_ts = 0;
rtph264depay->current_fu_type = 0; rtph264depay->current_fu_type = 0;
rtph264depay->new_codec_data = FALSE; rtph264depay->new_codec_data = FALSE;
rtph264depay->width = 0;
rtph264depay->height = 0;
g_ptr_array_set_size (rtph264depay->sps, 0); g_ptr_array_set_size (rtph264depay->sps, 0);
g_ptr_array_set_size (rtph264depay->pps, 0); g_ptr_array_set_size (rtph264depay->pps, 0);
} }
@ -305,6 +316,11 @@ gst_rtp_h264_set_src_caps (GstRtpH264Depay * rtph264depay)
rtph264depay->byte_stream ? "byte-stream" : "avc", rtph264depay->byte_stream ? "byte-stream" : "avc",
"alignment", G_TYPE_STRING, rtph264depay->merge ? "au" : "nal", NULL); "alignment", G_TYPE_STRING, rtph264depay->merge ? "au" : "nal", NULL);
if (rtph264depay->width > 0 && rtph264depay->height > 0) {
gst_caps_set_simple (srccaps, "width", G_TYPE_INT, rtph264depay->width,
"height", G_TYPE_INT, rtph264depay->height, NULL);
}
if (!rtph264depay->byte_stream) { if (!rtph264depay->byte_stream) {
GstBuffer *codec_data; GstBuffer *codec_data;
GstMapInfo map; GstMapInfo map;
@ -519,6 +535,7 @@ gst_rtp_h264_depay_setcaps (GstRTPBaseDepayload * depayload, GstCaps * caps)
GstBuffer *codec_data; GstBuffer *codec_data;
GstMapInfo map; GstMapInfo map;
guint8 *ptr; guint8 *ptr;
gint width = 0, height = 0;
rtph264depay = GST_RTP_H264_DEPAY (depayload); rtph264depay = GST_RTP_H264_DEPAY (depayload);
@ -618,6 +635,16 @@ gst_rtp_h264_depay_setcaps (GstRTPBaseDepayload * depayload, GstCaps * caps)
goto incomplete_caps; goto incomplete_caps;
} }
if (gst_structure_get_int (structure, "width", &width) && width <= 0) {
goto invalid_dimension;
}
if (gst_structure_get_int (structure, "height", &height) && height <= 0) {
goto invalid_dimension;
}
rtph264depay->width = width;
rtph264depay->height = height;
return gst_rtp_h264_set_src_caps (rtph264depay); return gst_rtp_h264_set_src_caps (rtph264depay);
/* ERRORS */ /* ERRORS */
@ -627,6 +654,11 @@ incomplete_caps:
" doing setcaps later"); " doing setcaps later");
return TRUE; return TRUE;
} }
invalid_dimension:
{
GST_ERROR_OBJECT (depayload, "invalid width/height from caps");
return FALSE;
}
} }
static GstBuffer * static GstBuffer *

View file

@ -66,6 +66,8 @@ struct _GstRtpH264Depay
GPtrArray *sps; GPtrArray *sps;
GPtrArray *pps; GPtrArray *pps;
gboolean new_codec_data; gboolean new_codec_data;
gint width;
gint height;
}; };
struct _GstRtpH264DepayClass struct _GstRtpH264DepayClass

View file

@ -47,9 +47,11 @@ static GstStaticPadTemplate gst_rtp_h264_pay_sink_template =
GST_PAD_SINK, GST_PAD_SINK,
GST_PAD_ALWAYS, GST_PAD_ALWAYS,
GST_STATIC_CAPS ("video/x-h264, " GST_STATIC_CAPS ("video/x-h264, "
"stream-format = (string) avc, alignment = (string) au;" "stream-format = (string) avc, alignment = (string) au, "
"width = (int) [ 1, MAX ], height = (int) [ 1, MAX ]; "
"video/x-h264, " "video/x-h264, "
"stream-format = (string) byte-stream, alignment = (string) { nal, au }") "stream-format = (string) byte-stream, alignment = (string) { nal, au }, "
"width = (int) [ 1, MAX ], height = (int) [ 1, MAX ]")
); );
static GstStaticPadTemplate gst_rtp_h264_pay_src_template = static GstStaticPadTemplate gst_rtp_h264_pay_src_template =
@ -59,7 +61,9 @@ GST_STATIC_PAD_TEMPLATE ("src",
GST_STATIC_CAPS ("application/x-rtp, " GST_STATIC_CAPS ("application/x-rtp, "
"media = (string) \"video\", " "media = (string) \"video\", "
"payload = (int) " GST_RTP_PAYLOAD_DYNAMIC_STRING ", " "payload = (int) " GST_RTP_PAYLOAD_DYNAMIC_STRING ", "
"clock-rate = (int) 90000, " "encoding-name = (string) \"H264\"") "clock-rate = (int) 90000, "
"encoding-name = (string) \"H264\", "
"width = (int) [ 1, MAX ], height = (int) [ 1, MAX ]")
); );
#define DEFAULT_SPROP_PARAMETER_SETS NULL #define DEFAULT_SPROP_PARAMETER_SETS NULL
@ -426,6 +430,7 @@ gst_rtp_h264_pay_setcaps (GstRTPBasePayload * basepayload, GstCaps * caps)
const gchar *alignment, *stream_format; const gchar *alignment, *stream_format;
gchar *sprops; gchar *sprops;
gboolean caps_set; gboolean caps_set;
gint width, height;
rtph264pay = GST_RTP_H264_PAY (basepayload); rtph264pay = GST_RTP_H264_PAY (basepayload);
@ -453,6 +458,13 @@ gst_rtp_h264_pay_setcaps (GstRTPBasePayload * basepayload, GstCaps * caps)
rtph264pay->stream_format = GST_H264_STREAM_FORMAT_BYTESTREAM; rtph264pay->stream_format = GST_H264_STREAM_FORMAT_BYTESTREAM;
} }
if (!gst_structure_get_int (str, "height", &height) || height <= 0) {
goto invalid_dimension;
}
if (!gst_structure_get_int (str, "width", &width) || width <= 0) {
goto invalid_dimension;
}
/* packetized AVC video has a codec_data */ /* packetized AVC video has a codec_data */
if ((value = gst_structure_get_value (str, "codec_data"))) { if ((value = gst_structure_get_value (str, "codec_data"))) {
guint num_sps, num_pps; guint num_sps, num_pps;
@ -558,10 +570,12 @@ gst_rtp_h264_pay_setcaps (GstRTPBasePayload * basepayload, GstCaps * caps)
} }
if (sprops != NULL) { if (sprops != NULL) {
caps_set = gst_rtp_base_payload_set_outcaps (basepayload, caps_set = gst_rtp_base_payload_set_outcaps (basepayload, "width",
G_TYPE_INT, width, "height", G_TYPE_INT, height,
"sprop-parameter-sets", G_TYPE_STRING, sprops, NULL); "sprop-parameter-sets", G_TYPE_STRING, sprops, NULL);
} else { } else {
caps_set = gst_rtp_base_payload_set_outcaps (basepayload, NULL); caps_set = gst_rtp_base_payload_set_outcaps (basepayload, "width",
G_TYPE_INT, width, "height", G_TYPE_INT, height, NULL);
} }
if (sprops != NULL) { if (sprops != NULL) {
@ -594,6 +608,11 @@ set_caps_failed:
GST_ERROR_OBJECT (rtph264pay, "failed to set caps"); GST_ERROR_OBJECT (rtph264pay, "failed to set caps");
return FALSE; return FALSE;
} }
invalid_dimension:
{
GST_ERROR_OBJECT (rtph264pay, "invalid width/height from caps");
return FALSE;
}
error: error:
{ {
gst_buffer_unmap (buffer, &map); gst_buffer_unmap (buffer, &map);

View file

@ -519,8 +519,9 @@ GST_START_TEST (rtp_h264)
/* FIXME 0.11: fully specify h264 caps (and make payloader check) */ /* FIXME 0.11: fully specify h264 caps (and make payloader check) */
rtp_pipeline_test (rtp_h264_frame_data, rtp_h264_frame_data_size, rtp_pipeline_test (rtp_h264_frame_data, rtp_h264_frame_data_size,
rtp_h264_frame_count, rtp_h264_frame_count,
"video/x-h264,stream-format=(string)byte-stream,alignment=(string)nal", "video/x-h264,stream-format=(string)byte-stream,alignment=(string)nal,"
"rtph264pay", "rtph264depay", 0, 0, FALSE); "width=(int)320,height=(int)240", "rtph264pay", "rtph264depay", 0, 0,
FALSE);
} }
GST_END_TEST; GST_END_TEST;
@ -546,8 +547,8 @@ GST_START_TEST (rtp_h264_list_lt_mtu)
/* FIXME 0.11: fully specify h264 caps (and make payloader check) */ /* FIXME 0.11: fully specify h264 caps (and make payloader check) */
rtp_pipeline_test (rtp_h264_list_lt_mtu_frame_data, rtp_pipeline_test (rtp_h264_list_lt_mtu_frame_data,
rtp_h264_list_lt_mtu_frame_data_size, rtp_h264_list_lt_mtu_frame_count, rtp_h264_list_lt_mtu_frame_data_size, rtp_h264_list_lt_mtu_frame_count,
"video/x-h264,stream-format=(string)byte-stream,alignment=(string)nal", "video/x-h264,stream-format=(string)byte-stream,alignment=(string)nal,"
"rtph264pay", "rtph264depay", "width=(int)320,height=(int)240", "rtph264pay", "rtph264depay",
rtp_h264_list_lt_mtu_bytes_sent, rtp_h264_list_lt_mtu_mtu_size, TRUE); rtp_h264_list_lt_mtu_bytes_sent, rtp_h264_list_lt_mtu_mtu_size, TRUE);
} }
@ -570,9 +571,10 @@ GST_START_TEST (rtp_h264_list_lt_mtu_avc)
rtp_pipeline_test (rtp_h264_list_lt_mtu_frame_data_avc, rtp_pipeline_test (rtp_h264_list_lt_mtu_frame_data_avc,
rtp_h264_list_lt_mtu_frame_data_size, rtp_h264_list_lt_mtu_frame_count, rtp_h264_list_lt_mtu_frame_data_size, rtp_h264_list_lt_mtu_frame_count,
"video/x-h264,stream-format=(string)avc,alignment=(string)au," "video/x-h264,stream-format=(string)avc,alignment=(string)au,"
"codec_data=(buffer)01640014ffe1001867640014acd94141fb0110000003001773594000f142996001000568ebecb22c", "codec_data=(buffer)01640014ffe1001867640014acd94141fb0110000003001773594000f142996001000568ebecb22c,"
"rtph264pay", "rtph264depay", "width=(int)320,height=(int)240,framerate=(fraction)30/1", "rtph264pay",
rtp_h264_list_lt_mtu_bytes_sent_avc, rtp_h264_list_lt_mtu_mtu_size, TRUE); "rtph264depay", rtp_h264_list_lt_mtu_bytes_sent_avc,
rtp_h264_list_lt_mtu_mtu_size, TRUE);
} }
GST_END_TEST; GST_END_TEST;
@ -600,8 +602,8 @@ GST_START_TEST (rtp_h264_list_gt_mtu)
/* FIXME 0.11: fully specify h264 caps (and make payloader check) */ /* FIXME 0.11: fully specify h264 caps (and make payloader check) */
rtp_pipeline_test (rtp_h264_list_gt_mtu_frame_data, rtp_pipeline_test (rtp_h264_list_gt_mtu_frame_data,
rtp_h264_list_gt_mtu_frame_data_size, rtp_h264_list_gt_mtu_frame_count, rtp_h264_list_gt_mtu_frame_data_size, rtp_h264_list_gt_mtu_frame_count,
"video/x-h264,stream-format=(string)byte-stream,alignment=(string)nal", "video/x-h264,stream-format=(string)byte-stream,alignment=(string)nal,"
"rtph264pay", "rtph264depay", "width=(int)320,height=(int)240", "rtph264pay", "rtph264depay",
rtp_h264_list_gt_mtu_bytes_sent, rtp_h264_list_gt_mtu_mty_size, TRUE); rtp_h264_list_gt_mtu_bytes_sent, rtp_h264_list_gt_mtu_mty_size, TRUE);
} }
@ -625,9 +627,10 @@ GST_START_TEST (rtp_h264_list_gt_mtu_avc)
rtp_pipeline_test (rtp_h264_list_gt_mtu_frame_data_avc, rtp_pipeline_test (rtp_h264_list_gt_mtu_frame_data_avc,
rtp_h264_list_gt_mtu_frame_data_size, rtp_h264_list_gt_mtu_frame_count, rtp_h264_list_gt_mtu_frame_data_size, rtp_h264_list_gt_mtu_frame_count,
"video/x-h264,stream-format=(string)avc,alignment=(string)au," "video/x-h264,stream-format=(string)avc,alignment=(string)au,"
"codec_data=(buffer)01640014ffe1001867640014acd94141fb0110000003001773594000f142996001000568ebecb22c", "codec_data=(buffer)01640014ffe1001867640014acd94141fb0110000003001773594000f142996001000568ebecb22c,"
"rtph264pay", "rtph264depay", "width=(int)320,height=(int)240,framerate=(fraction)30/1" , "rtph264pay",
rtp_h264_list_gt_mtu_bytes_sent_avc, rtp_h264_list_gt_mtu_mty_size, TRUE); "rtph264depay", rtp_h264_list_gt_mtu_bytes_sent_avc,
rtp_h264_list_gt_mtu_mty_size, TRUE);
} }
GST_END_TEST; GST_END_TEST;