158 PROP_0, |
176 PROP_0, |
159 PROP_DEVICE, |
177 PROP_DEVICE, |
160 VOLUME, |
178 VOLUME, |
161 MAXVOLUME, |
179 MAXVOLUME, |
162 VOLUMERAMP, |
180 VOLUMERAMP, |
163 CHANNELS, |
181 /* CHANNELS,*/ |
164 LEFTBALANCE, |
182 LEFTBALANCE, |
165 RIGHTBALANCE, |
183 RIGHTBALANCE, |
166 RATE, |
184 /* RATE,*/ |
167 PRIORITY, |
185 PRIORITY, |
168 PREFERENCE, |
186 PREFERENCE, |
169 SAMPLESPLAYED, |
187 /* SAMPLESPLAYED,*/ |
170 FOURCC, //FOURCC is not needed |
188 /* FOURCC, //FOURCC is not needed*/ |
171 MIMETYPE, |
189 /* MIMETYPE,*/ |
172 OUTPUTDEVICE |
190 OUTPUTDEVICE |
173 }; |
191 }; |
174 |
192 |
175 enum command_to_consumer_thread_enum |
193 enum command_to_consumer_thread_enum |
176 { |
194 { |
177 OPEN = 2, |
195 OPEN = 2, |
178 WRITEDATA, |
196 PLAYING, |
|
197 PAUSE, |
|
198 RESUME, |
179 /*UPDATE,*/ |
199 /*UPDATE,*/ |
|
200 WAIT, |
180 CLOSE |
201 CLOSE |
181 }; |
202 }; |
182 enum command_to_consumer_thread_enum cmd; |
203 enum command_to_consumer_thread_enum cmd; |
183 |
204 |
184 static GstStaticPadTemplate devsoundsink_sink_factory= |
205 static GstStaticPadTemplate devsoundsink_sink_factory= |
185 GST_STATIC_PAD_TEMPLATE ("sink", |
206 GST_STATIC_PAD_TEMPLATE ("sink", |
186 GST_PAD_SINK, |
207 GST_PAD_SINK, |
187 GST_PAD_ALWAYS, |
208 GST_PAD_ALWAYS, |
188 GST_STATIC_CAPS ("audio/x-raw-int, " |
209 GST_STATIC_CAPS ("audio/x-raw-int, " "endianness = (int) { " G_STRINGIFY (G_BYTE_ORDER) " }, " "signed = (boolean) TRUE, " "width = (int) 16, " "depth = (int) 16, " "rate = (int) [ 8000, 48000 ]," "channels = (int) [ 1, 2 ]; " |
189 "endianness = (int) { " G_STRINGIFY (G_BYTE_ORDER) " }, " |
210 "audio/amr, " "rate = (int) 8000, " "channels = (int) 1 ; " |
190 "signed = (boolean) TRUE, " |
211 "audio/AMR, " "rate = (int) 8000, " "channels = (int) 1 ; " |
191 "width = (int) 16, " |
212 "audio/x-alaw, " "rate = (int) [ 8000, 48000 ], " "channels = (int) [ 1, 2 ]; " |
192 "depth = (int) 16, " |
213 "audio/g729, " "rate = (int) [ 8000, 48000 ], " "channels = (int) [ 1, 2 ]; " |
193 "rate = (int) [ 8000, 48000 ]," |
214 "audio/mpeg, mpegversion = (int) 1, layer = (int) [ 1, 3 ], rate = (int) [ 8000, 48000 ], channels = (int) [ 1, 2 ]; " |
194 "channels = (int) [ 1, 2 ]; " |
215 "audio/ilbc, " "rate = (int) [ 8000, 48000 ], " "channels = (int) [ 1, 2 ]; " |
195 "audio/amr, " |
216 "audio/x-mulaw, " "rate = (int) [ 8000, 48000 ], " "channels = (int) [ 1, 2 ]") |
196 //"width = (int) 8, " |
|
197 //"depth = (int) 8, " |
|
198 "rate = (int) 8000, " |
|
199 "channels = (int) 1 ; " |
|
200 "audio/x-alaw, " |
|
201 "rate = (int) [ 8000, 48000 ], " |
|
202 "channels = (int) [ 1, 2 ]; " |
|
203 "audio/g729, " |
|
204 "rate = (int) [ 8000, 48000 ], " |
|
205 "channels = (int) [ 1, 2 ]; " |
|
206 "audio/mp3, " |
|
207 "rate = (int) [ 8000, 48000 ], " |
|
208 "channels = (int) [ 1, 2 ]; " |
|
209 "audio/ilbc, " |
|
210 "rate = (int) [ 8000, 48000 ], " |
|
211 "channels = (int) [ 1, 2 ]; " |
|
212 "audio/x-mulaw, " |
|
213 "rate = (int) [ 8000, 48000 ], " |
|
214 "channels = (int) [ 1, 2 ]") |
|
215 ); |
217 ); |
216 |
218 |
217 static GstElementClass *parent_class= NULL; |
219 static GstElementClass *parent_class= NULL; |
218 |
220 |
219 GType gst_devsound_sink_get_type(void) |
221 GType gst_devsound_sink_get_type(void) |
322 |
330 |
323 gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_devsound_sink_dispose); |
331 gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_devsound_sink_dispose); |
324 gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_devsound_sink_finalise); |
332 gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_devsound_sink_finalise); |
325 gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_devsound_sink_get_property); |
333 gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_devsound_sink_get_property); |
326 gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_devsound_sink_set_property); |
334 gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_devsound_sink_set_property); |
327 |
335 |
|
336 |
|
337 gstelement_class->change_state = GST_DEBUG_FUNCPTR(gst_devsound_sink_change_state); |
|
338 |
328 g_object_class_install_property(gobject_class, PROP_DEVICE, |
339 g_object_class_install_property(gobject_class, PROP_DEVICE, |
329 g_param_spec_string("device", "Device", "Devsound device ", |
340 g_param_spec_string("device", "Device", "Devsound device ", |
330 DEFAULT_DEVICE, G_PARAM_READWRITE)); |
341 DEFAULT_DEVICE, (GParamFlags)G_PARAM_READWRITE)); |
331 |
342 |
332 g_object_class_install_property(gobject_class, VOLUME, |
343 g_object_class_install_property(gobject_class, VOLUME, |
333 g_param_spec_int("volume", "Volume", "Devsound volume", |
344 g_param_spec_int("volume", "Volume", "Devsound volume", |
334 -1, G_MAXINT, -1, G_PARAM_READWRITE)); |
345 -1, G_MAXINT, -1, (GParamFlags)G_PARAM_READWRITE)); |
335 |
346 |
336 g_object_class_install_property(gobject_class, VOLUMERAMP, |
347 g_object_class_install_property(gobject_class, VOLUMERAMP, |
337 g_param_spec_int("volumeramp", "VolumeRamp", "Devsound volume ramp", |
348 g_param_spec_int("volumeramp", "VolumeRamp", "Devsound volume ramp", |
338 -1, G_MAXINT, -1, G_PARAM_READWRITE)); |
349 -1, G_MAXINT, -1, (GParamFlags)G_PARAM_READWRITE)); |
339 |
350 |
340 g_object_class_install_property(gobject_class, MAXVOLUME, |
351 g_object_class_install_property(gobject_class, MAXVOLUME, |
341 g_param_spec_int("maxvolume", "MaxVolume", "Devsound max volume", |
352 g_param_spec_int("maxvolume", "MaxVolume", "Devsound max volume", |
342 -1, G_MAXINT, -1, G_PARAM_READABLE)); |
353 -1, G_MAXINT, -1, G_PARAM_READABLE)); |
343 |
354 |
344 g_object_class_install_property(gobject_class, LEFTBALANCE, |
355 g_object_class_install_property(gobject_class, LEFTBALANCE, |
345 g_param_spec_int("leftbalance", "Left Balance", "Left Balance", |
356 g_param_spec_int("leftbalance", "Left Balance", "Left Balance", |
346 -1, G_MAXINT, -1, G_PARAM_READWRITE)); |
357 -1, G_MAXINT, -1, (GParamFlags)G_PARAM_READWRITE)); |
347 |
358 |
348 g_object_class_install_property(gobject_class, RIGHTBALANCE, |
359 g_object_class_install_property(gobject_class, RIGHTBALANCE, |
349 g_param_spec_int("rightbalance", "Right Balance", "Right Balance", |
360 g_param_spec_int("rightbalance", "Right Balance", "Right Balance", |
350 -1, G_MAXINT, -1, G_PARAM_READWRITE)); |
361 -1, G_MAXINT, -1, (GParamFlags)G_PARAM_READWRITE)); |
351 |
362 /* |
352 g_object_class_install_property(gobject_class, SAMPLESPLAYED, |
363 g_object_class_install_property(gobject_class, SAMPLESPLAYED, |
353 g_param_spec_int("samplesplayed", "Samples Played", "Samples Played", |
364 g_param_spec_int("samplesplayed", "Samples Played", "Samples Played", |
354 -1, G_MAXINT, -1, G_PARAM_READABLE)); |
365 -1, G_MAXINT, -1, G_PARAM_READABLE)); |
355 |
366 */ |
356 g_object_class_install_property(gobject_class, PRIORITY, |
367 g_object_class_install_property(gobject_class, PRIORITY, |
357 g_param_spec_int("priority", "Priority", "Priority ", -1, |
368 g_param_spec_int("priority", "Priority", "Priority ", -1, |
358 G_MAXINT, -1, |
369 G_MAXINT, -1, |
359 G_PARAM_READWRITE)); |
370 (GParamFlags)G_PARAM_READWRITE)); |
360 |
371 |
361 g_object_class_install_property(gobject_class, PREFERENCE, |
372 g_object_class_install_property(gobject_class, PREFERENCE, |
362 g_param_spec_int("preference", "Preference", "Preference ", -1, |
373 g_param_spec_int("preference", "Preference", "Preference ", -1, |
363 G_MAXINT, -1, |
374 G_MAXINT, -1, |
364 G_PARAM_READWRITE)); |
375 (GParamFlags)G_PARAM_READWRITE)); |
365 |
376 /* |
366 g_object_class_install_property(gobject_class, RATE, |
377 g_object_class_install_property(gobject_class, RATE, |
367 g_param_spec_int("rate", "Rate", "Rate ", -1, |
378 g_param_spec_int("rate", "Rate", "Rate ", -1, |
368 G_MAXINT, -1, |
379 G_MAXINT, -1, |
369 G_PARAM_READWRITE)); |
380 G_PARAM_READWRITE)); |
370 |
381 |
371 g_object_class_install_property(gobject_class, CHANNELS, |
382 g_object_class_install_property(gobject_class, CHANNELS, |
372 g_param_spec_int("channels", "Channels", "Channels ", -1, |
383 g_param_spec_int("channels", "Channels", "Channels ", -1, |
373 G_MAXINT, -1, |
384 G_MAXINT, -1, |
374 G_PARAM_READWRITE)); |
385 G_PARAM_READWRITE)); |
375 |
386 */ |
376 g_object_class_install_property(gobject_class, OUTPUTDEVICE, |
387 g_object_class_install_property(gobject_class, OUTPUTDEVICE, |
377 g_param_spec_int("outputdevice", "Output Device", "Output Device ", -1, |
388 g_param_spec_int("outputdevice", "Output Device", "Output Device ", -1, |
378 G_MAXINT, -1, |
389 G_MAXINT, -1, |
379 G_PARAM_READWRITE)); |
390 (GParamFlags)G_PARAM_READWRITE)); |
380 |
391 |
|
392 #ifdef AV_SYNC |
|
393 gstelement_class->provide_clock = GST_DEBUG_FUNCPTR (gst_devsound_sink_provide_clock); |
|
394 #endif /*AV_SYNC*/ |
|
395 |
381 gstbasesink_class->start = GST_DEBUG_FUNCPTR (gst_sink_start); |
396 gstbasesink_class->start = GST_DEBUG_FUNCPTR (gst_sink_start); |
382 gstbasesink_class->stop = GST_DEBUG_FUNCPTR (gst_sink_stop); |
397 gstbasesink_class->stop = GST_DEBUG_FUNCPTR (gst_sink_stop); |
383 gstbasesink_class->render = GST_DEBUG_FUNCPTR (gst_sink_render); |
398 gstbasesink_class->render = GST_DEBUG_FUNCPTR (gst_sink_render); |
384 |
399 |
385 gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_devsound_sink_getcaps); |
400 gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_devsound_sink_getcaps); |
386 gstbasesink_class->set_caps = GST_DEBUG_FUNCPTR (gst_devsound_sink_setcaps); |
401 gstbasesink_class->set_caps = GST_DEBUG_FUNCPTR (gst_devsound_sink_setcaps); |
387 gstbasesink_class->event = GST_DEBUG_FUNCPTR (gst_devsound_sink_event); |
402 gstbasesink_class->event = GST_DEBUG_FUNCPTR (gst_devsound_sink_event); |
388 } |
403 #ifdef AV_SYNC |
389 |
404 gstbasesink_class->get_times = GST_DEBUG_FUNCPTR (gst_devsound_sink_get_times); |
390 static void gst_devsound_sink_init(GstDevsoundSink * devsoundsink) |
405 #endif /*AV_SYNC*/ |
391 { |
406 } |
392 GST_DEBUG_OBJECT(devsoundsink, "initializing devsoundsink"); |
407 |
393 devsoundsink->device = g_strdup(DEFAULT_DEVICE); |
408 static void gst_devsound_sink_init(GstDevsoundSink * dssink) |
394 devsoundsink->handle = NULL; |
409 { |
395 devsoundsink->preference = 0; //default=>EMdaPriorityPreferenceNone; |
410 GST_DEBUG_OBJECT(dssink, "initializing devsoundsink"); |
396 devsoundsink->priority = 0; //default=>EMdaPriorityNormal; |
411 dssink->device = g_strdup(DEFAULT_DEVICE); |
|
412 dssink->handle = NULL; |
|
413 dssink->preference = 0; //default=>EMdaPriorityPreferenceNone; |
|
414 dssink->priority = 0; //default=>EMdaPriorityNormal; |
|
415 #ifdef AV_SYNC |
|
416 dssink->time_or_samples_played = 0; |
|
417 dssink->timeplayedavailable = FALSE; |
|
418 /* Create the provided clock. */ |
|
419 dssink->clock = gst_audio_clock_new ("clock", gst_devsound_sink_get_time, dssink); |
|
420 #endif /*AV_SYNC*/ |
397 pthread_mutex_init(&ds_mutex, NULL); |
421 pthread_mutex_init(&ds_mutex, NULL); |
398 pthread_cond_init(&ds_condition, NULL); |
422 pthread_cond_init(&ds_condition, NULL); |
399 } |
423 } |
400 |
424 |
401 static void *StartDevSoundThread(void *threadarg) |
425 static void *StartDevSoundThread(void *threadarg) |
402 { |
426 { |
403 |
427 GstDevsoundSink *dssink; |
404 GstDevsoundSink *devsound; |
|
405 |
428 |
406 gint remainingDataLen = 0; |
429 gint remainingDataLen = 0; |
407 GstBuffer *buffer = NULL; |
430 GstBuffer *buffer = NULL; |
408 gboolean lastBufferSet=FALSE; |
431 gboolean lastBufferSet=FALSE; |
409 devsound = (GstDevsoundSink*) threadarg; |
432 dssink = (GstDevsoundSink*) threadarg; |
410 |
433 |
411 open_devsound(&(devsound->handle)); |
434 // TODO handle error here |
|
435 open_devsound(&(dssink->handle)); |
|
436 #ifdef AV_SYNC |
|
437 dssink->timeplayedavailable = is_timeplayed_supported(dssink->handle); |
|
438 #endif /*AV_SYNC*/ |
412 |
439 |
413 |
440 |
414 //get supported (in/out)put datatypes |
441 //get supported (in/out)put datatypes |
415 //from devsound to build caps |
442 //from devsound to build caps |
416 getsupporteddatatypes(devsound); |
443 getsupporteddatatypes(dssink); |
417 |
444 |
418 // TODO obtain mutex to update variable here??? |
445 // TODO obtain mutex to update variable here??? |
419 consumer_thread_state = CONSUMER_THREAD_INITIALIZED; |
446 consumer_thread_state = CONSUMER_THREAD_INITIALIZED; |
420 |
447 |
421 // Signal any waiting threads that consumer thread creation was successful. |
448 // Signal any waiting threads that consumer thread creation was successful. |
436 // without putting it to play state |
463 // without putting it to play state |
437 if ( cmd != CLOSE ) |
464 if ( cmd != CLOSE ) |
438 { |
465 { |
439 //TODO if there is preemption we have to somehow signal |
466 //TODO if there is preemption we have to somehow signal |
440 //the pipeline in the render |
467 //the pipeline in the render |
441 initialize_devsound(devsound); |
468 initialize_devsound(dssink); |
442 |
469 |
443 playinit(devsound->handle); |
470 playinit(dssink->handle); |
444 initproperties(devsound); |
471 dssink->eosreceived = FALSE; |
|
472 initproperties(dssink); |
445 } |
473 } |
446 while (1) |
474 while (1) |
447 { |
475 { |
448 switch (cmd) |
476 switch (cmd) |
449 { |
477 { |
450 case WRITEDATA: |
478 case PAUSE: |
|
479 pause_devsound(dssink); |
|
480 cmd = WAIT; |
|
481 break; |
|
482 |
|
483 case RESUME: |
|
484 resume_devsound(dssink); |
|
485 cmd = PLAYING; |
|
486 break; |
|
487 |
|
488 case WAIT: |
|
489 pthread_mutex_lock(&ds_mutex); |
|
490 pthread_cond_signal(&ds_condition); |
|
491 pthread_mutex_unlock(&ds_mutex); |
|
492 |
|
493 pthread_mutex_lock(&ds_mutex); |
|
494 pthread_cond_wait(&ds_condition, &ds_mutex); |
|
495 pthread_mutex_unlock(&ds_mutex); |
|
496 break; |
|
497 |
|
498 case PLAYING: |
451 { |
499 { |
452 pre_init_setconf(devsound); |
500 pre_init_setconf(dssink); |
453 gst_Apply_ErrorConcealment_Update(devsound); |
501 gst_Apply_ErrorConcealment_Update(dssink); |
454 gst_Apply_G711_Decoder_Update(devsound); |
502 gst_Apply_G711_Decoder_Update(dssink); |
455 gst_Apply_G729_Decoder_Update(devsound); |
503 gst_Apply_G729_Decoder_Update(dssink); |
456 gst_Apply_Ilbc_Decoder_Update(devsound); |
504 gst_Apply_Ilbc_Decoder_Update(dssink); |
457 |
505 |
458 // TODO we could do this in BTBF callback |
506 // TODO we could do this in BTBF callback |
459 populateproperties(devsound); |
507 populateproperties(dssink); |
460 |
508 get_PopulateIntfcProperties(dssink); |
461 framemodereq = devsound->framemodereq; |
509 |
462 g711cng = devsound->g711cng; |
|
463 ilbccng = devsound->ilbccng; |
|
464 output = devsound->output; |
|
465 |
|
466 if(buffer_queue->length > 0) |
510 if(buffer_queue->length > 0) |
467 { |
511 { |
468 if (remainingDataLen == 0) |
512 if (remainingDataLen == 0) |
469 { |
513 { |
470 // TODO enable lock and unlock |
514 // TODO enable lock and unlock |
471 GST_OBJECT_LOCK (devsound); |
515 GST_OBJECT_LOCK (dssink); |
472 buffer = GST_BUFFER_CAST(g_queue_peek_head(buffer_queue)); |
516 buffer = GST_BUFFER_CAST(g_queue_peek_head(buffer_queue)); |
473 GST_OBJECT_UNLOCK(devsound); |
517 GST_OBJECT_UNLOCK(dssink); |
474 remainingDataLen = GST_BUFFER_SIZE(buffer); |
518 remainingDataLen = GST_BUFFER_SIZE(buffer); |
475 } |
519 } |
476 |
520 |
477 lastBufferSet = GST_BUFFER_FLAG_IS_SET(buffer,GST_BUFFER_FLAG_LAST); |
521 lastBufferSet = GST_BUFFER_FLAG_IS_SET(buffer,GST_BUFFER_FLAG_LAST); |
478 remainingDataLen = write_data(devsound->handle, |
522 remainingDataLen = write_data(dssink->handle, |
479 GST_BUFFER_DATA(buffer) + (GST_BUFFER_SIZE(buffer) - remainingDataLen), |
523 GST_BUFFER_DATA(buffer) + (GST_BUFFER_SIZE(buffer) - remainingDataLen), |
480 remainingDataLen, |
524 remainingDataLen, |
481 lastBufferSet); |
525 lastBufferSet); |
482 |
526 |
483 if (remainingDataLen == 0) |
527 if (remainingDataLen == 0) |
484 { |
528 { |
485 GST_OBJECT_LOCK (devsound); |
529 GST_OBJECT_LOCK (dssink); |
486 buffer = GST_BUFFER_CAST(g_queue_pop_head(buffer_queue)); |
530 buffer = GST_BUFFER_CAST(g_queue_pop_head(buffer_queue)); |
487 GST_OBJECT_UNLOCK(devsound); |
531 GST_OBJECT_UNLOCK(dssink); |
488 gst_buffer_unref(buffer); |
532 gst_buffer_unref(buffer); |
489 buffer = NULL; |
533 buffer = NULL; |
490 } |
534 } |
491 |
535 |
492 if (lastBufferSet && remainingDataLen == 0) |
536 if (lastBufferSet && remainingDataLen == 0) |
493 { |
537 { |
494 // Last Buffer is already sent to DevSound |
538 lastBufferSet = FALSE; |
495 // and we have received PlayError so now we exit |
539 dssink->eosreceived = FALSE; |
496 // from the big loop next time |
540 playinit(dssink->handle); |
497 /* |
541 initproperties(dssink); |
498 pthread_mutex_lock(&ds_mutex); |
542 get_PopulateIntfcProperties(dssink); |
499 pthread_cond_signal(&ds_condition); |
543 cmd = WAIT; |
500 pthread_mutex_unlock(&ds_mutex); |
544 } |
501 */ |
|
502 cmd = CLOSE; |
|
503 } |
|
504 } |
545 } |
505 else |
546 else |
506 { |
547 { |
507 pthread_mutex_lock(&ds_mutex); |
548 cmd = WAIT; |
508 pthread_cond_wait(&ds_condition, &ds_mutex); |
|
509 pthread_mutex_unlock(&ds_mutex); |
|
510 } |
549 } |
511 } |
550 } |
512 break; |
551 break; |
513 case CLOSE: |
552 case CLOSE: |
514 { |
553 { |
515 close_devsound(devsound); |
554 close_devsound(dssink); |
516 devsound->handle= NULL; |
555 dssink->handle= NULL; |
517 pthread_mutex_lock(&ds_mutex); |
556 pthread_mutex_lock(&ds_mutex); |
518 pthread_cond_signal(&ds_condition); |
557 pthread_cond_signal(&ds_condition); |
519 pthread_mutex_unlock(&ds_mutex); |
558 pthread_mutex_unlock(&ds_mutex); |
520 // TODO obtain mutex here |
559 // TODO obtain mutex here |
521 consumer_thread_state = CONSUMER_THREAD_UNINITIALIZED; |
560 consumer_thread_state = CONSUMER_THREAD_UNINITIALIZED; |
572 } |
611 } |
573 |
612 |
574 static gboolean gst_sink_stop (GstBaseSink * sink) |
613 static gboolean gst_sink_stop (GstBaseSink * sink) |
575 { |
614 { |
576 GstBuffer *tmp_gstbuffer=NULL; |
615 GstBuffer *tmp_gstbuffer=NULL; |
577 GstDevsoundSink *devsound = GST_DEVSOUND_SINK(sink); |
616 GstDevsoundSink *dssink = GST_DEVSOUND_SINK(sink); |
578 |
617 |
579 cmd = CLOSE; |
618 cmd = CLOSE; |
580 |
619 |
581 pthread_mutex_lock(&ds_mutex); |
620 pthread_mutex_lock(&ds_mutex); |
582 pthread_cond_signal(&ds_condition); |
621 pthread_cond_signal(&ds_condition); |
583 pthread_mutex_unlock(&ds_mutex); |
622 pthread_mutex_unlock(&ds_mutex); |
584 |
623 |
585 GST_OBJECT_LOCK(devsound); |
624 pthread_mutex_lock(&ds_mutex); |
|
625 pthread_cond_wait(&ds_condition, &ds_mutex); |
|
626 pthread_mutex_unlock(&ds_mutex); |
|
627 |
|
628 |
|
629 GST_OBJECT_LOCK(dssink); |
586 while (buffer_queue->length) |
630 while (buffer_queue->length) |
587 { |
631 { |
588 tmp_gstbuffer = (GstBuffer*)g_queue_pop_tail(buffer_queue); |
632 tmp_gstbuffer = (GstBuffer*)g_queue_pop_tail(buffer_queue); |
589 gst_buffer_unref(tmp_gstbuffer); |
633 gst_buffer_unref(tmp_gstbuffer); |
590 } |
634 } |
591 g_queue_free(buffer_queue); |
635 g_queue_free(buffer_queue); |
592 buffer_queue = NULL; |
636 buffer_queue = NULL; |
593 GST_OBJECT_UNLOCK(devsound); |
637 GST_OBJECT_UNLOCK(dssink); |
594 |
638 |
595 return TRUE; |
639 return TRUE; |
596 } |
640 } |
597 |
641 |
598 static GstFlowReturn gst_sink_render (GstBaseSink * sink, |
642 static GstFlowReturn gst_sink_render (GstBaseSink * sink, |
599 GstBuffer * buffer) |
643 GstBuffer * buffer) |
600 { |
644 { |
601 GstDevsoundSink *devsound = GST_DEVSOUND_SINK(sink); |
645 GstDevsoundSink *dssink = GST_DEVSOUND_SINK(sink); |
602 GstBuffer* tmp; |
646 GstBuffer* tmp; |
603 |
647 |
604 if (get_ds_cb_error(devsound->handle)) |
648 if (get_ds_cb_error(dssink->handle)) |
605 { |
649 { |
606 return GST_FLOW_CUSTOM_ERROR; |
650 return GST_FLOW_CUSTOM_ERROR; |
607 } |
651 } |
608 |
652 |
609 tmp = gst_buffer_copy(buffer); |
653 tmp = gst_buffer_copy(buffer); |
610 |
654 |
611 GST_OBJECT_LOCK (devsound); |
655 GST_OBJECT_LOCK (dssink); |
612 g_queue_push_tail (buffer_queue, tmp); |
656 g_queue_push_tail (buffer_queue, tmp); |
613 GST_OBJECT_UNLOCK (devsound); |
657 GST_OBJECT_UNLOCK (dssink); |
614 |
658 |
615 cmd = WRITEDATA; |
659 cmd = PLAYING; |
616 pthread_mutex_lock(&ds_mutex); |
660 pthread_mutex_lock(&ds_mutex); |
617 pthread_cond_signal(&ds_condition); |
661 pthread_cond_signal(&ds_condition); |
618 pthread_mutex_unlock(&ds_mutex); |
662 pthread_mutex_unlock(&ds_mutex); |
619 |
663 |
620 return GST_FLOW_OK; |
664 return GST_FLOW_OK; |
621 } |
665 } |
622 |
666 |
623 static void gst_devsound_sink_finalise(GObject * object) |
667 static void gst_devsound_sink_finalise(GObject * object) |
624 { |
668 { |
625 GstDevsoundSink *devsoundsink= GST_DEVSOUND_SINK (object); |
669 GstDevsoundSink *devsoundsink = GST_DEVSOUND_SINK (object); |
626 g_free(devsoundsink->device); |
670 g_free(devsoundsink->device); |
627 |
671 |
628 } |
672 } |
629 |
673 |
630 static void gst_devsound_sink_set_property(GObject * object, guint prop_id, |
674 static void gst_devsound_sink_set_property(GObject * object, guint prop_id, |
960 } |
1003 } |
961 |
1004 |
962 return TRUE; |
1005 return TRUE; |
963 } |
1006 } |
964 |
1007 |
|
1008 #ifdef AV_SYNC |
|
1009 static void gst_devsound_sink_get_times (GstBaseSink * bsink, GstBuffer * buffer, |
|
1010 GstClockTime * start, GstClockTime * end) |
|
1011 { |
|
1012 /* Like GstBaseAudioSink, we set these to NONE */ |
|
1013 *start = GST_CLOCK_TIME_NONE; |
|
1014 *end = GST_CLOCK_TIME_NONE; |
|
1015 } |
|
1016 |
|
1017 static GstClock *gst_devsound_sink_provide_clock (GstElement * element) |
|
1018 { |
|
1019 GstDevsoundSink *sink = GST_DEVSOUND_SINK (element); |
|
1020 return GST_CLOCK (gst_object_ref (sink->clock)); |
|
1021 } |
|
1022 |
|
1023 static GstClockTime gst_devsound_sink_get_time (GstClock * clock, gpointer user_data) |
|
1024 { |
|
1025 GstClockTime result = 0; |
|
1026 GstDevsoundSink *sink = GST_DEVSOUND_SINK (user_data); |
|
1027 |
|
1028 /* The value returned must be in nano seconds. 1 sec = 1000000000 nano seconds (9 zeros)*/ |
|
1029 /*If time played is available from DevSound (a3f devsound onwards) get it*/ |
|
1030 if (sink->timeplayedavailable) |
|
1031 { |
|
1032 result = sink->time_or_samples_played; |
|
1033 } |
|
1034 else if ((sink->time_or_samples_played > 0 ) && (sink->rate > 0 ))/*This is a pre-a3f devsound. So calculate times played based on samples played*/ |
|
1035 { /*GST_SECOND = 1000000000*/ |
|
1036 result = gst_util_uint64_scale_int (sink->time_or_samples_played, GST_SECOND, sink->rate); |
|
1037 } |
|
1038 GST_LOG_OBJECT (sink, "Time: %" GST_TIME_FORMAT, GST_TIME_ARGS (result)); |
|
1039 return result; |
|
1040 } |
|
1041 #endif /*AV_SYNC*/ |
|
1042 |
|
1043 static GstStateChangeReturn gst_devsound_sink_change_state (GstElement * element, GstStateChange transition) |
|
1044 { |
|
1045 GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; |
|
1046 GstDevsoundSink *sink= GST_DEVSOUND_SINK (element); |
|
1047 |
|
1048 switch (transition) |
|
1049 { |
|
1050 case GST_STATE_CHANGE_NULL_TO_READY: |
|
1051 { |
|
1052 #ifdef AV_SYNC |
|
1053 sink->time_or_samples_played = 0; |
|
1054 #endif /*AV_SYNC*/ |
|
1055 } |
|
1056 break; |
|
1057 |
|
1058 case GST_STATE_CHANGE_PAUSED_TO_PLAYING: |
|
1059 if(cmd == WAIT) |
|
1060 { |
|
1061 cmd = RESUME; |
|
1062 pthread_mutex_lock(&ds_mutex); |
|
1063 pthread_cond_signal(&ds_condition); |
|
1064 pthread_mutex_unlock(&ds_mutex); |
|
1065 |
|
1066 pthread_mutex_lock(&ds_mutex); |
|
1067 pthread_cond_wait(&ds_condition, &ds_mutex); |
|
1068 pthread_mutex_unlock(&ds_mutex); |
|
1069 } |
|
1070 break; |
|
1071 default: |
|
1072 break; |
|
1073 } |
|
1074 |
|
1075 ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); |
|
1076 if (G_UNLIKELY (ret == GST_STATE_CHANGE_FAILURE)) |
|
1077 goto activate_failed; |
|
1078 |
|
1079 switch (transition) { |
|
1080 |
|
1081 case GST_STATE_CHANGE_PLAYING_TO_PAUSED: |
|
1082 cmd = PAUSE; |
|
1083 pthread_mutex_lock(&ds_mutex); |
|
1084 pthread_cond_signal(&ds_condition); |
|
1085 pthread_mutex_unlock(&ds_mutex); |
|
1086 |
|
1087 pthread_mutex_lock(&ds_mutex); |
|
1088 pthread_cond_wait(&ds_condition, &ds_mutex); |
|
1089 pthread_mutex_unlock(&ds_mutex); |
|
1090 break; |
|
1091 default: |
|
1092 break; |
|
1093 } |
|
1094 |
|
1095 return ret; |
|
1096 |
|
1097 activate_failed: |
|
1098 { |
|
1099 GST_DEBUG_OBJECT (sink, |
|
1100 "element failed to change states -- activation problem?"); |
|
1101 return GST_STATE_CHANGE_FAILURE; |
|
1102 } |
|
1103 } |
|
1104 |
965 |
1105 |
966 /************************************ |
1106 /************************************ |
967 * Error Concealment Interface begins |
1107 * Error Concealment Interface begins |
968 * **********************************/ |
1108 * **********************************/ |
969 static void gst_error_concealment_handler_init (gpointer g_iface, |
1109 static void gst_error_concealment_handler_init (gpointer g_iface, |