mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-11 01:45:33 +00:00
videoparsers: port to 0.11
Unit tests missing for now.
This commit is contained in:
parent
4a8373b267
commit
e6df0b672f
6 changed files with 268 additions and 216 deletions
|
@ -302,7 +302,7 @@ GST_PLUGINS_NONPORTED=" adpcmdec adpcmenc aiff asfmux \
|
|||
mpegpsmux mpegvideoparse mve mxf mythtv nsf nuvdemux \
|
||||
patchdetect pcapparse pnm rawparse real removesilence rtpmux rtpvp8 scaletempo \
|
||||
sdi segmentclip siren speed subenc stereo tta videofilters \
|
||||
videomaxrate videomeasure videoparsers videosignal vmnc \
|
||||
videomaxrate videomeasure videosignal vmnc \
|
||||
decklink fbdev linsys shm vcd \
|
||||
voaacenc apexsink bz2 camerabin2 cdaudio celt cog curl dc1394 dirac directfb dts resindvd \
|
||||
gsettings gsm jp2k ladspa modplug mpeg2enc mplex mimic \
|
||||
|
|
|
@ -95,13 +95,20 @@ GST_STATIC_PAD_TEMPLATE ("src",
|
|||
|
||||
/* class initialization */
|
||||
|
||||
GST_BOILERPLATE (GstDiracParse, gst_dirac_parse, GstBaseParse,
|
||||
GST_TYPE_BASE_PARSE);
|
||||
#define parent_class gst_dirac_parse_parent_class
|
||||
G_DEFINE_TYPE (GstDiracParse, gst_dirac_parse, GST_TYPE_BASE_PARSE);
|
||||
|
||||
static void
|
||||
gst_dirac_parse_base_init (gpointer g_class)
|
||||
gst_dirac_parse_class_init (GstDiracParseClass * klass)
|
||||
{
|
||||
GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
|
||||
GstBaseParseClass *base_parse_class = GST_BASE_PARSE_CLASS (klass);
|
||||
|
||||
gobject_class->set_property = gst_dirac_parse_set_property;
|
||||
gobject_class->get_property = gst_dirac_parse_get_property;
|
||||
gobject_class->dispose = gst_dirac_parse_dispose;
|
||||
gobject_class->finalize = gst_dirac_parse_finalize;
|
||||
|
||||
gst_element_class_add_pad_template (element_class,
|
||||
gst_static_pad_template_get (&gst_dirac_parse_src_template));
|
||||
|
@ -111,18 +118,7 @@ gst_dirac_parse_base_init (gpointer g_class)
|
|||
gst_element_class_set_details_simple (element_class, "Dirac parser",
|
||||
"Codec/Parser/Video", "Parses Dirac streams",
|
||||
"David Schleef <ds@schleef.org>");
|
||||
}
|
||||
|
||||
static void
|
||||
gst_dirac_parse_class_init (GstDiracParseClass * klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
GstBaseParseClass *base_parse_class = GST_BASE_PARSE_CLASS (klass);
|
||||
|
||||
gobject_class->set_property = gst_dirac_parse_set_property;
|
||||
gobject_class->get_property = gst_dirac_parse_get_property;
|
||||
gobject_class->dispose = gst_dirac_parse_dispose;
|
||||
gobject_class->finalize = gst_dirac_parse_finalize;
|
||||
base_parse_class->start = GST_DEBUG_FUNCPTR (gst_dirac_parse_start);
|
||||
base_parse_class->stop = GST_DEBUG_FUNCPTR (gst_dirac_parse_stop);
|
||||
base_parse_class->set_sink_caps =
|
||||
|
@ -140,11 +136,9 @@ gst_dirac_parse_class_init (GstDiracParseClass * klass)
|
|||
}
|
||||
|
||||
static void
|
||||
gst_dirac_parse_init (GstDiracParse * diracparse,
|
||||
GstDiracParseClass * diracparse_class)
|
||||
gst_dirac_parse_init (GstDiracParse * diracparse)
|
||||
{
|
||||
gst_base_parse_set_min_frame_size (GST_BASE_PARSE (diracparse), 13);
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -219,37 +213,38 @@ static gboolean
|
|||
gst_dirac_parse_check_valid_frame (GstBaseParse * parse,
|
||||
GstBaseParseFrame * frame, guint * framesize, gint * skipsize)
|
||||
{
|
||||
GstByteReader reader = GST_BYTE_READER_INIT_FROM_BUFFER (frame->buffer);
|
||||
int off;
|
||||
guint32 next_header;
|
||||
guint8 *data;
|
||||
int size;
|
||||
gsize size;
|
||||
gboolean have_picture = FALSE;
|
||||
int offset;
|
||||
|
||||
data = GST_BUFFER_DATA (frame->buffer);
|
||||
size = GST_BUFFER_SIZE (frame->buffer);
|
||||
data = gst_buffer_map (frame->buffer, &size, NULL, GST_MAP_READ);
|
||||
|
||||
if (G_UNLIKELY (size < 13))
|
||||
return FALSE;
|
||||
goto out;
|
||||
|
||||
GST_DEBUG ("%d: %02x %02x %02x %02x", size, data[0], data[1], data[2],
|
||||
data[3]);
|
||||
|
||||
if (GST_READ_UINT32_BE (data) != 0x42424344) {
|
||||
GstByteReader reader;
|
||||
|
||||
gst_byte_reader_init (&reader, data, size);
|
||||
off = gst_byte_reader_masked_scan_uint32 (&reader, 0xffffffff,
|
||||
0x42424344, 0, GST_BUFFER_SIZE (frame->buffer));
|
||||
0x42424344, 0, size);
|
||||
|
||||
if (off < 0) {
|
||||
*skipsize = GST_BUFFER_SIZE (frame->buffer) - 3;
|
||||
return FALSE;
|
||||
*skipsize = size - 3;
|
||||
goto out;
|
||||
}
|
||||
|
||||
GST_LOG_OBJECT (parse, "possible sync at buffer offset %d", off);
|
||||
|
||||
GST_DEBUG ("skipping %d", off);
|
||||
*skipsize = off;
|
||||
return FALSE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* have sync, parse chunks */
|
||||
|
@ -260,7 +255,7 @@ gst_dirac_parse_check_valid_frame (GstBaseParse * parse,
|
|||
|
||||
if (offset + 13 >= size) {
|
||||
*framesize = offset + 13;
|
||||
return FALSE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
GST_DEBUG ("chunk type %02x", data[offset + 4]);
|
||||
|
@ -268,7 +263,7 @@ gst_dirac_parse_check_valid_frame (GstBaseParse * parse,
|
|||
if (GST_READ_UINT32_BE (data + offset) != 0x42424344) {
|
||||
GST_DEBUG ("bad header");
|
||||
*skipsize = 3;
|
||||
return FALSE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
next_header = GST_READ_UINT32_BE (data + offset + 5);
|
||||
|
@ -283,14 +278,20 @@ gst_dirac_parse_check_valid_frame (GstBaseParse * parse,
|
|||
offset += next_header;
|
||||
if (offset >= size) {
|
||||
*framesize = offset;
|
||||
return FALSE;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
gst_buffer_unmap (frame->buffer, data, size);
|
||||
|
||||
*framesize = offset;
|
||||
GST_DEBUG ("framesize %d", *framesize);
|
||||
|
||||
return TRUE;
|
||||
|
||||
out:
|
||||
gst_buffer_unmap (frame->buffer, data, size);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static GstFlowReturn
|
||||
|
@ -298,14 +299,13 @@ gst_dirac_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
|
|||
{
|
||||
GstDiracParse *diracparse = GST_DIRAC_PARSE (parse);
|
||||
guint8 *data;
|
||||
int size;
|
||||
gsize size;
|
||||
|
||||
/* Called when processing incoming buffers. Function should parse
|
||||
a checked frame. */
|
||||
/* MUST implement */
|
||||
|
||||
data = GST_BUFFER_DATA (frame->buffer);
|
||||
size = GST_BUFFER_SIZE (frame->buffer);
|
||||
data = gst_buffer_map (frame->buffer, &size, NULL, GST_MAP_READ);
|
||||
|
||||
//GST_ERROR("got here %d", size);
|
||||
|
||||
|
@ -339,8 +339,7 @@ gst_dirac_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
|
|||
}
|
||||
}
|
||||
|
||||
gst_buffer_set_caps (frame->buffer,
|
||||
GST_PAD_CAPS (GST_BASE_PARSE_SRC_PAD (parse)));
|
||||
gst_buffer_unmap (frame->buffer, data, size);
|
||||
|
||||
gst_base_parse_set_min_frame_size (parse, 13);
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@ GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK,
|
|||
GST_STATIC_CAPS ("video/x-h263, variant = (string) itu")
|
||||
);
|
||||
|
||||
GST_BOILERPLATE (GstH263Parse, gst_h263_parse, GstElement, GST_TYPE_BASE_PARSE);
|
||||
G_DEFINE_TYPE (GstH263Parse, gst_h263_parse, GST_TYPE_BASE_PARSE);
|
||||
|
||||
static gboolean gst_h263_parse_start (GstBaseParse * parse);
|
||||
static gboolean gst_h263_parse_stop (GstBaseParse * parse);
|
||||
|
@ -60,9 +60,12 @@ static GstFlowReturn gst_h263_parse_parse_frame (GstBaseParse * parse,
|
|||
GstBaseParseFrame * frame);
|
||||
|
||||
static void
|
||||
gst_h263_parse_base_init (gpointer g_class)
|
||||
gst_h263_parse_class_init (GstH263ParseClass * klass)
|
||||
{
|
||||
GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
|
||||
GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
|
||||
GstBaseParseClass *parse_class = GST_BASE_PARSE_CLASS (klass);
|
||||
|
||||
GST_DEBUG_CATEGORY_INIT (h263_parse_debug, "h263parse", 0, "h263 parser");
|
||||
|
||||
gst_element_class_add_pad_template (gstelement_class,
|
||||
gst_static_pad_template_get (&srctemplate));
|
||||
|
@ -74,14 +77,6 @@ gst_h263_parse_base_init (gpointer g_class)
|
|||
"Arun Raghavan <arun.raghavan@collabora.co.uk>,"
|
||||
"Edward Hervey <edward.hervey@collabora.co.uk>");
|
||||
|
||||
GST_DEBUG_CATEGORY_INIT (h263_parse_debug, "h263parse", 0, "h263 parser");
|
||||
}
|
||||
|
||||
static void
|
||||
gst_h263_parse_class_init (GstH263ParseClass * klass)
|
||||
{
|
||||
GstBaseParseClass *parse_class = GST_BASE_PARSE_CLASS (klass);
|
||||
|
||||
/* Override BaseParse vfuncs */
|
||||
parse_class->start = GST_DEBUG_FUNCPTR (gst_h263_parse_start);
|
||||
parse_class->stop = GST_DEBUG_FUNCPTR (gst_h263_parse_stop);
|
||||
|
@ -92,7 +87,7 @@ gst_h263_parse_class_init (GstH263ParseClass * klass)
|
|||
}
|
||||
|
||||
static void
|
||||
gst_h263_parse_init (GstH263Parse * h263parse, GstH263ParseClass * g_class)
|
||||
gst_h263_parse_init (GstH263Parse * h263parse)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -153,10 +148,13 @@ gst_h263_parse_sink_event (GstBaseParse * parse, GstEvent * event)
|
|||
static guint
|
||||
find_psc (GstBuffer * buffer, guint skip)
|
||||
{
|
||||
guint8 *buf_data;
|
||||
gsize buf_size;
|
||||
GstByteReader br;
|
||||
guint psc_pos = -1, psc;
|
||||
|
||||
gst_byte_reader_init_from_buffer (&br, buffer);
|
||||
buf_data = gst_buffer_map (buffer, &buf_size, NULL, GST_MAP_READ);
|
||||
gst_byte_reader_init (&br, buf_data, buf_size);
|
||||
|
||||
if (!gst_byte_reader_set_pos (&br, skip))
|
||||
goto out;
|
||||
|
@ -174,6 +172,7 @@ find_psc (GstBuffer * buffer, guint skip)
|
|||
}
|
||||
|
||||
out:
|
||||
gst_buffer_unmap (buffer, buf_data, buf_size);
|
||||
return psc_pos;
|
||||
}
|
||||
|
||||
|
@ -187,16 +186,16 @@ gst_h263_parse_set_src_caps (GstH263Parse * h263parse,
|
|||
|
||||
g_assert (h263parse->state == PASSTHROUGH || h263parse->state == GOT_HEADER);
|
||||
|
||||
caps = GST_PAD_CAPS (GST_BASE_PARSE_SINK_PAD (h263parse));
|
||||
caps = gst_pad_get_current_caps (GST_BASE_PARSE_SINK_PAD (h263parse));
|
||||
if (caps) {
|
||||
caps = gst_caps_copy (caps);
|
||||
caps = gst_caps_make_writable (caps);
|
||||
} else {
|
||||
caps = gst_caps_new_simple ("video/x-h263",
|
||||
"variant", G_TYPE_STRING, "itu", NULL);
|
||||
}
|
||||
gst_caps_set_simple (caps, "parsed", G_TYPE_BOOLEAN, TRUE, NULL);
|
||||
|
||||
sink_caps = GST_PAD_CAPS (GST_BASE_PARSE_SINK_PAD (h263parse));
|
||||
sink_caps = gst_pad_get_current_caps (GST_BASE_PARSE_SINK_PAD (h263parse));
|
||||
if (sink_caps && (st = gst_caps_get_structure (sink_caps, 0)) &&
|
||||
gst_structure_get_fraction (st, "framerate", &fr_num, &fr_denom)) {
|
||||
/* Got it in caps - nothing more to do */
|
||||
|
@ -253,19 +252,21 @@ gst_h263_parse_check_valid_frame (GstBaseParse * parse,
|
|||
GstH263Parse *h263parse;
|
||||
GstBuffer *buffer;
|
||||
guint psc_pos, next_psc_pos;
|
||||
gsize size;
|
||||
|
||||
h263parse = GST_H263_PARSE (parse);
|
||||
buffer = frame->buffer;
|
||||
size = gst_buffer_get_size (buffer);
|
||||
|
||||
if (GST_BUFFER_SIZE (buffer) < 3)
|
||||
if (size < 3)
|
||||
return FALSE;
|
||||
|
||||
psc_pos = find_psc (buffer, 0);
|
||||
|
||||
if (psc_pos == -1) {
|
||||
/* PSC not found, need more data */
|
||||
if (GST_BUFFER_SIZE (buffer) > 3)
|
||||
psc_pos = GST_BUFFER_SIZE (buffer) - 3;
|
||||
if (size > 3)
|
||||
psc_pos = size - 3;
|
||||
else
|
||||
psc_pos = 0;
|
||||
goto more;
|
||||
|
@ -278,7 +279,7 @@ gst_h263_parse_check_valid_frame (GstBaseParse * parse,
|
|||
if (next_psc_pos == -1) {
|
||||
if (GST_BASE_PARSE_DRAINING (parse))
|
||||
/* FLUSH/EOS, it's okay if we can't find the next frame */
|
||||
next_psc_pos = GST_BUFFER_SIZE (buffer);
|
||||
next_psc_pos = size;
|
||||
else
|
||||
goto more;
|
||||
}
|
||||
|
@ -347,9 +348,6 @@ gst_h263_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
|
|||
|
||||
/* h263parse->state is now GOT_HEADER */
|
||||
|
||||
gst_buffer_set_caps (buffer,
|
||||
GST_PAD_CAPS (GST_BASE_PARSE_SRC_PAD (GST_BASE_PARSE (h263parse))));
|
||||
|
||||
if (gst_h263_parse_is_delta_unit (¶ms))
|
||||
GST_BUFFER_FLAG_UNSET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);
|
||||
else
|
||||
|
|
|
@ -71,8 +71,8 @@ static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
|
|||
"stream-format=(string) { avc, byte-stream }, "
|
||||
"alignment=(string) { au, nal }"));
|
||||
|
||||
GST_BOILERPLATE (GstH264Parse, gst_h264_parse, GstBaseParse,
|
||||
GST_TYPE_BASE_PARSE);
|
||||
#define parent_class gst_h264_parse_parent_class
|
||||
G_DEFINE_TYPE (GstH264Parse, gst_h264_parse, GST_TYPE_BASE_PARSE);
|
||||
|
||||
static void gst_h264_parse_finalize (GObject * object);
|
||||
|
||||
|
@ -91,32 +91,19 @@ static void gst_h264_parse_get_property (GObject * object, guint prop_id,
|
|||
GValue * value, GParamSpec * pspec);
|
||||
|
||||
static gboolean gst_h264_parse_set_caps (GstBaseParse * parse, GstCaps * caps);
|
||||
static GstCaps *gst_h264_parse_get_caps (GstBaseParse * parse);
|
||||
static GstFlowReturn gst_h264_parse_chain (GstPad * pad, GstBuffer * buffer);
|
||||
|
||||
static void
|
||||
gst_h264_parse_base_init (gpointer g_class)
|
||||
{
|
||||
GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
|
||||
|
||||
gst_element_class_add_pad_template (gstelement_class,
|
||||
gst_static_pad_template_get (&srctemplate));
|
||||
gst_element_class_add_pad_template (gstelement_class,
|
||||
gst_static_pad_template_get (&sinktemplate));
|
||||
|
||||
gst_element_class_set_details_simple (gstelement_class, "H.264 parser",
|
||||
"Codec/Parser/Converter/Video",
|
||||
"Parses H.264 streams",
|
||||
"Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>");
|
||||
|
||||
GST_DEBUG_CATEGORY_INIT (h264_parse_debug, "h264parse", 0, "h264 parser");
|
||||
}
|
||||
static GstCaps *gst_h264_parse_get_caps (GstBaseParse * parse,
|
||||
GstCaps * filter);
|
||||
static GstFlowReturn gst_h264_parse_chain (GstPad * pad, GstObject * parent,
|
||||
GstBuffer * buffer);
|
||||
|
||||
static void
|
||||
gst_h264_parse_class_init (GstH264ParseClass * klass)
|
||||
{
|
||||
GObjectClass *gobject_class = (GObjectClass *) klass;
|
||||
GstBaseParseClass *parse_class = GST_BASE_PARSE_CLASS (klass);
|
||||
GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
|
||||
|
||||
GST_DEBUG_CATEGORY_INIT (h264_parse_debug, "h264parse", 0, "h264 parser");
|
||||
|
||||
gobject_class->finalize = gst_h264_parse_finalize;
|
||||
gobject_class->set_property = gst_h264_parse_set_property;
|
||||
|
@ -140,10 +127,20 @@ gst_h264_parse_class_init (GstH264ParseClass * klass)
|
|||
GST_DEBUG_FUNCPTR (gst_h264_parse_pre_push_frame);
|
||||
parse_class->set_sink_caps = GST_DEBUG_FUNCPTR (gst_h264_parse_set_caps);
|
||||
parse_class->get_sink_caps = GST_DEBUG_FUNCPTR (gst_h264_parse_get_caps);
|
||||
|
||||
gst_element_class_add_pad_template (gstelement_class,
|
||||
gst_static_pad_template_get (&srctemplate));
|
||||
gst_element_class_add_pad_template (gstelement_class,
|
||||
gst_static_pad_template_get (&sinktemplate));
|
||||
|
||||
gst_element_class_set_details_simple (gstelement_class, "H.264 parser",
|
||||
"Codec/Parser/Converter/Video",
|
||||
"Parses H.264 streams",
|
||||
"Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>");
|
||||
}
|
||||
|
||||
static void
|
||||
gst_h264_parse_init (GstH264Parse * h264parse, GstH264ParseClass * g_class)
|
||||
gst_h264_parse_init (GstH264Parse * h264parse)
|
||||
{
|
||||
h264parse->frame_out = gst_adapter_new ();
|
||||
|
||||
|
@ -340,22 +337,23 @@ gst_h264_parse_wrap_nal (GstH264Parse * h264parse, guint format, guint8 * data,
|
|||
{
|
||||
GstBuffer *buf;
|
||||
guint nl = h264parse->nal_length_size;
|
||||
guint32 tmp;
|
||||
|
||||
GST_DEBUG_OBJECT (h264parse, "nal length %d", size);
|
||||
|
||||
buf = gst_buffer_new_and_alloc (size + nl + 4);
|
||||
buf = gst_buffer_new_allocate (NULL, nl + size, 0);
|
||||
if (format == GST_H264_PARSE_FORMAT_AVC) {
|
||||
GST_WRITE_UINT32_BE (GST_BUFFER_DATA (buf), size << (32 - 8 * nl));
|
||||
tmp = GUINT32_TO_BE (size << (32 - 8 * nl));
|
||||
} else {
|
||||
/* HACK: nl should always be 4 here, otherwise this won't work.
|
||||
* There are legit cases where nl in avc stream is 2, but byte-stream
|
||||
* SC is still always 4 bytes. */
|
||||
nl = 4;
|
||||
GST_WRITE_UINT32_BE (GST_BUFFER_DATA (buf), 1);
|
||||
tmp = GUINT32_TO_BE (1);
|
||||
}
|
||||
|
||||
GST_BUFFER_SIZE (buf) = size + nl;
|
||||
memcpy (GST_BUFFER_DATA (buf) + nl, data, size);
|
||||
gst_buffer_fill (buf, 0, &tmp, sizeof (guint32));
|
||||
gst_buffer_fill (buf, nl, data, size);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
@ -383,8 +381,8 @@ gst_h264_parser_store_nal (GstH264Parse * h264parse, guint id,
|
|||
return;
|
||||
}
|
||||
|
||||
buf = gst_buffer_new_and_alloc (size);
|
||||
memcpy (GST_BUFFER_DATA (buf), nalu->data + nalu->offset, size);
|
||||
buf = gst_buffer_new_allocate (NULL, size, 0);
|
||||
gst_buffer_fill (buf, 0, nalu->data + nalu->offset, size);
|
||||
|
||||
if (store[id])
|
||||
gst_buffer_unref (store[id]);
|
||||
|
@ -592,14 +590,19 @@ gst_h264_parse_check_valid_frame (GstBaseParse * parse,
|
|||
GstH264Parse *h264parse = GST_H264_PARSE (parse);
|
||||
GstBuffer *buffer = frame->buffer;
|
||||
guint8 *data;
|
||||
guint size, current_off = 0;
|
||||
gsize size;
|
||||
guint current_off = 0;
|
||||
gboolean drain;
|
||||
GstH264NalParser *nalparser = h264parse->nalparser;
|
||||
GstH264NalUnit nalu = h264parse->nalu;
|
||||
|
||||
data = gst_buffer_map (buffer, &size, NULL, GST_MAP_READ);
|
||||
|
||||
/* expect at least 3 bytes startcode == sc, and 2 bytes NALU payload */
|
||||
if (G_UNLIKELY (GST_BUFFER_SIZE (buffer) < 5))
|
||||
if (G_UNLIKELY (size < 5)) {
|
||||
gst_buffer_unmap (buffer, data, size);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* need to configure aggregation */
|
||||
if (G_UNLIKELY (h264parse->format == GST_H264_PARSE_FORMAT_NONE))
|
||||
|
@ -614,9 +617,6 @@ gst_h264_parse_check_valid_frame (GstBaseParse * parse,
|
|||
GST_LOG_OBJECT (h264parse, "resuming frame parsing");
|
||||
}
|
||||
|
||||
data = GST_BUFFER_DATA (buffer);
|
||||
size = GST_BUFFER_SIZE (buffer);
|
||||
|
||||
drain = FALSE;
|
||||
current_off = h264parse->current_off;
|
||||
|
||||
|
@ -645,7 +645,7 @@ gst_h264_parse_check_valid_frame (GstBaseParse * parse,
|
|||
}
|
||||
break;
|
||||
case GST_H264_PARSER_BROKEN_LINK:
|
||||
return FALSE;
|
||||
goto out;
|
||||
case GST_H264_PARSER_ERROR:
|
||||
current_off = size - 3;
|
||||
goto parsing_error;
|
||||
|
@ -711,6 +711,7 @@ end:
|
|||
*framesize = nalu.offset + nalu.size - h264parse->nalu.sc_offset;
|
||||
h264parse->current_off = current_off;
|
||||
|
||||
gst_buffer_unmap (buffer, data, size);
|
||||
return TRUE;
|
||||
|
||||
parsing_error:
|
||||
|
@ -733,11 +734,14 @@ more:
|
|||
/* Restart parsing from here next time */
|
||||
h264parse->current_off = current_off;
|
||||
|
||||
/* Fall-through. */
|
||||
out:
|
||||
gst_buffer_unmap (buffer, data, size);
|
||||
return FALSE;
|
||||
|
||||
invalid:
|
||||
gst_h264_parse_reset_frame (h264parse);
|
||||
return FALSE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* byte together avc codec data based on collected pps and sps so far */
|
||||
|
@ -748,20 +752,23 @@ gst_h264_parse_make_codec_data (GstH264Parse * h264parse)
|
|||
gint i, sps_size = 0, pps_size = 0, num_sps = 0, num_pps = 0;
|
||||
guint8 profile_idc = 0, profile_comp = 0, level_idc = 0;
|
||||
gboolean found = FALSE;
|
||||
guint8 *data;
|
||||
guint8 *buf_data, *data;
|
||||
|
||||
/* only nal payload in stored nals */
|
||||
|
||||
for (i = 0; i < GST_H264_MAX_SPS_COUNT; i++) {
|
||||
if ((nal = h264parse->sps_nals[i])) {
|
||||
gsize size = gst_buffer_get_size (nal);
|
||||
num_sps++;
|
||||
/* size bytes also count */
|
||||
sps_size += GST_BUFFER_SIZE (nal) + 2;
|
||||
if (GST_BUFFER_SIZE (nal) >= 4) {
|
||||
sps_size += size + 2;
|
||||
if (size >= 4) {
|
||||
guint8 tmp[3];
|
||||
found = TRUE;
|
||||
profile_idc = (GST_BUFFER_DATA (nal))[1];
|
||||
profile_comp = (GST_BUFFER_DATA (nal))[2];
|
||||
level_idc = (GST_BUFFER_DATA (nal))[3];
|
||||
gst_buffer_extract (nal, 1, tmp, 3);
|
||||
profile_idc = tmp[0];
|
||||
profile_comp = tmp[1];
|
||||
level_idc = tmp[2];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -769,7 +776,7 @@ gst_h264_parse_make_codec_data (GstH264Parse * h264parse)
|
|||
if ((nal = h264parse->pps_nals[i])) {
|
||||
num_pps++;
|
||||
/* size bytes also count */
|
||||
pps_size += GST_BUFFER_SIZE (nal) + 2;
|
||||
pps_size += gst_buffer_get_size (nal) + 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -779,8 +786,9 @@ gst_h264_parse_make_codec_data (GstH264Parse * h264parse)
|
|||
if (!found || !num_pps)
|
||||
return NULL;
|
||||
|
||||
buf = gst_buffer_new_and_alloc (5 + 1 + sps_size + 1 + pps_size);
|
||||
data = GST_BUFFER_DATA (buf);
|
||||
buf = gst_buffer_new_allocate (NULL, 5 + 1 + sps_size + 1 + pps_size, 0);
|
||||
buf_data = gst_buffer_map (buf, NULL, NULL, GST_MAP_WRITE);
|
||||
data = buf_data;
|
||||
|
||||
data[0] = 1; /* AVC Decoder Configuration Record ver. 1 */
|
||||
data[1] = profile_idc; /* profile_idc */
|
||||
|
@ -792,9 +800,10 @@ gst_h264_parse_make_codec_data (GstH264Parse * h264parse)
|
|||
data += 6;
|
||||
for (i = 0; i < GST_H264_MAX_SPS_COUNT; i++) {
|
||||
if ((nal = h264parse->sps_nals[i])) {
|
||||
GST_WRITE_UINT16_BE (data, GST_BUFFER_SIZE (nal));
|
||||
memcpy (data + 2, GST_BUFFER_DATA (nal), GST_BUFFER_SIZE (nal));
|
||||
data += 2 + GST_BUFFER_SIZE (nal);
|
||||
gsize nal_size = gst_buffer_get_size (nal);
|
||||
GST_WRITE_UINT16_BE (data, nal_size);
|
||||
gst_buffer_extract (nal, 0, data + 2, nal_size);
|
||||
data += 2 + nal_size;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -802,12 +811,15 @@ gst_h264_parse_make_codec_data (GstH264Parse * h264parse)
|
|||
data++;
|
||||
for (i = 0; i < GST_H264_MAX_PPS_COUNT; i++) {
|
||||
if ((nal = h264parse->pps_nals[i])) {
|
||||
GST_WRITE_UINT16_BE (data, GST_BUFFER_SIZE (nal));
|
||||
memcpy (data + 2, GST_BUFFER_DATA (nal), GST_BUFFER_SIZE (nal));
|
||||
data += 2 + GST_BUFFER_SIZE (nal);
|
||||
gsize nal_size = gst_buffer_get_size (nal);
|
||||
GST_WRITE_UINT16_BE (data, nal_size);
|
||||
gst_buffer_extract (nal, 0, data + 2, nal_size);
|
||||
data += 2 + nal_size;
|
||||
}
|
||||
}
|
||||
|
||||
gst_buffer_unmap (buf, buf_data, -1);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
@ -819,7 +831,8 @@ gst_h264_parse_update_src_caps (GstH264Parse * h264parse, GstCaps * caps)
|
|||
gboolean modified = FALSE;
|
||||
GstBuffer *buf = NULL;
|
||||
|
||||
if (G_UNLIKELY (!GST_PAD_CAPS (GST_BASE_PARSE_SRC_PAD (h264parse))))
|
||||
if (G_UNLIKELY (!gst_pad_has_current_caps (GST_BASE_PARSE_SRC_PAD
|
||||
(h264parse))))
|
||||
modified = TRUE;
|
||||
else if (G_UNLIKELY (!h264parse->update_caps))
|
||||
return;
|
||||
|
@ -829,13 +842,11 @@ gst_h264_parse_update_src_caps (GstH264Parse * h264parse, GstCaps * caps)
|
|||
if (caps)
|
||||
sink_caps = caps;
|
||||
else
|
||||
sink_caps = GST_PAD_CAPS (GST_BASE_PARSE_SINK_PAD (h264parse));
|
||||
sink_caps = gst_pad_get_current_caps (GST_BASE_PARSE_SINK_PAD (h264parse));
|
||||
|
||||
/* carry over input caps as much as possible; override with our own stuff */
|
||||
if (sink_caps)
|
||||
gst_caps_ref (sink_caps);
|
||||
else
|
||||
sink_caps = gst_caps_new_simple ("video/x-h264", NULL);
|
||||
if (!sink_caps)
|
||||
sink_caps = gst_caps_new_empty_simple ("video/x-h264");
|
||||
|
||||
sps = h264parse->nalparser->last_sps;
|
||||
GST_DEBUG_OBJECT (h264parse, "sps: %p", sps);
|
||||
|
@ -845,10 +856,15 @@ gst_h264_parse_update_src_caps (GstH264Parse * h264parse, GstCaps * caps)
|
|||
h264parse->align == GST_H264_PARSE_ALIGN_AU) {
|
||||
buf = gst_h264_parse_make_codec_data (h264parse);
|
||||
if (buf && h264parse->codec_data) {
|
||||
if (GST_BUFFER_SIZE (buf) != GST_BUFFER_SIZE (h264parse->codec_data) ||
|
||||
memcmp (GST_BUFFER_DATA (buf),
|
||||
GST_BUFFER_DATA (h264parse->codec_data), GST_BUFFER_SIZE (buf)))
|
||||
gsize size;
|
||||
gpointer data;
|
||||
|
||||
data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ);
|
||||
if (size != gst_buffer_get_size (h264parse->codec_data) ||
|
||||
gst_buffer_memcmp (h264parse->codec_data, 0, data, size))
|
||||
modified = TRUE;
|
||||
|
||||
gst_buffer_unmap (buf, data, size);
|
||||
} else {
|
||||
if (h264parse->codec_data)
|
||||
buf = gst_buffer_ref (h264parse->codec_data);
|
||||
|
@ -1061,7 +1077,7 @@ gst_h264_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
|
|||
GstBuffer *buf;
|
||||
|
||||
buf = gst_adapter_take_buffer (h264parse->frame_out, av);
|
||||
gst_buffer_copy_metadata (buf, buffer, GST_BUFFER_COPY_ALL);
|
||||
gst_buffer_copy_into (buf, buffer, GST_BUFFER_COPY_METADATA, 0, -1);
|
||||
gst_buffer_replace (&frame->buffer, buf);
|
||||
gst_buffer_unref (buf);
|
||||
}
|
||||
|
@ -1075,14 +1091,16 @@ static GstFlowReturn
|
|||
gst_h264_parse_push_codec_buffer (GstH264Parse * h264parse, GstBuffer * nal,
|
||||
GstClockTime ts)
|
||||
{
|
||||
nal = gst_h264_parse_wrap_nal (h264parse, h264parse->format,
|
||||
GST_BUFFER_DATA (nal), GST_BUFFER_SIZE (nal));
|
||||
gpointer data;
|
||||
gsize size;
|
||||
|
||||
data = gst_buffer_map (nal, &size, NULL, GST_MAP_READ);
|
||||
nal = gst_h264_parse_wrap_nal (h264parse, h264parse->format, data, size);
|
||||
gst_buffer_unmap (nal, data, size);
|
||||
|
||||
GST_BUFFER_TIMESTAMP (nal) = ts;
|
||||
GST_BUFFER_DURATION (nal) = 0;
|
||||
|
||||
gst_buffer_set_caps (nal, GST_PAD_CAPS (GST_BASE_PARSE_SRC_PAD (h264parse)));
|
||||
|
||||
return gst_pad_push (GST_BASE_PARSE_SRC_PAD (h264parse), nal);
|
||||
}
|
||||
|
||||
|
@ -1156,36 +1174,33 @@ gst_h264_parse_pre_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
|
|||
GstBuffer *new_buf;
|
||||
const gboolean bs = h264parse->format == GST_H264_PARSE_FORMAT_BYTE;
|
||||
|
||||
gst_byte_writer_init_with_size (&bw, GST_BUFFER_SIZE (buffer), FALSE);
|
||||
gst_byte_writer_put_data (&bw, GST_BUFFER_DATA (buffer),
|
||||
h264parse->idr_pos);
|
||||
gst_byte_writer_init_with_size (&bw, gst_buffer_get_size (buffer),
|
||||
FALSE);
|
||||
gst_byte_writer_put_buffer (&bw, buffer, 0, h264parse->idr_pos);
|
||||
GST_DEBUG_OBJECT (h264parse, "- inserting SPS/PPS");
|
||||
for (i = 0; i < GST_H264_MAX_SPS_COUNT; i++) {
|
||||
if ((codec_nal = h264parse->sps_nals[i])) {
|
||||
gsize nal_size = gst_buffer_get_size (codec_nal);
|
||||
GST_DEBUG_OBJECT (h264parse, "inserting SPS nal");
|
||||
gst_byte_writer_put_uint32_be (&bw,
|
||||
bs ? 1 : GST_BUFFER_SIZE (codec_nal));
|
||||
gst_byte_writer_put_data (&bw, GST_BUFFER_DATA (codec_nal),
|
||||
GST_BUFFER_SIZE (codec_nal));
|
||||
gst_byte_writer_put_uint32_be (&bw, bs ? 1 : nal_size);
|
||||
gst_byte_writer_put_buffer (&bw, codec_nal, 0, nal_size);
|
||||
h264parse->last_report = new_ts;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < GST_H264_MAX_PPS_COUNT; i++) {
|
||||
if ((codec_nal = h264parse->pps_nals[i])) {
|
||||
gsize nal_size = gst_buffer_get_size (codec_nal);
|
||||
GST_DEBUG_OBJECT (h264parse, "inserting PPS nal");
|
||||
gst_byte_writer_put_uint32_be (&bw,
|
||||
bs ? 1 : GST_BUFFER_SIZE (codec_nal));
|
||||
gst_byte_writer_put_data (&bw, GST_BUFFER_DATA (codec_nal),
|
||||
GST_BUFFER_SIZE (codec_nal));
|
||||
gst_byte_writer_put_uint32_be (&bw, bs ? 1 : nal_size);
|
||||
gst_byte_writer_put_buffer (&bw, codec_nal, 0, nal_size);
|
||||
h264parse->last_report = new_ts;
|
||||
}
|
||||
}
|
||||
gst_byte_writer_put_data (&bw,
|
||||
GST_BUFFER_DATA (buffer) + h264parse->idr_pos,
|
||||
GST_BUFFER_SIZE (buffer) - h264parse->idr_pos);
|
||||
gst_byte_writer_put_buffer (&bw, buffer, h264parse->idr_pos, -1);
|
||||
/* collect result and push */
|
||||
new_buf = gst_byte_writer_reset_and_get_buffer (&bw);
|
||||
gst_buffer_copy_metadata (new_buf, buffer, GST_BUFFER_COPY_ALL);
|
||||
gst_buffer_copy_into (new_buf, buffer, GST_BUFFER_COPY_METADATA, 0,
|
||||
-1);
|
||||
gst_buffer_replace (&frame->buffer, new_buf);
|
||||
gst_buffer_unref (new_buf);
|
||||
}
|
||||
|
@ -1207,7 +1222,8 @@ gst_h264_parse_set_caps (GstBaseParse * parse, GstCaps * caps)
|
|||
GstStructure *str;
|
||||
const GValue *value;
|
||||
GstBuffer *codec_data = NULL;
|
||||
guint size, format, align, off;
|
||||
gsize size;
|
||||
guint format, align, off;
|
||||
GstH264NalUnit nalu;
|
||||
GstH264ParserResult parseres;
|
||||
|
||||
|
@ -1241,15 +1257,18 @@ gst_h264_parse_set_caps (GstBaseParse * parse, GstCaps * caps)
|
|||
codec_data = gst_value_get_buffer (value);
|
||||
if (!codec_data)
|
||||
goto wrong_type;
|
||||
data = GST_BUFFER_DATA (codec_data);
|
||||
size = GST_BUFFER_SIZE (codec_data);
|
||||
data = gst_buffer_map (codec_data, &size, NULL, GST_MAP_READ);
|
||||
|
||||
/* parse the avcC data */
|
||||
if (size < 8)
|
||||
if (size < 8) {
|
||||
gst_buffer_unmap (codec_data, data, size);
|
||||
goto avcc_too_small;
|
||||
}
|
||||
/* parse the version, this must be 1 */
|
||||
if (data[0] != 1)
|
||||
if (data[0] != 1) {
|
||||
gst_buffer_unmap (codec_data, data, size);
|
||||
goto wrong_version;
|
||||
}
|
||||
|
||||
/* AVCProfileIndication */
|
||||
/* profile_compat */
|
||||
|
@ -1269,8 +1288,10 @@ gst_h264_parse_set_caps (GstBaseParse * parse, GstCaps * caps)
|
|||
for (i = 0; i < num_sps; i++) {
|
||||
parseres = gst_h264_parser_identify_nalu_avc (h264parse->nalparser,
|
||||
data, off, size, 2, &nalu);
|
||||
if (parseres != GST_H264_PARSER_OK)
|
||||
if (parseres != GST_H264_PARSER_OK) {
|
||||
gst_buffer_unmap (codec_data, data, size);
|
||||
goto avcc_too_small;
|
||||
}
|
||||
|
||||
gst_h264_parse_process_nal (h264parse, &nalu);
|
||||
off = nalu.offset + nalu.size;
|
||||
|
@ -1283,6 +1304,7 @@ gst_h264_parse_set_caps (GstBaseParse * parse, GstCaps * caps)
|
|||
parseres = gst_h264_parser_identify_nalu_avc (h264parse->nalparser,
|
||||
data, off, size, 2, &nalu);
|
||||
if (parseres != GST_H264_PARSER_OK) {
|
||||
gst_buffer_unmap (codec_data, data, size);
|
||||
goto avcc_too_small;
|
||||
}
|
||||
|
||||
|
@ -1290,6 +1312,8 @@ gst_h264_parse_set_caps (GstBaseParse * parse, GstCaps * caps)
|
|||
off = nalu.offset + nalu.size;
|
||||
}
|
||||
|
||||
gst_buffer_unmap (codec_data, data, size);
|
||||
|
||||
h264parse->codec_data = gst_buffer_ref (codec_data);
|
||||
|
||||
/* if upstream sets codec_data without setting stream-format and alignment, we
|
||||
|
@ -1354,11 +1378,13 @@ refuse_caps:
|
|||
}
|
||||
|
||||
static GstCaps *
|
||||
gst_h264_parse_get_caps (GstBaseParse * parse)
|
||||
gst_h264_parse_get_caps (GstBaseParse * parse, GstCaps * filter)
|
||||
{
|
||||
GstCaps *peercaps;
|
||||
GstCaps *peercaps, *template_caps;
|
||||
GstCaps *res;
|
||||
|
||||
template_caps =
|
||||
gst_pad_get_pad_template_caps (GST_BASE_PARSE_SINK_PAD (parse));
|
||||
peercaps = gst_pad_get_allowed_caps (GST_BASE_PARSE_SRC_PAD (parse));
|
||||
if (peercaps) {
|
||||
guint i, n;
|
||||
|
@ -1372,24 +1398,28 @@ gst_h264_parse_get_caps (GstBaseParse * parse)
|
|||
gst_structure_remove_field (s, "parsed");
|
||||
}
|
||||
|
||||
res =
|
||||
gst_caps_intersect_full (peercaps,
|
||||
gst_pad_get_pad_template_caps (GST_BASE_PARSE_SINK_PAD (parse)),
|
||||
res = gst_caps_intersect_full (peercaps, template_caps,
|
||||
GST_CAPS_INTERSECT_FIRST);
|
||||
gst_caps_unref (peercaps);
|
||||
gst_caps_unref (template_caps);
|
||||
} else {
|
||||
res =
|
||||
gst_caps_copy (gst_pad_get_pad_template_caps (GST_BASE_PARSE_SINK_PAD
|
||||
(parse)));
|
||||
res = template_caps;
|
||||
}
|
||||
|
||||
if (filter) {
|
||||
GstCaps *tmp = gst_caps_intersect_full (res, filter,
|
||||
GST_CAPS_INTERSECT_FIRST);
|
||||
gst_caps_unref (res);
|
||||
res = tmp;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static GstFlowReturn
|
||||
gst_h264_parse_chain (GstPad * pad, GstBuffer * buffer)
|
||||
gst_h264_parse_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
|
||||
{
|
||||
GstH264Parse *h264parse = GST_H264_PARSE (GST_PAD_PARENT (pad));
|
||||
GstH264Parse *h264parse = GST_H264_PARSE (parent);
|
||||
|
||||
if (h264parse->packetized && buffer) {
|
||||
GstBuffer *sub;
|
||||
|
@ -1397,6 +1427,8 @@ gst_h264_parse_chain (GstPad * pad, GstBuffer * buffer)
|
|||
GstH264ParserResult parse_res;
|
||||
GstH264NalUnit nalu;
|
||||
const guint nl = h264parse->nal_length_size;
|
||||
gpointer data;
|
||||
gsize size;
|
||||
|
||||
if (nl < 1 || nl > 4) {
|
||||
GST_DEBUG_OBJECT (h264parse, "insufficient data to split input");
|
||||
|
@ -1405,11 +1437,13 @@ gst_h264_parse_chain (GstPad * pad, GstBuffer * buffer)
|
|||
return GST_FLOW_NOT_NEGOTIATED;
|
||||
}
|
||||
|
||||
GST_LOG_OBJECT (h264parse, "processing packet buffer of size %d",
|
||||
GST_BUFFER_SIZE (buffer));
|
||||
data = gst_buffer_map (buffer, &size, NULL, GST_MAP_READ);
|
||||
|
||||
GST_LOG_OBJECT (h264parse,
|
||||
"processing packet buffer of size %" G_GSIZE_FORMAT, size);
|
||||
|
||||
parse_res = gst_h264_parser_identify_nalu_avc (h264parse->nalparser,
|
||||
GST_BUFFER_DATA (buffer), 0, GST_BUFFER_SIZE (buffer), nl, &nalu);
|
||||
data, 0, size, nl, &nalu);
|
||||
|
||||
while (parse_res == GST_H264_PARSER_OK) {
|
||||
GST_DEBUG_OBJECT (h264parse, "AVC nal offset %d",
|
||||
|
@ -1422,7 +1456,7 @@ gst_h264_parse_chain (GstPad * pad, GstBuffer * buffer)
|
|||
/* at least this should make sense */
|
||||
GST_BUFFER_TIMESTAMP (sub) = GST_BUFFER_TIMESTAMP (buffer);
|
||||
GST_LOG_OBJECT (h264parse, "pushing NAL of size %d", nalu.size);
|
||||
ret = h264parse->parse_chain (pad, sub);
|
||||
ret = h264parse->parse_chain (pad, parent, sub);
|
||||
} else {
|
||||
/* pass-through: no looking for frames (and nal processing),
|
||||
* so need to parse to collect data here */
|
||||
|
@ -1434,10 +1468,11 @@ gst_h264_parse_chain (GstPad * pad, GstBuffer * buffer)
|
|||
}
|
||||
|
||||
parse_res = gst_h264_parser_identify_nalu_avc (h264parse->nalparser,
|
||||
GST_BUFFER_DATA (buffer), nalu.offset + nalu.size,
|
||||
GST_BUFFER_SIZE (buffer), nl, &nalu);
|
||||
data, nalu.offset + nalu.size, size, nl, &nalu);
|
||||
}
|
||||
|
||||
gst_buffer_unmap (buffer, data, size);
|
||||
|
||||
if (h264parse->split_packetized) {
|
||||
gst_buffer_unref (buffer);
|
||||
return ret;
|
||||
|
@ -1463,7 +1498,7 @@ gst_h264_parse_chain (GstPad * pad, GstBuffer * buffer)
|
|||
}
|
||||
}
|
||||
|
||||
return h264parse->parse_chain (pad, buffer);
|
||||
return h264parse->parse_chain (pad, parent, buffer);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -61,8 +61,8 @@ enum
|
|||
PROP_LAST
|
||||
};
|
||||
|
||||
GST_BOILERPLATE (GstMpegvParse, gst_mpegv_parse, GstBaseParse,
|
||||
GST_TYPE_BASE_PARSE);
|
||||
#define parent_class gst_mpegv_parse_parent_class
|
||||
G_DEFINE_TYPE (GstMpegvParse, gst_mpegv_parse, GST_TYPE_BASE_PARSE);
|
||||
|
||||
static gboolean gst_mpegv_parse_start (GstBaseParse * parse);
|
||||
static gboolean gst_mpegv_parse_stop (GstBaseParse * parse);
|
||||
|
@ -79,28 +79,6 @@ static void gst_mpegv_parse_set_property (GObject * object, guint prop_id,
|
|||
static void gst_mpegv_parse_get_property (GObject * object, guint prop_id,
|
||||
GValue * value, GParamSpec * pspec);
|
||||
|
||||
static void
|
||||
gst_mpegv_parse_base_init (gpointer klass)
|
||||
{
|
||||
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
|
||||
|
||||
gst_element_class_add_pad_template (element_class,
|
||||
gst_static_pad_template_get (&src_template));
|
||||
gst_element_class_add_pad_template (element_class,
|
||||
gst_static_pad_template_get (&sink_template));
|
||||
|
||||
gst_element_class_set_details_simple (element_class,
|
||||
"MPEG video elementary stream parser",
|
||||
"Codec/Parser/Video",
|
||||
"Parses and frames MPEG-1 and MPEG-2 elementary video streams",
|
||||
"Wim Taymans <wim.taymans@ccollabora.co.uk>, "
|
||||
"Jan Schmidt <thaytan@mad.scientist.com>, "
|
||||
"Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>");
|
||||
|
||||
GST_DEBUG_CATEGORY_INIT (mpegv_parse_debug, "mpegvideoparse", 0,
|
||||
"MPEG-1/2 video parser");
|
||||
}
|
||||
|
||||
static void
|
||||
gst_mpegv_parse_set_property (GObject * object, guint property_id,
|
||||
const GValue * value, GParamSpec * pspec)
|
||||
|
@ -141,8 +119,12 @@ static void
|
|||
gst_mpegv_parse_class_init (GstMpegvParseClass * klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
|
||||
GstBaseParseClass *parse_class = GST_BASE_PARSE_CLASS (klass);
|
||||
|
||||
GST_DEBUG_CATEGORY_INIT (mpegv_parse_debug, "mpegvideoparse", 0,
|
||||
"MPEG-1/2 video parser");
|
||||
|
||||
parent_class = g_type_class_peek_parent (klass);
|
||||
|
||||
gobject_class->set_property = gst_mpegv_parse_set_property;
|
||||
|
@ -159,6 +141,19 @@ gst_mpegv_parse_class_init (GstMpegvParseClass * klass)
|
|||
"Split frame when encountering GOP", DEFAULT_PROP_GOP_SPLIT,
|
||||
G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
gst_element_class_add_pad_template (element_class,
|
||||
gst_static_pad_template_get (&src_template));
|
||||
gst_element_class_add_pad_template (element_class,
|
||||
gst_static_pad_template_get (&sink_template));
|
||||
|
||||
gst_element_class_set_details_simple (element_class,
|
||||
"MPEG video elementary stream parser",
|
||||
"Codec/Parser/Video",
|
||||
"Parses and frames MPEG-1 and MPEG-2 elementary video streams",
|
||||
"Wim Taymans <wim.taymans@ccollabora.co.uk>, "
|
||||
"Jan Schmidt <thaytan@mad.scientist.com>, "
|
||||
"Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>");
|
||||
|
||||
/* Override BaseParse vfuncs */
|
||||
parse_class->start = GST_DEBUG_FUNCPTR (gst_mpegv_parse_start);
|
||||
parse_class->stop = GST_DEBUG_FUNCPTR (gst_mpegv_parse_stop);
|
||||
|
@ -171,7 +166,7 @@ gst_mpegv_parse_class_init (GstMpegvParseClass * klass)
|
|||
}
|
||||
|
||||
static void
|
||||
gst_mpegv_parse_init (GstMpegvParse * parse, GstMpegvParseClass * g_class)
|
||||
gst_mpegv_parse_init (GstMpegvParse * parse)
|
||||
{
|
||||
parse->mpeg_version = 0;
|
||||
}
|
||||
|
@ -231,16 +226,21 @@ gst_mpegv_parse_process_config (GstMpegvParse * mpvparse, GstBuffer * buf,
|
|||
guint size)
|
||||
{
|
||||
GList *tmp;
|
||||
guint8 *data = GST_BUFFER_DATA (buf);
|
||||
data = data + mpvparse->seq_offset;
|
||||
guint8 *buf_data, *data;
|
||||
gsize buf_size;
|
||||
|
||||
buf_data = gst_buffer_map (buf, &buf_size, NULL, GST_MAP_READ);
|
||||
data = buf_data + mpvparse->seq_offset;
|
||||
|
||||
/* only do stuff if something new */
|
||||
if (mpvparse->config && size == GST_BUFFER_SIZE (mpvparse->config) &&
|
||||
memcmp (GST_BUFFER_DATA (mpvparse->config), data, size) == 0)
|
||||
if (mpvparse->config && size == gst_buffer_get_size (mpvparse->config) &&
|
||||
gst_buffer_memcmp (mpvparse->config, 0, data, size) == 0) {
|
||||
gst_buffer_unmap (buf, buf_data, buf_size);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (gst_mpeg_video_parse_sequence_header (&mpvparse->sequencehdr, data,
|
||||
GST_BUFFER_SIZE (buf) - mpvparse->seq_offset, 0)) {
|
||||
buf_size - mpvparse->seq_offset, 0)) {
|
||||
if (mpvparse->fps_num == 0 || mpvparse->fps_den == 0) {
|
||||
mpvparse->fps_num = mpvparse->sequencehdr.fps_n;
|
||||
mpvparse->fps_den = mpvparse->sequencehdr.fps_d;
|
||||
|
@ -249,6 +249,7 @@ gst_mpegv_parse_process_config (GstMpegvParse * mpvparse, GstBuffer * buf,
|
|||
GST_DEBUG_OBJECT (mpvparse,
|
||||
"failed to parse config data (size %d) at offset %d",
|
||||
size, mpvparse->seq_offset);
|
||||
gst_buffer_unmap (buf, buf_data, buf_size);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -266,8 +267,7 @@ gst_mpegv_parse_process_config (GstMpegvParse * mpvparse, GstBuffer * buf,
|
|||
mpvparse->mpeg_version = 2;
|
||||
|
||||
if (gst_mpeg_video_parse_sequence_extension (&mpvparse->sequenceext,
|
||||
GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf),
|
||||
tpoffsz->offset)) {
|
||||
buf_data, buf_size, tpoffsz->offset)) {
|
||||
mpvparse->fps_num =
|
||||
mpvparse->sequencehdr.fps_n * (mpvparse->sequenceext.fps_n_ext +
|
||||
1) * 2;
|
||||
|
@ -284,11 +284,13 @@ gst_mpegv_parse_process_config (GstMpegvParse * mpvparse, GstBuffer * buf,
|
|||
gst_buffer_unref (mpvparse->config);
|
||||
|
||||
mpvparse->config = gst_buffer_new_and_alloc (size);
|
||||
memcpy (GST_BUFFER_DATA (mpvparse->config), data, size);
|
||||
gst_buffer_fill (mpvparse->config, 0, data, size);
|
||||
|
||||
/* trigger src caps update */
|
||||
mpvparse->update_caps = TRUE;
|
||||
|
||||
gst_buffer_unmap (buf, buf_data, buf_size);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -354,8 +356,12 @@ static void
|
|||
parse_picture_extension (GstMpegvParse * mpvparse, GstBuffer * buf, guint off)
|
||||
{
|
||||
GstMpegVideoPictureExt ext;
|
||||
if (gst_mpeg_video_parse_picture_extension (&ext, GST_BUFFER_DATA (buf),
|
||||
GST_BUFFER_SIZE (buf), off)) {
|
||||
gpointer data;
|
||||
gsize size;
|
||||
|
||||
data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ);
|
||||
|
||||
if (gst_mpeg_video_parse_picture_extension (&ext, data, size, off)) {
|
||||
mpvparse->frame_repeat_count = 1;
|
||||
|
||||
if (ext.repeat_first_field) {
|
||||
|
@ -369,6 +375,8 @@ parse_picture_extension (GstMpegvParse * mpvparse, GstBuffer * buf, guint off)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
gst_buffer_unmap (buf, data, size);
|
||||
}
|
||||
|
||||
/* caller guarantees at least start code in @buf at @off */
|
||||
|
@ -380,7 +388,7 @@ gst_mpegv_parse_process_sc (GstMpegvParse * mpvparse,
|
|||
{
|
||||
gboolean ret = FALSE, packet = TRUE;
|
||||
|
||||
g_return_val_if_fail (buf && GST_BUFFER_SIZE (buf) >= 4, FALSE);
|
||||
g_return_val_if_fail (buf && gst_buffer_get_size (buf) >= 4, FALSE);
|
||||
|
||||
GST_LOG_OBJECT (mpvparse, "process startcode %x (%s)", code,
|
||||
picture_start_code_name (code));
|
||||
|
@ -427,14 +435,19 @@ gst_mpegv_parse_process_sc (GstMpegvParse * mpvparse,
|
|||
|
||||
/* extract some picture info if there is any in the frame being terminated */
|
||||
if (ret && mpvparse->pic_offset >= 0 && mpvparse->pic_offset < off) {
|
||||
gsize size;
|
||||
gpointer data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ);
|
||||
|
||||
if (gst_mpeg_video_parse_picture_header (&mpvparse->pichdr,
|
||||
GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf), mpvparse->pic_offset))
|
||||
data, size, mpvparse->pic_offset))
|
||||
GST_LOG_OBJECT (mpvparse, "picture_coding_type %d (%s), ending"
|
||||
"frame of size %d", mpvparse->pichdr.pic_type,
|
||||
picture_type_name (mpvparse->pichdr.pic_type), off - 4);
|
||||
else
|
||||
GST_LOG_OBJECT (mpvparse, "Couldn't parse picture at offset %d",
|
||||
mpvparse->pic_offset);
|
||||
|
||||
gst_buffer_unmap (buf, data, size);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -487,14 +500,17 @@ gst_mpegv_parse_check_valid_frame (GstBaseParse * parse,
|
|||
gboolean ret = FALSE;
|
||||
GList *tmp;
|
||||
gint off = 0, fsize = -1;
|
||||
gpointer buf_data;
|
||||
gsize buf_size;
|
||||
|
||||
update_frame_parsing_status (mpvparse, frame);
|
||||
|
||||
if (mpvparse->last_sc >= 0)
|
||||
off = mpvparse->last_sc;
|
||||
|
||||
mpvparse->typeoffsize =
|
||||
gst_mpeg_video_parse (GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf), off);
|
||||
buf_data = gst_buffer_map (buf, &buf_size, NULL, GST_MAP_READ);
|
||||
mpvparse->typeoffsize = gst_mpeg_video_parse (buf_data, buf_size, off);
|
||||
gst_buffer_unmap (buf, buf_data, buf_size);
|
||||
|
||||
/* No sc found */
|
||||
if (mpvparse->typeoffsize == NULL)
|
||||
|
@ -531,15 +547,15 @@ end:
|
|||
*framesize = fsize;
|
||||
ret = TRUE;
|
||||
} else if (GST_BASE_PARSE_DRAINING (parse)) {
|
||||
*framesize = GST_BUFFER_SIZE (buf);
|
||||
*framesize = buf_size;
|
||||
ret = TRUE;
|
||||
|
||||
} else {
|
||||
/* resume scan where we left it */
|
||||
if (!mpvparse->last_sc)
|
||||
*skipsize = mpvparse->last_sc = GST_BUFFER_SIZE (buf) - 3;
|
||||
*skipsize = mpvparse->last_sc = buf_size - 3;
|
||||
else if (mpvparse->typeoffsize)
|
||||
mpvparse->last_sc = GST_BUFFER_SIZE (buf) - 3;
|
||||
mpvparse->last_sc = buf_size - 3;
|
||||
else
|
||||
*skipsize = 0;
|
||||
|
||||
|
@ -561,16 +577,16 @@ gst_mpegv_parse_update_src_caps (GstMpegvParse * mpvparse)
|
|||
GstCaps *caps = NULL;
|
||||
|
||||
/* only update if no src caps yet or explicitly triggered */
|
||||
if (G_LIKELY (GST_PAD_CAPS (GST_BASE_PARSE_SRC_PAD (mpvparse)) &&
|
||||
if (G_LIKELY (gst_pad_has_current_caps (GST_BASE_PARSE_SRC_PAD (mpvparse)) &&
|
||||
!mpvparse->update_caps))
|
||||
return;
|
||||
|
||||
/* carry over input caps as much as possible; override with our own stuff */
|
||||
caps = GST_PAD_CAPS (GST_BASE_PARSE_SINK_PAD (mpvparse));
|
||||
caps = gst_pad_get_current_caps (GST_BASE_PARSE_SINK_PAD (mpvparse));
|
||||
if (caps) {
|
||||
caps = gst_caps_copy (caps);
|
||||
caps = gst_caps_make_writable (caps);
|
||||
} else {
|
||||
caps = gst_caps_new_simple ("video/mpeg", NULL);
|
||||
caps = gst_caps_new_empty_simple ("video/mpeg");
|
||||
}
|
||||
|
||||
/* typically we don't output buffers until we have properly parsed some
|
||||
|
@ -722,13 +738,11 @@ gst_mpegv_parse_pre_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
|
|||
|
||||
/* codec tag */
|
||||
codec = g_strdup_printf ("MPEG %d Video", mpvparse->mpeg_version);
|
||||
taglist = gst_tag_list_new ();
|
||||
gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
|
||||
GST_TAG_VIDEO_CODEC, codec, NULL);
|
||||
taglist = gst_tag_list_new (GST_TAG_VIDEO_CODEC, codec, NULL);
|
||||
g_free (codec);
|
||||
|
||||
gst_element_found_tags_for_pad (GST_ELEMENT (mpvparse),
|
||||
GST_BASE_PARSE_SRC_PAD (mpvparse), taglist);
|
||||
gst_pad_push_event (GST_BASE_PARSE_SRC_PAD (mpvparse),
|
||||
gst_event_new_tag (taglist));
|
||||
|
||||
mpvparse->send_codec_tag = FALSE;
|
||||
}
|
||||
|
@ -756,7 +770,7 @@ gst_mpegv_parse_set_caps (GstBaseParse * parse, GstCaps * caps)
|
|||
/* best possible parse attempt,
|
||||
* src caps are based on sink caps so it will end up in there
|
||||
* whether sucessful or not */
|
||||
gst_mpegv_parse_process_config (mpvparse, buf, GST_BUFFER_SIZE (buf));
|
||||
gst_mpegv_parse_process_config (mpvparse, buf, gst_buffer_get_size (buf));
|
||||
}
|
||||
|
||||
/* let's not interfere and accept regardless of config parsing success */
|
||||
|
|
|
@ -73,14 +73,18 @@ gst_h263_parse_get_params (H263Params * params, GstBuffer * buffer,
|
|||
};
|
||||
|
||||
GstBitReader br;
|
||||
guint8 *buf_data;
|
||||
gsize buf_size;
|
||||
guint8 tr;
|
||||
guint32 psc = 0, temp32;
|
||||
guint8 temp8, pquant;
|
||||
gboolean hasplusptype;
|
||||
|
||||
buf_data = gst_buffer_map (buffer, &buf_size, NULL, GST_MAP_READ);
|
||||
|
||||
/* FIXME: we can optimise a little by checking the value of available
|
||||
* instead of calling using the bit reader's get_bits_* functions. */
|
||||
gst_bit_reader_init_from_buffer (&br, buffer);
|
||||
gst_bit_reader_init (&br, buf_data, buf_size);
|
||||
|
||||
/* Default PCF is CIF PCF = 30000/1001 */
|
||||
params->pcfnum = 30000;
|
||||
|
@ -445,10 +449,12 @@ gst_h263_parse_get_params (H263Params * params, GstBuffer * buffer,
|
|||
done:
|
||||
*state = GOT_HEADER;
|
||||
more:
|
||||
gst_buffer_unmap (buffer, buf_data, buf_size);
|
||||
return GST_FLOW_OK;
|
||||
|
||||
beach:
|
||||
*state = PASSTHROUGH;
|
||||
gst_buffer_unmap (buffer, buf_data, buf_size);
|
||||
return GST_FLOW_OK;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue