FS-7514: slow down vlc callback by syncing with video flow

This commit is contained in:
Anthony Minessale 2015-02-26 13:54:26 -06:00 committed by Michael Jerris
parent af0f2e6ea8
commit 6b289ed02a

View File

@ -79,7 +79,7 @@ struct vlc_file_context {
switch_memory_pool_t *pool; switch_memory_pool_t *pool;
switch_buffer_t *audio_buffer; switch_buffer_t *audio_buffer;
switch_mutex_t *audio_mutex; switch_mutex_t *audio_mutex;
switch_thread_cond_t *started; switch_thread_cond_t *cond;
char *path; char *path;
int samples; int samples;
int playing; int playing;
@ -100,11 +100,11 @@ struct vlc_video_context {
switch_mutex_t *audio_mutex; switch_mutex_t *audio_mutex;
switch_file_handle_t fh; switch_file_handle_t fh;
switch_memory_pool_t *pool; switch_memory_pool_t *pool;
switch_thread_cond_t *started; switch_thread_cond_t *cond;
switch_buffer_t *audio_buffer; switch_buffer_t *audio_buffer;
switch_queue_t *video_queue; switch_queue_t *video_queue;
int playing; int playing;
int ending;
switch_mutex_t *video_mutex; switch_mutex_t *video_mutex;
switch_core_session_t *session; switch_core_session_t *session;
@ -171,7 +171,7 @@ static void vlc_mediaplayer_error_callback(const libvlc_event_t * event, void *
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Got a libvlc_MediaPlayerEncounteredError callback. mediaPlayer Status: %d\n", status); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Got a libvlc_MediaPlayerEncounteredError callback. mediaPlayer Status: %d\n", status);
if (status == libvlc_Error) { if (status == libvlc_Error) {
context->err = 1; context->err = 1;
switch_thread_cond_signal(context->started); switch_thread_cond_signal(context->cond);
} }
} }
static void vlc_media_state_callback(const libvlc_event_t * event, void * data) static void vlc_media_state_callback(const libvlc_event_t * event, void * data)
@ -181,7 +181,7 @@ static void vlc_media_state_callback(const libvlc_event_t * event, void * data)
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Got a libvlc_MediaStateChanged callback. New state: %d\n", new_state); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Got a libvlc_MediaStateChanged callback. New state: %d\n", new_state);
if (new_state == libvlc_Ended || new_state == libvlc_Error) { if (new_state == libvlc_Ended || new_state == libvlc_Error) {
switch_thread_cond_signal(context->started); switch_thread_cond_signal(context->cond);
} }
} }
@ -200,7 +200,7 @@ void vlc_auto_play_callback(void *data, const void *samples, unsigned count, int
if(!context->playing ) { if(!context->playing ) {
context->playing = 1; context->playing = 1;
switch_thread_cond_signal(context->started); switch_thread_cond_signal(context->cond);
} }
switch_mutex_unlock(context->audio_mutex); switch_mutex_unlock(context->audio_mutex);
} }
@ -223,7 +223,7 @@ void vlc_play_audio_callback(void *data, const void *samples, unsigned count, in
if (!context->playing) { if (!context->playing) {
context->playing = 1; context->playing = 1;
if (context->started) switch_thread_cond_signal(context->started); if (context->cond) switch_thread_cond_signal(context->cond);
} }
switch_mutex_unlock(context->audio_mutex); switch_mutex_unlock(context->audio_mutex);
@ -407,7 +407,7 @@ static switch_status_t vlc_file_open(switch_file_handle_t *handle, const char *p
switch_buffer_create_dynamic(&(context->audio_buffer), VLC_BUFFER_SIZE, VLC_BUFFER_SIZE * 8, 0); switch_buffer_create_dynamic(&(context->audio_buffer), VLC_BUFFER_SIZE, VLC_BUFFER_SIZE * 8, 0);
switch_mutex_init(&context->audio_mutex, SWITCH_MUTEX_NESTED, context->pool); switch_mutex_init(&context->audio_mutex, SWITCH_MUTEX_NESTED, context->pool);
switch_thread_cond_create(&(context->started), context->pool); switch_thread_cond_create(&(context->cond), context->pool);
if (switch_test_flag(handle, SWITCH_FILE_FLAG_READ)) { if (switch_test_flag(handle, SWITCH_FILE_FLAG_READ)) {
@ -531,7 +531,7 @@ static switch_status_t vlc_file_read(switch_file_handle_t *handle, void *data, s
switch_mutex_lock(context->audio_mutex); switch_mutex_lock(context->audio_mutex);
while (context->playing == 0 && status != libvlc_Ended && status != libvlc_Error) { while (context->playing == 0 && status != libvlc_Ended && status != libvlc_Error) {
switch_thread_cond_wait(context->started, context->audio_mutex); switch_thread_cond_wait(context->cond, context->audio_mutex);
status = libvlc_media_get_state(context->m); status = libvlc_media_get_state(context->m);
} }
@ -679,7 +679,7 @@ SWITCH_STANDARD_APP(play_video_function)
switch_mutex_init(&context->audio_mutex, SWITCH_MUTEX_NESTED, context->pool); switch_mutex_init(&context->audio_mutex, SWITCH_MUTEX_NESTED, context->pool);
switch_mutex_init(&context->video_mutex, SWITCH_MUTEX_NESTED, context->pool); switch_mutex_init(&context->video_mutex, SWITCH_MUTEX_NESTED, context->pool);
switch_thread_cond_create(&(context->started), context->pool); switch_thread_cond_create(&(context->cond), context->pool);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "VLC open %s for reading\n", path); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "VLC open %s for reading\n", path);
@ -812,14 +812,12 @@ int vlc_write_video_imem_get_callback(void *data, const char *cookie, int64_t *
int bytes = 0, bread = 0, blen = 0; int bytes = 0, bread = 0, blen = 0;
int r = 0; int r = 0;
if (!context->ending) {
switch_mutex_lock(context->audio_mutex); switch_mutex_lock(context->video_mutex);
if (!switch_queue_size(context->video_queue)) {
if (!switch_channel_ready(context->channel)) { switch_thread_cond_wait(context->cond, context->video_mutex);
if (!switch_buffer_inuse(context->audio_buffer) && switch_queue_size(context->video_queue) == 0) {
r = -1;
goto nada;
} }
switch_mutex_unlock(context->video_mutex);
} }
if (*cookie == 'v') { if (*cookie == 'v') {
@ -849,10 +847,11 @@ int vlc_write_video_imem_get_callback(void *data, const char *cookie, int64_t *
switch_img_convert(img, SWITCH_CONVERT_FMT_YUYV, *output, size); switch_img_convert(img, SWITCH_CONVERT_FMT_YUYV, *output, size);
switch_img_free(&img); switch_img_free(&img);
goto ok; return 0;
} }
switch_mutex_lock(context->audio_mutex);
if ((blen = switch_buffer_inuse(context->audio_buffer))) { if ((blen = switch_buffer_inuse(context->audio_buffer))) {
switch_buffer_read(context->audio_buffer, &context->pts, sizeof(context->pts)); switch_buffer_read(context->audio_buffer, &context->pts, sizeof(context->pts));
blen = switch_buffer_inuse(context->audio_buffer); blen = switch_buffer_inuse(context->audio_buffer);
@ -860,6 +859,7 @@ int vlc_write_video_imem_get_callback(void *data, const char *cookie, int64_t *
} }
if (!(bytes = blen)) { if (!(bytes = blen)) {
switch_mutex_unlock(context->audio_mutex);
goto nada; goto nada;
} }
@ -874,28 +874,24 @@ int vlc_write_video_imem_get_callback(void *data, const char *cookie, int64_t *
*size = (size_t) bread; *size = (size_t) bread;
//printf("A SIZE %ld ts %ld %p\n", *size, *pts, (void *)pthread_self());
ok:
switch_mutex_unlock(context->audio_mutex); switch_mutex_unlock(context->audio_mutex);
return 0; return 0;
nada: nada:
switch_mutex_unlock(context->audio_mutex); if (context->ending) {
if (*cookie == 'a') {
if (!switch_channel_ready(context->channel)) { if (!switch_buffer_inuse(context->audio_buffer)) {
if (!switch_buffer_inuse(context->audio_buffer) && switch_queue_size(context->video_queue) == 0) { r = -1;
r = -1; }
} else {
if (switch_queue_size(context->video_queue) == 0) {
r = -1;
}
} }
} }
//printf("nada %s\n", cookie);
//switch_core_timer_sync(&context->timer);
*dts = *pts = 0;
*size = 0; *size = 0;
*output = NULL; *output = NULL;
@ -914,16 +910,28 @@ static switch_status_t video_read_callback(switch_core_session_t *session, switc
vlc_frame_data_t *fdata = NULL; vlc_frame_data_t *fdata = NULL;
if (frame->img) { if (frame->img) {
unsigned int size = switch_queue_size(context->video_queue);
switch_img_copy(frame->img, &img_copy); switch_img_copy(frame->img, &img_copy);
switch_zmalloc(fdata, sizeof(*fdata)); switch_zmalloc(fdata, sizeof(*fdata));
switch_mutex_lock(context->audio_mutex);
switch_core_timer_sync(&context->timer); switch_core_timer_sync(&context->timer);
fdata->pts = context->timer.samplecount; fdata->pts = context->timer.samplecount;
switch_mutex_unlock(context->audio_mutex);
img_copy->user_priv = (void *) fdata; img_copy->user_priv = (void *) fdata;
switch_queue_push(context->video_queue, img_copy); switch_queue_push(context->video_queue, img_copy);
if (!size) { /* was empty before this push */
if (switch_mutex_trylock(context->video_mutex) == SWITCH_STATUS_SUCCESS) {
switch_thread_cond_signal(context->cond);
switch_mutex_unlock(context->video_mutex);
}
}
} }
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
@ -992,6 +1000,7 @@ SWITCH_STANDARD_APP(capture_video_function)
switch_buffer_create_dynamic(&(context->audio_buffer), VLC_BUFFER_SIZE, VLC_BUFFER_SIZE * 8, 0); switch_buffer_create_dynamic(&(context->audio_buffer), VLC_BUFFER_SIZE, VLC_BUFFER_SIZE * 8, 0);
switch_mutex_init(&context->audio_mutex, SWITCH_MUTEX_NESTED, context->pool); switch_mutex_init(&context->audio_mutex, SWITCH_MUTEX_NESTED, context->pool);
switch_mutex_init(&context->video_mutex, SWITCH_MUTEX_NESTED, context->pool); switch_mutex_init(&context->video_mutex, SWITCH_MUTEX_NESTED, context->pool);
switch_thread_cond_create(&context->cond, context->pool);
switch_core_timer_init(&context->timer, "soft", 1, 1000, context->pool); switch_core_timer_init(&context->timer, "soft", 1, 1000, context->pool);
@ -1106,7 +1115,15 @@ SWITCH_STANDARD_APP(capture_video_function)
} }
} }
while(switch_buffer_inuse(context->audio_buffer)) { switch_core_session_set_video_read_callback(session, NULL, NULL);
context->ending = 1;
if (switch_mutex_trylock(context->video_mutex) == SWITCH_STATUS_SUCCESS) {
switch_thread_cond_signal(context->cond);
switch_mutex_unlock(context->video_mutex);
}
while(switch_buffer_inuse(context->audio_buffer) || switch_queue_size(context->video_queue)) {
libvlc_state_t status = libvlc_media_get_state(context->m); libvlc_state_t status = libvlc_media_get_state(context->m);
if (status == libvlc_Ended || status == libvlc_Error || status == libvlc_Stopped ) { if (status == libvlc_Ended || status == libvlc_Error || status == libvlc_Stopped ) {
@ -1118,7 +1135,7 @@ SWITCH_STANDARD_APP(capture_video_function)
} }
context->playing = 0; context->playing = 0;
switch_core_session_set_video_read_callback(session, NULL, NULL);
if (context->mp) libvlc_media_player_stop(context->mp); if (context->mp) libvlc_media_player_stop(context->mp);
if (context->m) libvlc_media_release(context->m); if (context->m) libvlc_media_release(context->m);