Feature add linux gstreamer support#11
Feature add linux gstreamer support#11hhoegelo wants to merge 31 commits intoNativeInstruments:masterfrom
Conversation
… library this is the initial revision, tests are not yet green, to be continued
|
Hey Henry! That's great! Thanks a lot for the contribution. I will look at it as soon as possible. In the mean time could you please update the travis-ci to retrieve the gstreamer package so that the linux build passes? Thanks, |
audiostream/CMakeLists.txt
Outdated
|
|
||
| set( COMPILE_WITH_COREAUDIO DONT_COMPILE) | ||
| set( COMPILE_WITH_MEDIA_FOUNDATION DONT_COMPILE) | ||
| set( COMPILE_WITH_GSTREAMER DONT_COMPILE) |
There was a problem hiding this comment.
pedantic: align DONT_COMPILE with above statements
audiostream/CMakeLists.txt
Outdated
| add_src_file (FILES_media_audio_source "src/ni/media/audio/source/core_audio_file_source.cpp" ${COMPILE_WITH_COREAUDIO} WITH_HEADER ) | ||
| add_src_file (FILES_media_audio_source "src/ni/media/audio/source/media_foundation_helper.h" ${COMPILE_WITH_MEDIA_FOUNDATION} ) | ||
| add_src_file (FILES_media_audio_source "src/ni/media/audio/source/media_foundation_file_source.cpp" ${COMPILE_WITH_MEDIA_FOUNDATION} WITH_HEADER ) | ||
| add_src_file (FILES_media_audio_source "src/ni/media/audio/source/gstreamer_file_source.cpp" ${COMPILE_WITH_GSTREAMER} WITH_HEADER ) |
cmake/FindGStreamer.cmake
Outdated
|
|
||
|
|
||
| if( GSTREAMER_FOUND ) | ||
| if( NOT TARGET GSTREAMER::gstreamer ) |
cmake/FindGStreamerApp.cmake
Outdated
|
|
||
|
|
||
| if( GSTREAMERAPP_FOUND ) | ||
| if( NOT TARGET GSTREAMERAPP::gstreamerapp ) |
|
|
||
| if ( numBytesRequested ) | ||
| { | ||
| tGstPtr<GstElement> sink( gst_bin_get_by_name( GST_BIN( m_pipeline.get() ), "sink" ), gst_object_unref ); |
There was a problem hiding this comment.
It would be better to store the sink pointer somewhere instead of retrieving it all the time
| { | ||
| pcm::number_type number_type = gst_format_char_to_number_type( format[0] ); | ||
| auto srcDepth = std::atol( format + 1 ); | ||
| auto endian = ( strcmp( format, "BE" ) == 0 ) ? pcm::big_endian : pcm::little_endian; |
There was a problem hiding this comment.
You probably want to use GstAudioInfo here and in the function above. it gives you a simple C struct with all these information you want to extract from the caps. Also check the GstAudioFormatInfo that is part of the GstAudioInfo.
| if ( wait_for_async_operation() != GST_STATE_PAUSED ) | ||
| throw std::runtime_error( "gstreamer_file_source: pipeline doesn't preroll into paused state" ); | ||
|
|
||
| gst_element_set_state( m_pipeline.get(), GST_STATE_PLAYING ); |
|
|
||
| void gstreamer_file_source::preroll_pipeline() | ||
| { | ||
| gst_element_set_state( m_pipeline.get(), GST_STATE_PAUSED ); |
|
|
||
| gst_bin_add_many( GST_BIN( m_pipeline.get() ), source, decodebin, queue, sink, nullptr ); | ||
| gst_element_link_many( source, decodebin, NULL ); | ||
| gst_element_link_many( queue, sink, NULL ); |
There was a problem hiding this comment.
best to check return values, things can fail
| auto sinkpad = gst_element_get_static_pad( sink, "sink" ); | ||
| auto caps = gst_pad_get_current_caps( sinkpad ); | ||
| auto caps_struct = gst_caps_get_structure( caps, 0 ); | ||
| fill_format_info( caps_struct, container ); |
There was a problem hiding this comment.
You're leaking the caps and sinkpad here.
| gstreamer_file_source::~gstreamer_file_source() | ||
| { | ||
| gst_element_set_state( m_pipeline.get(), GST_STATE_NULL ); | ||
| wait_for_async_operation(); |
|
@hhoegelo Can you explain the easiest way to reproduce the 1-sample-off problem and what information you gathered so far? If I understand correctly, this happens on specific files (WMA? Or everything? All WMA files or a specific one?) and if you decode from the beginning vs. you seek to a position, you would end up one sample off? Is it always absolutely one sample, or would it sometimes be more or less, or would every seek make it one more sample off? Re main loop: this is not required, correct. You have multiple options, but first of all: why do you care? You want to block until error or reading samples is possible? And then blocking-read the samples?
From what I saw in the code so far I would suggest a combination of 1) and 3). You block until error or the sink is ready (you received the |
|
Sorry if some comments appeared twice, GitHub had some kind of hickup while I was doing the review and returned a few server errors |
|
thanks for the thorough look @sdroege really appreciate seeing this level of collab |
… library this is the initial revision, tests are not yet green, to be continued
1c58318 to
54ea50d
Compare
| gst_element_set_state( m_pipeline.get(), GST_STATE_PAUSED ); | ||
|
|
||
| if ( wait_for_async_operation() != GST_STATE_PAUSED ) | ||
| throw std::runtime_error( "gstreamer_file_source: pipeline doesn't preroll into paused state" ); |
There was a problem hiding this comment.
This line randomly throws. There seems to be a race condition when setting / checking the state
|
@hhoegelo can you please pull in my branch https://github.com/marcrambo/ni-media/tree/feature-add-linux-gstreamer-support? I reenabled the tests and commited a fix for all the tests failing due to an exception thrown while retrieving the track length. Also I improved the logging so we have a better overview of which tests are still failing. |
|
@sdroege Thanks a lot for your help which is really greatly appreciated! I was wondering if it was possible to run gstreamer in "synchronous" mode i.e. without having to do "preroll pipeline" and so on. Calls to |
@marcrambo That's exactly how it would behave with my suggestion (1 + 3) from comment #11 (comment) While GStreamer is always async to some degree, there is API that makes it easy enough to build a sync API on top |
If you like, you can pull my attempt of adding mp3, m4a, alac and wma support on linux platform by using gstreamer framework. I didn't manage to have all tests green, though. For example, the 'interlaced_by_67_frames'-tests are off by 1 sample, which I - so far - couldn't find a reason for.
Most likely other people won't notice my fork. I hope, if you pull it into the base fork, we have a higher chance that anyone can help fixing.