videoparsers: adjust to modified baseparse API

This commit is contained in:
Mark Nauwelaerts 2012-02-13 18:44:01 +01:00
parent ea6a192b13
commit b10b9cf109
5 changed files with 111 additions and 133 deletions

View file

@ -56,10 +56,8 @@ static gboolean gst_dirac_parse_set_sink_caps (GstBaseParse * parse,
GstCaps * caps); GstCaps * caps);
static GstCaps *gst_dirac_parse_get_sink_caps (GstBaseParse * parse, static GstCaps *gst_dirac_parse_get_sink_caps (GstBaseParse * parse,
GstCaps * filter); GstCaps * filter);
static gboolean gst_dirac_parse_check_valid_frame (GstBaseParse * parse, static GstFlowReturn gst_dirac_parse_handle_frame (GstBaseParse * parse,
GstBaseParseFrame * frame, guint * framesize, gint * skipsize); GstBaseParseFrame * frame, gint * skipsize);
static GstFlowReturn gst_dirac_parse_parse_frame (GstBaseParse * parse,
GstBaseParseFrame * frame);
static gboolean gst_dirac_parse_convert (GstBaseParse * parse, static gboolean gst_dirac_parse_convert (GstBaseParse * parse,
GstFormat src_format, gint64 src_value, GstFormat dest_format, GstFormat src_format, gint64 src_value, GstFormat dest_format,
gint64 * dest_value); gint64 * dest_value);
@ -127,10 +125,8 @@ gst_dirac_parse_class_init (GstDiracParseClass * klass)
GST_DEBUG_FUNCPTR (gst_dirac_parse_set_sink_caps); GST_DEBUG_FUNCPTR (gst_dirac_parse_set_sink_caps);
base_parse_class->get_sink_caps = base_parse_class->get_sink_caps =
GST_DEBUG_FUNCPTR (gst_dirac_parse_get_sink_caps); GST_DEBUG_FUNCPTR (gst_dirac_parse_get_sink_caps);
base_parse_class->check_valid_frame = base_parse_class->handle_frame =
GST_DEBUG_FUNCPTR (gst_dirac_parse_check_valid_frame); GST_DEBUG_FUNCPTR (gst_dirac_parse_handle_frame);
base_parse_class->parse_frame =
GST_DEBUG_FUNCPTR (gst_dirac_parse_parse_frame);
base_parse_class->convert = GST_DEBUG_FUNCPTR (gst_dirac_parse_convert); base_parse_class->convert = GST_DEBUG_FUNCPTR (gst_dirac_parse_convert);
base_parse_class->event = GST_DEBUG_FUNCPTR (gst_dirac_parse_event); base_parse_class->event = GST_DEBUG_FUNCPTR (gst_dirac_parse_event);
base_parse_class->src_event = GST_DEBUG_FUNCPTR (gst_dirac_parse_src_event); base_parse_class->src_event = GST_DEBUG_FUNCPTR (gst_dirac_parse_src_event);
@ -213,9 +209,9 @@ gst_dirac_parse_set_sink_caps (GstBaseParse * parse, GstCaps * caps)
return TRUE; return TRUE;
} }
static gboolean static GstFlowReturn
gst_dirac_parse_check_valid_frame (GstBaseParse * parse, gst_dirac_parse_handle_frame (GstBaseParse * parse,
GstBaseParseFrame * frame, guint * framesize, gint * skipsize) GstBaseParseFrame * frame, gint * skipsize)
{ {
int off; int off;
guint32 next_header; guint32 next_header;
@ -224,13 +220,16 @@ gst_dirac_parse_check_valid_frame (GstBaseParse * parse,
gsize size; gsize size;
gboolean have_picture = FALSE; gboolean have_picture = FALSE;
int offset; int offset;
guint framesize = 0;
gst_buffer_map (frame->buffer, &map, GST_MAP_READ); gst_buffer_map (frame->buffer, &map, GST_MAP_READ);
data = map.data; data = map.data;
size = map.size; size = map.size;
if (G_UNLIKELY (size < 13)) if (G_UNLIKELY (size < 13)) {
*skipsize = 1;
goto out; goto out;
}
GST_DEBUG ("%" G_GSIZE_FORMAT ": %02x %02x %02x %02x", size, data[0], data[1], GST_DEBUG ("%" G_GSIZE_FORMAT ": %02x %02x %02x %02x", size, data[0], data[1],
data[2], data[3]); data[2], data[3]);
@ -261,7 +260,7 @@ gst_dirac_parse_check_valid_frame (GstBaseParse * parse,
GST_DEBUG ("offset %d:", offset); GST_DEBUG ("offset %d:", offset);
if (offset + 13 >= size) { if (offset + 13 >= size) {
*framesize = offset + 13; framesize = offset + 13;
goto out; goto out;
} }
@ -284,43 +283,21 @@ gst_dirac_parse_check_valid_frame (GstBaseParse * parse,
offset += next_header; offset += next_header;
if (offset >= size) { if (offset >= size) {
*framesize = offset; framesize = offset;
goto out; goto out;
} }
} }
gst_buffer_unmap (frame->buffer, &map); gst_buffer_unmap (frame->buffer, &map);
*framesize = offset; framesize = offset;
GST_DEBUG ("framesize %d", *framesize); GST_DEBUG ("framesize %d", framesize);
return TRUE; g_assert (framesize <= size);
out:
gst_buffer_unmap (frame->buffer, &map);
return FALSE;
}
static GstFlowReturn
gst_dirac_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
{
GstDiracParse *diracparse = GST_DIRAC_PARSE (parse);
GstMapInfo map;
guint8 *data;
gsize size;
/* Called when processing incoming buffers. Function should parse
a checked frame. */
/* MUST implement */
gst_buffer_map (frame->buffer, &map, GST_MAP_READ);
data = map.data;
size = map.size;
//GST_ERROR("got here %d", size);
if (data[4] == SCHRO_PARSE_CODE_SEQUENCE_HEADER) { if (data[4] == SCHRO_PARSE_CODE_SEQUENCE_HEADER) {
GstCaps *caps; GstCaps *caps;
GstDiracParse *diracparse = GST_DIRAC_PARSE (parse);
DiracSequenceHeader sequence_header; DiracSequenceHeader sequence_header;
int ret; int ret;
@ -349,10 +326,14 @@ gst_dirac_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
} }
} }
gst_buffer_unmap (frame->buffer, &map);
gst_base_parse_set_min_frame_size (parse, 13); gst_base_parse_set_min_frame_size (parse, 13);
return gst_base_parse_finish_frame (parse, frame, framesize);
out:
gst_buffer_unmap (frame->buffer, &map);
if (framesize)
gst_base_parse_set_min_frame_size (parse, framesize);
return GST_FLOW_OK; return GST_FLOW_OK;
} }

View file

@ -32,6 +32,8 @@
#include <gst/base/gstbytereader.h> #include <gst/base/gstbytereader.h>
#include "gsth263parse.h" #include "gsth263parse.h"
#include <string.h>
GST_DEBUG_CATEGORY (h263_parse_debug); GST_DEBUG_CATEGORY (h263_parse_debug);
#define GST_CAT_DEFAULT h263_parse_debug #define GST_CAT_DEFAULT h263_parse_debug
@ -54,10 +56,8 @@ static gboolean gst_h263_parse_start (GstBaseParse * parse);
static gboolean gst_h263_parse_stop (GstBaseParse * parse); static gboolean gst_h263_parse_stop (GstBaseParse * parse);
static gboolean gst_h263_parse_sink_event (GstBaseParse * parse, static gboolean gst_h263_parse_sink_event (GstBaseParse * parse,
GstEvent * event); GstEvent * event);
static gboolean gst_h263_parse_check_valid_frame (GstBaseParse * parse, static GstFlowReturn gst_h263_parse_handle_frame (GstBaseParse * parse,
GstBaseParseFrame * frame, guint * framesize, gint * skipsize); GstBaseParseFrame * frame, gint * skipsize);
static GstFlowReturn gst_h263_parse_parse_frame (GstBaseParse * parse,
GstBaseParseFrame * frame);
static GstCaps *gst_h263_parse_get_sink_caps (GstBaseParse * parse, static GstCaps *gst_h263_parse_get_sink_caps (GstBaseParse * parse,
GstCaps * filter); GstCaps * filter);
@ -83,9 +83,7 @@ gst_h263_parse_class_init (GstH263ParseClass * klass)
parse_class->start = GST_DEBUG_FUNCPTR (gst_h263_parse_start); parse_class->start = GST_DEBUG_FUNCPTR (gst_h263_parse_start);
parse_class->stop = GST_DEBUG_FUNCPTR (gst_h263_parse_stop); parse_class->stop = GST_DEBUG_FUNCPTR (gst_h263_parse_stop);
parse_class->event = GST_DEBUG_FUNCPTR (gst_h263_parse_sink_event); parse_class->event = GST_DEBUG_FUNCPTR (gst_h263_parse_sink_event);
parse_class->check_valid_frame = parse_class->handle_frame = GST_DEBUG_FUNCPTR (gst_h263_parse_handle_frame);
GST_DEBUG_FUNCPTR (gst_h263_parse_check_valid_frame);
parse_class->parse_frame = GST_DEBUG_FUNCPTR (gst_h263_parse_parse_frame);
parse_class->get_sink_caps = GST_DEBUG_FUNCPTR (gst_h263_parse_get_sink_caps); parse_class->get_sink_caps = GST_DEBUG_FUNCPTR (gst_h263_parse_get_sink_caps);
} }
@ -256,21 +254,25 @@ gst_h263_parse_set_src_caps (GstH263Parse * h263parse,
gst_caps_unref (caps); gst_caps_unref (caps);
} }
static gboolean static GstFlowReturn
gst_h263_parse_check_valid_frame (GstBaseParse * parse, gst_h263_parse_handle_frame (GstBaseParse * parse,
GstBaseParseFrame * frame, guint * framesize, gint * skipsize) GstBaseParseFrame * frame, gint * skipsize)
{ {
GstH263Parse *h263parse; GstH263Parse *h263parse;
GstBuffer *buffer; GstBuffer *buffer;
guint psc_pos, next_psc_pos; guint psc_pos, next_psc_pos;
gsize size; gsize size;
H263Params params = { 0, };
GstFlowReturn res = GST_FLOW_OK;
h263parse = GST_H263_PARSE (parse); h263parse = GST_H263_PARSE (parse);
buffer = frame->buffer; buffer = frame->buffer;
size = gst_buffer_get_size (buffer); size = gst_buffer_get_size (buffer);
if (size < 3) if (size < 3) {
return FALSE; *skipsize = 1;
return GST_FLOW_OK;
}
psc_pos = find_psc (buffer, 0); psc_pos = find_psc (buffer, 0);
@ -283,6 +285,10 @@ gst_h263_parse_check_valid_frame (GstBaseParse * parse,
goto more; goto more;
} }
/* need to skip */
if (psc_pos > 0)
goto more;
/* Found the start of the frame, now try to find the end */ /* Found the start of the frame, now try to find the end */
next_psc_pos = psc_pos + 3; next_psc_pos = psc_pos + 3;
next_psc_pos = find_psc (buffer, next_psc_pos); next_psc_pos = find_psc (buffer, next_psc_pos);
@ -299,9 +305,6 @@ gst_h263_parse_check_valid_frame (GstBaseParse * parse,
/* If this is the first frame, parse and set srcpad caps */ /* If this is the first frame, parse and set srcpad caps */
if (h263parse->state == PARSING) { if (h263parse->state == PARSING) {
H263Params params = { 0, };
GstFlowReturn res;
res = gst_h263_parse_get_params (&params, buffer, FALSE, &h263parse->state); res = gst_h263_parse_get_params (&params, buffer, FALSE, &h263parse->state);
if (res != GST_FLOW_OK || h263parse->state != GOT_HEADER) { if (res != GST_FLOW_OK || h263parse->state != GOT_HEADER) {
GST_WARNING ("Couldn't parse header - setting passthrough mode"); GST_WARNING ("Couldn't parse header - setting passthrough mode");
@ -311,42 +314,18 @@ gst_h263_parse_check_valid_frame (GstBaseParse * parse,
gst_h263_parse_set_src_caps (h263parse, &params); gst_h263_parse_set_src_caps (h263parse, &params);
gst_base_parse_set_passthrough (parse, FALSE); gst_base_parse_set_passthrough (parse, FALSE);
} }
memset (&params, 0, sizeof (params));
} }
*skipsize = psc_pos;
*framesize = next_psc_pos - psc_pos;
/* XXX: After getting a keyframe, should we adjust min_frame_size to /* XXX: After getting a keyframe, should we adjust min_frame_size to
* something smaller so we don't end up collecting too many non-keyframes? */ * something smaller so we don't end up collecting too many non-keyframes? */
GST_DEBUG_OBJECT (h263parse, "found a frame of size %d at pos %d", GST_DEBUG_OBJECT (h263parse, "found a frame of size %u at pos %u",
*framesize, *skipsize); next_psc_pos, psc_pos);
return TRUE;
more:
/* ask for best next available */
*framesize = G_MAXUINT;
*skipsize = psc_pos;
return FALSE;
}
static GstFlowReturn
gst_h263_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
{
GstH263Parse *h263parse;
GstBuffer *buffer;
GstFlowReturn res;
H263Params params = { 0, };
h263parse = GST_H263_PARSE (parse);
buffer = frame->buffer;
res = gst_h263_parse_get_params (&params, buffer, TRUE, &h263parse->state); res = gst_h263_parse_get_params (&params, buffer, TRUE, &h263parse->state);
if (res != GST_FLOW_OK) if (res != GST_FLOW_OK)
goto out; goto more;
if (h263parse->state == PASSTHROUGH || h263parse->state == PARSING) { if (h263parse->state == PASSTHROUGH || h263parse->state == PARSING) {
/* There's a feature we don't support, or we didn't have enough data to /* There's a feature we don't support, or we didn't have enough data to
@ -354,17 +333,18 @@ gst_h263_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
* passthrough mode and let downstream handle it if it can. */ * passthrough mode and let downstream handle it if it can. */
GST_WARNING ("Couldn't parse header - setting passthrough mode"); GST_WARNING ("Couldn't parse header - setting passthrough mode");
gst_base_parse_set_passthrough (parse, TRUE); gst_base_parse_set_passthrough (parse, TRUE);
goto out; goto more;
} }
/* h263parse->state is now GOT_HEADER */
if (gst_h263_parse_is_delta_unit (&params)) if (gst_h263_parse_is_delta_unit (&params))
GST_BUFFER_FLAG_UNSET (buffer, GST_BUFFER_FLAG_DELTA_UNIT); GST_BUFFER_FLAG_UNSET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);
else else
GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT); GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);
out: return gst_base_parse_finish_frame (parse, frame, next_psc_pos);
more:
*skipsize = psc_pos;
return res; return res;
} }

