]> git.sesse.net Git - mlt/blob - src/modules/jackrack/consumer_jack.c
Add service metadata for jack consumer.
[mlt] / src / modules / jackrack / consumer_jack.c
1 /*
2  * consumer_jack.c -- a JACK audio consumer
3  * Copyright (C) 2011 Dan Dennedy <dan@dennedy.org>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software Foundation,
17  * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18  */
19
20 #include <framework/mlt.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <pthread.h>
25 #include <sys/time.h>
26 #include <unistd.h>
27 #include <jack/jack.h>
28 #include <jack/ringbuffer.h>
29
30 #define BUFFER_LEN (204800 * 6)
31
32 /** This classes definition.
33 */
34
35 typedef struct consumer_jack_s *consumer_jack;
36
37 struct consumer_jack_s
38 {
39         struct mlt_consumer_s parent;
40         jack_client_t *jack;
41         mlt_deque queue;
42         pthread_t thread;
43         int joined;
44         int running;
45         pthread_mutex_t video_mutex;
46         pthread_cond_t video_cond;
47         int playing;
48
49         pthread_cond_t refresh_cond;
50         pthread_mutex_t refresh_mutex;
51         int refresh_count;
52         int counter;
53         jack_ringbuffer_t **ringbuffers;
54         jack_port_t **ports;
55 };
56
57 /** Forward references to static functions.
58 */
59
60 static int consumer_start( mlt_consumer parent );
61 static int consumer_stop( mlt_consumer parent );
62 static int consumer_is_stopped( mlt_consumer parent );
63 static void consumer_close( mlt_consumer parent );
64 static void *consumer_thread( void * );
65 static void consumer_refresh_cb( mlt_consumer sdl, mlt_consumer parent, char *name );
66 static int jack_process( jack_nframes_t frames, void * data );
67
68 /** Constructor
69 */
70
71 mlt_consumer consumer_jack_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
72 {
73         // Create the consumer object
74         consumer_jack self = calloc( 1, sizeof( struct consumer_jack_s ) );
75
76         // If no malloc'd and consumer init ok
77         if ( self != NULL && mlt_consumer_init( &self->parent, self, profile ) == 0 )
78         {
79                 char name[14];
80
81                 snprintf( name, sizeof( name ), "mlt%d", getpid() );
82                 if (( self->jack = jack_client_open( name, JackNullOption, NULL ) ))
83                 {
84                         jack_set_process_callback( self->jack, jack_process, self );
85
86                         // Create the queue
87                         self->queue = mlt_deque_init( );
88
89                         // Get the parent consumer object
90                         mlt_consumer parent = &self->parent;
91
92                         // We have stuff to clean up, so override the close method
93                         parent->close = consumer_close;
94
95                         // get a handle on properties
96                         mlt_service service = MLT_CONSUMER_SERVICE( parent );
97                         mlt_properties properties = MLT_SERVICE_PROPERTIES( service );
98
99                         // This is the initialisation of the consumer
100                         pthread_mutex_init( &self->video_mutex, NULL );
101                         pthread_cond_init( &self->video_cond, NULL);
102
103                         // Default scaler (for now we'll use nearest)
104                         mlt_properties_set( properties, "rescale", "nearest" );
105                         mlt_properties_set( properties, "deinterlace_method", "onefield" );
106
107                         // Default buffer for low latency
108                         mlt_properties_set_int( properties, "buffer", 1 );
109
110                         // Set frequency from JACK
111                         mlt_properties_set_int( properties, "frequency", (int) jack_get_sample_rate( self->jack ) );
112
113                         // Set default volume
114                         mlt_properties_set_double( properties, "volume", 1.0 );
115
116                         // Ensure we don't join on a non-running object
117                         self->joined = 1;
118
119                         // Allow thread to be started/stopped
120                         parent->start = consumer_start;
121                         parent->stop = consumer_stop;
122                         parent->is_stopped = consumer_is_stopped;
123
124                         // Initialize the refresh handler
125                         pthread_cond_init( &self->refresh_cond, NULL );
126                         pthread_mutex_init( &self->refresh_mutex, NULL );
127                         mlt_events_listen( MLT_CONSUMER_PROPERTIES( parent ), self, "property-changed", ( mlt_listener )consumer_refresh_cb );
128
129                         // Return the consumer produced
130                         return parent;
131                 }
132         }
133
134         // malloc or consumer init failed
135         free( self );
136
137         // Indicate failure
138         return NULL;
139 }
140
141 static void consumer_refresh_cb( mlt_consumer sdl, mlt_consumer parent, char *name )
142 {
143         if ( !strcmp( name, "refresh" ) )
144         {
145                 consumer_jack self = parent->child;
146                 pthread_mutex_lock( &self->refresh_mutex );
147                 self->refresh_count = self->refresh_count <= 0 ? 1 : self->refresh_count + 1;
148                 pthread_cond_broadcast( &self->refresh_cond );
149                 pthread_mutex_unlock( &self->refresh_mutex );
150         }
151 }
152
153 static int consumer_start( mlt_consumer parent )
154 {
155         consumer_jack self = parent->child;
156
157         if ( !self->running )
158         {
159                 consumer_stop( parent );
160                 self->running = 1;
161                 self->joined = 0;
162                 pthread_create( &self->thread, NULL, consumer_thread, self );
163         }
164
165         return 0;
166 }
167
168 static int consumer_stop( mlt_consumer parent )
169 {
170         // Get the actual object
171         consumer_jack self = parent->child;
172
173         if ( self->running && !self->joined )
174         {
175                 // Kill the thread and clean up
176                 self->joined = 1;
177                 self->running = 0;
178
179                 // Unlatch the consumer thread
180                 pthread_mutex_lock( &self->refresh_mutex );
181                 pthread_cond_broadcast( &self->refresh_cond );
182                 pthread_mutex_unlock( &self->refresh_mutex );
183
184                 // Cleanup the main thread
185 #ifndef WIN32
186                 if ( self->thread )
187 #endif
188                         pthread_join( self->thread, NULL );
189
190                 // Unlatch the video thread
191                 pthread_mutex_lock( &self->video_mutex );
192                 pthread_cond_broadcast( &self->video_cond );
193                 pthread_mutex_unlock( &self->video_mutex );
194
195                 // Cleanup JACK
196                 if ( self->playing )
197                         jack_deactivate( self->jack );
198                 if ( self->ringbuffers )
199                 {
200                         int n = mlt_properties_get_int( MLT_CONSUMER_PROPERTIES( parent ), "channels" );
201                         while ( n-- )
202                         {
203                                 jack_ringbuffer_free( self->ringbuffers[n] );
204                                 jack_port_unregister( self->jack, self->ports[n] );
205                         }
206                         mlt_pool_release( self->ringbuffers );
207                 }
208                 self->ringbuffers = NULL;
209                 if ( self->ports )
210                         mlt_pool_release( self->ports );
211                 self->ports = NULL;
212         }
213
214         return 0;
215 }
216
217 static int consumer_is_stopped( mlt_consumer parent )
218 {
219         consumer_jack self = parent->child;
220         return !self->running;
221 }
222
223 static int jack_process( jack_nframes_t frames, void * data )
224 {
225         int error = 0;
226         consumer_jack self = (consumer_jack) data;
227         mlt_properties properties = MLT_CONSUMER_PROPERTIES( &self->parent );
228         int channels = mlt_properties_get_int( properties, "channels" );
229         int i;
230
231         if ( !self->ringbuffers )
232                 return 1;
233
234         for ( i = 0; i < channels; i++ )
235         {
236                 size_t jack_size = ( frames * sizeof(float) );
237                 size_t ring_size = jack_ringbuffer_read_space( self->ringbuffers[i] );
238                 char *dest = jack_port_get_buffer( self->ports[i], frames );
239
240                 jack_ringbuffer_read( self->ringbuffers[i], dest, ring_size < jack_size ? ring_size : jack_size );
241         }
242
243         return error;
244 }
245
246 static void initialise_jack_ports( consumer_jack self )
247 {
248         int i;
249         char mlt_name[20], con_name[30];
250         mlt_properties properties = MLT_CONSUMER_PROPERTIES( &self->parent );
251
252         // Propogate these for the Jack processing callback
253         int channels = mlt_properties_get_int( properties, "channels" );
254
255         // Allocate buffers and ports
256         self->ringbuffers = mlt_pool_alloc( sizeof( jack_ringbuffer_t *) * channels );
257         self->ports = mlt_pool_alloc( sizeof(jack_port_t *) * channels );
258
259         // Start Jack processing - required before registering ports
260         jack_activate( self->jack );
261         self->playing = 1;
262
263         // Register Jack ports
264         for ( i = 0; i < channels; i++ )
265         {
266                 self->ringbuffers[i] = jack_ringbuffer_create( BUFFER_LEN * sizeof(float) );
267                 snprintf( mlt_name, sizeof( mlt_name ), "out_%d", i + 1 );
268                 self->ports[i] = jack_port_register( self->jack, mlt_name, JACK_DEFAULT_AUDIO_TYPE,
269                                 JackPortIsOutput | JackPortIsTerminal, 0 );
270         }
271
272         // Establish connections
273         for ( i = 0; i < channels; i++ )
274         {
275                 snprintf( mlt_name, sizeof( mlt_name ), "%s", jack_port_name( self->ports[i] ) );
276                 if ( mlt_properties_get( properties, con_name ) )
277                         snprintf( con_name, sizeof( con_name ), "%s", mlt_properties_get( properties, con_name ) );
278                 else
279                         snprintf( con_name, sizeof( con_name ), "system:playback_%d", i + 1);
280
281                 mlt_log_verbose( NULL, "JACK connect %s to %s\n", mlt_name, con_name );
282                 jack_connect( self->jack, mlt_name, con_name );
283         }
284 }
285
286 static int consumer_play_audio( consumer_jack self, mlt_frame frame, int init_audio, int *duration )
287 {
288         // Get the properties of this consumer
289         mlt_properties properties = MLT_CONSUMER_PROPERTIES( &self->parent );
290         mlt_audio_format afmt = mlt_audio_float;
291
292         // Set the preferred params of the test card signal
293         int channels = mlt_properties_get_int( properties, "channels" );
294         int frequency = mlt_properties_get_int( properties, "frequency" );
295         int samples = mlt_sample_calculator( mlt_properties_get_double( properties, "fps" ), frequency, self->counter++ );
296         float *buffer;
297
298         mlt_frame_get_audio( frame, (void**) &buffer, &afmt, &frequency, &channels, &samples );
299         *duration = ( ( samples * 1000 ) / frequency );
300
301         if ( mlt_properties_get_int( properties, "audio_off" ) )
302         {
303                 init_audio = 1;
304                 return init_audio;
305         }
306
307         if ( init_audio == 1 )
308         {
309                 self->playing = 0;
310                 initialise_jack_ports( self );
311                 init_audio = 0;
312         }
313
314         if ( init_audio == 0 )
315         {
316                 int i;
317                 size_t mlt_size = samples * sizeof(float);
318                 float volume = mlt_properties_get_double( properties, "volume" );
319
320                 if ( volume != 1.0 )
321                 {
322                         float *p = buffer;
323                         i = samples * channels + 1;
324                         while (--i)
325                                 *p++ *= volume;
326                 }
327
328                 // Write into output ringbuffer
329                 for ( i = 0; i < channels; i++ )
330                 {
331                         size_t ring_size = jack_ringbuffer_write_space( self->ringbuffers[i] );
332                         if ( ring_size >= mlt_size )
333                                 jack_ringbuffer_write( self->ringbuffers[i], (char*)( buffer + i * samples ), mlt_size );
334                 }
335         }
336
337         return init_audio;
338 }
339
340 static int consumer_play_video( consumer_jack self, mlt_frame frame )
341 {
342         // Get the properties of this consumer
343         mlt_properties properties = MLT_CONSUMER_PROPERTIES( &self->parent );
344         if ( self->running && !mlt_consumer_is_stopped( &self->parent ) )
345                 mlt_events_fire( properties, "consumer-frame-show", frame, NULL );
346
347         return 0;
348 }
349
350 static void *video_thread( void *arg )
351 {
352         // Identify the arg
353         consumer_jack self = arg;
354
355         // Obtain time of thread start
356         struct timeval now;
357         int64_t start = 0;
358         int64_t elapsed = 0;
359         struct timespec tm;
360         mlt_frame next = NULL;
361         mlt_properties properties = NULL;
362         double speed = 0;
363
364         // Get real time flag
365         int real_time = mlt_properties_get_int( MLT_CONSUMER_PROPERTIES( &self->parent ), "real_time" );
366
367         // Get the current time
368         gettimeofday( &now, NULL );
369
370         // Determine start time
371         start = ( int64_t )now.tv_sec * 1000000 + now.tv_usec;
372
373         while ( self->running )
374         {
375                 // Pop the next frame
376                 pthread_mutex_lock( &self->video_mutex );
377                 next = mlt_deque_pop_front( self->queue );
378                 while ( next == NULL && self->running )
379                 {
380                         pthread_cond_wait( &self->video_cond, &self->video_mutex );
381                         next = mlt_deque_pop_front( self->queue );
382                 }
383                 pthread_mutex_unlock( &self->video_mutex );
384
385                 if ( !self->running || next == NULL ) break;
386
387                 // Get the properties
388                 properties =  MLT_FRAME_PROPERTIES( next );
389
390                 // Get the speed of the frame
391                 speed = mlt_properties_get_double( properties, "_speed" );
392
393                 // Get the current time
394                 gettimeofday( &now, NULL );
395
396                 // Get the elapsed time
397                 elapsed = ( ( int64_t )now.tv_sec * 1000000 + now.tv_usec ) - start;
398
399                 // See if we have to delay the display of the current frame
400                 if ( mlt_properties_get_int( properties, "rendered" ) == 1 && self->running )
401                 {
402                         // Obtain the scheduled playout time
403                         int64_t scheduled = mlt_properties_get_int( properties, "playtime" );
404
405                         // Determine the difference between the elapsed time and the scheduled playout time
406                         int64_t difference = scheduled - elapsed;
407
408                         // Smooth playback a bit
409                         if ( real_time && ( difference > 20000 && speed == 1.0 ) )
410                         {
411                                 tm.tv_sec = difference / 1000000;
412                                 tm.tv_nsec = ( difference % 1000000 ) * 500;
413                                 nanosleep( &tm, NULL );
414                         }
415
416                         // Show current frame if not too old
417                         if ( !real_time || ( difference > -10000 || speed != 1.0 || mlt_deque_count( self->queue ) < 2 ) )
418                                 consumer_play_video( self, next );
419
420                         // If the queue is empty, recalculate start to allow build up again
421                         if ( real_time && ( mlt_deque_count( self->queue ) == 0 && speed == 1.0 ) )
422                         {
423                                 gettimeofday( &now, NULL );
424                                 start = ( ( int64_t )now.tv_sec * 1000000 + now.tv_usec ) - scheduled + 20000;
425                         }
426                 }
427
428                 // This frame can now be closed
429                 mlt_frame_close( next );
430                 next = NULL;
431         }
432
433         if ( next != NULL )
434                 mlt_frame_close( next );
435
436         mlt_consumer_stopped( &self->parent );
437
438         return NULL;
439 }
440
441 /** Threaded wrapper for pipe.
442 */
443
444 static void *consumer_thread( void *arg )
445 {
446         // Identify the arg
447         consumer_jack self = arg;
448
449         // Get the consumer
450         mlt_consumer consumer = &self->parent;
451
452         // Get the properties
453         mlt_properties consumer_props = MLT_CONSUMER_PROPERTIES( consumer );
454
455         // Video thread
456         pthread_t thread;
457
458         // internal intialization
459         int init_audio = 1;
460         int init_video = 1;
461         mlt_frame frame = NULL;
462         mlt_properties properties = NULL;
463         int duration = 0;
464         int64_t playtime = 0;
465         struct timespec tm = { 0, 100000 };
466 //      int last_position = -1;
467         self->refresh_count = 0;
468
469         // Loop until told not to
470         while( self->running )
471         {
472                 // Get a frame from the attached producer
473                 frame = mlt_consumer_rt_frame( consumer );
474
475                 // Ensure that we have a frame
476                 if ( frame )
477                 {
478                         // Get the frame properties
479                         properties =  MLT_FRAME_PROPERTIES( frame );
480
481                         // Get the speed of the frame
482                         double speed = mlt_properties_get_double( properties, "_speed" );
483
484                         // Get refresh request for the current frame
485                         int refresh = mlt_properties_get_int( consumer_props, "refresh" );
486
487                         // Clear refresh
488                         mlt_events_block( consumer_props, consumer_props );
489                         mlt_properties_set_int( consumer_props, "refresh", 0 );
490                         mlt_events_unblock( consumer_props, consumer_props );
491
492                         // Play audio
493                         init_audio = consumer_play_audio( self, frame, init_audio, &duration );
494
495                         // Determine the start time now
496                         if ( self->playing && init_video )
497                         {
498                                 // Create the video thread
499                                 pthread_create( &thread, NULL, video_thread, self );
500
501                                 // Video doesn't need to be initialised any more
502                                 init_video = 0;
503                         }
504
505                         // Set playtime for this frame
506                         mlt_properties_set_int( properties, "playtime", playtime );
507
508                         while ( self->running && speed != 0 && mlt_deque_count( self->queue ) > 15 )
509                                 nanosleep( &tm, NULL );
510
511                         // Push this frame to the back of the queue
512                         if ( self->running && speed )
513                         {
514                                 pthread_mutex_lock( &self->video_mutex );
515                                 mlt_deque_push_back( self->queue, frame );
516                                 pthread_cond_broadcast( &self->video_cond );
517                                 pthread_mutex_unlock( &self->video_mutex );
518
519                                 // Calculate the next playtime
520                                 playtime += ( duration * 1000 );
521                         }
522                         else if ( self->running )
523                         {
524                                 pthread_mutex_lock( &self->refresh_mutex );
525                                 if ( refresh == 0 && self->refresh_count <= 0 )
526                                 {
527                                         consumer_play_video( self, frame );
528                                         pthread_cond_wait( &self->refresh_cond, &self->refresh_mutex );
529                                 }
530                                 mlt_frame_close( frame );
531                                 self->refresh_count --;
532                                 pthread_mutex_unlock( &self->refresh_mutex );
533                         }
534                         else
535                         {
536                                 mlt_frame_close( frame );
537                                 frame = NULL;
538                         }
539
540                         // Optimisation to reduce latency
541                         if ( frame && speed == 1.0 )
542                         {
543                                 // TODO: disabled due to misbehavior on parallel-consumer
544 //                              if ( last_position != -1 && last_position + 1 != mlt_frame_get_position( frame ) )
545 //                                      mlt_consumer_purge( consumer );
546 //                              last_position = mlt_frame_get_position( frame );
547                         }
548                         else
549                         {
550                                 mlt_consumer_purge( consumer );
551 //                              last_position = -1;
552                         }
553                 }
554         }
555
556         // Kill the video thread
557         if ( init_video == 0 )
558         {
559                 pthread_mutex_lock( &self->video_mutex );
560                 pthread_cond_broadcast( &self->video_cond );
561                 pthread_mutex_unlock( &self->video_mutex );
562                 pthread_join( thread, NULL );
563         }
564
565         while( mlt_deque_count( self->queue ) )
566                 mlt_frame_close( mlt_deque_pop_back( self->queue ) );
567
568         return NULL;
569 }
570
571 /** Callback to allow override of the close method.
572 */
573
574 static void consumer_close( mlt_consumer parent )
575 {
576         // Get the actual object
577         consumer_jack self = parent->child;
578
579         // Stop the consumer
580         mlt_consumer_stop( parent );
581
582         // Now clean up the rest
583         mlt_consumer_close( parent );
584
585         // Close the queue
586         mlt_deque_close( self->queue );
587
588         // Destroy mutexes
589         pthread_mutex_destroy( &self->video_mutex );
590         pthread_cond_destroy( &self->video_cond );
591         pthread_mutex_destroy( &self->refresh_mutex );
592         pthread_cond_destroy( &self->refresh_cond );
593
594         // Disconnect from JACK
595         jack_client_close( self->jack );
596
597         // Finally deallocate self
598         free( self );
599 }