opusdec: fix lost packet handling for FEC/PLC
authorVincent Penquerc'h <vincent.penquerch@collabora.co.uk>
Mon, 30 Apr 2012 13:40:02 +0000 (14:40 +0100)
committerVincent Penquerc'h <vincent.penquerch@collabora.co.uk>
Thu, 24 May 2012 21:56:41 +0000 (22:56 +0100)
The base audio decoder sends zero size packets, not NULL buffers,
to signal dropped packets.

ext/opus/gstopusdec.c

index a21b187..626e785 100644 (file)
@@ -393,17 +393,20 @@ opus_dec_chain_parse_data (GstOpusDec * dec, GstBuffer * buffer)
      to potentially wait for next buffer to decode a missing buffer */
   if (dec->use_inband_fec && !dec->primed) {
     GST_DEBUG_OBJECT (dec, "First buffer received in FEC mode, early out");
+    gst_buffer_replace (&dec->last_buffer, buffer);
+    dec->primed = TRUE;
     goto done;
   }
 
   /* That's the buffer we'll be sending to the opus decoder. */
-  buf = dec->use_inband_fec && dec->last_buffer ? dec->last_buffer : buffer;
+  buf = (dec->use_inband_fec
+      && gst_buffer_get_size (dec->last_buffer) >
+      0) ? dec->last_buffer : buffer;
 
-  if (buf) {
+  if (buf && gst_buffer_get_size (buf) > 0) {
     gst_buffer_map (buf, &map, GST_MAP_READ);
     data = map.data;
     size = map.size;
-
     GST_DEBUG_OBJECT (dec, "Using buffer of size %u", size);
   } else {
     /* concealment data, pass NULL as the bits parameters */
@@ -428,15 +431,18 @@ opus_dec_chain_parse_data (GstOpusDec * dec, GstBuffer * buffer)
   if (dec->use_inband_fec) {
     if (dec->last_buffer) {
       /* normal delayed decode */
+      GST_LOG_OBJECT (dec, "FEC enabled, decoding last delayed buffer");
       n = opus_multistream_decode (dec->state, data, size, out_data, samples,
           0);
     } else {
       /* FEC reconstruction decode */
+      GST_LOG_OBJECT (dec, "FEC enabled, reconstructing last buffer");
       n = opus_multistream_decode (dec->state, data, size, out_data, samples,
           1);
     }
   } else {
     /* normal decode */
+    GST_LOG_OBJECT (dec, "FEC disabled, decoding buffer");
     n = opus_multistream_decode (dec->state, data, size, out_data, samples, 0);
   }
   gst_buffer_unmap (outbuf, &omap);
@@ -445,6 +451,7 @@ opus_dec_chain_parse_data (GstOpusDec * dec, GstBuffer * buffer)
 
   if (n < 0) {
     GST_ELEMENT_ERROR (dec, STREAM, DECODE, ("Decoding error: %d", n), (NULL));
+    gst_buffer_unref (outbuf);
     return GST_FLOW_ERROR;
   }
   GST_DEBUG_OBJECT (dec, "decoded %d samples", n);
@@ -495,17 +502,16 @@ opus_dec_chain_parse_data (GstOpusDec * dec, GstBuffer * buffer)
     gst_buffer_unmap (outbuf, &omap);
   }
 
+  if (dec->use_inband_fec) {
+    gst_buffer_replace (&dec->last_buffer, buffer);
+  }
+
   res = gst_audio_decoder_finish_frame (GST_AUDIO_DECODER (dec), outbuf, 1);
 
   if (res != GST_FLOW_OK)
     GST_DEBUG_OBJECT (dec, "flow: %s", gst_flow_get_name (res));
 
 done:
-  if (dec->use_inband_fec) {
-    gst_buffer_replace (&dec->last_buffer, buffer);
-    dec->primed = TRUE;
-  }
-
   return res;
 
 creation_failed: