Skip to content

Commit 54ea50d

Browse files
committed
incorporated some of sdroege's comments
1 parent 59bd834 commit 54ea50d

File tree

2 files changed

+45
-28
lines changed

2 files changed

+45
-28
lines changed

audiostream/src/ni/media/audio/source/gstreamer_file_source.cpp

Lines changed: 37 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
#include <boost/make_unique.hpp>
2929

3030
#include <algorithm>
31-
#include <gst/app/gstappsink.h>
3231

3332
namespace detail
3433
{
@@ -37,9 +36,9 @@ struct RingBuffer
3736
{
3837
static constexpr size_t size = s;
3938
static constexpr size_t mask = ( s - 1 );
40-
std::array<T, s> m_buffer;
41-
uint64_t m_write_head = 0;
42-
uint64_t m_read_head = 0;
39+
std::array<T, s> m_buffer;
40+
uint64_t m_write_head = 0;
41+
uint64_t m_read_head = 0;
4342

4443
void push( const T* data, size_t count )
4544
{
@@ -86,6 +85,7 @@ gstreamer_file_source::gstreamer_file_source( const std::string&
8685
audio::ifstream_info::container_type container,
8786
size_t stream )
8887
: m_pipeline( nullptr, gst_object_unref )
88+
, m_sink( nullptr, gst_object_unref )
8989
, m_ring_buffer( new RingBuffer() )
9090
{
9191
init_gstreamer();
@@ -133,10 +133,10 @@ void gstreamer_file_source::init_gstreamer()
133133

134134
void gstreamer_file_source::setup_source( const std::string& path, audio::ifstream_info::container_type container )
135135
{
136-
GstElement* sink = prepare_pipeline( path );
137-
auto sinkpad = gst_element_get_static_pad( sink, "sink" );
138-
auto caps = gst_pad_get_current_caps( sinkpad );
139-
auto caps_struct = gst_caps_get_structure( caps, 0 );
136+
m_sink.reset( prepare_pipeline( path ) );
137+
auto sinkpad = gst_element_get_static_pad( m_sink.get(), "sink" );
138+
auto caps = gst_pad_get_current_caps( sinkpad );
139+
auto caps_struct = gst_caps_get_structure( caps, 0 );
140140
fill_format_info( caps_struct, container );
141141
}
142142

@@ -151,11 +151,12 @@ GstElement* gstreamer_file_source::prepare_pipeline( const std::string& path )
151151
GstElement* queue = gst_element_factory_make( "queue", "queue" );
152152
GstElement* sink = gst_element_factory_make( "appsink", "sink" );
153153

154-
gst_bin_add_many( GST_BIN( m_pipeline.get() ), source, decodebin, queue, sink, nullptr );
154+
gst_bin_add_many( GST_BIN( m_pipeline.get() ), source, decodebin, queue, gst_object_ref( sink ), nullptr );
155155
gst_element_link_many( source, decodebin, NULL );
156156
gst_element_link_many( queue, sink, NULL );
157157

158158
g_object_set( source, "location", path.c_str(), NULL );
159+
g_object_set( sink, "sync", FALSE, NULL );
159160

160161
g_signal_connect( decodebin, "pad-added", G_CALLBACK( &onPadAdded ), queue );
161162

@@ -187,18 +188,19 @@ void gstreamer_file_source::fill_format_info( GstStructure*
187188
m_info.codec( audio::ifstream_info::codec_type::mp3 );
188189
m_info.lossless( false );
189190

190-
gint64 num_frames = 0;
191-
if ( !gst_element_query_duration( m_pipeline.get(), GST_FORMAT_DEFAULT, &num_frames ) )
192-
throw std::runtime_error( "gstreamer_file_source: could not query duration from gstreamer" );
193-
194-
m_info.num_frames( num_frames );
195-
196191
int sample_rate = 0;
197192
if ( !gst_structure_get_int( caps_struct, "rate", &sample_rate ) )
198193
throw std::runtime_error( "gstreamer_file_source: could not query sample rate from gstreamer" );
199194

200195
m_info.sample_rate( sample_rate );
201196

197+
gint64 num_ns = 0;
198+
if ( !gst_element_query_duration( m_pipeline.get(), GST_FORMAT_TIME, &num_ns ) )
199+
throw std::runtime_error( "gstreamer_file_source: could not query duration from gstreamer" );
200+
201+
gint64 num_frames = sample_rate * num_ns / GST_SECOND;
202+
m_info.num_frames( num_frames );
203+
202204
int num_channels = 0;
203205
if ( !gst_structure_get_int( caps_struct, "channels", &num_channels ) )
204206
throw std::runtime_error( "gstreamer_file_source: could not query number of channels from gstreamer" );
@@ -239,7 +241,21 @@ pcm::number_type gstreamer_file_source::gst_format_char_to_number_type( const gc
239241
void gstreamer_file_source::onPadAdded( GstElement* element, GstPad* pad, GstElement* sink )
240242
{
241243
tGstPtr<GstPad> sinkpad( gst_element_get_static_pad( sink, "sink" ), gst_object_unref );
242-
gst_pad_link( pad, sinkpad.get() );
244+
245+
if ( gst_pad_is_linked( sinkpad.get() ) )
246+
return; // already linked
247+
248+
tGstPtr<GstCaps> caps( gst_pad_get_current_caps( pad ), gst_object_unref );
249+
auto s = gst_caps_get_structure( caps.get(), 0 );
250+
auto name = gst_structure_get_name( s );
251+
252+
if ( !g_str_has_prefix( name, "audio/" ) )
253+
return; // not the kind of pad we are looking for, maybe video?
254+
255+
auto result = gst_pad_link( pad, sinkpad.get() );
256+
257+
if ( result != GST_PAD_LINK_OK )
258+
throw std::runtime_error( "gstreamer_file_source: could not link pad" );
243259
}
244260

245261
//----------------------------------------------------------------------------------------------------------------------
@@ -305,14 +321,13 @@ std::streamsize gstreamer_file_source::recursive_read( char* dst, std::streamsiz
305321

306322
if ( numBytesRequested )
307323
{
308-
tGstPtr<GstElement> sink( gst_bin_get_by_name( GST_BIN( m_pipeline.get() ), "sink" ), gst_object_unref );
309-
GstAppSink* app_sink = reinterpret_cast<GstAppSink*>( sink.get() );
310-
311-
tGstPtr<GstSample> sample( gst_app_sink_pull_sample( app_sink ), (GUnref) gst_sample_unref );
324+
GstSample* samplePtr = nullptr;
325+
g_signal_emit_by_name( m_sink.get(), "try-pull-sample", &samplePtr, nullptr );
312326

313-
if ( sample )
327+
if ( samplePtr )
314328
{
315-
auto buffer = gst_sample_get_buffer( sample.get() );
329+
tGstPtr<GstSample> sample( samplePtr, (GUnref) gst_sample_unref );
330+
auto buffer = gst_sample_get_buffer( sample.get() );
316331

317332
GstMapInfo mapped;
318333

audiostream/src/ni/media/audio/source/gstreamer_file_source.h

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -59,13 +59,13 @@ class gstreamer_file_source
5959
private:
6060
static void init_gstreamer();
6161
static pcm::runtime_format create_runtime_format( GstStructure* caps_struct );
62-
static pcm::number_type gst_format_char_to_number_type( const gchar format );
62+
static pcm::number_type gst_format_char_to_number_type( const gchar format );
6363

64-
void setup_source( const std::string& path, audio::ifstream_info::container_type container );
65-
GstElement* prepare_pipeline( const std::string& path );
66-
void preroll_pipeline();
67-
GstState wait_for_async_operation();
68-
void fill_format_info( GstStructure* caps_struct, audio::ifstream_info::container_type container );
64+
void setup_source( const std::string& path, audio::ifstream_info::container_type container );
65+
GstElement* prepare_pipeline( const std::string& path );
66+
void preroll_pipeline();
67+
GstState wait_for_async_operation();
68+
void fill_format_info( GstStructure* caps_struct, audio::ifstream_info::container_type container );
6969
std::streamsize recursive_read( char* dst, std::streamsize numBytesRequested );
7070

7171
static void onPadAdded( GstElement* element, GstPad* pad, GstElement* sink );
@@ -74,7 +74,9 @@ class gstreamer_file_source
7474
using GUnref = void ( * )( gpointer );
7575
template <typename T>
7676
using tGstPtr = std::unique_ptr<T, GUnref>;
77+
7778
tGstPtr<GstElement> m_pipeline;
79+
tGstPtr<GstElement> m_sink;
7880

7981
using RingBuffer = detail::RingBuffer<char, 65536>;
8082
std::unique_ptr<RingBuffer> m_ring_buffer;

0 commit comments

Comments
 (0)