ducatividdec: do not discard unused input data
authorVincent Penquerc'h <vincent.penquerch@collabora.co.uk>
Tue, 17 Jul 2012 10:07:11 +0000 (10:07 +0000)
committerVincent Penquerc'h <vincent.penquerch@collabora.co.uk>
Tue, 17 Jul 2012 10:17:33 +0000 (10:17 +0000)
The video decoder may not use all data applied to it in a decode call.
When this happens, we want to supply the remaining data again next time,
or corruption will happen due to "missing" data.

The data is currently copied, which is not an issue in practice as this
seems to happen not often, and more a small amount of data.

src/gstducatividdec.c

index 7f3d8a5125c61ef5b54a5c6fcae08fe9a41c1968..205dca17fa5db24ae89bdd507e2e81c76a2ba770 100644 (file)
@@ -505,7 +505,9 @@ gst_ducati_viddec_codec_flush (GstDucatiVidDec * self, gboolean eos)
   self->ts_may_be_pts = TRUE;
   self->ts_is_pts = FALSE;
   self->wait_keyframe = TRUE;
+  self->in_size = 0;
   self->needs_flushing = FALSE;
+  self->need_out_buf = TRUE;
 
   if (G_UNLIKELY (self->first_in_buffer)) {
     goto out;
@@ -1019,7 +1021,6 @@ allocate_buffer:
   }
 
 have_out_buf:
-  self->in_size = 0;
   buf = GST_DUCATIVIDDEC_GET_CLASS (self)->push_input (self, buf);
 
   if (ts != GST_CLOCK_TIME_NONE) {
@@ -1059,6 +1060,27 @@ have_out_buf:
 
   self->first_in_buffer = FALSE;
 
+  /* The copy could be avoided by playing with the buffer pointer,
+     but it seems to be rare and for not many bytes */
+  GST_DEBUG_OBJECT (self, "Consumed %d/%d (%d) bytes, %d left",
+      self->outArgs->bytesConsumed, self->in_size,
+      self->inArgs->numBytes,
+      self->in_size - self->outArgs->bytesConsumed);
+  if (self->outArgs->bytesConsumed > 0) {
+    if (self->outArgs->bytesConsumed > self->in_size) {
+      GST_WARNING_OBJECT (self, "Codec claims to have used more bytes than supplied");
+      self->in_size = 0;
+    } else {
+      if (self->outArgs->bytesConsumed < self->in_size) {
+        GST_DEBUG_OBJECT (self, "First 16 were:");
+        gst_util_dump_mem (self->input, 16);
+        memmove (self->input, self->input + self->outArgs->bytesConsumed,
+            self->in_size - self->outArgs->bytesConsumed);
+      }
+      self->in_size -= self->outArgs->bytesConsumed;
+    }
+  }
+
   if (self->outArgs->outBufsInUseFlag) {
     GST_DEBUG_OBJECT (self, "outBufsInUseFlag set");
     self->need_out_buf = FALSE;