View file

@ -79,8 +79,8 @@ static void gst_h264_parse_finalize (GObject * object);
static gboolean gst_h264_parse_start (GstBaseParse * parse); static gboolean gst_h264_parse_start (GstBaseParse * parse);
static gboolean gst_h264_parse_stop (GstBaseParse * parse); static gboolean gst_h264_parse_stop (GstBaseParse * parse);
static gboolean gst_h264_parse_check_valid_frame (GstBaseParse * parse, static GstFlowReturn gst_h264_parse_handle_frame (GstBaseParse * parse,
GstBaseParseFrame * frame, guint * framesize, gint * skipsize); GstBaseParseFrame * frame, gint * skipsize);
static GstFlowReturn gst_h264_parse_parse_frame (GstBaseParse * parse, static GstFlowReturn gst_h264_parse_parse_frame (GstBaseParse * parse,
GstBaseParseFrame * frame); GstBaseParseFrame * frame);
static GstFlowReturn gst_h264_parse_pre_push_frame (GstBaseParse * parse, static GstFlowReturn gst_h264_parse_pre_push_frame (GstBaseParse * parse,
@ -124,9 +124,7 @@ gst_h264_parse_class_init (GstH264ParseClass * klass)
/* Override BaseParse vfuncs */ /* Override BaseParse vfuncs */
parse_class->start = GST_DEBUG_FUNCPTR (gst_h264_parse_start); parse_class->start = GST_DEBUG_FUNCPTR (gst_h264_parse_start);
parse_class->stop = GST_DEBUG_FUNCPTR (gst_h264_parse_stop); parse_class->stop = GST_DEBUG_FUNCPTR (gst_h264_parse_stop);
parse_class->check_valid_frame = parse_class->handle_frame = GST_DEBUG_FUNCPTR (gst_h264_parse_handle_frame);
GST_DEBUG_FUNCPTR (gst_h264_parse_check_valid_frame);
parse_class->parse_frame = GST_DEBUG_FUNCPTR (gst_h264_parse_parse_frame);
parse_class->pre_push_frame = parse_class->pre_push_frame =
GST_DEBUG_FUNCPTR (gst_h264_parse_pre_push_frame); GST_DEBUG_FUNCPTR (gst_h264_parse_pre_push_frame);
parse_class->set_sink_caps = GST_DEBUG_FUNCPTR (gst_h264_parse_set_caps); parse_class->set_sink_caps = GST_DEBUG_FUNCPTR (gst_h264_parse_set_caps);
@ -645,9 +643,9 @@ gst_h264_parse_collect_nal (GstH264Parse * h264parse, const guint8 * data,
* see https://bugzilla.gnome.org/show_bug.cgi?id=650093 */ * see https://bugzilla.gnome.org/show_bug.cgi?id=650093 */
#define GST_BASE_PARSE_FRAME_FLAG_PARSING 0x10000 #define GST_BASE_PARSE_FRAME_FLAG_PARSING 0x10000
static gboolean static GstFlowReturn
gst_h264_parse_check_valid_frame (GstBaseParse * parse, gst_h264_parse_handle_frame (GstBaseParse * parse,
GstBaseParseFrame * frame, guint * framesize, gint * skipsize) GstBaseParseFrame * frame, gint * skipsize)
{ {
GstH264Parse *h264parse = GST_H264_PARSE (parse); GstH264Parse *h264parse = GST_H264_PARSE (parse);
GstBuffer *buffer = frame->buffer; GstBuffer *buffer = frame->buffer;
@ -659,6 +657,7 @@ gst_h264_parse_check_valid_frame (GstBaseParse * parse,
GstH264NalParser *nalparser = h264parse->nalparser; GstH264NalParser *nalparser = h264parse->nalparser;
GstH264NalUnit nalu; GstH264NalUnit nalu;
GstH264ParserResult pres; GstH264ParserResult pres;
gint framesize;
gst_buffer_map (buffer, &map, GST_MAP_READ); gst_buffer_map (buffer, &map, GST_MAP_READ);
data = map.data; data = map.data;
@ -667,7 +666,8 @@ gst_h264_parse_check_valid_frame (GstBaseParse * parse,
/* expect at least 3 bytes startcode == sc, and 2 bytes NALU payload */ /* expect at least 3 bytes startcode == sc, and 2 bytes NALU payload */
if (G_UNLIKELY (size < 5)) { if (G_UNLIKELY (size < 5)) {
gst_buffer_unmap (buffer, &map); gst_buffer_unmap (buffer, &map);
return FALSE; *skipsize = 1;
return GST_FLOW_OK;
} }
/* need to configure aggregation */ /* need to configure aggregation */
@ -820,14 +820,15 @@ gst_h264_parse_check_valid_frame (GstBaseParse * parse,
} }
end: end:
*framesize = nalu.offset + nalu.size; framesize = nalu.offset + nalu.size;
gst_buffer_unmap (buffer, &map); gst_buffer_unmap (buffer, &map);
return TRUE;
gst_h264_parse_parse_frame (parse, frame);
return gst_base_parse_finish_frame (parse, frame, framesize);
more: more:
/* ask for best next available */
*framesize = G_MAXUINT;
*skipsize = 0; *skipsize = 0;
/* Restart parsing from here next time */ /* Restart parsing from here next time */
@ -837,7 +838,7 @@ more:
/* Fall-through. */ /* Fall-through. */
out: out:
gst_buffer_unmap (buffer, &map); gst_buffer_unmap (buffer, &map);
return FALSE; return GST_FLOW_OK;
skip: skip:
GST_DEBUG_OBJECT (h264parse, "skipping %d", *skipsize); GST_DEBUG_OBJECT (h264parse, "skipping %d", *skipsize);
@ -1321,7 +1322,7 @@ gst_h264_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
buf = gst_adapter_take_buffer (h264parse->frame_out, av); buf = gst_adapter_take_buffer (h264parse->frame_out, av);
gst_buffer_copy_into (buf, buffer, GST_BUFFER_COPY_METADATA, 0, -1); gst_buffer_copy_into (buf, buffer, GST_BUFFER_COPY_METADATA, 0, -1);
gst_buffer_replace (&frame->buffer, buf); gst_buffer_replace (&frame->out_buffer, buf);
gst_buffer_unref (buf); gst_buffer_unref (buf);
} }
@ -1541,7 +1542,7 @@ gst_h264_parse_pre_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
/* should already be keyframe/IDR, but it may not have been, /* should already be keyframe/IDR, but it may not have been,
* so mark it as such to avoid being discarded by picky decoder */ * so mark it as such to avoid being discarded by picky decoder */
GST_BUFFER_FLAG_UNSET (new_buf, GST_BUFFER_FLAG_DELTA_UNIT); GST_BUFFER_FLAG_UNSET (new_buf, GST_BUFFER_FLAG_DELTA_UNIT);
gst_buffer_replace (&frame->buffer, new_buf); gst_buffer_replace (&frame->out_buffer, new_buf);
gst_buffer_unref (new_buf); gst_buffer_unref (new_buf);
} }
} }

