flacparse: fix header rewriting being ignored
authorVincent Penquerc'h <vincent.penquerch@collabora.co.uk>
Fri, 21 Oct 2016 14:49:36 +0000 (15:49 +0100)
committerVincent Penquerc'h <vincent.penquerch@collabora.co.uk>
Thu, 10 Nov 2016 12:51:08 +0000 (12:51 +0000)
https://bugzilla.gnome.org/show_bug.cgi?id=727802

gst/audioparsers/gstflacparse.c
gst/audioparsers/gstflacparse.h

index 4a36137..819edde 100644 (file)
@@ -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);
index 3bd718e..2ce282e 100644 (file)
@@ -85,6 +85,10 @@ struct _GstFlacParse {
   GstBuffer *seektable;
 
   gboolean force_variable_block_size;
+
+  gsize header_size;
+  gsize byte_offset;
+  gboolean byte_mode;
 };
 
 struct _GstFlacParseClass {