X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fmodules%2Frtaudio%2Fconsumer_rtaudio.cpp;h=8b6e599e0cd60bf897666d243431480eaabbcd05;hb=6453d1c04f43c722559ceff2293a24b281ff3262;hp=de786450d98d1a1ed75d66c2080c6ca3700dd194;hpb=9e3b7c1e4c79f0488b0fe8d236139f63ca9006fc;p=mlt diff --git a/src/modules/rtaudio/consumer_rtaudio.cpp b/src/modules/rtaudio/consumer_rtaudio.cpp index de786450..8b6e599e 100644 --- a/src/modules/rtaudio/consumer_rtaudio.cpp +++ b/src/modules/rtaudio/consumer_rtaudio.cpp @@ -50,18 +50,23 @@ public: pthread_cond_t refresh_cond; pthread_mutex_t refresh_mutex; int refresh_count; + bool is_purge; mlt_consumer getConsumer() { return &consumer; } RtAudioConsumer() : device_id(-1) + , queue(NULL) , joined(0) , running(0) , audio_avail(0) , playing(0) , refresh_count(0) - {} + , is_purge(false) + { + memset( &consumer, 0, sizeof( consumer ) ); + } ~RtAudioConsumer() { @@ -88,13 +93,10 @@ public: return false; } - if ( !arg || !strcmp( arg, "" ) ) - { #ifndef __LINUX_ALSA__ - device_id = rt.getDefaultOutputDevice(); + device_id = rt.getDefaultOutputDevice(); #endif - } - else if ( strcmp( arg, "default" ) ) + if ( arg && strcmp( arg, "" ) && strcmp( arg, "default" ) ) { // Get device ID by name unsigned int n = rt.getDeviceCount(); @@ -112,7 +114,7 @@ public: break; } } - // Name selection failed, treat arg as numeric + // Name selection failed, try arg as numeric if ( i == n ) device_id = (int) strtol( arg, NULL, 0 ); } @@ -142,6 +144,9 @@ public: // Default audio buffer mlt_properties_set_int( properties, "audio_buffer", 1024 ); + // Set the resource to the device name arg + mlt_properties_set( properties, "resource", arg ); + // Ensure we don't join on a non-running object joined = 1; @@ -205,6 +210,24 @@ public: return 0; } + void purge() + { + if ( running ) + { + pthread_mutex_lock( &video_mutex ); + mlt_frame frame = MLT_FRAME( mlt_deque_peek_back( queue ) ); + // When playing rewind or fast forward then we need to keep one + // frame in the queue to prevent playback stalling. + double speed = frame? mlt_properties_get_double( MLT_FRAME_PROPERTIES(frame), "_speed" ) : 0; + int n = ( speed == 0.0 || speed == 1.0 ) ? 0 : 1; + while ( mlt_deque_count( queue ) > n ) + mlt_frame_close( MLT_FRAME( mlt_deque_pop_back( queue ) ) ); + is_purge = true; + pthread_cond_broadcast( &video_cond ); + pthread_mutex_unlock( &video_mutex ); + } + } + void consumer_thread() { // Get the properties @@ -222,7 +245,10 @@ public: int64_t playtime = 0; struct timespec tm = { 0, 100000 }; // int last_position = -1; + + pthread_mutex_lock( &refresh_mutex ); refresh_count = 0; + pthread_mutex_unlock( &refresh_mutex ); // Loop until told not to while ( running ) @@ -270,8 +296,16 @@ public: if ( running && speed ) { pthread_mutex_lock( &video_mutex ); - mlt_deque_push_back( queue, frame ); - pthread_cond_broadcast( &video_cond ); + if ( is_purge && speed == 1.0 ) + { + mlt_frame_close( frame ); + is_purge = false; + } + else + { + mlt_deque_push_back( queue, frame ); + pthread_cond_broadcast( &video_cond ); + } pthread_mutex_unlock( &video_mutex ); // Calculate the next playtime @@ -389,6 +423,7 @@ public: // Set the preferred params of the test card signal int channels = mlt_properties_get_int( properties, "channels" ); int frequency = mlt_properties_get_int( properties, "frequency" ); + int scrub = mlt_properties_get_int( properties, "scrub_audio" ); static int counter = 0; int samples = mlt_sample_calculator( mlt_properties_get_double( properties, "fps" ), frequency, counter++ ); int16_t *pcm; @@ -409,16 +444,20 @@ public: parameters.nChannels = channels; parameters.firstChannel = 0; RtAudio::StreamOptions options; -#ifdef __LINUX_ALSA__ + unsigned int bufferFrames = mlt_properties_get_int( properties, "audio_buffer" ); + if ( device_id == -1 ) { options.flags = RTAUDIO_ALSA_USE_DEFAULT; parameters.deviceId = 0; } -#endif - unsigned int bufferFrames = mlt_properties_get_int( properties, "audio_buffer" ); + if ( mlt_properties_get( properties, "resource" ) ) + parameters.deviceName = mlt_properties_get( properties, "resource" ); try { + if ( rt.isStreamOpen() ) { + rt.closeStream(); + } rt.openStream( ¶meters, NULL, RTAUDIO_SINT16, frequency, &bufferFrames, &rtaudio_callback, this, &options ); rt.startStream(); @@ -440,7 +479,7 @@ public: pthread_cond_wait( &audio_cond, &audio_mutex ); if ( running ) { - if ( mlt_properties_get_double( properties, "_speed" ) == 1 ) + if ( scrub || mlt_properties_get_double( properties, "_speed" ) == 1 ) memcpy( &audio_buffer[ audio_avail ], pcm, bytes ); else memset( &audio_buffer[ audio_avail ], 0, bytes ); @@ -611,6 +650,12 @@ static int is_stopped( mlt_consumer consumer ) return !rtaudio->running; } +static void purge( mlt_consumer consumer ) +{ + RtAudioConsumer* rtaudio = (RtAudioConsumer*) consumer->child; + rtaudio->purge(); +} + /** Close the consumer. */ @@ -639,7 +684,7 @@ mlt_consumer consumer_rtaudio_init( mlt_profile profile, mlt_service_type type, if ( rtaudio && !mlt_consumer_init( rtaudio->getConsumer(), rtaudio, profile ) ) { // If initialises without error - if ( rtaudio->open( arg ) ) + if ( rtaudio->open( arg? arg : getenv( "AUDIODEV" ) ) ) { // Setup callbacks consumer = rtaudio->getConsumer(); @@ -647,6 +692,7 @@ mlt_consumer consumer_rtaudio_init( mlt_profile profile, mlt_service_type type, consumer->start = start; consumer->stop = stop; consumer->is_stopped = is_stopped; + consumer->purge = purge; } else {