diff --git a/gst/videoparsers/gstjpeg2000parse.c b/gst/videoparsers/gstjpeg2000parse.c index e2ebc8cda1..f20aea0f1f 100644 --- a/gst/videoparsers/gstjpeg2000parse.c +++ b/gst/videoparsers/gstjpeg2000parse.c @@ -25,6 +25,35 @@ #include "gstjpeg2000parse.h" #include +/* Not used at the moment +static gboolean gst_jpeg2000_parse_is_cinema(guint16 rsiz) { + return ((rsiz >= GST_JPEG2000_PARSE_PROFILE_CINEMA_2K) && (rsiz <= GST_JPEG2000_PARSE_PROFILE_CINEMA_S4K)); +} +static gboolean gst_jpeg2000_parse_is_storage(guint16 rsiz) { + return (rsiz == GST_JPEG2000_PARSE_PROFILE_CINEMA_LTS); +} +*/ +static gboolean +gst_jpeg2000_parse_is_broadcast (guint16 rsiz) +{ + return ((rsiz >= GST_JPEG2000_PARSE_PROFILE_BC_SINGLE) && + (rsiz <= ((GST_JPEG2000_PARSE_PROFILE_BC_MULTI_R) | (0x000b))) + && ((rsiz & (~GST_JPEG2000_PARSE_PROFILE_BC_MASK)) == 0)); +} + +static gboolean +gst_jpeg2000_parse_is_imf (guint16 rsiz) +{ + return ((rsiz >= GST_JPEG2000_PARSE_PROFILE_IMF_2K) + && (rsiz <= ((GST_JPEG2000_PARSE_PROFILE_IMF_8K_R) | (0x009b)))); +} + +static gboolean +gst_jpeg2000_parse_is_part_2 (guint16 rsiz) +{ + return (rsiz & GST_JPEG2000_PARSE_PROFILE_PART2); +} + static void @@ -67,11 +96,13 @@ static GstStaticPadTemplate srctemplate = " width = (int)[1, MAX], height = (int)[1, MAX]," GST_JPEG2000_SAMPLING_LIST "," GST_JPEG2000_COLORSPACE_LIST "," + " profile = (int)[0, 49151]," " parsed = (boolean) true;" "image/x-j2c," " width = (int)[1, MAX], height = (int)[1, MAX]," GST_JPEG2000_SAMPLING_LIST "," - GST_JPEG2000_COLORSPACE_LIST "," " parsed = (boolean) true") + GST_JPEG2000_COLORSPACE_LIST "," + " profile = (int)[0, 49151]," " parsed = (boolean) true") ); static GstStaticPadTemplate sinktemplate = @@ -272,6 +303,11 @@ gst_jpeg2000_parse_handle_frame (GstBaseParse * parse, guint8 dx[GST_JPEG2000_PARSE_MAX_SUPPORTED_COMPONENTS]; guint8 dy[GST_JPEG2000_PARSE_MAX_SUPPORTED_COMPONENTS]; guint16 numcomps; + guint16 capabilities = 0; + guint16 profile = 0; + gboolean validate_main_level = FALSE; + guint8 main_level = 0; + guint8 sub_level = 0; guint16 compno; GstJPEG2000Sampling parsed_sampling = GST_JPEG2000_SAMPLING_NONE; const gchar *sink_sampling_string = NULL; @@ -361,10 +397,47 @@ gst_jpeg2000_parse_handle_frame (GstBaseParse * parse, goto beach; } - /* 2 to skip marker size, and another 2 to skip rsiz field */ - if (!gst_byte_reader_skip (&reader, num_prefix_bytes + 2 + 2)) + /* 2 to skip marker size */ + if (!gst_byte_reader_skip (&reader, num_prefix_bytes + 2)) goto beach; + if (!gst_byte_reader_get_uint16_be (&reader, &capabilities)) + goto beach; + + profile = capabilities & GST_JPEG2000_PARSE_PROFILE_MASK; + if (!gst_jpeg2000_parse_is_part_2 (capabilities)) { + if ((profile > GST_JPEG2000_PARSE_PROFILE_CINEMA_LTS) + && !gst_jpeg2000_parse_is_broadcast (profile) + && !gst_jpeg2000_parse_is_imf (profile)) { + GST_ELEMENT_ERROR (jpeg2000parse, STREAM, DECODE, NULL, + ("Unrecognized JPEG 2000 profile %d", profile)); + ret = GST_FLOW_ERROR; + goto beach; + } + if (gst_jpeg2000_parse_is_broadcast (profile)) { + main_level = capabilities & 0xF; + validate_main_level = TRUE; + } else if (gst_jpeg2000_parse_is_imf (profile)) { + main_level = capabilities & 0xF; + validate_main_level = TRUE; + sub_level = (capabilities >> 4) & 0xF; + if (sub_level > 9) { + GST_ELEMENT_ERROR (jpeg2000parse, STREAM, DECODE, NULL, + ("Sub level %d is invalid", sub_level)); + ret = GST_FLOW_ERROR; + goto beach; + } + } + if (validate_main_level && main_level > 11) { + GST_ELEMENT_ERROR (jpeg2000parse, STREAM, DECODE, NULL, + ("Main level %d is invalid", main_level)); + ret = GST_FLOW_ERROR; + goto beach; + + } + } + + if (!gst_byte_reader_get_uint32_be (&reader, &x1)) goto beach; @@ -560,10 +633,23 @@ gst_jpeg2000_parse_handle_frame (GstBaseParse * parse, src_caps = gst_caps_new_simple (media_type_from_codec_format - (jpeg2000parse->codec_format), "width", G_TYPE_INT, width, "height", - G_TYPE_INT, height, "colorspace", G_TYPE_STRING, + (jpeg2000parse->codec_format), + "width", G_TYPE_INT, width, + "height", G_TYPE_INT, height, + "colorspace", G_TYPE_STRING, gst_jpeg2000_colorspace_to_string (colorspace), "sampling", - G_TYPE_STRING, gst_jpeg2000_sampling_to_string (source_sampling), NULL); + G_TYPE_STRING, gst_jpeg2000_sampling_to_string (source_sampling), + "profile", G_TYPE_UINT, profile, NULL); + + if (gst_jpeg2000_parse_is_broadcast (capabilities) + || gst_jpeg2000_parse_is_imf (capabilities)) { + gst_caps_set_simple (src_caps, "main-level", G_TYPE_UINT, main_level, + NULL); + if (gst_jpeg2000_parse_is_imf (capabilities)) { + gst_caps_set_simple (src_caps, "sub-level", G_TYPE_UINT, sub_level, + NULL); + } + } if (gst_structure_get_fraction (current_caps_struct, "framerate", &fr_num, &fr_denom)) { diff --git a/gst/videoparsers/gstjpeg2000parse.h b/gst/videoparsers/gstjpeg2000parse.h index 93236dbaa4..6000f349b0 100644 --- a/gst/videoparsers/gstjpeg2000parse.h +++ b/gst/videoparsers/gstjpeg2000parse.h @@ -42,7 +42,64 @@ G_BEGIN_DECLS typedef struct _GstJPEG2000Parse GstJPEG2000Parse; typedef struct _GstJPEG2000ParseClass GstJPEG2000ParseClass; -#define GST_JPEG2000_PARSE_MAX_SUPPORTED_COMPONENTS 4 + +/** + * JPEG 2000 Profiles (stored in rsiz/capabilities field in code stream header) + * See Table A.10 from 15444-1 (updated in various AMDs) + * + * For broadcast profiles, the GST_JPEG2000_PARSE_PROFILE_BC_XXXX profile value must be combined with the target + * main level (3-0 LSBs, with value between 0 and 11). + * Example: + * capabilities GST_JPEG2000_PARSE_PROFILE_BC_MULTI | 0x0005 (in this case, main level equals 5) + * + * For IMF profiles, the GST_JPEG2000_PARSE_PROFILE_IMF_XXXX profile value must be combined with the target main level + * (3-0 LSBs, with value between 0 and 11), and target sub level (7-4 LSBs, with value between 0 and 9). + * Example: + * capabilities GST_JPEG2000_PARSE_PROFILE_IMF_2K | 0x0040 | 0x0005 (in this case, main level equals 5 and sub level equals 4) + * + * + * Broadcast main level (15444-1 AMD4,AMD8) + * + * Note: Mbit/s == 10^6 bits/s; Msamples/s == 10^6 samples/s + * + * Level 0: no max rate + * Level 1: 200 Mbits/s, 65 Msamples/s + * Level 2: 200 Mbits/s, 130 Msamples/s + * Level 3: 200 Mbits/s, 195 Msamples/s + * Level 4: 400 Mbits/s, 260 Msamples/s + * Level 5: 800Mbits/s, 520 Msamples/s + * Level >= 6: 2^(Level-6) * 1600 Mbits/s, 2^(Level-6) * 1200 Msamples/s + * + * Broadcast tiling + * + * Either single-tile or multi-tile. Multi-tile only permits + * 1 or 4 tiles per frame, where multiple tiles have identical + * sizes, and are configured in either 2x2 or 1x4 layout. + * + * */ + +#define GST_JPEG2000_PARSE_PROFILE_NONE 0x0000 /** no profile - defined in 15444-1 */ +#define GST_JPEG2000_PARSE_PROFILE_0 0x0001 /** Profile 0 - defined in 15444-1,Table A.45 */ +#define GST_JPEG2000_PARSE_PROFILE_1 0x0002 /** Profile 1 - defined in 15444-1,Table A.45 */ +#define GST_JPEG2000_PARSE_PROFILE_CINEMA_2K 0x0003 /** 2K Cinema profile - defined in 15444-1 AMD1 */ +#define GST_JPEG2000_PARSE_PROFILE_CINEMA_4K 0x0004 /** 4K Cinema profile - defined in 15444-1 AMD1 */ +#define GST_JPEG2000_PARSE_PROFILE_CINEMA_S2K 0x0005 /** Scalable 2K Cinema profile - defined in 15444-1 AMD2 */ +#define GST_JPEG2000_PARSE_PROFILE_CINEMA_S4K 0x0006 /** Scalable 4K Cinema profile - defined in 15444-1 AMD2 */ +#define GST_JPEG2000_PARSE_PROFILE_CINEMA_LTS 0x0007/** Long Term Storage Cinema profile - defined in 15444-1 AMD2 */ +#define GST_JPEG2000_PARSE_PROFILE_BC_SINGLE 0x0100 /** Single Tile Broadcast profile - defined in 15444-1 AMD3 */ +#define GST_JPEG2000_PARSE_PROFILE_BC_MULTI 0x0200 /** Multi Tile Broadcast profile - defined in 15444-1 AMD3 */ +#define GST_JPEG2000_PARSE_PROFILE_BC_MULTI_R 0x0300 /** Multi Tile Reversible Broadcast profile - defined in 15444-1 AMD3 */ +#define GST_JPEG2000_PARSE_PROFILE_BC_MASK 0x0F0F /** Mask for broadcast profile, including main level */ +#define GST_JPEG2000_PARSE_PROFILE_IMF_2K 0x0400 /** 2K Single Tile Lossy IMF profile - defined in 15444-1 AMD 8 */ +#define GST_JPEG2000_PARSE_PROFILE_IMF_4K 0x0401 /** 4K Single Tile Lossy IMF profile - defined in 15444-1 AMD 8 */ +#define GST_JPEG2000_PARSE_PROFILE_IMF_8K 0x0402 /** 8K Single Tile Lossy IMF profile - defined in 15444-1 AMD 8 */ +#define GST_JPEG2000_PARSE_PROFILE_IMF_2K_R 0x0403 /** 2K Single/Multi Tile Reversible IMF profile - defined in 15444-1 AMD 8 */ +#define GST_JPEG2000_PARSE_PROFILE_IMF_4K_R 0x0800 /** 4K Single/Multi Tile Reversible IMF profile - defined in 15444-1 AMD 8 */ +#define GST_JPEG2000_PARSE_PROFILE_IMF_8K_R 0x0801 /** 8K Single/Multi Tile Reversible IMF profile - defined in 15444-1 AMD 8 */ +#define GST_JPEG2000_PARSE_PROFILE_MASK 0xBFFF /** Mask for profile bits */ +#define GST_JPEG2000_PARSE_PROFILE_PART2 0x8000 /** At least 1 extension defined in 15444-2 (Part-2) */ + +#define GST_JPEG2000_PARSE_MAX_SUPPORTED_COMPONENTS 4 typedef enum {