summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gst/videoparsers/gstvc1parse.c587
-rw-r--r--gst/videoparsers/gstvc1parse.h7
2 files changed, 370 insertions, 224 deletions
diff --git a/gst/videoparsers/gstvc1parse.c b/gst/videoparsers/gstvc1parse.c
index 922394dc4..611aa7b76 100644
--- a/gst/videoparsers/gstvc1parse.c
+++ b/gst/videoparsers/gstvc1parse.c
@@ -154,33 +154,33 @@ static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
GST_STATIC_CAPS ("video/x-wmv, wmvversion=(int) 3, "
- "format=(fourcc) {WVC1, WMV3}"));
+ "format=(string) {WVC1, WMV3}"));
static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
GST_PAD_SRC,
GST_PAD_ALWAYS,
GST_STATIC_CAPS ("video/x-wmv, wmvversion=(int) 3, "
- "format=(fourcc) {WVC1, WMV3}, "
+ "format=(string) {WVC1, WMV3}, "
"stream-format=(string) {bdu, bdu-frame, sequence-layer-bdu, "
"sequence-layer-bdu-frame, sequence-layer-raw-frame, "
"sequence-layer-frame-layer, asf, frame-layer}, "
"header-format=(string) {none, asf, sequence-layer}"));
-GST_BOILERPLATE (GstVC1Parse, gst_vc1_parse, GstBaseParse, GST_TYPE_BASE_PARSE);
+#define parent_class gst_vc1_parse_parent_class
+G_DEFINE_TYPE (GstVC1Parse, gst_vc1_parse, GST_TYPE_BASE_PARSE);
static void gst_vc1_parse_finalize (GObject * object);
static gboolean gst_vc1_parse_start (GstBaseParse * parse);
static gboolean gst_vc1_parse_stop (GstBaseParse * parse);
-static gboolean gst_vc1_parse_check_valid_frame (GstBaseParse * parse,
- GstBaseParseFrame * frame, guint * framesize, gint * skipsize);
-static GstFlowReturn gst_vc1_parse_parse_frame (GstBaseParse * parse,
- GstBaseParseFrame * frame);
+static GstFlowReturn gst_vc1_parse_handle_frame (GstBaseParse * parse,
+ GstBaseParseFrame * frame, gint * skipsize);
static GstFlowReturn gst_vc1_parse_pre_push_frame (GstBaseParse * parse,
GstBaseParseFrame * frame);
static gboolean gst_vc1_parse_set_caps (GstBaseParse * parse, GstCaps * caps);
-static GstCaps *gst_vc1_parse_get_sink_caps (GstBaseParse * parse);
+static GstCaps *gst_vc1_parse_get_sink_caps (GstBaseParse * parse,
+ GstCaps * filter);
static GstFlowReturn gst_vc1_parse_detect (GstBaseParse * parse,
GstBuffer * buffer);
@@ -195,36 +195,29 @@ static void gst_vc1_parse_update_stream_format_properties (GstVC1Parse *
vc1parse);
static void
-gst_vc1_parse_base_init (gpointer g_class)
+gst_vc1_parse_class_init (GstVC1ParseClass * klass)
{
- GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
+ GObjectClass *gobject_class = (GObjectClass *) klass;
+ GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+ GstBaseParseClass *parse_class = GST_BASE_PARSE_CLASS (klass);
- gst_element_class_add_pad_template (gstelement_class,
+ GST_DEBUG_CATEGORY_INIT (vc1_parse_debug, "vc1parse", 0, "vc1 parser");
+
+ gobject_class->finalize = gst_vc1_parse_finalize;
+
+ gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&srctemplate));
- gst_element_class_add_pad_template (gstelement_class,
+ gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&sinktemplate));
- gst_element_class_set_details_simple (gstelement_class, "VC1 parser",
+ gst_element_class_set_static_metadata (element_class, "VC1 parser",
"Codec/Parser/Converter/Video",
"Parses VC1 streams",
"Sebastian Dröge <sebastian.droege@collabora.co.uk>");
- GST_DEBUG_CATEGORY_INIT (vc1_parse_debug, "vc1parse", 0, "vc1 parser");
-}
-
-static void
-gst_vc1_parse_class_init (GstVC1ParseClass * klass)
-{
- GObjectClass *gobject_class = (GObjectClass *) klass;
- GstBaseParseClass *parse_class = GST_BASE_PARSE_CLASS (klass);
-
- gobject_class->finalize = gst_vc1_parse_finalize;
-
parse_class->start = GST_DEBUG_FUNCPTR (gst_vc1_parse_start);
parse_class->stop = GST_DEBUG_FUNCPTR (gst_vc1_parse_stop);
- parse_class->check_valid_frame =
- GST_DEBUG_FUNCPTR (gst_vc1_parse_check_valid_frame);
- parse_class->parse_frame = GST_DEBUG_FUNCPTR (gst_vc1_parse_parse_frame);
+ parse_class->handle_frame = GST_DEBUG_FUNCPTR (gst_vc1_parse_handle_frame);
parse_class->pre_push_frame =
GST_DEBUG_FUNCPTR (gst_vc1_parse_pre_push_frame);
parse_class->set_sink_caps = GST_DEBUG_FUNCPTR (gst_vc1_parse_set_caps);
@@ -233,7 +226,7 @@ gst_vc1_parse_class_init (GstVC1ParseClass * klass)
}
static void
-gst_vc1_parse_init (GstVC1Parse * vc1parse, GstVC1ParseClass * g_class)
+gst_vc1_parse_init (GstVC1Parse * vc1parse)
{
/* Default values for stream-format=raw, i.e.
* raw VC1 frames with startcodes */
@@ -256,7 +249,7 @@ gst_vc1_parse_reset (GstVC1Parse * vc1parse)
{
vc1parse->profile = -1;
vc1parse->level = -1;
- vc1parse->fourcc = 0;
+ vc1parse->format = 0;
vc1parse->width = 0;
vc1parse->height = 0;
vc1parse->fps_n = vc1parse->fps_d = 0;
@@ -306,9 +299,6 @@ gst_vc1_parse_renegotiate (GstVC1Parse * vc1parse)
{
GstCaps *allowed_caps;
- if (!vc1parse->renegotiate)
- return TRUE;
-
/* Negotiate with downstream here */
GST_DEBUG_OBJECT (vc1parse, "Renegotiating");
@@ -322,7 +312,7 @@ gst_vc1_parse_renegotiate (GstVC1Parse * vc1parse)
allowed_caps);
allowed_caps = gst_caps_make_writable (allowed_caps);
- gst_caps_truncate (allowed_caps);
+ allowed_caps = gst_caps_truncate (allowed_caps);
s = gst_caps_get_structure (allowed_caps, 0);
/* If already fixed this does nothing */
@@ -374,14 +364,14 @@ gst_vc1_parse_renegotiate (GstVC1Parse * vc1parse)
}
static GstCaps *
-gst_vc1_parse_get_sink_caps (GstBaseParse * parse)
+gst_vc1_parse_get_sink_caps (GstBaseParse * parse, GstCaps * filter)
{
GstCaps *peercaps;
- const GstCaps *templ;
+ GstCaps *templ;
GstCaps *ret;
templ = gst_pad_get_pad_template_caps (GST_BASE_PARSE_SINK_PAD (parse));
- peercaps = gst_pad_peer_get_caps (GST_BASE_PARSE_SRC_PAD (parse));
+ peercaps = gst_pad_peer_query_caps (GST_BASE_PARSE_SRC_PAD (parse), NULL);
if (peercaps) {
guint i, n;
GstStructure *s;
@@ -400,8 +390,16 @@ gst_vc1_parse_get_sink_caps (GstBaseParse * parse)
ret = gst_caps_intersect_full (peercaps, templ, GST_CAPS_INTERSECT_FIRST);
gst_caps_unref (peercaps);
+ gst_caps_unref (templ);
} else {
- ret = gst_caps_copy (templ);
+ ret = templ;
+ }
+
+ if (filter) {
+ GstCaps *tmp =
+ gst_caps_intersect_full (filter, ret, GST_CAPS_INTERSECT_FIRST);
+ gst_caps_unref (ret);
+ ret = tmp;
}
return ret;
@@ -411,14 +409,18 @@ static GstFlowReturn
gst_vc1_parse_detect (GstBaseParse * parse, GstBuffer * buffer)
{
GstVC1Parse *vc1parse = GST_VC1_PARSE (parse);
+ GstMapInfo minfo;
guint8 *data;
gint size;
if (!vc1parse->detecting_stream_format)
return GST_FLOW_OK;
- data = GST_BUFFER_DATA (buffer);
- size = GST_BUFFER_SIZE (buffer);
+ if (!gst_buffer_map (buffer, &minfo, GST_MAP_READ))
+ return GST_FLOW_ERROR;
+
+ data = minfo.data;
+ size = minfo.size;
#if 0
/* FIXME: disable BDU check for now as BDU parsing needs more work.
@@ -437,8 +439,6 @@ gst_vc1_parse_detect (GstBaseParse * parse, GstBuffer * buffer)
}
#endif
- data = GST_BUFFER_DATA (buffer);
- size = GST_BUFFER_SIZE (buffer);
while (size >= 40) {
if (data[3] == 0xc5 && GST_READ_UINT32_BE (data + 4) == 0x00000004 &&
GST_READ_UINT32_BE (data + 20) == 0x0000000c) {
@@ -463,14 +463,16 @@ gst_vc1_parse_detect (GstBaseParse * parse, GstBuffer * buffer)
size -= 4;
}
- if (GST_BUFFER_SIZE (buffer) <= 128) {
+ if (gst_buffer_get_size (buffer) <= 128) {
GST_DEBUG_OBJECT (vc1parse, "Requesting more data");
+ gst_buffer_unmap (buffer, &minfo);
return GST_FLOW_NOT_NEGOTIATED;
}
if (GST_BASE_PARSE_DRAINING (vc1parse)) {
GST_ERROR_OBJECT (vc1parse, "Failed to detect or assume a stream format "
"and draining now");
+ gst_buffer_unmap (buffer, &minfo);
return GST_FLOW_ERROR;
}
@@ -485,6 +487,7 @@ gst_vc1_parse_detect (GstBaseParse * parse, GstBuffer * buffer)
goto detected;
} else {
GST_ERROR_OBJECT (vc1parse, "Can't detect or assume a stream format");
+ gst_buffer_unmap (buffer, &minfo);
return GST_FLOW_ERROR;
}
@@ -492,127 +495,31 @@ gst_vc1_parse_detect (GstBaseParse * parse, GstBuffer * buffer)
return GST_FLOW_ERROR;
detected:
+
+ gst_buffer_unmap (buffer, &minfo);
vc1parse->detecting_stream_format = FALSE;
gst_vc1_parse_update_stream_format_properties (vc1parse);
return GST_FLOW_OK;
}
static gboolean
-gst_vc1_parse_check_valid_frame (GstBaseParse * parse,
- GstBaseParseFrame * frame, guint * framesize, gint * skipsize)
-{
- GstVC1Parse *vc1parse = GST_VC1_PARSE (parse);
- GstBuffer *buffer = frame->buffer;
- guint8 *data = GST_BUFFER_DATA (buffer);
- guint size = GST_BUFFER_SIZE (buffer);
-
- if (vc1parse->renegotiate) {
- if (!gst_vc1_parse_renegotiate (vc1parse)) {
- GST_ERROR_OBJECT (vc1parse, "Failed to negotiate with downstream");
- return FALSE;
- }
- }
-
- if (!vc1parse->seq_layer_buffer
- && (vc1parse->input_stream_format == VC1_STREAM_FORMAT_SEQUENCE_LAYER_BDU
- || vc1parse->input_stream_format ==
- VC1_STREAM_FORMAT_SEQUENCE_LAYER_BDU_FRAME
- || vc1parse->input_stream_format ==
- VC1_STREAM_FORMAT_SEQUENCE_LAYER_RAW_FRAME
- || vc1parse->input_stream_format ==
- VC1_STREAM_FORMAT_SEQUENCE_LAYER_FRAME_LAYER)) {
- if (data[3] == 0xc5 && GST_READ_UINT32_BE (data + 4) == 0x00000004
- && GST_READ_UINT32_BE (data + 20) == 0x0000000c) {
- *framesize = 36;
- return TRUE;
- }
- return FALSE;
- } else if (vc1parse->input_stream_format == VC1_STREAM_FORMAT_BDU ||
- vc1parse->input_stream_format == VC1_STREAM_FORMAT_BDU_FRAME ||
- (vc1parse->seq_layer_buffer
- && (vc1parse->input_stream_format ==
- VC1_STREAM_FORMAT_SEQUENCE_LAYER_BDU
- || vc1parse->input_stream_format ==
- VC1_STREAM_FORMAT_SEQUENCE_LAYER_BDU_FRAME))) {
- GstVC1ParserResult pres;
- GstVC1BDU bdu;
- g_assert (size >= 4);
- memset (&bdu, 0, sizeof (bdu));
- GST_DEBUG_OBJECT (vc1parse,
- "Handling buffer of size %u at offset %" G_GUINT64_FORMAT, size,
- GST_BUFFER_OFFSET (buffer));
- /* XXX: when a buffer contains multiple BDUs, does the first one start with
- * a startcode?
- */
- pres = gst_vc1_identify_next_bdu (data, size, &bdu);
- switch (pres) {
- case GST_VC1_PARSER_OK:
- GST_DEBUG_OBJECT (vc1parse, "Have complete BDU");
- if (bdu.sc_offset > 4) {
- *skipsize = bdu.sc_offset;
- return FALSE;
- } else {
- *framesize = bdu.offset + bdu.size;
- return TRUE;
- }
- break;
- case GST_VC1_PARSER_BROKEN_DATA:
- GST_ERROR_OBJECT (vc1parse, "Broken data");
- return FALSE;
- break;
- case GST_VC1_PARSER_NO_BDU:
- GST_DEBUG_OBJECT (vc1parse, "Found no BDU startcode");
- *skipsize = size - 3;
- return FALSE;
- break;
- case GST_VC1_PARSER_NO_BDU_END:
- GST_DEBUG_OBJECT (vc1parse, "Found no BDU end");
- if (G_UNLIKELY (GST_BASE_PARSE_DRAINING (vc1parse))) {
- GST_DEBUG_OBJECT (vc1parse, "Draining - assuming complete frame");
- *framesize = size;
- return TRUE;
- } else {
- *skipsize = 0;
- /* Request all that is available */
- *framesize = G_MAXUINT;
- return FALSE;
- }
- break;
- case GST_VC1_PARSER_ERROR:
- GST_ERROR_OBJECT (vc1parse, "Parsing error");
- return FALSE;
- break;
- default:
- g_assert_not_reached ();
- break;
- }
- } else if (vc1parse->input_stream_format == VC1_STREAM_FORMAT_ASF ||
- (vc1parse->seq_layer_buffer
- && vc1parse->input_stream_format ==
- VC1_STREAM_FORMAT_SEQUENCE_LAYER_RAW_FRAME)) {
- /* Must be packetized already */
- *framesize = size;
- return TRUE;
- } else {
- /* frame-layer or sequence-layer-frame-layer */
- g_assert (size >= 8);
- /* Parse frame layer size */
- *framesize = GST_READ_UINT24_BE (data + 1) + 8;
- return TRUE;
- }
-
- return FALSE;
-}
-
-static gboolean
gst_vc1_parse_update_caps (GstVC1Parse * vc1parse)
{
GstCaps *caps;
GstVC1Profile profile;
- if (GST_PAD_CAPS (GST_BASE_PARSE_SRC_PAD (vc1parse))
+ const gchar *stream_format, *header_format;
+
+ if (gst_pad_has_current_caps (GST_BASE_PARSE_SRC_PAD (vc1parse))
&& !vc1parse->update_caps)
return TRUE;
+
caps = gst_caps_new_simple ("video/x-wmv", "wmvversion", G_TYPE_INT, 3, NULL);
+
+ header_format = header_format_to_string (vc1parse->output_header_format);
+ stream_format = stream_format_to_string (vc1parse->output_stream_format);
+ gst_caps_set_simple (caps, "header-format", G_TYPE_STRING, header_format,
+ "stream-format", G_TYPE_STRING, stream_format, NULL);
+
/* Must have this here from somewhere */
g_assert (vc1parse->width != 0 && vc1parse->height != 0);
gst_caps_set_simple (caps, "width", G_TYPE_INT, vc1parse->width, "height",
@@ -624,15 +531,18 @@ gst_vc1_parse_update_caps (GstVC1Parse * vc1parse)
vc1parse->frame_duration = gst_util_uint64_scale (GST_SECOND,
vc1parse->fps_d, vc1parse->fps_n);
}
+
if (vc1parse->par_n != 0 && vc1parse->par_d != 0)
gst_caps_set_simple (caps, "pixel-aspect-ratio", GST_TYPE_FRACTION,
vc1parse->par_n, vc1parse->par_d, NULL);
+
if (vc1parse->seq_hdr_buffer)
profile = vc1parse->seq_hdr.profile;
else if (vc1parse->seq_layer_buffer)
profile = vc1parse->seq_layer.struct_c.profile;
else
g_assert_not_reached ();
+
if (profile == GST_VC1_PROFILE_ADVANCED) {
const gchar *level;
/* Caller must make sure this is valid here */
@@ -658,21 +568,21 @@ gst_vc1_parse_update_caps (GstVC1Parse * vc1parse)
break;
}
- gst_caps_set_simple (caps, "format", GST_TYPE_FOURCC,
- GST_MAKE_FOURCC ('W', 'V', 'C', '1'),
+ gst_caps_set_simple (caps, "format", G_TYPE_STRING, "WVC1",
"profile", G_TYPE_STRING, "advanced",
"level", G_TYPE_STRING, level, NULL);
- } else
- if (profile == GST_VC1_PROFILE_SIMPLE
+ } else if (profile == GST_VC1_PROFILE_SIMPLE
|| profile == GST_VC1_PROFILE_MAIN) {
const gchar *profile_str;
+
if (profile == GST_VC1_PROFILE_SIMPLE)
profile_str = "simple";
else
profile_str = "main";
- gst_caps_set_simple (caps, "format", GST_TYPE_FOURCC,
- GST_MAKE_FOURCC ('W', 'M', 'V', '3'),
+
+ gst_caps_set_simple (caps, "format", G_TYPE_STRING, "WMV3",
"profile", G_TYPE_STRING, profile_str, NULL);
+
if (vc1parse->seq_layer_buffer) {
const gchar *level;
switch (vc1parse->seq_layer.struct_b.level) {
@@ -700,10 +610,15 @@ gst_vc1_parse_update_caps (GstVC1Parse * vc1parse)
case VC1_HEADER_FORMAT_ASF:
if (vc1parse->profile != GST_VC1_PROFILE_ADVANCED) {
GstBuffer *codec_data;
+
if (vc1parse->seq_hdr_buffer) {
- codec_data = gst_buffer_create_sub (vc1parse->seq_hdr_buffer, 0, 4);
+ codec_data =
+ gst_buffer_copy_region (vc1parse->seq_hdr_buffer,
+ GST_BUFFER_COPY_ALL, 0, 4);
} else {
+ GstMapInfo minfo;
guint32 seq_hdr = 0;
+
/* Build simple/main sequence header from sequence layer */
seq_hdr |= (vc1parse->profile << 30);
seq_hdr |= (vc1parse->seq_layer.struct_c.wmvp << 28);
@@ -722,7 +637,10 @@ gst_vc1_parse_update_caps (GstVC1Parse * vc1parse)
seq_hdr |= (vc1parse->seq_layer.struct_c.quantizer << 2);
seq_hdr |= (vc1parse->seq_layer.struct_c.finterpflag << 1);
codec_data = gst_buffer_new_and_alloc (4);
- GST_WRITE_UINT32_BE (GST_BUFFER_DATA (codec_data), seq_hdr);
+
+ gst_buffer_map (codec_data, &minfo, GST_MAP_WRITE);
+ GST_WRITE_UINT32_BE (minfo.data, seq_hdr);
+ gst_buffer_unmap (codec_data, &minfo);
}
gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER, codec_data,
@@ -730,26 +648,33 @@ gst_vc1_parse_update_caps (GstVC1Parse * vc1parse)
gst_buffer_unref (codec_data);
} else {
GstBuffer *codec_data;
+ GstMapInfo minfo, sminfo, eminfo;
+
/* Should have seqhdr and entrypoint for the advanced profile here */
g_assert (vc1parse->seq_hdr_buffer && vc1parse->entrypoint_buffer);
codec_data =
gst_buffer_new_and_alloc (1 + 4 +
- GST_BUFFER_SIZE (vc1parse->seq_hdr_buffer) + 4 +
- GST_BUFFER_SIZE (vc1parse->entrypoint_buffer));
+ gst_buffer_get_size (vc1parse->seq_hdr_buffer) + 4 +
+ gst_buffer_get_size (vc1parse->entrypoint_buffer));
+
+ gst_buffer_map (codec_data, &minfo, GST_MAP_WRITE);
+ gst_buffer_map (vc1parse->seq_hdr_buffer, &sminfo, GST_MAP_READ);
+ gst_buffer_map (vc1parse->entrypoint_buffer, &eminfo, GST_MAP_READ);
+
if (vc1parse->profile == GST_VC1_PROFILE_SIMPLE)
- GST_WRITE_UINT8 (GST_BUFFER_DATA (codec_data), 0x29);
+ GST_WRITE_UINT8 (minfo.data, 0x29);
else
- GST_WRITE_UINT8 (GST_BUFFER_DATA (codec_data), 0x2b);
- GST_WRITE_UINT32_BE (GST_BUFFER_DATA (codec_data) + 1, 0x0000010f);
- memcpy (GST_BUFFER_DATA (codec_data) + 1 + 4,
- GST_BUFFER_DATA (vc1parse->seq_hdr_buffer),
- GST_BUFFER_SIZE (vc1parse->seq_hdr_buffer));
- GST_WRITE_UINT32_BE (GST_BUFFER_DATA (codec_data) + 1 + 4 +
- GST_BUFFER_SIZE (vc1parse->seq_hdr_buffer), 0x0000010e);
- memcpy (GST_BUFFER_DATA (codec_data) + 1 + 4 +
- GST_BUFFER_SIZE (vc1parse->seq_hdr_buffer) + 4,
- GST_BUFFER_DATA (vc1parse->entrypoint_buffer),
- GST_BUFFER_SIZE (vc1parse->entrypoint_buffer));
+ GST_WRITE_UINT8 (minfo.data, 0x2b);
+
+ GST_WRITE_UINT32_BE (minfo.data + 1, 0x0000010f);
+ memcpy (minfo.data + 1 + 4, sminfo.data, sminfo.size);
+ GST_WRITE_UINT32_BE (minfo.data + 1 + 4 +
+ gst_buffer_get_size (vc1parse->seq_hdr_buffer), 0x0000010e);
+ memcpy (minfo.data + 1 + 4 + sminfo.size + 4, eminfo.data, eminfo.size);
+ gst_buffer_unmap (codec_data, &minfo);
+ gst_buffer_unmap (vc1parse->seq_hdr_buffer, &sminfo);
+ gst_buffer_unmap (vc1parse->entrypoint_buffer, &eminfo);
+
gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER, codec_data,
NULL);
gst_buffer_unref (codec_data);
@@ -761,8 +686,13 @@ gst_vc1_parse_update_caps (GstVC1Parse * vc1parse)
vc1parse->seq_layer_buffer, NULL);
} else {
GstBuffer *codec_data = gst_buffer_new_and_alloc (36);
- guint8 *data = GST_BUFFER_DATA (codec_data);
+ guint8 *data;
guint32 structC = 0;
+ GstMapInfo minfo;
+
+ gst_buffer_map (codec_data, &minfo, GST_MAP_WRITE);
+
+ data = minfo.data;
/* Unknown number of frames and start code */
data[0] = 0xff;
data[1] = 0xff;
@@ -814,6 +744,8 @@ gst_vc1_parse_update_caps (GstVC1Parse * vc1parse)
GST_WRITE_UINT32_BE (data + 32,
((guint32) (((gdouble) vc1parse->fps_n) /
((gdouble) vc1parse->fps_d) + 0.5)));
+ gst_buffer_unmap (codec_data, &minfo);
+
gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER, codec_data,
NULL);
gst_buffer_unref (codec_data);
@@ -870,7 +802,12 @@ gst_vc1_parse_handle_bdus (GstVC1Parse * vc1parse, GstBuffer * buffer,
{
GstVC1BDU bdu;
GstVC1ParserResult pres;
- guint8 *data = GST_BUFFER_DATA (buffer) + offset;
+ guint8 *data;
+ GstMapInfo minfo;
+
+ gst_buffer_map (buffer, &minfo, GST_MAP_READ);
+
+ data = minfo.data + offset;
do {
memset (&bdu, 0, sizeof (bdu));
@@ -885,14 +822,18 @@ gst_vc1_parse_handle_bdus (GstVC1Parse * vc1parse, GstBuffer * buffer,
size -= bdu.offset;
if (!gst_vc1_parse_handle_bdu (vc1parse, bdu.type, buffer,
- data - GST_BUFFER_DATA (buffer), bdu.size))
+ data - minfo.data, bdu.size)) {
+ gst_buffer_unmap (buffer, &minfo);
return FALSE;
+ }
data += bdu.size;
size -= bdu.size;
}
} while (pres == GST_VC1_PARSER_OK && size > 0);
+ gst_buffer_unmap (buffer, &minfo);
+
if (pres != GST_VC1_PARSER_OK) {
GST_DEBUG_OBJECT (vc1parse, "Failed to parse BDUs");
return FALSE;
@@ -901,12 +842,129 @@ gst_vc1_parse_handle_bdus (GstVC1Parse * vc1parse, GstBuffer * buffer,
}
static GstFlowReturn
-gst_vc1_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
+gst_vc1_parse_handle_frame (GstBaseParse * parse, GstBaseParseFrame * frame,
+ gint * skipsize)
{
GstVC1Parse *vc1parse = GST_VC1_PARSE (parse);
GstBuffer *buffer = frame->buffer;
- guint8 *data = GST_BUFFER_DATA (buffer);
- guint size = GST_BUFFER_SIZE (buffer);
+ guint8 *data;
+ gsize size;
+ gsize framesize = -1;
+ GstFlowReturn ret = GST_FLOW_OK;
+ GstMapInfo minfo;
+
+ memset (&minfo, 0, sizeof (minfo));
+
+ *skipsize = 0;
+
+ if (vc1parse->renegotiate
+ || gst_pad_check_reconfigure (GST_BASE_PARSE_SRC_PAD (parse))) {
+ if (!gst_vc1_parse_renegotiate (vc1parse)) {
+ GST_ERROR_OBJECT (vc1parse, "Failed to negotiate with downstream");
+ ret = GST_FLOW_NOT_NEGOTIATED;
+ goto done;
+ }
+ }
+
+ if (!gst_buffer_map (buffer, &minfo, GST_MAP_READ)) {
+ GST_ERROR_OBJECT (vc1parse, "Failed to map buffer");
+ ret = GST_FLOW_ERROR;
+ goto done;
+ }
+
+ data = minfo.data;
+ size = minfo.size;
+
+ /* First check if we have a valid, complete frame here */
+ if (!vc1parse->seq_layer_buffer
+ && (vc1parse->input_stream_format == VC1_STREAM_FORMAT_SEQUENCE_LAYER_BDU
+ || vc1parse->input_stream_format ==
+ VC1_STREAM_FORMAT_SEQUENCE_LAYER_BDU_FRAME
+ || vc1parse->input_stream_format ==
+ VC1_STREAM_FORMAT_SEQUENCE_LAYER_RAW_FRAME
+ || vc1parse->input_stream_format ==
+ VC1_STREAM_FORMAT_SEQUENCE_LAYER_FRAME_LAYER)) {
+ if (data[3] == 0xc5 && GST_READ_UINT32_BE (data + 4) == 0x00000004
+ && GST_READ_UINT32_BE (data + 20) == 0x0000000c) {
+ framesize = 36;
+ } else {
+ *skipsize = 1;
+ }
+ } else if (vc1parse->input_stream_format == VC1_STREAM_FORMAT_BDU ||
+ vc1parse->input_stream_format == VC1_STREAM_FORMAT_BDU_FRAME ||
+ (vc1parse->seq_layer_buffer
+ && (vc1parse->input_stream_format ==
+ VC1_STREAM_FORMAT_SEQUENCE_LAYER_BDU
+ || vc1parse->input_stream_format ==
+ VC1_STREAM_FORMAT_SEQUENCE_LAYER_BDU_FRAME))) {
+ GstVC1ParserResult pres;
+ GstVC1BDU bdu;
+
+ g_assert (size >= 4);
+ memset (&bdu, 0, sizeof (bdu));
+ GST_DEBUG_OBJECT (vc1parse,
+ "Handling buffer of size %u at offset %" G_GUINT64_FORMAT, size,
+ GST_BUFFER_OFFSET (buffer));
+ /* XXX: when a buffer contains multiple BDUs, does the first one start with
+ * a startcode?
+ */
+ pres = gst_vc1_identify_next_bdu (data, size, &bdu);
+ switch (pres) {
+ case GST_VC1_PARSER_OK:
+ GST_DEBUG_OBJECT (vc1parse, "Have complete BDU");
+ if (bdu.sc_offset > 4) {
+ *skipsize = bdu.sc_offset;
+ } else {
+ framesize = bdu.offset + bdu.size;
+ }
+ break;
+ case GST_VC1_PARSER_BROKEN_DATA:
+ GST_ERROR_OBJECT (vc1parse, "Broken data");
+ *skipsize = 1;
+ break;
+ case GST_VC1_PARSER_NO_BDU:
+ GST_DEBUG_OBJECT (vc1parse, "Found no BDU startcode");
+ *skipsize = size - 3;
+ break;
+ case GST_VC1_PARSER_NO_BDU_END:
+ GST_DEBUG_OBJECT (vc1parse, "Found no BDU end");
+ if (G_UNLIKELY (GST_BASE_PARSE_DRAINING (vc1parse))) {
+ GST_DEBUG_OBJECT (vc1parse, "Draining - assuming complete frame");
+ framesize = size;
+ } else {
+ /* Need more data */
+ *skipsize = 0;
+ }
+ break;
+ case GST_VC1_PARSER_ERROR:
+ GST_ERROR_OBJECT (vc1parse, "Parsing error");
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+ } else if (vc1parse->input_stream_format == VC1_STREAM_FORMAT_ASF ||
+ (vc1parse->seq_layer_buffer
+ && vc1parse->input_stream_format ==
+ VC1_STREAM_FORMAT_SEQUENCE_LAYER_RAW_FRAME)) {
+ /* Must be packetized already */
+ framesize = size;
+ } else {
+ /* frame-layer or sequence-layer-frame-layer */
+ g_assert (size >= 8);
+ /* Parse frame layer size */
+ framesize = GST_READ_UINT24_BE (data + 1) + 8;
+ }
+
+
+ if (framesize == -1) {
+ GST_DEBUG_OBJECT (vc1parse, "Not a complete frame, skipping %d", *skipsize);
+ ret = GST_FLOW_OK;
+ goto done;
+ }
+ g_assert (*skipsize == 0);
+
+ /* We have a complete frame at this point */
if (!vc1parse->seq_layer_buffer
&& (vc1parse->input_stream_format == VC1_STREAM_FORMAT_SEQUENCE_LAYER_BDU
@@ -919,7 +977,8 @@ gst_vc1_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
g_assert (size >= 36);
if (!gst_vc1_parse_handle_seq_layer (vc1parse, buffer, 0, size)) {
GST_ERROR_OBJECT (vc1parse, "Invalid sequence layer");
- return GST_FLOW_ERROR;
+ ret = GST_FLOW_ERROR;
+ goto done;
}
frame->flags |= GST_BASE_PARSE_FRAME_FLAG_NO_FRAME;
@@ -935,6 +994,8 @@ gst_vc1_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
/* frame-layer */
gst_base_parse_set_min_frame_size (GST_BASE_PARSE (vc1parse), 8);
}
+
+ ret = GST_FLOW_OK;
} else if (vc1parse->input_stream_format == VC1_STREAM_FORMAT_BDU ||
vc1parse->input_stream_format == VC1_STREAM_FORMAT_BDU_FRAME ||
(vc1parse->seq_layer_buffer
@@ -952,7 +1013,8 @@ gst_vc1_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
if (!vc1parse->seq_hdr_buffer && !vc1parse->seq_layer_buffer) {
GST_ERROR_OBJECT (vc1parse,
"Need sequence header/layer before anything else");
- return GST_FLOW_ERROR;
+ ret = GST_FLOW_ERROR;
+ goto done;
}
} else if (startcode != GST_VC1_ENTRYPOINT
&& vc1parse->profile == GST_VC1_PROFILE_ADVANCED) {
@@ -960,12 +1022,17 @@ gst_vc1_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
GST_ERROR_OBJECT (vc1parse,
"Need entrypoint header after the sequence header for the "
"advanced profile");
- return GST_FLOW_ERROR;
+ ret = GST_FLOW_ERROR;
+ goto done;
}
}
- if (!gst_vc1_parse_handle_bdu (vc1parse, startcode, buffer, 4, size - 4))
- return GST_FLOW_ERROR;
+ if (!gst_vc1_parse_handle_bdu (vc1parse, startcode, buffer, 4, size - 4)) {
+ ret = GST_FLOW_ERROR;
+ goto done;
+ }
+
+ ret = GST_FLOW_OK;
} else if (vc1parse->input_stream_format == VC1_STREAM_FORMAT_ASF ||
(vc1parse->seq_layer_buffer
&& vc1parse->input_stream_format ==
@@ -974,7 +1041,8 @@ gst_vc1_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
if (!vc1parse->seq_hdr_buffer && !vc1parse->seq_layer_buffer) {
GST_ERROR_OBJECT (vc1parse, "Need a sequence header or sequence layer");
- return GST_FLOW_ERROR;
+ ret = GST_FLOW_ERROR;
+ goto done;
}
if (GST_CLOCK_TIME_IS_VALID (vc1parse->frame_duration))
@@ -985,24 +1053,29 @@ gst_vc1_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
gboolean startcodes = FALSE;
if (size >= 4) {
- guint32 startcode = GST_READ_UINT32_BE (data);
+ guint32 startcode = GST_READ_UINT32_BE (data + 4);
+
startcodes = ((startcode & 0xffffff00) == 0x00000100);
}
if (startcodes) {
- if (!gst_vc1_parse_handle_bdus (vc1parse, buffer, 0, size))
- return GST_FLOW_ERROR;
+ if (!gst_vc1_parse_handle_bdus (vc1parse, buffer, 0, size)) {
+ ret = GST_FLOW_ERROR;
+ goto done;
+ }
/* For the advanced profile we need a sequence header here */
if (!vc1parse->seq_hdr_buffer) {
GST_ERROR_OBJECT (vc1parse, "Need sequence header");
- return GST_FLOW_ERROR;
+ ret = GST_FLOW_ERROR;
+ goto done;
}
} else {
/* Must be a frame or a frame + field */
/* TODO: Check if keyframe */
}
}
+ ret = GST_FLOW_OK;
} else {
GstVC1ParserResult pres;
GstVC1FrameLayer flayer;
@@ -1015,6 +1088,7 @@ gst_vc1_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
*/
if (size >= 8 + 4) {
guint32 startcode = GST_READ_UINT32_BE (data + 8);
+
startcodes = ((startcode & 0xffffff00) == 0x00000100);
}
@@ -1026,24 +1100,28 @@ gst_vc1_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
*/
if (!vc1parse->seq_layer_buffer && !vc1parse->seq_hdr_buffer && !startcodes) {
GST_ERROR_OBJECT (vc1parse, "Need a sequence header or sequence layer");
- return GST_FLOW_ERROR;
+ ret = GST_FLOW_ERROR;
+ goto done;
}
if ((vc1parse->seq_layer_buffer || vc1parse->seq_hdr_buffer)
&& vc1parse->profile == GST_VC1_PROFILE_ADVANCED && !startcodes) {
GST_ERROR_OBJECT (vc1parse,
"Advanced profile frame-layer data must start with startcodes");
- return GST_FLOW_ERROR;
+ ret = GST_FLOW_ERROR;
+ goto done;
}
memset (&flayer, 0, sizeof (flayer));
+
pres = gst_vc1_parse_frame_layer (data, size, &flayer);
+
if (pres != GST_VC1_PARSER_OK) {
GST_ERROR_OBJECT (vc1parse, "Invalid VC1 frame layer");
- return GST_FLOW_ERROR;
+ ret = GST_FLOW_ERROR;
+ goto done;
}
- frame->buffer = buffer = gst_buffer_make_metadata_writable (buffer);
GST_BUFFER_TIMESTAMP (buffer) =
gst_util_uint64_scale (flayer.timestamp, GST_MSECOND, 1);
if (!flayer.key)
@@ -1060,20 +1138,26 @@ gst_vc1_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
*/
if (startcodes) {
/* skip frame layer header */
- if (!gst_vc1_parse_handle_bdus (vc1parse, buffer, 8, size - 8))
- return GST_FLOW_ERROR;
+ if (!gst_vc1_parse_handle_bdus (vc1parse, buffer, 8, size - 8)) {
+ ret = GST_FLOW_ERROR;
+ goto done;
+ }
/* For the advanced profile we need a sequence header here */
if (!vc1parse->seq_hdr_buffer) {
GST_ERROR_OBJECT (vc1parse, "Need sequence header");
- return GST_FLOW_ERROR;
+ ret = GST_FLOW_ERROR;
+ goto done;
}
}
+
+ ret = GST_FLOW_OK;
}
/* Need sequence header or sequence layer here, above code
* checks this already */
g_assert (vc1parse->seq_layer_buffer || vc1parse->seq_hdr_buffer);
+
/* We need the entrypoint BDU for the advanced profile before we can set
* the caps. For the ASF header format it will already be in the codec_data,
* for the frame-layer stream format it will be in the first frame already.
@@ -1088,17 +1172,30 @@ gst_vc1_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
|| vc1parse->input_stream_format == VC1_STREAM_FORMAT_SEQUENCE_LAYER_BDU
|| vc1parse->input_stream_format ==
VC1_STREAM_FORMAT_SEQUENCE_LAYER_BDU_FRAME) {
- return GST_BASE_PARSE_FLOW_QUEUED;
+ frame->flags |= GST_BASE_PARSE_FRAME_FLAG_QUEUE;
+ ret = GST_FLOW_OK;
} else {
GST_ERROR_OBJECT (vc1parse, "Need entrypoint for the advanced profile");
- return GST_FLOW_ERROR;
+ ret = GST_FLOW_ERROR;
+ goto done;
}
}
- if (!gst_vc1_parse_update_caps (vc1parse))
- return GST_FLOW_NOT_NEGOTIATED;
+ if (!gst_vc1_parse_update_caps (vc1parse)) {
+ ret = GST_FLOW_NOT_NEGOTIATED;
+ goto done;
+ }
- return GST_FLOW_OK;
+ gst_buffer_unmap (buffer, &minfo);
+ memset (&minfo, 0, sizeof (minfo));
+ GST_DEBUG_OBJECT (vc1parse, "Finishing frame of size %d", framesize);
+ ret = gst_base_parse_finish_frame (parse, frame, framesize);
+
+done:
+ if (minfo.data)
+ gst_buffer_unmap (buffer, &minfo);
+
+ return ret;
}
static GstFlowReturn
@@ -1159,17 +1256,24 @@ gst_vc1_parse_handle_seq_hdr (GstVC1Parse * vc1parse,
{
GstVC1ParserResult pres;
GstVC1Profile profile;
- g_assert (GST_BUFFER_SIZE (buf) >= offset + size);
+ GstMapInfo minfo;
+
+ g_assert (gst_buffer_get_size (buf) >= offset + size);
gst_buffer_replace (&vc1parse->seq_hdr_buffer, NULL);
memset (&vc1parse->seq_hdr, 0, sizeof (vc1parse->seq_hdr));
+
+ gst_buffer_map (buf, &minfo, GST_MAP_READ);
pres =
- gst_vc1_parse_sequence_header (GST_BUFFER_DATA (buf) + offset,
+ gst_vc1_parse_sequence_header (minfo.data + offset,
size, &vc1parse->seq_hdr);
+ gst_buffer_unmap (buf, &minfo);
+
if (pres != GST_VC1_PARSER_OK) {
GST_ERROR_OBJECT (vc1parse, "Invalid VC1 sequence header");
return FALSE;
}
- vc1parse->seq_hdr_buffer = gst_buffer_create_sub (buf, offset, size);
+ vc1parse->seq_hdr_buffer =
+ gst_buffer_copy_region (buf, GST_BUFFER_COPY_ALL, offset, size);
profile = vc1parse->seq_hdr.profile;
if (vc1parse->profile != profile) {
vc1parse->update_caps = TRUE;
@@ -1283,17 +1387,25 @@ gst_vc1_parse_handle_seq_layer (GstVC1Parse * vc1parse,
GstVC1Profile profile;
GstVC1Level level;
gint width, height;
- g_assert (GST_BUFFER_SIZE (buf) >= offset + size);
+ GstMapInfo minfo;
+
+ g_assert (gst_buffer_get_size (buf) >= offset + size);
+
gst_buffer_replace (&vc1parse->seq_layer_buffer, NULL);
memset (&vc1parse->seq_layer, 0, sizeof (vc1parse->seq_layer));
+
+ gst_buffer_map (buf, &minfo, GST_MAP_READ);
pres =
- gst_vc1_parse_sequence_layer (GST_BUFFER_DATA (buf) + offset,
+ gst_vc1_parse_sequence_layer (minfo.data + offset,
size, &vc1parse->seq_layer);
+ gst_buffer_unmap (buf, &minfo);
+
if (pres != GST_VC1_PARSER_OK) {
GST_ERROR_OBJECT (vc1parse, "Invalid VC1 sequence layer");
return FALSE;
}
- vc1parse->seq_layer_buffer = gst_buffer_create_sub (buf, offset, size);
+ vc1parse->seq_layer_buffer =
+ gst_buffer_copy_region (buf, GST_BUFFER_COPY_ALL, offset, size);
profile = vc1parse->seq_layer.struct_c.profile;
if (vc1parse->profile != profile) {
vc1parse->update_caps = TRUE;
@@ -1339,9 +1451,12 @@ static gboolean
gst_vc1_parse_handle_entrypoint (GstVC1Parse * vc1parse,
GstBuffer * buf, guint offset, guint size)
{
- g_assert (GST_BUFFER_SIZE (buf) >= offset + size);
+ g_assert (gst_buffer_get_size (buf) >= offset + size);
+
gst_buffer_replace (&vc1parse->entrypoint_buffer, NULL);
- vc1parse->entrypoint_buffer = gst_buffer_create_sub (buf, offset, size);
+ vc1parse->entrypoint_buffer =
+ gst_buffer_copy_region (buf, GST_BUFFER_COPY_ALL, offset, size);
+
return TRUE;
}
@@ -1393,25 +1508,36 @@ gst_vc1_parse_set_caps (GstBaseParse * parse, GstCaps * caps)
const gchar *stream_format = NULL;
const gchar *header_format = NULL;
const gchar *profile = NULL;
+ const gchar *format;
+
GST_DEBUG_OBJECT (parse, "caps %" GST_PTR_FORMAT, caps);
/* Parse the caps to get as much information as possible */
s = gst_caps_get_structure (caps, 0);
+
vc1parse->width = 0;
gst_structure_get_int (s, "width", &vc1parse->width);
vc1parse->height = 0;
gst_structure_get_int (s, "height", &vc1parse->height);
+
vc1parse->fps_n = vc1parse->fps_d = 0;
vc1parse->fps_from_caps = FALSE;
gst_structure_get_fraction (s, "framerate", &vc1parse->fps_n,
&vc1parse->fps_d);
if (vc1parse->fps_d != 0)
vc1parse->fps_from_caps = TRUE;
+
gst_structure_get_fraction (s, "pixel-aspect-ratio",
&vc1parse->par_n, &vc1parse->par_d);
if (vc1parse->par_n != 0 && vc1parse->par_d != 0)
vc1parse->par_from_caps = TRUE;
- vc1parse->fourcc = 0;
- gst_structure_get_fourcc (s, "format", &vc1parse->fourcc);
+
+ vc1parse->format = 0;
+ format = gst_structure_get_string (s, "format");
+ if (format && strcmp (format, "WVC1") == 0)
+ vc1parse->format = GST_VC1_PARSE_FORMAT_WVC1;
+ else
+ vc1parse->format = GST_VC1_PARSE_FORMAT_WMV3;
+
vc1parse->profile = -1;
profile = gst_structure_get_string (s, "profile");
if (profile && strcmp (profile, "simple"))
@@ -1420,14 +1546,16 @@ gst_vc1_parse_set_caps (GstBaseParse * parse, GstCaps * caps)
vc1parse->profile = GST_VC1_PROFILE_MAIN;
else if (profile && strcmp (profile, "advanced"))
vc1parse->profile = GST_VC1_PROFILE_ADVANCED;
- else if (vc1parse->fourcc == GST_MAKE_FOURCC ('W', 'V', 'C', '1'))
+ else if (vc1parse->format == GST_VC1_PARSE_FORMAT_WVC1)
vc1parse->profile = GST_VC1_PROFILE_ADVANCED;
- else if (vc1parse->fourcc == GST_MAKE_FOURCC ('W', 'M', 'V', '3'))
+ else if (vc1parse->format == GST_VC1_PARSE_FORMAT_WMV3)
vc1parse->profile = GST_VC1_PROFILE_MAIN; /* or SIMPLE */
+
vc1parse->level = -1;
vc1parse->detecting_stream_format = FALSE;
header_format = gst_structure_get_string (s, "header-format");
stream_format = gst_structure_get_string (s, "stream-format");
+
/* Now parse the codec_data */
gst_buffer_replace (&vc1parse->seq_layer_buffer, NULL);
gst_buffer_replace (&vc1parse->seq_hdr_buffer, NULL);
@@ -1435,28 +1563,34 @@ gst_vc1_parse_set_caps (GstBaseParse * parse, GstCaps * caps)
memset (&vc1parse->seq_layer, 0, sizeof (vc1parse->seq_layer));
memset (&vc1parse->seq_hdr, 0, sizeof (vc1parse->seq_hdr));
value = gst_structure_get_value (s, "codec_data");
+
if (value != NULL) {
+ gsize codec_data_size;
+ GstMapInfo minfo;
+
codec_data = gst_value_get_buffer (value);
- if ((GST_BUFFER_SIZE (codec_data) == 4 ||
- GST_BUFFER_SIZE (codec_data) == 5)) {
+ gst_buffer_map (codec_data, &minfo, GST_MAP_READ);
+ codec_data_size = gst_buffer_get_size (codec_data);
+ if ((codec_data_size == 4 || codec_data_size == 5)) {
/* ASF, VC1/WMV3 simple/main profile
* This is the sequence header without start codes
*/
if (!gst_vc1_parse_handle_seq_hdr (vc1parse, codec_data,
- 0, GST_BUFFER_SIZE (codec_data)))
+ 0, codec_data_size)) {
+ gst_buffer_unmap (codec_data, &minfo);
return FALSE;
+ }
if (header_format && strcmp (header_format, "asf") != 0)
GST_WARNING_OBJECT (vc1parse,
"Upstream claimed '%s' header format but 'asf' detected",
header_format);
vc1parse->input_header_format = VC1_HEADER_FORMAT_ASF;
- } else
- if (GST_BUFFER_SIZE (codec_data) == 36 &&
- GST_BUFFER_DATA (codec_data)[3] == 0xc5) {
+ } else if (codec_data_size == 36 && minfo.data[3] == 0xc5) {
/* Sequence Layer, SMPTE S421M-2006 Annex L.3 */
if (!gst_vc1_parse_handle_seq_layer (vc1parse, codec_data, 0,
- GST_BUFFER_SIZE (codec_data))) {
+ codec_data_size)) {
GST_ERROR_OBJECT (vc1parse, "Invalid VC1 sequence layer");
+ gst_buffer_unmap (codec_data, &minfo);
return FALSE;
}
@@ -1473,33 +1607,39 @@ gst_vc1_parse_set_caps (GstBaseParse * parse, GstCaps * caps)
* 2) Sequence Header with startcode
* 3) EntryPoint Header with startcode
*/
- if (GST_BUFFER_SIZE (codec_data) < 1 + 4 + 4 + 4 + 2) {
+ if (codec_data_size < 1 + 4 + 4 + 4 + 2) {
GST_ERROR_OBJECT (vc1parse,
"Too small for VC1 advanced profile ASF header");
+ gst_buffer_unmap (codec_data, &minfo);
return FALSE;
}
/* Some sanity checking */
- if ((GST_BUFFER_DATA (codec_data)[0] & 0x01) != 0x01) {
+ if ((minfo.data[0] & 0x01) != 0x01) {
GST_ERROR_OBJECT (vc1parse,
"Invalid binding byte for VC1 advanced profile ASF header");
+ gst_buffer_unmap (codec_data, &minfo);
return FALSE;
}
- start_code = GST_READ_UINT32_BE (GST_BUFFER_DATA (codec_data) + 1);
+ start_code = GST_READ_UINT32_BE (minfo.data + 1);
if (start_code != 0x000010f) {
GST_ERROR_OBJECT (vc1parse,
"VC1 advanced profile ASF header does not start with SequenceHeader startcode");
+ gst_buffer_unmap (codec_data, &minfo);
return FALSE;
}
if (!gst_vc1_parse_handle_bdus (vc1parse, codec_data, 1,
- GST_BUFFER_SIZE (codec_data) - 1))
+ codec_data_size - 1)) {
+ gst_buffer_unmap (codec_data, &minfo);
return FALSE;
+ }
if (!vc1parse->seq_hdr_buffer || !vc1parse->entrypoint_buffer) {
GST_ERROR_OBJECT (vc1parse,
"Need sequence header and entrypoint header in the codec_data");
+ gst_buffer_unmap (codec_data, &minfo);
return FALSE;
}
@@ -1510,6 +1650,7 @@ gst_vc1_parse_set_caps (GstBaseParse * parse, GstCaps * caps)
vc1parse->input_header_format = VC1_HEADER_FORMAT_ASF;
}
+ gst_buffer_unmap (codec_data, &minfo);
} else {
vc1parse->input_header_format = VC1_HEADER_FORMAT_NONE;
if (header_format && strcmp (header_format, "sequence-layer") != 0)
diff --git a/gst/videoparsers/gstvc1parse.h b/gst/videoparsers/gstvc1parse.h
index c1abe6e70..ec09fd491 100644
--- a/gst/videoparsers/gstvc1parse.h
+++ b/gst/videoparsers/gstvc1parse.h
@@ -55,6 +55,11 @@ typedef enum {
VC1_STREAM_FORMAT_FRAME_LAYER
} VC1StreamFormat;
+typedef enum {
+ GST_VC1_PARSE_FORMAT_WMV3,
+ GST_VC1_PARSE_FORMAT_WVC1
+} GstVC1ParseFormat;
+
/* FIXME move into baseparse, or anything equivalent;
* see https://bugzilla.gnome.org/show_bug.cgi?id=650093 */
#define GST_BASE_PARSE_FRAME_FLAG_PARSING 0x10000
@@ -69,7 +74,7 @@ struct _GstVC1Parse
/* Caps */
GstVC1Profile profile;
GstVC1Level level;
- guint32 fourcc;
+ GstVC1ParseFormat format;
gint width, height;
gint fps_n, fps_d;