<html><head></head><body><div class="ydp407da3b7yahoo-style-wrap" style="font-family:Helvetica Neue, Helvetica, Arial, sans-serif;font-size:13px;"><div><div dir="ltr" data-setdir="false"><span>GstBuffer *bufferOut = gst_buffer_copy(buffer); </span></div><div><br></div><div class="ydp407da3b7signature"><div dir="ltr" data-setdir="false">you are making copy of the buffer adding the signal and the modifcation never gone to downstream.<br>Instead, map the buffer directly.<br><br></div><div><br></div><div>Sent from Yahoo Mail. <a href="https://yho.com/148vdq" rel="nofollow" target="_blank">Get the app</a></div></div></div>
        <div><br></div><div><br></div>
        
        </div><div id="yahoo_quoted_8797225348" class="yahoo_quoted">
            <div style="font-family:'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;color:#26282a;">
                
                <div>
                    On Thursday, 9 March, 2023 at 05:46:34 am GMT-6, Sergei Hrushev via gstreamer-devel <gstreamer-devel@lists.freedesktop.org> wrote:
                </div>
                <div><br></div>
                <div><br></div>
                <div><div dir="ltr">Hello Mr. Kesti!<br></div><div dir="ltr"><br></div><div dir="ltr">> Then it is something to do with the probe callback function. If you can post your your probe function may be I can help here/<br></div><div dir="ltr"><br></div><div dir="ltr">I prepared the complete example of a small app which modifies audio<br></div><div dir="ltr">frames directly in the BUFFER probe on the fly.<br></div><div dir="ltr"><br></div><div dir="ltr">In this app I'm adding probe to the CapsFilter 'src' pad - and the app<br></div><div dir="ltr">works as expected,<br></div><div dir="ltr">it properly overwrites the default signal with sine wave of different frequency.<br></div><div dir="ltr">(maybe there's a better way to determine amount of frames in the<br></div><div dir="ltr">current buffer?).<br></div><div dir="ltr"><br></div><div dir="ltr">Also in my real app when I'm adding similar probe for example to the<br></div><div dir="ltr">Tee 'src' pad - it also works.<br></div><div dir="ltr">But I need to use it on AudioAggregator 'src' pad - and there the<br></div><div dir="ltr">produced sound is "jammed".<br></div><div dir="ltr"><br></div><div dir="ltr">As in my case the entire audio pipeline works in Docker - I use<br></div><div dir="ltr">streaming to get the audio on host,<br></div><div dir="ltr">but it's easy to change the code to force it to play instead.<br></div><div dir="ltr">To play from streaming I'm using this:<br></div><div dir="ltr"><br></div><div dir="ltr">gst-launch-1.0 -v udpsrc port=50111 ! \<br></div><div dir="ltr">  application/x-rtp,media=audio,payload=96,encoding-name=OPUS,clock-rate=48000<br></div><div dir="ltr">! \<br></div><div dir="ltr">  rtpssrcdemux ! rtpopusdepay ! opusdec ! audioconvert ! audioresample<br></div><div dir="ltr">! queue ! autoaudiosink<br></div><div dir="ltr"><br></div><div dir="ltr">Best regards, Sergei Hrushev.<br></div><div dir="ltr"><br></div><div dir="ltr">--------  Code example -------<br></div><div dir="ltr"><br></div><div dir="ltr"><br></div><div dir="ltr">// Most of the boilerplate code is just a variation of code took from here:<br></div><div dir="ltr">//   <a href="https://gstreamer.freedesktop.org/documentation/plugin-development/basics/testapp.html?gi-language=c" target="_blank">https://gstreamer.freedesktop.org/documentation/plugin-development/basics/testapp.html?gi-language=c</a><br></div><div dir="ltr"><br></div><div dir="ltr">#include <gst/gst.h><br></div><div dir="ltr"><br></div><div dir="ltr">#include <cmath><br></div><div dir="ltr">#include <string><br></div><div dir="ltr"><br></div><div dir="ltr">struct Storage {<br></div><div dir="ltr">  GMainLoop* loop;<br></div><div dir="ltr">  GstElement* pipeline;<br></div><div dir="ltr">  GstBus* bus;<br></div><div dir="ltr">  guint idWatch;<br></div><div dir="ltr">  GstElement* src1;<br></div><div dir="ltr">  GstElement* convert1;<br></div><div dir="ltr">  GstElement* resample1;<br></div><div dir="ltr">  GstElement* capsfilter1;<br></div><div dir="ltr">  gulong idProbe;<br></div><div dir="ltr">  GstElement* opusenc1;<br></div><div dir="ltr">  GstElement* rtpopuspay1;<br></div><div dir="ltr">  GstElement* udpsink1;<br></div><div dir="ltr"><br></div><div dir="ltr">  guint pos;<br></div><div dir="ltr">};<br></div><div dir="ltr"><br></div><div dir="ltr">static gboolean callbackBus(<br></div><div dir="ltr">  GstBus* bus,<br></div><div dir="ltr">  GstMessage* msg,<br></div><div dir="ltr">  gpointer data) {<br></div><div dir="ltr"><br></div><div dir="ltr">  GMainLoop* loop = static_cast<GMainLoop*>(data);<br></div><div dir="ltr"><br></div><div dir="ltr">  switch (GST_MESSAGE_TYPE (msg)) {<br></div><div dir="ltr">    case GST_MESSAGE_EOS:<br></div><div dir="ltr">      g_print ("End-of-stream\n");<br></div><div dir="ltr">      g_main_loop_quit (loop);<br></div><div dir="ltr">      break;<br></div><div dir="ltr">    case GST_MESSAGE_ERROR: {<br></div><div dir="ltr">      gchar* debug = NULL;<br></div><div dir="ltr">      GError* err = NULL;<br></div><div dir="ltr"><br></div><div dir="ltr">      gst_message_parse_error (msg, &err, &debug);<br></div><div dir="ltr"><br></div><div dir="ltr">      g_print ("Error: %s\n", err->message);<br></div><div dir="ltr">      g_error_free (err);<br></div><div dir="ltr"><br></div><div dir="ltr">      if (debug != nullptr) {<br></div><div dir="ltr">        g_print ("Debug details: %s\n", debug);<br></div><div dir="ltr">        g_free (debug);<br></div><div dir="ltr">      }<br></div><div dir="ltr"><br></div><div dir="ltr">      g_main_loop_quit (loop);<br></div><div dir="ltr">      break;<br></div><div dir="ltr">    }<br></div><div dir="ltr">    default:<br></div><div dir="ltr">      break;<br></div><div dir="ltr">  }<br></div><div dir="ltr"><br></div><div dir="ltr">  return TRUE;<br></div><div dir="ltr">}<br></div><div dir="ltr"><br></div><div dir="ltr">void generateSin(<br></div><div dir="ltr">  Storage* storage,<br></div><div dir="ltr">  int16_t* buf,<br></div><div dir="ltr">  int frequency,<br></div><div dir="ltr">  guint sampleRate,<br></div><div dir="ltr">  guint numChannels,<br></div><div dir="ltr">  guint numFrames) {<br></div><div dir="ltr"><br></div><div dir="ltr">  float valuePi = std::numbers::pi_v<float>;<br></div><div dir="ltr"><br></div><div dir="ltr">  // Amplitude<br></div><div dir="ltr">  int A = 16383; // 32767;<br></div><div dir="ltr">  // Frequency<br></div><div dir="ltr">  float freq = 1.0f * frequency;<br></div><div dir="ltr"><br></div><div dir="ltr">  float rate = 1.0f * sampleRate;<br></div><div dir="ltr">  float delta = 2 * valuePi / (rate / freq);<br></div><div dir="ltr"><br></div><div dir="ltr">  for(guint i = 0; i < numFrames; i++) {<br></div><div dir="ltr">    float angle = storage->pos * delta;<br></div><div dir="ltr">    int16_t v = static_cast<int16_t>(A * std::sin(angle));<br></div><div dir="ltr"><br></div><div dir="ltr">    for(guint ch = 0; ch < numChannels; ch++) {<br></div><div dir="ltr">      *(buf + i * numChannels + ch) = v;<br></div><div dir="ltr">    }<br></div><div dir="ltr"><br></div><div dir="ltr">    storage->pos++;<br></div><div dir="ltr">    storage->pos %= 48000;<br></div><div dir="ltr">  }<br></div><div dir="ltr">}<br></div><div dir="ltr"><br></div><div dir="ltr">GstPadProbeReturn probe(<br></div><div dir="ltr">  GstPad* pad,<br></div><div dir="ltr">  GstPadProbeInfo* info,<br></div><div dir="ltr">  gpointer user_data) {<br></div><div dir="ltr"><br></div><div dir="ltr">  Storage* storage = static_cast<Storage*>(user_data);<br></div><div dir="ltr"><br></div><div dir="ltr">  GstBuffer* buffer = GST_PAD_PROBE_INFO_BUFFER(info);<br></div><div dir="ltr"><br></div><div dir="ltr">  GstBuffer* bufferOut = gst_buffer_copy(buffer);<br></div><div dir="ltr">  if (bufferOut == NULL) {<br></div><div dir="ltr">    return GST_PAD_PROBE_OK;<br></div><div dir="ltr">  }<br></div><div dir="ltr">  GST_PAD_PROBE_INFO_DATA(info) = bufferOut;<br></div><div dir="ltr">  gst_buffer_unref(buffer);<br></div><div dir="ltr"><br></div><div dir="ltr">  guint64 framesCountFromOffsets = 0;<br></div><div dir="ltr">  if(GST_BUFFER_OFFSET_IS_VALID(bufferOut)) {<br></div><div dir="ltr">    guint64 offset = GST_BUFFER_OFFSET(bufferOut);<br></div><div dir="ltr"><br></div><div dir="ltr">    if(GST_BUFFER_OFFSET_END_IS_VALID(bufferOut)) {<br></div><div dir="ltr">      guint64 offsetEnd = GST_BUFFER_OFFSET_END(bufferOut);<br></div><div dir="ltr">      framesCountFromOffsets = offsetEnd - offset;<br></div><div dir="ltr">    }<br></div><div dir="ltr">  }<br></div><div dir="ltr"><br></div><div dir="ltr">  GstMapInfo mapInfoOut;<br></div><div dir="ltr">  if (gst_buffer_map (bufferOut, &mapInfoOut, GST_MAP_WRITE)) {<br></div><div dir="ltr"><br></div><div dir="ltr">    // Check that we are use correct buffer parameters<br></div><div dir="ltr">    printf("Data size = %d byte(s), frames count = %" G_GUINT64_FORMAT "\n",<br></div><div dir="ltr">      mapInfoOut.size,<br></div><div dir="ltr">      framesCountFromOffsets);<br></div><div dir="ltr"><br></div><div dir="ltr">    auto audioBufferPtr = reinterpret_cast<int16_t*>(mapInfoOut.data);<br></div><div dir="ltr">    generateSin(storage, audioBufferPtr, 250, 48000, 1, mapInfoOut.size / 2);<br></div><div dir="ltr"><br></div><div dir="ltr">    gst_buffer_unmap (bufferOut, &mapInfoOut);<br></div><div dir="ltr">  } else {<br></div><div dir="ltr">    g_print("Unable to write to the output buffer!\n");<br></div><div dir="ltr">  }<br></div><div dir="ltr"><br></div><div dir="ltr">  return GST_PAD_PROBE_OK;<br></div><div dir="ltr">}<br></div><div dir="ltr"><br></div><div dir="ltr">int pipelineCreate(Storage* storage,<br></div><div dir="ltr">  std::string const& outputHost,<br></div><div dir="ltr">  uint16_t outputPort,<br></div><div dir="ltr">  int argc,<br></div><div dir="ltr">  char* argv[]) {<br></div><div dir="ltr"><br></div><div dir="ltr">  gst_init (&argc, &argv);<br></div><div dir="ltr"><br></div><div dir="ltr">  storage->loop = g_main_loop_new(NULL, FALSE);<br></div><div dir="ltr"><br></div><div dir="ltr">  storage->pipeline = gst_pipeline_new("pipeline_test");<br></div><div dir="ltr"><br></div><div dir="ltr">  // Watch for messages on the pipeline's bus,<br></div><div dir="ltr">  //   Note: it will work like this only when a GLib main loop is running.<br></div><div dir="ltr">  storage->bus = gst_pipeline_get_bus(GST_PIPELINE (storage->pipeline));<br></div><div dir="ltr">  storage->idWatch = gst_bus_add_watch(storage->bus, callbackBus,<br></div><div dir="ltr">storage->loop);<br></div><div dir="ltr"><br></div><div dir="ltr">  storage->src1 = gst_element_factory_make("audiotestsrc", "audiotestsrc1");<br></div><div dir="ltr">  storage->convert1 = gst_element_factory_make ("audioconvert",<br></div><div dir="ltr">"audioconvert1");<br></div><div dir="ltr">  storage->resample1 = gst_element_factory_make ("audioresample",<br></div><div dir="ltr">"audioresample1");<br></div><div dir="ltr"><br></div><div dir="ltr">  storage->capsfilter1 = gst_element_factory_make("capsfilter", "capsfilter1");<br></div><div dir="ltr">  GstCaps* caps = gst_caps_new_simple(<br></div><div dir="ltr">    "audio/x-raw",<br></div><div dir="ltr">    "format", G_TYPE_STRING, "S16LE",<br></div><div dir="ltr">    "rate", G_TYPE_INT, 48000,<br></div><div dir="ltr">    NULL);<br></div><div dir="ltr">  g_object_set(storage->capsfilter1, "caps", caps, NULL);<br></div><div dir="ltr">  gst_caps_unref(caps);<br></div><div dir="ltr"><br></div><div dir="ltr">  auto padSrcOfCapsFilter1 =<br></div><div dir="ltr">gst_element_get_static_pad(storage->capsfilter1, "src");<br></div><div dir="ltr">  if(padSrcOfCapsFilter1 == nullptr) {<br></div><div dir="ltr">    g_print("Failed to get an 'src' pad of the capsfilter1 element!\n");<br></div><div dir="ltr">    return -1;<br></div><div dir="ltr">  }<br></div><div dir="ltr">  storage->idProbe = gst_pad_add_probe(<br></div><div dir="ltr">    padSrcOfCapsFilter1,<br></div><div dir="ltr">    GST_PAD_PROBE_TYPE_BUFFER,<br></div><div dir="ltr">    static_cast<GstPadProbeCallback>(probe),<br></div><div dir="ltr">    static_cast<gpointer>(storage),<br></div><div dir="ltr">    NULL);<br></div><div dir="ltr">  gst_object_unref(padSrcOfCapsFilter1);<br></div><div dir="ltr"><br></div><div dir="ltr">  storage->opusenc1 = gst_element_factory_make("opusenc", "opusenc1");<br></div><div dir="ltr"><br></div><div dir="ltr">  storage->rtpopuspay1 = gst_element_factory_make("rtpopuspay", "rtpopuspay1");<br></div><div dir="ltr">  g_object_set(storage->rtpopuspay1,<br></div><div dir="ltr">    "pt", 96,<br></div><div dir="ltr">    NULL);<br></div><div dir="ltr"><br></div><div dir="ltr">  storage->udpsink1 = gst_element_factory_make("udpsink", "udpsink1");<br></div><div dir="ltr">  std::string addr = outputHost + ":" + std::to_string(outputPort);<br></div><div dir="ltr">  g_object_set(storage->udpsink1,<br></div><div dir="ltr">    "clients", addr.c_str(),<br></div><div dir="ltr">    "async", false,<br></div><div dir="ltr">    NULL);<br></div><div dir="ltr"><br></div><div dir="ltr">  gst_bin_add_many(GST_BIN(storage->pipeline),<br></div><div dir="ltr">    storage->src1,<br></div><div dir="ltr">    storage->convert1,<br></div><div dir="ltr">    storage->resample1,<br></div><div dir="ltr">    storage->capsfilter1,<br></div><div dir="ltr">    storage->opusenc1,<br></div><div dir="ltr">    storage->rtpopuspay1,<br></div><div dir="ltr">    storage->udpsink1,<br></div><div dir="ltr">    NULL);<br></div><div dir="ltr"><br></div><div dir="ltr">  // Link everything together<br></div><div dir="ltr">  if (!gst_element_link_many(<br></div><div dir="ltr">    storage->src1,<br></div><div dir="ltr">    storage->convert1,<br></div><div dir="ltr">    storage->resample1,<br></div><div dir="ltr">    storage->capsfilter1,<br></div><div dir="ltr">    storage->opusenc1,<br></div><div dir="ltr">    storage->rtpopuspay1,<br></div><div dir="ltr">    storage->udpsink1,<br></div><div dir="ltr">    NULL)) {<br></div><div dir="ltr"><br></div><div dir="ltr">    g_print("Failed to link one or more elements!\n");<br></div><div dir="ltr">    return -1;<br></div><div dir="ltr">  }<br></div><div dir="ltr"><br></div><div dir="ltr">  return 0;<br></div><div dir="ltr">}<br></div><div dir="ltr"><br></div><div dir="ltr">int pipelinePlay(Storage& storage) {<br></div><div dir="ltr">  GstStateChangeReturn ret = gst_element_set_state(storage.pipeline,<br></div><div dir="ltr">GST_STATE_PLAYING);<br></div><div dir="ltr">  if (ret == GST_STATE_CHANGE_FAILURE) {<br></div><div dir="ltr">    g_print("Failed to start up pipeline!\n");<br></div><div dir="ltr"><br></div><div dir="ltr">    // Check if there is an error message with details on the bus<br></div><div dir="ltr">    GstMessage* msg = gst_bus_poll(storage.bus, GST_MESSAGE_ERROR, 0);<br></div><div dir="ltr">    if (msg) {<br></div><div dir="ltr">      GError* err = NULL;<br></div><div dir="ltr"><br></div><div dir="ltr">      gst_message_parse_error(msg, &err, NULL);<br></div><div dir="ltr">      g_print("ERROR: %s\n", err->message);<br></div><div dir="ltr">      g_error_free(err);<br></div><div dir="ltr">      gst_message_unref(msg);<br></div><div dir="ltr">    }<br></div><div dir="ltr">    return -1;<br></div><div dir="ltr">  }<br></div><div dir="ltr"><br></div><div dir="ltr">  g_print("Playing...\n");<br></div><div dir="ltr"><br></div><div dir="ltr">  g_main_loop_run(storage.loop);<br></div><div dir="ltr"><br></div><div dir="ltr">  return 0;<br></div><div dir="ltr">}<br></div><div dir="ltr"><br></div><div dir="ltr">int pipelineDestroy(Storage& storage) {<br></div><div dir="ltr">  // Cleanup all<br></div><div dir="ltr">  gst_element_set_state(storage.pipeline, GST_STATE_NULL);<br></div><div dir="ltr">  gst_object_unref(storage.bus);<br></div><div dir="ltr">  gst_object_unref(storage.pipeline);<br></div><div dir="ltr">  g_source_remove(storage.idWatch);<br></div><div dir="ltr"><br></div><div dir="ltr">  g_main_loop_unref(storage.loop);<br></div><div dir="ltr"><br></div><div dir="ltr">  return 0;<br></div><div dir="ltr">}<br></div><div dir="ltr"><br></div><div dir="ltr">int main(int argc, char* argv[]) {<br></div><div dir="ltr">  Storage storage;<br></div><div dir="ltr">  storage.pos = 0;<br></div><div dir="ltr"><br></div><div dir="ltr">  std::string outputHost = "host.docker.internal";<br></div><div dir="ltr">  uint16_t outputPort = 50111;<br></div><div dir="ltr"><br></div><div dir="ltr">  int res = pipelineCreate(&storage, outputHost, outputPort, argc, argv);<br></div><div dir="ltr">  if(res != 0) {<br></div><div dir="ltr">    return res;<br></div><div dir="ltr">  }<br></div><div dir="ltr"><br></div><div dir="ltr">  res = pipelinePlay(storage);<br></div><div dir="ltr">  if(res != 0) {<br></div><div dir="ltr">    return res;<br></div><div dir="ltr">  }<br></div><div dir="ltr"><br></div><div dir="ltr">  res = pipelineDestroy(storage);<br></div><div dir="ltr">  if(res != 0) {<br></div><div dir="ltr">    return res;<br></div><div dir="ltr">  }<br></div><div dir="ltr"><br></div><div dir="ltr">  return res;<br></div><div dir="ltr">}<br></div></div>
            </div>
        </div></body></html>