diff --git a/gst/rtp/gstrtpj2kcommon.h b/gst/rtp/gstrtpj2kcommon.h index e4af8cb3a5..09f1bbbf7c 100644 --- a/gst/rtp/gstrtpj2kcommon.h +++ b/gst/rtp/gstrtpj2kcommon.h @@ -22,6 +22,59 @@ #define __GST_RTP_J2K_COMMON_H__ + +/* Sampling values from RFC 5371 for JPEG 2000 over RTP : https://datatracker.ietf.org/doc/rfc5371/C + +RGB: standard Red, Green, Blue color space. + +BGR: standard Blue, Green, Red color space. + +RGBA: standard Red, Green, Blue, Alpha color space. + +BGRA: standard Blue, Green, Red, Alpha color space. + +YCbCr-4:4:4: standard YCbCr color space; no subsampling. + +YCbCr-4:2:2: standard YCbCr color space; Cb and Cr are subsampled horizontally by 1/2. + +YCbCr-4:2:0: standard YCbCr color space; Cb and Cr are subsampled horizontally and vertically by 1/2. + +YCbCr-4:1:1: standard YCbCr color space; Cb and Cr are subsampled vertically by 1/4. + +GRAYSCALE: basically, a single component image of just multilevels of grey. +*/ + + +#define GST_RTP_J2K_RGB "RGB" +#define GST_RTP_J2K_BGR "BGR" +#define GST_RTP_J2K_RGBA "RGBA" +#define GST_RTP_J2K_BGRA "BGRA" +#define GST_RTP_J2K_YBRA "YCbCrA" +#define GST_RTP_J2K_YBR444 "YCbCr-4:4:4" +#define GST_RTP_J2K_YBR422 "YCbCr-4:2:2" +#define GST_RTP_J2K_YBR420 "YCbCr-4:2:0" +#define GST_RTP_J2K_YBR410 "YCbCr-4:1:0" +#define GST_RTP_J2K_GRAYSCALE "GRAYSCALE" + +#define GST_RTP_J2K_SAMPLING_LIST "sampling = (string) {\"RGB\", \"BGR\", \"RGBA\", \"BGRA\", \"YCbCrA\", \"YCbCr-4:4:4\", \"YCbCr-4:2:2\", \"YCbCr-4:2:0\", \"YCbCr-4:1:1\", \"GRAYSCALE\"}" + +typedef enum +{ + + GST_RTP_SAMPLING_NONE, + GST_RTP_SAMPLING_RGB, + GST_RTP_SAMPLING_BGR, + GST_RTP_SAMPLING_RGBA, + GST_RTP_SAMPLING_BGRA, + GST_RTP_SAMPLING_YBRA, + GST_RTP_SAMPLING_YBR444, + GST_RTP_SAMPLING_YBR422, + GST_RTP_SAMPLING_YBR420, + GST_RTP_SAMPLING_YBR410, + GST_RTP_SAMPLING_GRAYSCALE +} GstRtpSampling; + + /* * GstRtpJ2KMarker: * @GST_J2K_MARKER: Prefix for JPEG 2000 marker @@ -29,7 +82,7 @@ * @GST_J2K_MARKER_SOT: Start of tile * @GST_J2K_MARKER_EOC: End of Codestream * -* Identifers for markers in JPEG 2000 codestreams +* Identifiers for markers in JPEG 2000 code streams */ typedef enum { diff --git a/gst/rtp/gstrtpj2kdepay.c b/gst/rtp/gstrtpj2kdepay.c index 9dba811e62..6f1b1b2c26 100644 --- a/gst/rtp/gstrtpj2kdepay.c +++ b/gst/rtp/gstrtpj2kdepay.c @@ -47,16 +47,22 @@ static GstStaticPadTemplate gst_rtp_j2k_depay_src_template = GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, - GST_STATIC_CAPS ("image/x-jpc") + GST_STATIC_CAPS ("image/x-jpc, " + "colorspace = (string) { sRGB, sYUV, GRAY }") ); static GstStaticPadTemplate gst_rtp_j2k_depay_sink_template = -GST_STATIC_PAD_TEMPLATE ("sink", + GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, GST_STATIC_CAPS ("application/x-rtp, " - "media = (string) \"video\", " - "clock-rate = (int) 90000, " "encoding-name = (string) \"JPEG2000\"") + "media = (string) \"video\", " "clock-rate = (int) 90000, " + GST_RTP_J2K_SAMPLING_LIST "," + "encoding-name = (string) \"JPEG2000\";" + "application/x-rtp, " + "media = (string) \"video\", " "clock-rate = (int) 90000, " + "colorspace = (string) { sRGB, sYUV, GRAY }, " + "encoding-name = (string) \"JPEG2000\";") ); enum @@ -177,10 +183,12 @@ gst_rtp_j2k_depay_finalize (GObject * object) static gboolean gst_rtp_j2k_depay_setcaps (GstRTPBaseDepayload * depayload, GstCaps * caps) { - GstStructure *structure; + GstStructure *structure = NULL; gint clock_rate; - GstCaps *outcaps; - gboolean res; + GstCaps *outcaps = NULL; + gboolean res = FALSE; + const gchar *colorspace = NULL; + const gchar *sampling = NULL; structure = gst_caps_get_structure (caps, 0); @@ -188,10 +196,35 @@ gst_rtp_j2k_depay_setcaps (GstRTPBaseDepayload * depayload, GstCaps * caps) clock_rate = 90000; depayload->clock_rate = clock_rate; - outcaps = - gst_caps_new_simple ("image/x-jpc", "framerate", GST_TYPE_FRACTION, 0, 1, - "fields", G_TYPE_INT, 1, "colorspace", G_TYPE_STRING, "sYUV", NULL); + sampling = gst_structure_get_string (structure, "sampling"); + if (sampling) { + if (!strcmp (sampling, GST_RTP_J2K_RGB) || + !strcmp (sampling, GST_RTP_J2K_RGBA) || + !strcmp (sampling, GST_RTP_J2K_BGR) || + !strcmp (sampling, GST_RTP_J2K_BGRA)) + colorspace = "sRGB"; + else if (!strcmp (sampling, GST_RTP_J2K_GRAYSCALE)) + colorspace = "GRAY"; + else + colorspace = "sYUV"; + } else { + GST_ELEMENT_WARNING (depayload, STREAM, DEMUX, NULL, + ("Non-compliant stream: sampling field missing. Frames my appear incorrect")); + colorspace = gst_structure_get_string (structure, "colorspace"); + if (!strcmp (colorspace, "GRAY")) { + sampling = GST_RTP_J2K_GRAYSCALE; + } + } + + outcaps = gst_caps_new_simple ("image/x-jpc", + "framerate", GST_TYPE_FRACTION, 0, 1, + "fields", G_TYPE_INT, 1, "colorspace", G_TYPE_STRING, colorspace, NULL); + + if (sampling) + gst_caps_set_simple (outcaps, "sampling", G_TYPE_STRING, sampling, NULL); + res = gst_pad_set_caps (depayload->srcpad, outcaps); + gst_caps_unref (outcaps); return res; diff --git a/gst/rtp/gstrtpj2kpay.c b/gst/rtp/gstrtpj2kpay.c index 3949ccf7a6..f0b0979a93 100644 --- a/gst/rtp/gstrtpj2kpay.c +++ b/gst/rtp/gstrtpj2kpay.c @@ -48,9 +48,10 @@ static GstStaticPadTemplate gst_rtp_j2k_pay_sink_template = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, - GST_STATIC_CAPS ("image/x-jpc") + GST_STATIC_CAPS ("image/x-jpc, " GST_RTP_J2K_SAMPLING_LIST) ); + static GstStaticPadTemplate gst_rtp_j2k_pay_src_template = GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, @@ -59,7 +60,7 @@ GST_STATIC_PAD_TEMPLATE ("src", " media = (string) \"video\", " " payload = (int) " GST_RTP_PAYLOAD_DYNAMIC_STRING ", " " clock-rate = (int) 90000, " - " encoding-name = (string) \"JPEG2000\"") + GST_RTP_J2K_SAMPLING_LIST "," " encoding-name = (string) \"JPEG2000\"") ); GST_DEBUG_CATEGORY_STATIC (rtpj2kpay_debug); @@ -137,24 +138,29 @@ static gboolean gst_rtp_j2k_pay_setcaps (GstRTPBasePayload * basepayload, GstCaps * caps) { GstStructure *caps_structure = gst_caps_get_structure (caps, 0); - GstRtpJ2KPay *pay; - gint width = 0, height = 0; gboolean res; + gint width = 0, height = 0; + const gchar *sampling = NULL; - pay = GST_RTP_J2K_PAY (basepayload); + gboolean has_width = gst_structure_get_int (caps_structure, "width", &width); + gboolean has_height = + gst_structure_get_int (caps_structure, "height", &height); - /* these properties are not mandatory, we can get them from the stream */ - if (gst_structure_get_int (caps_structure, "height", &height)) { - pay->height = height; - } - if (gst_structure_get_int (caps_structure, "width", &width)) { - pay->width = width; - } + + /* sampling is a required field */ + sampling = gst_structure_get_string (caps_structure, "sampling"); gst_rtp_base_payload_set_options (basepayload, "video", TRUE, "JPEG2000", 90000); - res = gst_rtp_base_payload_set_outcaps (basepayload, NULL); + if (has_width && has_height) + res = gst_rtp_base_payload_set_outcaps (basepayload, + "sampling", G_TYPE_STRING, sampling, "width", G_TYPE_INT, width, + "height", G_TYPE_INT, height, NULL); + else + res = + gst_rtp_base_payload_set_outcaps (basepayload, "sampling", + G_TYPE_STRING, sampling, NULL); return res; }