opusenc: update output segment stop time to match clipped samples
authorVincent Penquerc'h <vincent.penquerch@collabora.co.uk>
Tue, 10 Jun 2014 08:33:40 +0000 (09:33 +0100)
committerVincent Penquerc'h <vincent.penquerch@collabora.co.uk>
Thu, 30 Oct 2014 14:41:44 +0000 (14:41 +0000)
This will let oggmux generate a granpos on the last page that properly
represents the clipped samples at the end of the stream.

ext/opus/gstopusenc.c
ext/opus/gstopusenc.h

index f9cf6244480e8a03b3fbe2e8b0bf00fc2d84f62c..4d118b054cf3584acd7d01b9da5e7490594616ee 100644 (file)
@@ -329,6 +329,7 @@ gst_opus_enc_start (GstAudioEncoder * benc)
   GST_DEBUG_OBJECT (enc, "start");
   enc->tags = gst_tag_list_new_empty ();
   enc->header_sent = FALSE;
+  enc->encoded_samples = 0;
 
   return TRUE;
 }
@@ -704,6 +705,9 @@ gst_opus_enc_sink_event (GstAudioEncoder * benc, GstEvent * event)
       gst_tag_setter_merge_tags (setter, list, mode);
       break;
     }
+    case GST_EVENT_SEGMENT:
+      enc->encoded_samples = 0;
+      break;
 
     default:
       break;
@@ -793,6 +797,8 @@ gst_opus_enc_encode (GstOpusEnc * enc, GstBuffer * buf)
   GstMapInfo omap;
   gint outsize;
   GstBuffer *outbuf;
+  GstSegment *segment;
+  GstClockTime duration;
 
   guint max_payload_size;
   gint frame_samples;
@@ -813,6 +819,26 @@ gst_opus_enc_encode (GstOpusEnc * enc, GstBuffer * buf)
     if (G_UNLIKELY (bsize % bytes)) {
       GST_DEBUG_OBJECT (enc, "draining; adding silence samples");
 
+      /* If encoding part of a frame, and we have no set stop time on
+       * the output segment, we update the segment stop time to reflect
+       * the last sample. This will let oggmux set the last page's
+       * granpos to tell a decoder the dummy samples should be clipped.
+       */
+      segment = &GST_AUDIO_ENCODER_OUTPUT_SEGMENT (enc);
+      if (!GST_CLOCK_TIME_IS_VALID (segment->stop)) {
+        int input_samples = bsize / (enc->n_channels * 2);
+        GST_DEBUG_OBJECT (enc,
+            "No stop time and partial frame, updating segment");
+        duration =
+            gst_util_uint64_scale (enc->encoded_samples + input_samples,
+            GST_SECOND, enc->sample_rate);
+        segment->stop = segment->start + duration;
+        GST_DEBUG_OBJECT (enc, "new output segment %" GST_SEGMENT_FORMAT,
+            segment);
+        gst_pad_push_event (GST_AUDIO_ENCODER_SRC_PAD (enc),
+            gst_event_new_segment (segment));
+      }
+
       size = ((bsize / bytes) + 1) * bytes;
       mdata = g_malloc0 (size);
       memcpy (mdata, bdata, bsize);
@@ -864,6 +890,7 @@ gst_opus_enc_encode (GstOpusEnc * enc, GstBuffer * buf)
   ret =
       gst_audio_encoder_finish_frame (GST_AUDIO_ENCODER (enc), outbuf,
       frame_samples);
+  enc->encoded_samples += frame_samples;
 
 done:
 
index 64f95e37c0d6d663ba1e61237a2a0b736548c83a..9e1d3600b2c6dadc7ad885614944c1220bab75b6 100644 (file)
@@ -74,6 +74,7 @@ struct _GstOpusEnc {
   gint                  sample_rate;
 
   gboolean              header_sent;
+  guint64               encoded_samples;
 
   GSList                *headers;