<div dir="ltr">Hello,<div><br></div><div>I'm using the code below to timestamp a pipeline and get a delay in the end for the buffers.</div><div>It work fine usually, putting the but timestamp at the src pad and getting the difference in the sink.</div><div>However, in a longer transcoding pipeline the transform function always get non writable buffers, and the meta is not replicated.</div><div><br></div><div>Is there a way to now who is blocking the buffer, or a workaround?<br></div><div><br></div><div>Any tips will be really appreciated.</div><div><br></div><div>Regards</div><div>Rafael</div><div><br></div><div>/* meta functions */</div><div><div>#include <gst/gst.h></div><div>#include <unistd.h></div><div>#include <sys/time.h></div><div>#include <glib.h></div><div>#include <stdlib.h></div><div>#include <string.h></div><div>#include <stdio.h></div><div>#include <argp.h></div><div><br></div><div>typedef struct _GstMetaTS GstMetaTS;</div><div><br></div><div>struct _GstMetaTS {</div><div>        GstMeta meta;</div><div>        GstClockTime in_timestamp;</div><div>};</div><div><br></div><div>GType gst_meta_ts_api_get_type (void);</div><div><br></div><div>const GstMetaInfo* gst_meta_ts_get_info (void);</div><div><br></div><div>#define GST_META_TS_GET(buf) ((GstMetaTS *)gst_buffer_get_meta(buf,gst_meta_ts_api_get_type()))</div><div>#define GST_META_TS_ADD(buf) ((GstMetaTS *)gst_buffer_add_meta(buf,gst_meta_ts_get_info(),(gpointer)NULL))</div><div><br></div><div>gboolean gst_meta_ts_transform (GstBuffer *dest_buf, GstMeta *src_meta, GstBuffer *src_buf, GQuark type, gpointer data) {</div><div>        GstBuffer * buf = NULL;</div><div>        if(! gst_buffer_is_writable(dest_buf))</div><div>        {</div><div>                GST_DEBUG("NOT WRITABLE, NOT ABLE TO TRANSFORM\n");</div><div>                return FALSE;</div><div>        }</div><div>        GstMeta* dest_meta = (GstMeta*)GST_META_TS_ADD(dest_buf);</div><div>        GstMetaTS* src_meta_ts = (GstMetaTS*)src_meta;</div><div>        GstMetaTS* dest_meta_ts = (GstMetaTS*)dest_meta;</div><div>        dest_meta_ts->in_timestamp = src_meta_ts->in_timestamp;</div><div>        return TRUE;</div><div>}</div><div><br></div><div>void gst_meta_ts_free (GstMeta *meta, GstBuffer *buffer) {</div><div>}</div><div><br></div><div>gboolean gst_meta_ts_init(GstMeta *meta, gpointer params, GstBuffer *buffer){</div><div>        GstMetaTS* ts_meta = (GstMetaTS*)meta;</div><div>        ts_meta->in_timestamp = GST_CLOCK_TIME_NONE;</div><div>        return TRUE;</div><div>}</div><div><br></div><div>GType gst_meta_ts_api_get_type (void){</div><div>  static volatile GType type;</div><div>  static const gchar *tags[] = { NULL };</div><div>  if (g_once_init_enter (&type)) {</div><div>        GType _type = gst_meta_api_type_register ("GstMetaTSAPI", tags);</div><div>        g_once_init_leave (&type, _type);</div><div>  }</div><div>  return type;</div><div>}</div></div><div><br></div><div>/* transcoder code */</div><div><div>static GstPadProbeReturn probe_src (GstPad *pad, GstPadProbeInfo *info, gpointer user_data){</div><div>        if (playing){</div><div>                GstBuffer *b;</div><div>                b = GST_PAD_PROBE_INFO_BUFFER (info);</div><div>                if (! gst_buffer_is_writable(b))</div><div>                {</div><div>                        return GST_PAD_PROBE_OK;</div><div>                }</div><div>                GstMetaTS* meta = GST_META_TS_ADD(b);</div><div>                GstClock* clock = gst_system_clock_obtain ();</div><div>                meta->in_timestamp = gst_clock_get_time(clock);</div><div>                gst_object_unref(clock);</div><div>        }</div><div>        return GST_PAD_PROBE_OK;</div><div>}</div><div><br></div><div>static GstPadProbeReturn probe_sink (GstPad *pad, GstPadProbeInfo *info, gpointer user_data){</div><div>        GstBuffer *b;</div><div>        b = GST_PAD_PROBE_INFO_BUFFER (info);</div><div>        if (! gst_buffer_is_writable(b))</div><div>        {</div><div>                return GST_PAD_PROBE_OK;</div><div>        }</div><div>        GstMetaTS* meta = GST_META_TS_GET(b);</div><div>        if(meta == NULL) {</div><div>                return GST_PAD_PROBE_OK;</div><div>        }</div><div>        GstClock* clock = gst_system_clock_obtain ();</div><div>        GstClockTimeDiff diff = GST_CLOCK_DIFF(meta->in_timestamp, gst_clock_get_time(clock));</div><div>        delay_avg = ((delay_avg*delay_count)+diff)/++delay_count;</div><div>        if (last_delay_print + DELAY_PRINT_INTERVAL < get_time_us()){</div><div>                printf("DELAY_NOW:%3.4fms,DELAY_AVG:%3.4fms\n",((double)diff)/1000/1000,delay_avg/1000/1000);</div><div>                last_delay_print = get_time_us();</div><div>        }</div><div>        gst_object_unref(clock);</div><div>        gst_buffer_remove_meta(b, (GstMeta*)meta);</div><div>        return GST_PAD_PROBE_OK;</div><div>}</div></div><div><br></div><div>(...)</div><div><br></div><div><div>GstPad *pad = gst_element_get_static_pad (tra_src, "src");</div><div>gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BUFFER, (GstPadProbeCallback) probe_src, NULL, NULL);</div><div>gst_object_unref (pad);</div><div><br></div><div>pad = gst_element_get_static_pad (tra_sink, "sink");</div><div>gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BUFFER, (GstPadProbeCallback) probe_sink, NULL, NULL);</div><div>gst_object_unref (pad);</div></div><div><br></div><div><br></div></div>