[Spice-devel] [PATCH v3 spice-gtk] gstreamer: set timestamp in buffer's GstReferenceTimestampMeta

Frediano Ziglio fziglio at redhat.com
Thu Jan 17 12:27:19 UTC 2019


> 
> Currently we set timestamps as buffer's PTS, this value may be changed by
> the pipeline in some cases and cause an unexpected buffer warnings (when
> GstVideoOverlay is not used). Use GstReferenceTimestampMeta when
> synchronization is made by spice.
> 
> Before applying this patch you can reproduce the warnings by runing with
> DISABLE_GSTVIDEOOVERLAY=1 and starting some audio playback in the guest.
> 
> Signed-off-by: Snir Sheriber <ssheribe at redhat.com>
> ---
> 
> Changes from v2:
> -Use buffer's PTS value, if GstReferenceTimestampMeta exists, use its
> timestamp instead.
> 

Surely this version won't crash but I'd like to understand better
the various behaviours:
- why Gstreamer changes PTS? Now that you I think I remember that GStreamer
  make sure that PTS is monotonic, in the sense that has always to
  grow, if you pass a buffer with a PTS smaller than the previous it
  changes the value to keep it monotonic. Is this your case?
  Maybe we should prevent this in our code instead.
- why for you the metadata is at the output and in my case not?
  Which codec where you using? Normal videos or streaming?

> ---
>  src/channel-display-gst.c | 32 +++++++++++++++++++++++++++++---
>  1 file changed, 29 insertions(+), 3 deletions(-)
> 
> diff --git a/src/channel-display-gst.c b/src/channel-display-gst.c
> index 2f556fe..a281032 100644
> --- a/src/channel-display-gst.c
> +++ b/src/channel-display-gst.c
> @@ -33,6 +33,10 @@ typedef struct SpiceGstFrame SpiceGstFrame;
>  
>  /* GStreamer decoder implementation */
>  
> +#if GST_CHECK_VERSION(1,14,0)
> +static GstStaticCaps stream_reference =
> GST_STATIC_CAPS("timestamp/spice-stream");
> +#endif
> +
>  typedef struct SpiceGstDecoder {
>      VideoDecoder base;
>  
> @@ -86,7 +90,16 @@ struct SpiceGstFrame {
>  static SpiceGstFrame *create_gst_frame(GstBuffer *buffer, SpiceFrame *frame)
>  {
>      SpiceGstFrame *gstframe = g_new(SpiceGstFrame, 1);
> +
>      gstframe->timestamp = GST_BUFFER_PTS(buffer);
> +#if GST_CHECK_VERSION(1,14,0)
> +    GstReferenceTimestampMeta *time_meta;
> +
> +    time_meta = gst_buffer_get_reference_timestamp_meta(buffer,
> gst_static_caps_get(&stream_reference));
> +    if (time_meta) {
> +        gstframe->timestamp = time_meta->timestamp;
> +    }
> +#endif
>      gstframe->frame = frame;
>      gstframe->sample = NULL;
>      return gstframe;
> @@ -211,6 +224,15 @@ static void fetch_pending_sample(SpiceGstDecoder
> *decoder)
>          decoder->pending_samples--;
>  
>          GstBuffer *buffer = gst_sample_get_buffer(sample);
> +        GstClockTime buffer_ts = GST_BUFFER_PTS(buffer);
> +#if GST_CHECK_VERSION(1,14,0)
> +        GstReferenceTimestampMeta *time_meta;
> +
> +        time_meta = gst_buffer_get_reference_timestamp_meta(buffer,
> gst_static_caps_get(&stream_reference));
> +        if (time_meta) {
> +            buffer_ts = time_meta->timestamp;
> +        }
> +#endif
>  
>          /* gst_app_sink_pull_sample() sometimes returns the same buffer
>          twice
>           * or buffers that have a modified, and thus unrecognizable, PTS.
> @@ -223,7 +245,7 @@ static void fetch_pending_sample(SpiceGstDecoder
> *decoder)
>          GList *l = g_queue_peek_head_link(decoder->decoding_queue);
>          while (l) {
>              gstframe = l->data;
> -            if (gstframe->timestamp == GST_BUFFER_PTS(buffer)) {
> +            if (gstframe->timestamp == buffer_ts) {
>                  /* The frame is now ready for display */
>                  gstframe->sample = sample;
>                  decoder->display_frame = gstframe;
> @@ -232,7 +254,7 @@ static void fetch_pending_sample(SpiceGstDecoder
> *decoder)
>                   * frames from the decoding queue.
>                   */
>                  while ((gstframe =
>                  g_queue_pop_head(decoder->decoding_queue))) {
> -                    if (gstframe->timestamp == GST_BUFFER_PTS(buffer)) {
> +                    if (gstframe->timestamp == buffer_ts) {
>                          break;
>                      }
>                      /* The GStreamer pipeline dropped the corresponding
> @@ -626,9 +648,13 @@ static gboolean
> spice_gst_decoder_queue_frame(VideoDecoder *video_decoder,
>                                                      frame->data,
>                                                      frame->size, 0,
>                                                      frame->size,
>                                                      frame->data_opaque,
>                                                      frame->unref_data);
>  
> +    GstClockTime pts = gst_clock_get_time(decoder->clock) -
> gst_element_get_base_time(decoder->pipeline) + ((uint64_t)MAX(0, latency)) *
> 1000 * 1000;
>      GST_BUFFER_DURATION(buffer) = GST_CLOCK_TIME_NONE;
>      GST_BUFFER_DTS(buffer) = GST_CLOCK_TIME_NONE;
> -    GST_BUFFER_PTS(buffer) = gst_clock_get_time(decoder->clock) -
> gst_element_get_base_time(decoder->pipeline) + ((uint64_t)MAX(0, latency)) *
> 1000 * 1000;
> +    GST_BUFFER_PTS(buffer) = pts;
> +#if GST_CHECK_VERSION(1,14,0)
> +    gst_buffer_add_reference_timestamp_meta(buffer, gst_static_caps_get
> (&stream_reference), pts, GST_CLOCK_TIME_NONE);
> +#endif
>  
>      if (decoder->appsink != NULL) {
>          SpiceGstFrame *gst_frame = create_gst_frame(buffer, frame);


More information about the Spice-devel mailing list