From adeee44b07a173b9ab4253216caba8f66dd43abb Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Fri, 21 Oct 2016 15:49:36 +0100 Subject: [PATCH] flacparse: fix header rewriting being ignored https://bugzilla.gnome.org/show_bug.cgi?id=727802 --- gst/audioparsers/gstflacparse.c | 49 ++++++++++++++++++++++++++++++++++++++++- gst/audioparsers/gstflacparse.h | 4 ++++ 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/gst/audioparsers/gstflacparse.c b/gst/audioparsers/gstflacparse.c index 4a36137..819edde 100644 --- a/gst/audioparsers/gstflacparse.c +++ b/gst/audioparsers/gstflacparse.c @@ -208,6 +208,8 @@ static GstFlowReturn gst_flac_parse_pre_push_frame (GstBaseParse * parse, static gboolean gst_flac_parse_convert (GstBaseParse * parse, GstFormat src_format, gint64 src_value, GstFormat dest_format, gint64 * dest_value); +static gboolean gst_flac_parse_sink_event (GstBaseParse * parse, + GstEvent * event); static gboolean gst_flac_parse_src_event (GstBaseParse * parse, GstEvent * event); static GstCaps *gst_flac_parse_get_sink_caps (GstBaseParse * parse, @@ -243,6 +245,7 @@ gst_flac_parse_class_init (GstFlacParseClass * klass) baseparse_class->pre_push_frame = GST_DEBUG_FUNCPTR (gst_flac_parse_pre_push_frame); baseparse_class->convert = GST_DEBUG_FUNCPTR (gst_flac_parse_convert); + baseparse_class->sink_event = GST_DEBUG_FUNCPTR (gst_flac_parse_sink_event); baseparse_class->src_event = GST_DEBUG_FUNCPTR (gst_flac_parse_src_event); baseparse_class->get_sink_caps = GST_DEBUG_FUNCPTR (gst_flac_parse_get_sink_caps); @@ -315,6 +318,8 @@ gst_flac_parse_reset (GstFlacParse * parser) g_list_foreach (parser->headers, (GFunc) gst_mini_object_unref, NULL); g_list_free (parser->headers); parser->headers = NULL; + parser->header_size = 0; + parser->byte_mode = FALSE; } static void @@ -791,7 +796,11 @@ gst_flac_parse_handle_frame (GstBaseParse * parse, goto cleanup; } - if ((GST_READ_UINT16_BE (map.data) & 0xfffe) == 0xfff8) { + if (flacparse->byte_mode && flacparse->byte_offset < flacparse->header_size) { + *skipsize = 0; + framesize = map.size; + goto cleanup; + } else if ((GST_READ_UINT16_BE (map.data) & 0xfffe) == 0xfff8) { gboolean ret; guint next; @@ -1332,6 +1341,7 @@ push_headers: /* push header buffers; update caps, so when we push the first buffer the * negotiated caps will change to caps that include the streamheader field */ + flacparse->header_size = 0; while (flacparse->headers) { GstBuffer *buf = GST_BUFFER (flacparse->headers->data); GstBaseParseFrame frame; @@ -1344,6 +1354,7 @@ push_headers: gst_base_parse_frame_init (&frame); frame.buffer = buf; frame.overhead = -1; + flacparse->header_size += gst_buffer_get_size (frame.buffer); res = gst_base_parse_push_frame (GST_BASE_PARSE (flacparse), &frame); gst_base_parse_frame_free (&frame); if (res != GST_FLOW_OK) @@ -1352,6 +1363,7 @@ push_headers: g_list_foreach (flacparse->headers, (GFunc) gst_mini_object_unref, NULL); g_list_free (flacparse->headers); flacparse->headers = NULL; + flacparse->byte_offset = flacparse->header_size; return res; } @@ -1591,6 +1603,11 @@ gst_flac_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame, /* DROPPED because we pushed already or will push all headers manually */ res = GST_BASE_PARSE_FLOW_DROPPED; } else { + if (flacparse->byte_mode && flacparse->byte_offset < flacparse->header_size) { + res = GST_FLOW_OK; + goto cleanup; + } + if (flacparse->offset != GST_BUFFER_OFFSET (buffer)) { FrameHeaderCheckReturn ret; @@ -1720,6 +1737,8 @@ gst_flac_parse_pre_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame) frame->flags |= GST_BASE_PARSE_FRAME_FLAG_CLIP; + flacparse->byte_offset += gst_buffer_get_size (frame->buffer); + return GST_FLOW_OK; } @@ -1756,6 +1775,34 @@ gst_flac_parse_convert (GstBaseParse * parse, } static gboolean +gst_flac_parse_sink_event (GstBaseParse * parse, GstEvent * event) +{ + GstFlacParse *flacparse = GST_FLAC_PARSE (parse); + const GstSegment *segment; + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_SEGMENT: + { + gst_event_parse_segment (event, &segment); + flacparse->byte_mode = (segment->format == GST_FORMAT_BYTES) + && flacparse->header_size > 0; + if (flacparse->byte_mode) { + /* we must pass every header update now */ + gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), 0); + /* we must drain any pending data before the seek */ + gst_base_parse_drain (parse); + flacparse->byte_offset = segment->start; + return gst_pad_push_event (GST_BASE_PARSE_SRC_PAD (parse), event); + } + break; + } + default: + break; + } + return GST_BASE_PARSE_CLASS (parent_class)->sink_event (parse, event); +} + +static gboolean gst_flac_parse_src_event (GstBaseParse * parse, GstEvent * event) { GstFlacParse *flacparse = GST_FLAC_PARSE (parse); diff --git a/gst/audioparsers/gstflacparse.h b/gst/audioparsers/gstflacparse.h index 3bd718e..2ce282e 100644 --- a/gst/audioparsers/gstflacparse.h +++ b/gst/audioparsers/gstflacparse.h @@ -85,6 +85,10 @@ struct _GstFlacParse { GstBuffer *seektable; gboolean force_variable_block_size; + + gsize header_size; + gsize byte_offset; + gboolean byte_mode; }; struct _GstFlacParseClass { -- 2.7.4