tagdemux: resize and trim buffer in place to fix interaction with oggdemux
authorTim-Philipp Müller <tim@centricular.com>
Mon, 4 Jan 2021 13:40:20 +0000 (13:40 +0000)
committerTim-Philipp Müller <tim@centricular.com>
Mon, 4 Jan 2021 14:21:43 +0000 (14:21 +0000)
Elements operating in pull mode may optionally pass a buffer to
pull_range that should be filled with the data. The only element
that does that at the moment is oggdemux operating in pull mode.

tagdemux currently creates a sub-buffer whenever a buffer pulled
from upstream (filesrc, usually) needs to be trimmed. This creates
a new buffer, however, so disregards any passed-in buffer from a
downstream oggdemux.

This would cause assertion failures and playback problems for
ogg files that contain ID3 tags at the end.

Fixes https://gitlab.freedesktop.org/gstreamer/gst-plugins-base/-/issues/848

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-base/-/merge_requests/994>

gst-libs/gst/tag/gsttagdemux.c

index f545857..8164c0d 100644 (file)
@@ -377,7 +377,8 @@ gst_tag_demux_trim_buffer (GstTagDemux * tagdemux, GstBuffer ** buf_ref,
   guint trim_start = 0;
   guint out_size, bsize;
   guint64 out_offset, boffset;
-  gboolean need_sub = FALSE;
+  gboolean need_fixup = FALSE;
+  gboolean is_writable;
 
   bsize = out_size = gst_buffer_get_size (buf);
   boffset = out_offset = GST_BUFFER_OFFSET (buf);
@@ -402,7 +403,7 @@ gst_tag_demux_trim_buffer (GstTagDemux * tagdemux, GstBuffer ** buf_ref,
 
       if (out_offset + out_size > v1tag_offset) {
         out_size = v1tag_offset - out_offset;
-        need_sub = TRUE;
+        need_fixup = TRUE;
       }
     }
   }
@@ -421,11 +422,16 @@ gst_tag_demux_trim_buffer (GstTagDemux * tagdemux, GstBuffer ** buf_ref,
     } else {
       out_offset -= tagdemux->priv->strip_start;
     }
-    need_sub = TRUE;
+    need_fixup = TRUE;
   }
 
-  if (need_sub) {
-    if (out_size != bsize || !gst_buffer_is_writable (buf)) {
+  if (!need_fixup)
+    goto done;
+
+  is_writable = gst_buffer_is_writable (buf);
+
+  if (out_size != bsize || !is_writable) {
+    if (!is_writable) {
       GstBuffer *sub;
 
       GST_DEBUG_OBJECT (tagdemux, "Sub-buffering to trim size %d offset %"
@@ -444,15 +450,23 @@ gst_tag_demux_trim_buffer (GstTagDemux * tagdemux, GstBuffer ** buf_ref,
       *buf_ref = buf = sub;
       *buf_size = out_size;
     } else {
-      GST_DEBUG_OBJECT (tagdemux, "Adjusting buffer from size %d offset %"
+      GST_DEBUG_OBJECT (tagdemux, "Resizing buffer to trim size %d offset %"
           G_GINT64_FORMAT " to %d offset %" G_GINT64_FORMAT,
           bsize, boffset, out_size, out_offset);
-    }
 
-    GST_BUFFER_OFFSET (buf) = out_offset;
-    GST_BUFFER_OFFSET_END (buf) = out_offset + out_size;
+      gst_buffer_resize (buf, trim_start, out_size);
+    }
+  } else {
+    GST_DEBUG_OBJECT (tagdemux, "Adjusting buffer from size %d offset %"
+        G_GINT64_FORMAT " to %d offset %" G_GINT64_FORMAT,
+        bsize, boffset, out_size, out_offset);
   }
 
+  GST_BUFFER_OFFSET (buf) = out_offset;
+  GST_BUFFER_OFFSET_END (buf) = out_offset + out_size;
+
+done:
+
   return TRUE;
 
 no_out_buffer_end: