jpeg2000parse: allow parsing when current caps are null

In this case, we assume that the format is jpc, and we infer the color
space from the number of components. This allows the parser to process a
jpc disk file coming from a filesrc element.

https://bugzilla.gnome.org/show_bug.cgi?id=783291
This commit is contained in:
Aaron Boxer 2017-06-12 09:47:49 -04:00 committed by Sebastian Dröge
parent eebc4c0022
commit 2cffa1579a

View file

@ -108,13 +108,7 @@ static GstStaticPadTemplate srctemplate =
static GstStaticPadTemplate sinktemplate = static GstStaticPadTemplate sinktemplate =
GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK,
GST_PAD_ALWAYS, GST_PAD_ALWAYS,
GST_STATIC_CAPS ("image/x-jpc," GST_STATIC_CAPS ("image/x-jpc;image/x-j2c")
GST_JPEG2000_SAMPLING_LIST ";"
"image/x-jpc, "
GST_JPEG2000_COLORSPACE_LIST ";"
"image/x-j2c,"
GST_JPEG2000_SAMPLING_LIST ";"
"image/x-j2c, " GST_JPEG2000_COLORSPACE_LIST)
); );
#define parent_class gst_jpeg2000_parse_parent_class #define parent_class gst_jpeg2000_parse_parent_class
@ -250,17 +244,12 @@ gst_jpeg2000_parse_negotiate (GstJPEG2000Parse * parse, GstCaps * in_caps)
} }
} }
/* FIXME We could fail the negotiation immediatly if caps are empty */
if (caps && !gst_caps_is_empty (caps)) { if (caps && !gst_caps_is_empty (caps)) {
/* fixate to avoid ambiguity with lists when parsing */ /* fixate to avoid ambiguity with lists when parsing */
caps = gst_caps_fixate (caps); caps = gst_caps_fixate (caps);
codec_format = format_from_media_type (gst_caps_get_structure (caps, 0)); codec_format = format_from_media_type (gst_caps_get_structure (caps, 0));
} }
/* default */
if (codec_format == GST_JPEG2000_PARSE_NO_CODEC)
codec_format = GST_JPEG2000_PARSE_J2C;
GST_DEBUG_OBJECT (parse, "selected codec format %d", codec_format); GST_DEBUG_OBJECT (parse, "selected codec format %d", codec_format);
parse->codec_format = codec_format; parse->codec_format = codec_format;
@ -296,7 +285,6 @@ gst_jpeg2000_parse_handle_frame (GstBaseParse * parse,
guint eoc_offset = 0; guint eoc_offset = 0;
GstCaps *current_caps = NULL; GstCaps *current_caps = NULL;
GstStructure *current_caps_struct = NULL; GstStructure *current_caps_struct = NULL;
const gchar *colorspace_string = NULL;
GstJPEG2000Colorspace colorspace = GST_JPEG2000_COLORSPACE_NONE; GstJPEG2000Colorspace colorspace = GST_JPEG2000_COLORSPACE_NONE;
guint x0, y0, x1, y1; guint x0, y0, x1, y1;
guint width = 0, height = 0; guint width = 0, height = 0;
@ -319,27 +307,45 @@ gst_jpeg2000_parse_handle_frame (GstBaseParse * parse,
GstCaps *src_caps = NULL; GstCaps *src_caps = NULL;
guint frame_size = 0; guint frame_size = 0;
gboolean is_j2c; gboolean is_j2c;
gboolean parsed_j2c_4cc = FALSE;
if (!gst_buffer_map (frame->buffer, &map, GST_MAP_READ)) { if (!gst_buffer_map (frame->buffer, &map, GST_MAP_READ)) {
GST_ERROR_OBJECT (jpeg2000parse, "Unable to map buffer"); GST_ERROR_OBJECT (jpeg2000parse, "Unable to map buffer");
return GST_FLOW_ERROR; return GST_FLOW_ERROR;
} }
gst_byte_reader_init (&reader, map.data, map.size);
/* try to get from caps */
if (jpeg2000parse->codec_format == GST_JPEG2000_PARSE_NO_CODEC) if (jpeg2000parse->codec_format == GST_JPEG2000_PARSE_NO_CODEC)
gst_jpeg2000_parse_negotiate (jpeg2000parse, NULL); gst_jpeg2000_parse_negotiate (jpeg2000parse, NULL);
is_j2c = jpeg2000parse->codec_format == GST_JPEG2000_PARSE_J2C; /* if we can't get from caps, then try to parse */
if (jpeg2000parse->codec_format == GST_JPEG2000_PARSE_NO_CODEC) {
gst_byte_reader_init (&reader, map.data, map.size);
num_prefix_bytes = GST_JPEG2000_MARKER_SIZE;
if (is_j2c) {
num_prefix_bytes +=
GST_JPEG2000_JP2_SIZE_OF_BOX_LEN + GST_JPEG2000_JP2_SIZE_OF_BOX_ID;
/* check for "jp2c" */ /* check for "jp2c" */
j2c_box_id_offset = gst_byte_reader_masked_scan_uint32 (&reader, 0xffffffff, j2c_box_id_offset = gst_byte_reader_masked_scan_uint32 (&reader, 0xffffffff,
GST_MAKE_FOURCC ('j', 'p', '2', 'c'), 0, GST_MAKE_FOURCC ('j', 'p', '2', 'c'), 0,
gst_byte_reader_get_remaining (&reader)); gst_byte_reader_get_remaining (&reader));
parsed_j2c_4cc = TRUE;
is_j2c = j2c_box_id_offset != -1;
/* since we only support j2c and jpc at the moment, we can deduce the codec format */
jpeg2000parse->codec_format =
is_j2c ? GST_JPEG2000_PARSE_J2C : GST_JPEG2000_PARSE_JPC;
} else {
is_j2c = jpeg2000parse->codec_format == GST_JPEG2000_PARSE_J2C;
}
num_prefix_bytes = GST_JPEG2000_MARKER_SIZE;
if (is_j2c) {
num_prefix_bytes +=
GST_JPEG2000_JP2_SIZE_OF_BOX_LEN + GST_JPEG2000_JP2_SIZE_OF_BOX_ID;
/* check for "jp2c" (may have already parsed j2c_box_id_offset if caps are empty) */
if (!parsed_j2c_4cc) {
j2c_box_id_offset =
gst_byte_reader_masked_scan_uint32 (&reader, 0xffffffff,
GST_MAKE_FOURCC ('j', 'p', '2', 'c'), 0,
gst_byte_reader_get_remaining (&reader));
}
if (j2c_box_id_offset == -1) { if (j2c_box_id_offset == -1) {
GST_ELEMENT_ERROR (jpeg2000parse, STREAM, DECODE, NULL, GST_ELEMENT_ERROR (jpeg2000parse, STREAM, DECODE, NULL,
@ -480,28 +486,46 @@ gst_jpeg2000_parse_handle_frame (GstBaseParse * parse,
} }
current_caps = gst_pad_get_current_caps (GST_BASE_PARSE_SINK_PAD (parse)); current_caps = gst_pad_get_current_caps (GST_BASE_PARSE_SINK_PAD (parse));
if (!current_caps) { if (current_caps) {
GST_ERROR_OBJECT (jpeg2000parse, "Unable to get current caps"); const gchar *colorspace_string = NULL;
ret = GST_FLOW_NOT_NEGOTIATED; current_caps_struct = gst_caps_get_structure (current_caps, 0);
goto beach; if (!current_caps_struct) {
} GST_ERROR_OBJECT (jpeg2000parse,
"Unable to get structure of current caps struct");
ret = GST_FLOW_NOT_NEGOTIATED;
goto beach;
}
current_caps_struct = gst_caps_get_structure (current_caps, 0); colorspace_string = gst_structure_get_string
if (!current_caps_struct) { (current_caps_struct, "colorspace");
GST_ERROR_OBJECT (jpeg2000parse, if (colorspace_string)
"Unable to get structure of current caps struct"); colorspace = gst_jpeg2000_colorspace_from_string (colorspace_string);
ret = GST_FLOW_NOT_NEGOTIATED; sink_sampling_string = gst_structure_get_string
goto beach; (current_caps_struct, "sampling");
} if (sink_sampling_string)
sink_sampling = gst_jpeg2000_sampling_from_string (sink_sampling_string);
colorspace_string = gst_structure_get_string } else {
(current_caps_struct, "colorspace"); /* guess color space based on number of components */
if (colorspace_string) if (numcomps == 0 || numcomps > 4) {
colorspace = gst_jpeg2000_colorspace_from_string (colorspace_string); GST_ERROR_OBJECT (jpeg2000parse,
sink_sampling_string = gst_structure_get_string "Unable to guess color space from number of components %d", numcomps);
(current_caps_struct, "sampling"); ret = GST_FLOW_NOT_NEGOTIATED;
if (sink_sampling_string) goto beach;
sink_sampling = gst_jpeg2000_sampling_from_string (sink_sampling_string); }
colorspace =
(numcomps >=
3) ? GST_JPEG2000_COLORSPACE_RGB : GST_JPEG2000_COLORSPACE_GRAY;
if (numcomps == 4) {
GST_WARNING_OBJECT (jpeg2000parse, "No caps available: assuming RGBA");
} else if (numcomps == 3) {
GST_WARNING_OBJECT (jpeg2000parse, "No caps available: assuming RGB");
} else if (numcomps == 2) {
GST_WARNING_OBJECT (jpeg2000parse,
"No caps available: assuming grayscale with alpha");
}
}
for (compno = 0; compno < numcomps; ++compno) { for (compno = 0; compno < numcomps; ++compno) {
@ -651,13 +675,15 @@ gst_jpeg2000_parse_handle_frame (GstBaseParse * parse,
} }
} }
if (gst_structure_get_fraction (current_caps_struct, "framerate", &fr_num, if (current_caps_struct &&
gst_structure_get_fraction (current_caps_struct, "framerate", &fr_num,
&fr_denom)) { &fr_denom)) {
gst_caps_set_simple (src_caps, "framerate", GST_TYPE_FRACTION, fr_num, gst_caps_set_simple (src_caps, "framerate", GST_TYPE_FRACTION, fr_num,
fr_denom, NULL); fr_denom, NULL);
} else { } else {
GST_WARNING_OBJECT (jpeg2000parse, "No framerate set"); GST_WARNING_OBJECT (jpeg2000parse, "No framerate set");
} }
if (!gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (parse), src_caps)) { if (!gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (parse), src_caps)) {
GST_ERROR_OBJECT (jpeg2000parse, "Unable to set source caps"); GST_ERROR_OBJECT (jpeg2000parse, "Unable to set source caps");
ret = GST_FLOW_NOT_NEGOTIATED; ret = GST_FLOW_NOT_NEGOTIATED;
@ -690,6 +716,8 @@ gst_jpeg2000_parse_handle_frame (GstBaseParse * parse,
frame_size, eoc_frame_size); frame_size, eoc_frame_size);
} }
frame_size = eoc_frame_size; frame_size = eoc_frame_size;
} else {
goto beach;
} }
/* clean up and finish frame */ /* clean up and finish frame */