Заставить буферы gstreamer appsink хранить только 10 мс данных

У меня есть конвейер gstreamer, который сбрасывает все свои данные в appsink:

command = g_strdup_printf ("autoaudiosrc ! audio/x-raw-int, signed=true, endianness=1234, depth=%d, width=%d, channels=%d, rate=%d !"
                " appsink name=soundSink max_buffers=2 drop=true ",
                  bitDepthIn, bitDepthIn, channelsIn, sampleRateIn);

Что обычно выглядит примерно так,

autoaudiosrc ! audio/x-raw-int, signed=true, endianness=1234, depth=16, width=16, channels=1, rate=16000 ! appsink name=soundSink max_buffers=2 drop=true

во время выполнения.

Он отлично записывает звук, проблема в том, что он имеет тенденцию захватывать любой произвольный объем данных, который он хочет, вместо заданного размера или временного интервала. Так, например, библиотека rtp, которая запрашивает данные, будет запрашивать только 960 байт (10 мс 48 кГц/1 1 канал/16 бит), но буферы будут иметь длину от 10 мс до 26 мс. Очень важно, чтобы этот конвейер возвращал только 10 мс на каждый буфер. Есть ли способ сделать это? Вот код, который захватывает данные.

void GSTMediaStream::GetAudioInputData(void* data, int max_size, int& written)
{
   if (soundAppSink != NULL) 
   {
         GstBuffer* buffer = gst_app_sink_pull_buffer (GST_APP_SINK (soundAppSink));
         if (buffer) 
         {
               uint bufSize = MIN (GST_BUFFER_SIZE (buffer), max_size);
               uint offset = 0;

               std::cout << "buffer time length is " << GST_BUFFER_DURATION(buffer) << "ns buffer size is " <<  GST_BUFFER_SIZE (buffer)
                       << " while max size is " << max_size << "\n";
               //if max_size is smaller than the buffer, then only grab the last 10ms captured.
               //I am assuming that the reason for the occasional difference is because the buffers are larger
               //in the amount of audio frames than the rtp stream wants.
               if(bufSize > 0)
                 uint offset = GST_BUFFER_SIZE (buffer)- bufSize;

               memcpy (data, buffer->data + offset, bufSize);
               written = bufSize;
               gst_buffer_unref(buffer);
             }
     }
}

Обновить Итак, я сузил проблему до подключаемого модуля пульсового звука для gstreamer. Autoaudiosrc использует плагин pulsesrc для захвата, и по какой-то причине сервер pulse замедляется после нескольких передискретизаций. Я тестировал с помощью alasrc, и, кажется, он обрабатывает изменения частоты дискретизации, сохраняя при этом буферы 10 мс, но проблема в том, что он не позволяет мне записывать звук в моно: только в стерео.


person Jonathan Henson    schedule 16.08.2011    source источник


Ответы (1)


Я избавился от autoaudiosrc и вместо этого подключил alasrc. Плагин pulsesrc был тем, что вызывало неустойчивое поведение блокировки при извлечении буфера, что давало мне разную длину буфера. Единственная проблема заключалась в том, что alsasrc не мог записывать в моно. Я исправил это, добавив в конвейер элемент audioconvert. Моя последняя трубка была:

alsasrc ! audioconvert ! audio/x-raw-int, signed=true, endianness=1234, depth=16, width=16, channels=1, rate=16000 ! appsink name=soundSink max_buffers=2 drop=true

Это дало мне необходимую длину буфера. Однако вызовет ли это какие-либо серьезные проблемы с производительностью, поскольку это будет на встроенном устройстве?

person Jonathan Henson    schedule 16.08.2011