View file

@ -70,8 +70,8 @@ G_DEFINE_TYPE (GstMpeg4VParse, gst_mpeg4vparse, GST_TYPE_BASE_PARSE);
static gboolean gst_mpeg4vparse_start (GstBaseParse * parse); static gboolean gst_mpeg4vparse_start (GstBaseParse * parse);
static gboolean gst_mpeg4vparse_stop (GstBaseParse * parse); static gboolean gst_mpeg4vparse_stop (GstBaseParse * parse);
static gboolean gst_mpeg4vparse_check_valid_frame (GstBaseParse * parse, static GstFlowReturn gst_mpeg4vparse_handle_frame (GstBaseParse * parse,
GstBaseParseFrame * frame, guint * framesize, gint * skipsize); GstBaseParseFrame * frame, gint * skipsize);
static GstFlowReturn gst_mpeg4vparse_parse_frame (GstBaseParse * parse, static GstFlowReturn gst_mpeg4vparse_parse_frame (GstBaseParse * parse,
GstBaseParseFrame * frame); GstBaseParseFrame * frame);
static GstFlowReturn gst_mpeg4vparse_pre_push_frame (GstBaseParse * parse, static GstFlowReturn gst_mpeg4vparse_pre_push_frame (GstBaseParse * parse,
@ -166,9 +166,7 @@ gst_mpeg4vparse_class_init (GstMpeg4VParseClass * klass)
/* Override BaseParse vfuncs */ /* Override BaseParse vfuncs */
parse_class->start = GST_DEBUG_FUNCPTR (gst_mpeg4vparse_start); parse_class->start = GST_DEBUG_FUNCPTR (gst_mpeg4vparse_start);
parse_class->stop = GST_DEBUG_FUNCPTR (gst_mpeg4vparse_stop); parse_class->stop = GST_DEBUG_FUNCPTR (gst_mpeg4vparse_stop);
parse_class->check_valid_frame = parse_class->handle_frame = GST_DEBUG_FUNCPTR (gst_mpeg4vparse_handle_frame);
GST_DEBUG_FUNCPTR (gst_mpeg4vparse_check_valid_frame);
parse_class->parse_frame = GST_DEBUG_FUNCPTR (gst_mpeg4vparse_parse_frame);
parse_class->pre_push_frame = parse_class->pre_push_frame =
GST_DEBUG_FUNCPTR (gst_mpeg4vparse_pre_push_frame); GST_DEBUG_FUNCPTR (gst_mpeg4vparse_pre_push_frame);
parse_class->set_sink_caps = GST_DEBUG_FUNCPTR (gst_mpeg4vparse_set_caps); parse_class->set_sink_caps = GST_DEBUG_FUNCPTR (gst_mpeg4vparse_set_caps);
@ -363,9 +361,9 @@ gst_mpeg4vparse_process_sc (GstMpeg4VParse * mp4vparse, GstMpeg4Packet * packet,
* see https://bugzilla.gnome.org/show_bug.cgi?id=650093 */ * see https://bugzilla.gnome.org/show_bug.cgi?id=650093 */
#define GST_BASE_PARSE_FRAME_FLAG_PARSING 0x10000 #define GST_BASE_PARSE_FRAME_FLAG_PARSING 0x10000
static gboolean static GstFlowReturn
gst_mpeg4vparse_check_valid_frame (GstBaseParse * parse, gst_mpeg4vparse_handle_frame (GstBaseParse * parse,
GstBaseParseFrame * frame, guint * framesize, gint * skipsize) GstBaseParseFrame * frame, gint * skipsize)
{ {
GstMpeg4VParse *mp4vparse = GST_MPEG4VIDEO_PARSE (parse); GstMpeg4VParse *mp4vparse = GST_MPEG4VIDEO_PARSE (parse);
GstMpeg4Packet packet; GstMpeg4Packet packet;
@ -374,6 +372,7 @@ gst_mpeg4vparse_check_valid_frame (GstBaseParse * parse,
gsize size; gsize size;
gint off = 0; gint off = 0;
gboolean ret = FALSE; gboolean ret = FALSE;
guint framesize;
gst_buffer_map (frame->buffer, &map, GST_MAP_READ); gst_buffer_map (frame->buffer, &map, GST_MAP_READ);
data = map.data; data = map.data;
@ -381,8 +380,10 @@ gst_mpeg4vparse_check_valid_frame (GstBaseParse * parse,
retry: retry:
/* at least start code and subsequent byte */ /* at least start code and subsequent byte */
if (G_UNLIKELY (size - off < 5)) if (G_UNLIKELY (size - off < 5)) {
*skipsize = 1;
goto out; goto out;
}
/* avoid stale cached parsing state */ /* avoid stale cached parsing state */
if (!(frame->flags & GST_BASE_PARSE_FRAME_FLAG_PARSING)) { if (!(frame->flags & GST_BASE_PARSE_FRAME_FLAG_PARSING)) {
@ -453,13 +454,11 @@ next:
case (GST_MPEG4_PARSER_ERROR): case (GST_MPEG4_PARSER_ERROR):
/* if draining, take all */ /* if draining, take all */
if (GST_BASE_PARSE_DRAINING (parse)) { if (GST_BASE_PARSE_DRAINING (parse)) {
*framesize = size; framesize = size;
ret = TRUE; ret = TRUE;
} else { } else {
/* resume scan where we left it */ /* resume scan where we left it */
mp4vparse->last_sc = size - 3; mp4vparse->last_sc = size - 3;
/* request best next available */
*framesize = G_MAXUINT;
} }
goto out; goto out;
break; break;
@ -472,14 +471,25 @@ next:
off = packet.offset; off = packet.offset;
if (ret) { if (ret) {
*framesize = off - 3; framesize = off - 3;
} else { } else {
goto next; goto next;
} }
out: out:
gst_buffer_unmap (frame->buffer, &map); gst_buffer_unmap (frame->buffer, &map);
return ret;
if (ret) {
GstFlowReturn res;
g_assert (framesize <= map.size);
res = gst_mpeg4vparse_parse_frame (parse, frame);
if (res == GST_BASE_PARSE_FLOW_DROPPED)
frame->flags |= GST_BASE_PARSE_FRAME_FLAG_DROP;
return gst_base_parse_finish_frame (parse, frame, framesize);
}
return GST_FLOW_OK;
} }
static void static void
@ -694,7 +704,7 @@ gst_mpeg4vparse_pre_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
superbuf = gst_buffer_merge (mp4vparse->config, buffer); superbuf = gst_buffer_merge (mp4vparse->config, buffer);
gst_buffer_copy_into (superbuf, buffer, GST_BUFFER_COPY_METADATA, 0, gst_buffer_copy_into (superbuf, buffer, GST_BUFFER_COPY_METADATA, 0,
csize); csize);
gst_buffer_replace (&frame->buffer, superbuf); gst_buffer_replace (&frame->out_buffer, superbuf);
gst_buffer_unref (superbuf); gst_buffer_unref (superbuf);
} else { } else {
GST_INFO_OBJECT (parse, "... but avoiding duplication"); GST_INFO_OBJECT (parse, "... but avoiding duplication");

View file

@ -66,8 +66,8 @@ G_DEFINE_TYPE (GstMpegvParse, gst_mpegv_parse, GST_TYPE_BASE_PARSE);
static gboolean gst_mpegv_parse_start (GstBaseParse * parse); static gboolean gst_mpegv_parse_start (GstBaseParse * parse);
static gboolean gst_mpegv_parse_stop (GstBaseParse * parse); static gboolean gst_mpegv_parse_stop (GstBaseParse * parse);
static gboolean gst_mpegv_parse_check_valid_frame (GstBaseParse * parse, static GstFlowReturn gst_mpegv_parse_handle_frame (GstBaseParse * parse,
GstBaseParseFrame * frame, guint * framesize, gint * skipsize); GstBaseParseFrame * frame, gint * skipsize);
static GstFlowReturn gst_mpegv_parse_parse_frame (GstBaseParse * parse, static GstFlowReturn gst_mpegv_parse_parse_frame (GstBaseParse * parse,
GstBaseParseFrame * frame); GstBaseParseFrame * frame);
static gboolean gst_mpegv_parse_set_caps (GstBaseParse * parse, GstCaps * caps); static gboolean gst_mpegv_parse_set_caps (GstBaseParse * parse, GstCaps * caps);
@ -159,9 +159,7 @@ gst_mpegv_parse_class_init (GstMpegvParseClass * klass)
/* Override BaseParse vfuncs */ /* Override BaseParse vfuncs */
parse_class->start = GST_DEBUG_FUNCPTR (gst_mpegv_parse_start); parse_class->start = GST_DEBUG_FUNCPTR (gst_mpegv_parse_start);
parse_class->stop = GST_DEBUG_FUNCPTR (gst_mpegv_parse_stop); parse_class->stop = GST_DEBUG_FUNCPTR (gst_mpegv_parse_stop);
parse_class->check_valid_frame = parse_class->handle_frame = GST_DEBUG_FUNCPTR (gst_mpegv_parse_handle_frame);
GST_DEBUG_FUNCPTR (gst_mpegv_parse_check_valid_frame);
parse_class->parse_frame = GST_DEBUG_FUNCPTR (gst_mpegv_parse_parse_frame);
parse_class->set_sink_caps = GST_DEBUG_FUNCPTR (gst_mpegv_parse_set_caps); parse_class->set_sink_caps = GST_DEBUG_FUNCPTR (gst_mpegv_parse_set_caps);
parse_class->get_sink_caps = GST_DEBUG_FUNCPTR (gst_mpegv_parse_get_caps); parse_class->get_sink_caps = GST_DEBUG_FUNCPTR (gst_mpegv_parse_get_caps);
parse_class->pre_push_frame = parse_class->pre_push_frame =
@ -493,9 +491,9 @@ update_frame_parsing_status (GstMpegvParse * mpvparse,
} }
static gboolean static GstFlowReturn
gst_mpegv_parse_check_valid_frame (GstBaseParse * parse, gst_mpegv_parse_handle_frame (GstBaseParse * parse,
GstBaseParseFrame * frame, guint * framesize, gint * skipsize) GstBaseParseFrame * frame, gint * skipsize)
{ {
GstMpegvParse *mpvparse = GST_MPEGVIDEO_PARSE (parse); GstMpegvParse *mpvparse = GST_MPEGVIDEO_PARSE (parse);
GstBuffer *buf = frame->buffer; GstBuffer *buf = frame->buffer;
@ -547,10 +545,9 @@ gst_mpegv_parse_check_valid_frame (GstBaseParse * parse,
end: end:
if (fsize > 0) { if (fsize > 0) {
*framesize = fsize;
ret = TRUE; ret = TRUE;
} else if (GST_BASE_PARSE_DRAINING (parse)) { } else if (GST_BASE_PARSE_DRAINING (parse)) {
*framesize = buf_size; fsize = buf_size;
ret = TRUE; ret = TRUE;
} else { } else {
@ -562,8 +559,6 @@ end:
else else
*skipsize = 0; *skipsize = 0;
/* request best next available */
*framesize = G_MAXUINT;
ret = FALSE; ret = FALSE;
} }
@ -571,7 +566,18 @@ end:
g_list_free (mpvparse->typeoffsize); g_list_free (mpvparse->typeoffsize);
mpvparse->typeoffsize = NULL; mpvparse->typeoffsize = NULL;
return ret; if (ret) {
GstFlowReturn res;
*skipsize = 0;
g_assert (fsize <= buf_size);
res = gst_mpegv_parse_parse_frame (parse, frame);
if (res == GST_BASE_PARSE_FLOW_DROPPED)
frame->flags |= GST_BASE_PARSE_FRAME_FLAG_DROP;
return gst_base_parse_finish_frame (parse, frame, fsize);
}
return GST_FLOW_OK;
} }
static void static void