mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 04:01:08 +00:00
jpeg2000parse: Add JPEG2000 parser element
https://bugzilla.gnome.org/show_bug.cgi?id=766236
This commit is contained in:
parent
eebb65e934
commit
fffee978c2
7 changed files with 511 additions and 0 deletions
|
@ -66,6 +66,7 @@ GObject
|
||||||
GstMpegvParse
|
GstMpegvParse
|
||||||
GstOpusParse
|
GstOpusParse
|
||||||
GstPngParse
|
GstPngParse
|
||||||
|
GstJPEG2000Parse
|
||||||
GstVC1Parse
|
GstVC1Parse
|
||||||
GstBaseSink
|
GstBaseSink
|
||||||
GstAudioBaseSink
|
GstAudioBaseSink
|
||||||
|
|
|
@ -156,6 +156,27 @@
|
||||||
</caps>
|
</caps>
|
||||||
</pads>
|
</pads>
|
||||||
</element>
|
</element>
|
||||||
|
<element>
|
||||||
|
<name>jpeg2000parse</name>
|
||||||
|
<longname>JPEG 2000 parser</longname>
|
||||||
|
<class>Codec/Parser/Video/Image</class>
|
||||||
|
<description>Parses JPEG 2000 files</description>
|
||||||
|
<author>Aaron Boxer <boxerab@gmail.com></author>
|
||||||
|
<pads>
|
||||||
|
<caps>
|
||||||
|
<name>sink</name>
|
||||||
|
<direction>sink</direction>
|
||||||
|
<presence>always</presence>
|
||||||
|
<details>image/x-jpc</details>
|
||||||
|
</caps>
|
||||||
|
<caps>
|
||||||
|
<name>src</name>
|
||||||
|
<direction>source</direction>
|
||||||
|
<presence>always</presence>
|
||||||
|
<details>image/x-jpc, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], parsed=(boolean)true</details>
|
||||||
|
</caps>
|
||||||
|
</pads>
|
||||||
|
</element>
|
||||||
<element>
|
<element>
|
||||||
<name>vc1parse</name>
|
<name>vc1parse</name>
|
||||||
<longname>VC1 parser</longname>
|
<longname>VC1 parser</longname>
|
||||||
|
|
|
@ -5,6 +5,7 @@ libgstvideoparsersbad_la_SOURCES = plugin.c \
|
||||||
gstdiracparse.c dirac_parse.c \
|
gstdiracparse.c dirac_parse.c \
|
||||||
gsth264parse.c gstmpegvideoparse.c \
|
gsth264parse.c gstmpegvideoparse.c \
|
||||||
gstmpeg4videoparse.c \
|
gstmpeg4videoparse.c \
|
||||||
|
gstjpeg2000parse.c \
|
||||||
gstpngparse.c \
|
gstpngparse.c \
|
||||||
gstvc1parse.c \
|
gstvc1parse.c \
|
||||||
gsth265parse.c
|
gsth265parse.c
|
||||||
|
@ -29,6 +30,7 @@ noinst_HEADERS = gsth263parse.h h263parse.h \
|
||||||
gstdiracparse.h dirac_parse.h \
|
gstdiracparse.h dirac_parse.h \
|
||||||
gsth264parse.h gstmpegvideoparse.h \
|
gsth264parse.h gstmpegvideoparse.h \
|
||||||
gstmpeg4videoparse.h \
|
gstmpeg4videoparse.h \
|
||||||
|
gstjpeg2000parse.h \
|
||||||
gstjpeg2000sampling.h \
|
gstjpeg2000sampling.h \
|
||||||
gstpngparse.h \
|
gstpngparse.h \
|
||||||
gstvc1parse.h \
|
gstvc1parse.h \
|
||||||
|
|
402
gst/videoparsers/gstjpeg2000parse.c
Normal file
402
gst/videoparsers/gstjpeg2000parse.c
Normal file
|
@ -0,0 +1,402 @@
|
||||||
|
/* GStreamer JPEG 2000 Parser
|
||||||
|
* Copyright (C) <2016> Grok Image Compession Inc.
|
||||||
|
* @author Aaron Boxer <boxerab@gmail.com>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "gstjpeg2000parse.h"
|
||||||
|
#include <gst/base/base.h>
|
||||||
|
|
||||||
|
/* SOC marker plus minimum size of SIZ marker */
|
||||||
|
#define GST_JPEG2000_PARSE_MIN_FRAME_SIZE (4+36)
|
||||||
|
#define GST_JPEG2000_PARSE_J2K_MAGIC 0xFF4FFF51
|
||||||
|
#define GST_JPEG2000_PARSE_SIZE_OF_J2K_MAGIC 4
|
||||||
|
|
||||||
|
GST_DEBUG_CATEGORY (jpeg2000_parse_debug);
|
||||||
|
#define GST_CAT_DEFAULT jpeg2000_parse_debug
|
||||||
|
|
||||||
|
static GstStaticPadTemplate srctemplate =
|
||||||
|
GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC,
|
||||||
|
GST_PAD_ALWAYS,
|
||||||
|
GST_STATIC_CAPS ("image/x-jpc,"
|
||||||
|
" width = (int)[1, MAX], height = (int)[1, MAX],"
|
||||||
|
"colorspace = (string) { sRGB, sYUV, GRAY }," "parsed = (boolean) true")
|
||||||
|
);
|
||||||
|
|
||||||
|
static GstStaticPadTemplate sinktemplate =
|
||||||
|
GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK,
|
||||||
|
GST_PAD_ALWAYS,
|
||||||
|
GST_STATIC_CAPS ("image/x-jpc,"
|
||||||
|
"colorspace = (string) { sRGB, sYUV, GRAY }")
|
||||||
|
);
|
||||||
|
|
||||||
|
#define parent_class gst_jpeg2000_parse_parent_class
|
||||||
|
G_DEFINE_TYPE (GstJPEG2000Parse, gst_jpeg2000_parse, GST_TYPE_BASE_PARSE);
|
||||||
|
|
||||||
|
static gboolean gst_jpeg2000_parse_start (GstBaseParse * parse);
|
||||||
|
static gboolean gst_jpeg2000_parse_event (GstBaseParse * parse,
|
||||||
|
GstEvent * event);
|
||||||
|
static GstFlowReturn gst_jpeg2000_parse_handle_frame (GstBaseParse * parse,
|
||||||
|
GstBaseParseFrame * frame, gint * skipsize);
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_jpeg2000_parse_class_init (GstJPEG2000ParseClass * klass)
|
||||||
|
{
|
||||||
|
GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
|
||||||
|
GstBaseParseClass *parse_class = GST_BASE_PARSE_CLASS (klass);
|
||||||
|
|
||||||
|
GST_DEBUG_CATEGORY_INIT (jpeg2000_parse_debug, "jpeg2000parse", 0,
|
||||||
|
"jpeg 2000 parser");
|
||||||
|
|
||||||
|
gst_element_class_add_static_pad_template (gstelement_class, &srctemplate);
|
||||||
|
gst_element_class_add_static_pad_template (gstelement_class, &sinktemplate);
|
||||||
|
gst_element_class_set_static_metadata (gstelement_class, "JPEG 2000 parser",
|
||||||
|
"Codec/Parser/Video/Image",
|
||||||
|
"Parses JPEG 2000 files", "Aaron Boxer <boxerab@gmail.com>");
|
||||||
|
|
||||||
|
/* Override BaseParse vfuncs */
|
||||||
|
parse_class->start = GST_DEBUG_FUNCPTR (gst_jpeg2000_parse_start);
|
||||||
|
parse_class->sink_event = GST_DEBUG_FUNCPTR (gst_jpeg2000_parse_event);
|
||||||
|
parse_class->handle_frame =
|
||||||
|
GST_DEBUG_FUNCPTR (gst_jpeg2000_parse_handle_frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_jpeg2000_parse_init (GstJPEG2000Parse * jpeg2000parse)
|
||||||
|
{
|
||||||
|
GST_PAD_SET_ACCEPT_INTERSECT (GST_BASE_PARSE_SINK_PAD (jpeg2000parse));
|
||||||
|
GST_PAD_SET_ACCEPT_TEMPLATE (GST_BASE_PARSE_SINK_PAD (jpeg2000parse));
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_jpeg2000_parse_start (GstBaseParse * parse)
|
||||||
|
{
|
||||||
|
GstJPEG2000Parse *jpeg2000parse = GST_JPEG2000_PARSE (parse);
|
||||||
|
guint i;
|
||||||
|
GST_DEBUG_OBJECT (jpeg2000parse, "start");
|
||||||
|
gst_base_parse_set_min_frame_size (parse, GST_JPEG2000_PARSE_MIN_FRAME_SIZE);
|
||||||
|
|
||||||
|
jpeg2000parse->width = 0;
|
||||||
|
jpeg2000parse->height = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < GST_JPEG2000_PARSE_MAX_SUPPORTED_COMPONENTS; ++i) {
|
||||||
|
jpeg2000parse->dx[i] = 0;
|
||||||
|
jpeg2000parse->dy[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
jpeg2000parse->sampling = GST_RTP_SAMPLING_NONE;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_jpeg2000_parse_event (GstBaseParse * parse, GstEvent * event)
|
||||||
|
{
|
||||||
|
gboolean res = GST_BASE_PARSE_CLASS (parent_class)->sink_event (parse, event);
|
||||||
|
switch (GST_EVENT_TYPE (event)) {
|
||||||
|
case GST_EVENT_FLUSH_STOP:
|
||||||
|
gst_base_parse_set_min_frame_size (parse,
|
||||||
|
GST_JPEG2000_PARSE_MIN_FRAME_SIZE);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstFlowReturn
|
||||||
|
gst_jpeg2000_parse_handle_frame (GstBaseParse * parse,
|
||||||
|
GstBaseParseFrame * frame, gint * skipsize)
|
||||||
|
{
|
||||||
|
GstJPEG2000Parse *jpeg2000parse = GST_JPEG2000_PARSE (parse);
|
||||||
|
GstMapInfo map;
|
||||||
|
GstByteReader reader;
|
||||||
|
GstFlowReturn ret = GST_FLOW_OK;
|
||||||
|
guint eoc_offset = 0;
|
||||||
|
|
||||||
|
GstCaps *current_caps = NULL;
|
||||||
|
GstStructure *current_caps_struct = NULL;
|
||||||
|
const gchar *colorspace = NULL;
|
||||||
|
guint x0, y0, x1, y1;
|
||||||
|
guint width, height;
|
||||||
|
gboolean dimensions_changed = FALSE;
|
||||||
|
guint8 dx[GST_JPEG2000_PARSE_MAX_SUPPORTED_COMPONENTS];
|
||||||
|
guint8 dy[GST_JPEG2000_PARSE_MAX_SUPPORTED_COMPONENTS]; /* sub-sampling factors */
|
||||||
|
gboolean subsampling_changed = FALSE;
|
||||||
|
guint16 numcomps;
|
||||||
|
guint16 compno;
|
||||||
|
const char *sampling = NULL;
|
||||||
|
GstRtpSampling samplingEnum = GST_RTP_SAMPLING_NONE;
|
||||||
|
guint magic_offset = 0;
|
||||||
|
|
||||||
|
if (!gst_buffer_map (frame->buffer, &map, GST_MAP_READ)) {
|
||||||
|
GST_ERROR_OBJECT (jpeg2000parse, "Unable to map buffer");
|
||||||
|
return GST_FLOW_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
gst_byte_reader_init (&reader, map.data, map.size);
|
||||||
|
|
||||||
|
/* skip to beginning of frame */
|
||||||
|
magic_offset = gst_byte_reader_masked_scan_uint32 (&reader, 0xffffffff,
|
||||||
|
GST_JPEG2000_PARSE_J2K_MAGIC, 0, gst_byte_reader_get_remaining (&reader));
|
||||||
|
|
||||||
|
if (magic_offset == -1) {
|
||||||
|
*skipsize =
|
||||||
|
gst_byte_reader_get_size (&reader) -
|
||||||
|
GST_JPEG2000_PARSE_SIZE_OF_J2K_MAGIC;
|
||||||
|
goto beach;
|
||||||
|
} else {
|
||||||
|
GST_DEBUG_OBJECT (jpeg2000parse, "Found magic at offset = %d",
|
||||||
|
magic_offset);
|
||||||
|
if (magic_offset > 0) {
|
||||||
|
*skipsize = magic_offset;
|
||||||
|
goto beach;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 2 to skip marker size, and another 2 to skip rsiz field */
|
||||||
|
if (!gst_byte_reader_skip (&reader,
|
||||||
|
GST_JPEG2000_PARSE_SIZE_OF_J2K_MAGIC + 2 + 2))
|
||||||
|
goto beach;
|
||||||
|
|
||||||
|
if (!gst_byte_reader_get_uint32_be (&reader, &x1))
|
||||||
|
goto beach;
|
||||||
|
|
||||||
|
if (!gst_byte_reader_get_uint32_be (&reader, &y1))
|
||||||
|
goto beach;
|
||||||
|
|
||||||
|
if (!gst_byte_reader_get_uint32_be (&reader, &x0))
|
||||||
|
goto beach;
|
||||||
|
|
||||||
|
if (!gst_byte_reader_get_uint32_be (&reader, &y0))
|
||||||
|
goto beach;
|
||||||
|
|
||||||
|
/* sanity check on image dimensions */
|
||||||
|
if (x1 < x0 || y1 < y0) {
|
||||||
|
GST_ELEMENT_ERROR (jpeg2000parse, STREAM, DECODE, NULL,
|
||||||
|
("Nonsensical image dimensions %d,%d,%d,%d", x0, y0, x1, y1));
|
||||||
|
ret = GST_FLOW_NOT_NEGOTIATED;
|
||||||
|
goto beach;
|
||||||
|
}
|
||||||
|
|
||||||
|
width = x1 - x0;
|
||||||
|
height = y1 - y0;
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (jpeg2000parse, "Parsed image dimensions %d,%d", width,
|
||||||
|
height);
|
||||||
|
|
||||||
|
/* skip tile dimensions */
|
||||||
|
if (!gst_byte_reader_skip (&reader, 4 * 4))
|
||||||
|
goto beach;
|
||||||
|
|
||||||
|
/* read number of components */
|
||||||
|
if (!gst_byte_reader_get_uint16_be (&reader, &numcomps))
|
||||||
|
goto beach;
|
||||||
|
|
||||||
|
if (numcomps > GST_JPEG2000_PARSE_MAX_SUPPORTED_COMPONENTS) {
|
||||||
|
GST_ELEMENT_ERROR (jpeg2000parse, STREAM, DECODE, NULL,
|
||||||
|
("Unsupported number of components %d", numcomps));
|
||||||
|
ret = GST_FLOW_NOT_NEGOTIATED;
|
||||||
|
goto beach;
|
||||||
|
}
|
||||||
|
|
||||||
|
current_caps = gst_pad_get_current_caps (GST_BASE_PARSE_SINK_PAD (parse));
|
||||||
|
if (!current_caps) {
|
||||||
|
GST_ERROR_OBJECT (jpeg2000parse, "Unable to get current caps");
|
||||||
|
ret = GST_FLOW_NOT_NEGOTIATED;
|
||||||
|
goto beach;
|
||||||
|
}
|
||||||
|
|
||||||
|
current_caps_struct = gst_caps_get_structure (current_caps, 0);
|
||||||
|
if (!current_caps_struct) {
|
||||||
|
GST_ERROR_OBJECT (jpeg2000parse, "Unable to get structure of current caps");
|
||||||
|
ret = GST_FLOW_NOT_NEGOTIATED;
|
||||||
|
goto beach;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* colorspace is a required field */
|
||||||
|
colorspace = gst_structure_get_string (current_caps_struct, "colorspace");
|
||||||
|
if (!colorspace) {
|
||||||
|
GST_ERROR_OBJECT (jpeg2000parse, "Missing color space");
|
||||||
|
ret = GST_FLOW_NOT_NEGOTIATED;
|
||||||
|
goto beach;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (compno = 0; compno < numcomps; ++compno) {
|
||||||
|
|
||||||
|
/* skip Ssiz (precision and signed/unsigned bit ) */
|
||||||
|
if (!gst_byte_reader_skip (&reader, 1))
|
||||||
|
goto beach;
|
||||||
|
|
||||||
|
if (!gst_byte_reader_get_uint8 (&reader, dx + compno))
|
||||||
|
goto beach;
|
||||||
|
|
||||||
|
if (!gst_byte_reader_get_uint8 (&reader, dy + compno))
|
||||||
|
goto beach;
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (jpeg2000parse,
|
||||||
|
"Parsed sub-sampling %d,%d for component %d", dx[compno], dy[compno],
|
||||||
|
compno);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* now we can set the dimensions and sub-sampling */
|
||||||
|
if (width != jpeg2000parse->width || height != jpeg2000parse->height) {
|
||||||
|
dimensions_changed = TRUE;
|
||||||
|
}
|
||||||
|
jpeg2000parse->width = width;
|
||||||
|
jpeg2000parse->height = height;
|
||||||
|
|
||||||
|
for (compno = 0; compno < numcomps; ++compno) {
|
||||||
|
if (dx[compno] != jpeg2000parse->dx[compno]
|
||||||
|
|| dy[compno] != jpeg2000parse->dy[compno]) {
|
||||||
|
subsampling_changed = TRUE;
|
||||||
|
}
|
||||||
|
jpeg2000parse->dx[compno] = dx[compno];
|
||||||
|
jpeg2000parse->dx[compno] = dy[compno];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* we do not set sampling field for sub-sampled RGB or monochrome */
|
||||||
|
for (compno = 0; compno < numcomps; ++compno) {
|
||||||
|
if (strcmp (colorspace, "sYUV") && (dx[compno] > 1 || dy[compno] > 1)) {
|
||||||
|
GST_WARNING_OBJECT (jpeg2000parse,
|
||||||
|
"Unable to set sampling field for sub-sampled RGB or monochrome color spaces");
|
||||||
|
goto set_caps;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* sanity check on sub-sampling */
|
||||||
|
if (dx[1] != dx[2] || dy[1] != dy[2]) {
|
||||||
|
GST_WARNING_OBJECT (jpeg2000parse,
|
||||||
|
"Unable to set sampling field because chroma channel sub-sampling factors are not equal");
|
||||||
|
goto set_caps;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strcmp (colorspace, "sYUV")) {
|
||||||
|
/* reject sub-sampled YUVA image */
|
||||||
|
if (numcomps == 4) {
|
||||||
|
guint i;
|
||||||
|
for (i = 0; i < 4; ++i) {
|
||||||
|
if (dx[i] > 1 || dy[i] > 1) {
|
||||||
|
GST_WARNING_OBJECT (jpeg2000parse,
|
||||||
|
"Unable to set sampling field for sub-sampled YUVA images");
|
||||||
|
goto set_caps;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sampling = GST_RTP_J2K_YBRA;
|
||||||
|
samplingEnum = GST_RTP_SAMPLING_YBRA;
|
||||||
|
|
||||||
|
} else if (numcomps == 3) {
|
||||||
|
/* use sub-sampling from U chroma channel */
|
||||||
|
if (dx[1] == 1 && dy[1] == 1) {
|
||||||
|
sampling = GST_RTP_J2K_YBR444;
|
||||||
|
samplingEnum = GST_RTP_SAMPLING_YBR444;
|
||||||
|
} else if (dx[1] == 2 && dy[1] == 2) {
|
||||||
|
sampling = GST_RTP_J2K_YBR420;
|
||||||
|
samplingEnum = GST_RTP_SAMPLING_YBR420;
|
||||||
|
} else if (dx[1] == 4 && dy[1] == 2) {
|
||||||
|
sampling = GST_RTP_J2K_YBR410;
|
||||||
|
samplingEnum = GST_RTP_SAMPLING_YBR410;
|
||||||
|
} else if (dx[1] == 2 && dy[1] == 1) {
|
||||||
|
sampling = GST_RTP_J2K_YBR422;
|
||||||
|
samplingEnum = GST_RTP_SAMPLING_YBR422;
|
||||||
|
} else {
|
||||||
|
GST_WARNING_OBJECT (jpeg2000parse,
|
||||||
|
"Unable to set sampling field for sub-sampling factors %d,%d",
|
||||||
|
dx[1], dy[1]);
|
||||||
|
goto set_caps;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (!strcmp (colorspace, "GRAY")) {
|
||||||
|
sampling = GST_RTP_J2K_GRAYSCALE;
|
||||||
|
samplingEnum = GST_RTP_SAMPLING_GRAYSCALE;
|
||||||
|
} else {
|
||||||
|
if (numcomps == 4) {
|
||||||
|
sampling = GST_RTP_J2K_RGBA;
|
||||||
|
samplingEnum = GST_RTP_SAMPLING_RGBA;
|
||||||
|
} else {
|
||||||
|
sampling = GST_RTP_J2K_RGB;
|
||||||
|
samplingEnum = GST_RTP_SAMPLING_RGB;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
set_caps:
|
||||||
|
|
||||||
|
if (dimensions_changed || subsampling_changed) {
|
||||||
|
GstCaps *src_caps = NULL;
|
||||||
|
gint fr_num, fr_denom;
|
||||||
|
|
||||||
|
src_caps =
|
||||||
|
gst_caps_new_simple (gst_structure_get_name (current_caps_struct),
|
||||||
|
"width", G_TYPE_INT, jpeg2000parse->width, "height", G_TYPE_INT,
|
||||||
|
jpeg2000parse->height, "colorspace", G_TYPE_STRING, colorspace, NULL);
|
||||||
|
|
||||||
|
|
||||||
|
if (sampling) {
|
||||||
|
gst_caps_set_simple (src_caps, "sampling", G_TYPE_STRING, sampling, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gst_structure_get_fraction (current_caps_struct, "framerate", &fr_num,
|
||||||
|
&fr_denom)) {
|
||||||
|
gst_caps_set_simple (src_caps, "framerate", GST_TYPE_FRACTION, fr_num,
|
||||||
|
fr_denom, NULL);
|
||||||
|
} else {
|
||||||
|
GST_WARNING_OBJECT (jpeg2000parse, "No framerate set");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (!gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (parse), src_caps)) {
|
||||||
|
GST_ERROR_OBJECT (jpeg2000parse, "Unable to set source caps");
|
||||||
|
ret = GST_FLOW_NOT_NEGOTIATED;
|
||||||
|
gst_caps_unref (src_caps);
|
||||||
|
goto beach;
|
||||||
|
}
|
||||||
|
|
||||||
|
gst_caps_unref (src_caps);
|
||||||
|
jpeg2000parse->sampling = samplingEnum;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* look for EOC end of codestream marker */
|
||||||
|
eoc_offset = gst_byte_reader_masked_scan_uint32 (&reader, 0x0000ffff,
|
||||||
|
0xFFD9, 0, gst_byte_reader_get_remaining (&reader));
|
||||||
|
|
||||||
|
if (eoc_offset != -1) {
|
||||||
|
/* add 4 for eoc marker and eoc marker size */
|
||||||
|
guint frame_size = gst_byte_reader_get_pos (&reader) + eoc_offset + 4;
|
||||||
|
GST_DEBUG_OBJECT (jpeg2000parse,
|
||||||
|
"Found EOC at offset = %d, frame size = %d", eoc_offset, frame_size);
|
||||||
|
|
||||||
|
if (frame_size < gst_byte_reader_get_size (&reader))
|
||||||
|
goto beach;
|
||||||
|
|
||||||
|
gst_caps_unref (current_caps);
|
||||||
|
gst_buffer_unmap (frame->buffer, &map);
|
||||||
|
return gst_base_parse_finish_frame (parse, frame, frame_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
beach:
|
||||||
|
if (current_caps)
|
||||||
|
gst_caps_unref (current_caps);
|
||||||
|
gst_buffer_unmap (frame->buffer, &map);
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
}
|
66
gst/videoparsers/gstjpeg2000parse.h
Normal file
66
gst/videoparsers/gstjpeg2000parse.h
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
/* GStreamer JPEG 2000 Parser
|
||||||
|
* Copyright (C) <2016> Grok Image Compression Inc.
|
||||||
|
* @author Aaron Boxer <boxerab@gmail.com>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GST_JPEG2000_PARSE_H__
|
||||||
|
#define __GST_JPEG2000_PARSE_H__
|
||||||
|
|
||||||
|
#include <gst/gst.h>
|
||||||
|
#include <gst/base/gstadapter.h>
|
||||||
|
#include <gst/base/gstbaseparse.h>
|
||||||
|
#include "gstjpeg2000sampling.h"
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
#define GST_TYPE_JPEG2000_PARSE \
|
||||||
|
(gst_jpeg2000_parse_get_type())
|
||||||
|
#define GST_JPEG2000_PARSE(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_JPEG2000_PARSE,GstJPEG2000Parse))
|
||||||
|
#define GST_JPEG2000_PARSE_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_JPEG2000_PARSE,GstJPEG2000ParseClass))
|
||||||
|
#define GST_IS_JPEG2000_PARSE(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_JPEG2000_PARSE))
|
||||||
|
#define GST_IS_JPEG2000_PARSE_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_JPEG2000_PARSE))
|
||||||
|
GType gst_jpeg2000_parse_get_type (void);
|
||||||
|
|
||||||
|
typedef struct _GstJPEG2000Parse GstJPEG2000Parse;
|
||||||
|
typedef struct _GstJPEG2000ParseClass GstJPEG2000ParseClass;
|
||||||
|
|
||||||
|
#define GST_JPEG2000_PARSE_MAX_SUPPORTED_COMPONENTS 4
|
||||||
|
|
||||||
|
struct _GstJPEG2000Parse
|
||||||
|
{
|
||||||
|
GstBaseParse baseparse;
|
||||||
|
|
||||||
|
guint width;
|
||||||
|
guint height;
|
||||||
|
|
||||||
|
guint8 dx[GST_JPEG2000_PARSE_MAX_SUPPORTED_COMPONENTS];
|
||||||
|
guint8 dy[GST_JPEG2000_PARSE_MAX_SUPPORTED_COMPONENTS]; /* subsampling factors */
|
||||||
|
|
||||||
|
GstRtpSampling sampling;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _GstJPEG2000ParseClass
|
||||||
|
{
|
||||||
|
GstBaseParseClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
#endif
|
|
@ -58,6 +58,22 @@ GRAYSCALE: basically, a single component image of just multilevels of grey.
|
||||||
|
|
||||||
#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\"}"
|
#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;
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* GstJ2KMarker:
|
* GstJ2KMarker:
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#include "gstmpegvideoparse.h"
|
#include "gstmpegvideoparse.h"
|
||||||
#include "gstmpeg4videoparse.h"
|
#include "gstmpeg4videoparse.h"
|
||||||
#include "gstpngparse.h"
|
#include "gstpngparse.h"
|
||||||
|
#include "gstjpeg2000parse.h"
|
||||||
#include "gstvc1parse.h"
|
#include "gstvc1parse.h"
|
||||||
#include "gsth265parse.h"
|
#include "gsth265parse.h"
|
||||||
|
|
||||||
|
@ -48,6 +49,8 @@ plugin_init (GstPlugin * plugin)
|
||||||
GST_RANK_PRIMARY + 1, GST_TYPE_MPEG4VIDEO_PARSE);
|
GST_RANK_PRIMARY + 1, GST_TYPE_MPEG4VIDEO_PARSE);
|
||||||
ret |= gst_element_register (plugin, "pngparse",
|
ret |= gst_element_register (plugin, "pngparse",
|
||||||
GST_RANK_PRIMARY, GST_TYPE_PNG_PARSE);
|
GST_RANK_PRIMARY, GST_TYPE_PNG_PARSE);
|
||||||
|
ret |= gst_element_register (plugin, "jpeg2000parse",
|
||||||
|
GST_RANK_PRIMARY, GST_TYPE_JPEG2000_PARSE);
|
||||||
ret |= gst_element_register (plugin, "h265parse",
|
ret |= gst_element_register (plugin, "h265parse",
|
||||||
GST_RANK_SECONDARY, GST_TYPE_H265_PARSE);
|
GST_RANK_SECONDARY, GST_TYPE_H265_PARSE);
|
||||||
ret |= gst_element_register (plugin, "vc1parse",
|
ret |= gst_element_register (plugin, "vc1parse",
|
||||||
|
|
Loading…
Reference in a new issue