mod_vlc adding faster response time to files. No longer has a one second delay before audio starts to play.

This commit is contained in:
William King 2012-03-24 14:09:24 -07:00
parent e4788c1d88
commit 6ef6d2419e
1 changed files with 86 additions and 42 deletions

View File

@ -49,7 +49,8 @@ static char *vlc_file_supported_formats[SWITCH_MAX_CODECS] = { 0 };
/* Change valud to -vvv for vlc related debug. Be careful since vlc is at least as verbose as FS about logging */ /* Change valud to -vvv for vlc related debug. Be careful since vlc is at least as verbose as FS about logging */
const char *vlc_args = ""; const char *vlc_args = "";
libvlc_instance_t *inst; libvlc_instance_t *read_inst;
libvlc_instance_t *inst_out;
struct vlc_file_context { struct vlc_file_context {
libvlc_media_player_t *mp; libvlc_media_player_t *mp;
@ -58,10 +59,12 @@ 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;
char *path; char *path;
int samples; int samples;
int playing; int playing;
int err; int err;
int pts;
}; };
typedef struct vlc_file_context vlc_file_context_t; typedef struct vlc_file_context vlc_file_context_t;
@ -79,6 +82,11 @@ void vlc_auto_play_callback(void *data, const void *samples, unsigned count, int
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Buffer error\n"); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Buffer error\n");
} }
} }
if(! context->playing ) {
context->playing = 1;
switch_thread_cond_signal(context->started);
}
switch_mutex_unlock(context->audio_mutex); switch_mutex_unlock(context->audio_mutex);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "VLC callback for %s %d \n", context->path, count); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "VLC callback for %s %d \n", context->path, count);
@ -87,43 +95,56 @@ void vlc_auto_play_callback(void *data, const void *samples, unsigned count, int
static switch_status_t vlc_file_open(switch_file_handle_t *handle, const char *path) static switch_status_t vlc_file_open(switch_file_handle_t *handle, const char *path)
{ {
vlc_file_context_t *context; vlc_file_context_t *context;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "VLC open %s\n", path);
context = switch_core_alloc(handle->memory_pool, sizeof(*context)); context = switch_core_alloc(handle->memory_pool, sizeof(*context));
context->pool = handle->memory_pool; context->pool = handle->memory_pool;
context->path = switch_core_strdup(context->pool, path); context->path = switch_core_strdup(context->pool, path);
switch_buffer_create_dynamic(&(context->audio_buffer), VLC_BUFFER_SIZE, VLC_BUFFER_SIZE * 2, 0); switch_buffer_create_dynamic(&(context->audio_buffer), VLC_BUFFER_SIZE, VLC_BUFFER_SIZE * 2, 0);
/* Determine if this is a url or a path */
/* TODO: Change this so that it tries local files first, and then if it fails try location. */
if(! strncmp(context->path, "http", 4)){
context->m = libvlc_media_new_location(inst, context->path);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "VLC Path is http %s\n", context->path);
} else if (! strncmp(context->path, "mms", 3)){
context->m = libvlc_media_new_path(inst, context->path);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "VLC Path is mms %s\n", context->path);
} else if (! strncmp(context->path, "/", 1)){
context->m = libvlc_media_new_path(inst, context->path);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "VLC Path is file %s\n", context->path);
} else {
context->m = libvlc_media_new_location(inst, context->path);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "VLC Path is unknown type %s\n", context->path);
}
context->playing = 0;
context->err = 0;
context->mp = libvlc_media_player_new_from_media(context->m);
if ( !handle->samplerate)
handle->samplerate = 16000;
libvlc_audio_set_format(context->mp, "S16N", handle->samplerate, 1);
libvlc_audio_set_callbacks(context->mp, vlc_auto_play_callback, NULL,NULL,NULL,NULL, (void *) context);
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);
if (switch_test_flag(handle, SWITCH_FILE_FLAG_READ)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "VLC open %s for reading\n", path);
/* Determine if this is a url or a path */
/* TODO: Change this so that it tries local files first, and then if it fails try location. */
if(! strncmp(context->path, "http", 4)){
context->m = libvlc_media_new_location(read_inst, context->path);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "VLC Path is http %s\n", context->path);
} else if (! strncmp(context->path, "mms", 3)){
context->m = libvlc_media_new_path(read_inst, context->path);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "VLC Path is mms %s\n", context->path);
} else if (! strncmp(context->path, "/", 1)){
context->m = libvlc_media_new_path(read_inst, context->path);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "VLC Path is file %s\n", context->path);
} else {
context->m = libvlc_media_new_location(read_inst, context->path);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "VLC Path is unknown type %s\n", context->path);
}
context->playing = 0;
context->err = 0;
context->mp = libvlc_media_player_new_from_media(context->m);
if ( !handle->samplerate)
handle->samplerate = 16000;
libvlc_audio_set_format(context->mp, "S16N", handle->samplerate, 1);
libvlc_audio_set_callbacks(context->mp, vlc_auto_play_callback, NULL,NULL,NULL,NULL, (void *) context);
libvlc_media_player_play(context->mp);
} else if (switch_test_flag(handle, SWITCH_FILE_FLAG_WRITE)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "VLC does not yet support writing to a output stream");
return SWITCH_STATUS_GENERR;
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "VLC tried to open %s for unknown reason\n", path);
return SWITCH_STATUS_GENERR;
}
handle->private_info = context; handle->private_info = context;
@ -133,7 +154,7 @@ static switch_status_t vlc_file_open(switch_file_handle_t *handle, const char *p
static switch_status_t vlc_file_read(switch_file_handle_t *handle, void *data, size_t *len) static switch_status_t vlc_file_read(switch_file_handle_t *handle, void *data, size_t *len)
{ {
vlc_file_context_t *context = handle->private_info; vlc_file_context_t *context = handle->private_info;
size_t bytes = *len * sizeof(int16_t); size_t bytes = *len * sizeof(int16_t), read;
libvlc_state_t status; libvlc_state_t status;
if (!context) { if (!context) {
@ -145,22 +166,33 @@ static switch_status_t vlc_file_read(switch_file_handle_t *handle, void *data, s
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "VLC error\n"); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "VLC error\n");
return SWITCH_STATUS_GENERR; return SWITCH_STATUS_GENERR;
} }
if(! context->playing ) {
context->playing = 1;
libvlc_media_player_play(context->mp);
}
status = libvlc_media_get_state(context->m); status = libvlc_media_get_state(context->m);
if (status == 6 || status == 7) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "VLC media state: %d\n", (int) status); if (status == 7) {
return SWITCH_STATUS_GENERR; return SWITCH_STATUS_GENERR;
} }
switch_mutex_lock(context->audio_mutex);
while (context->playing == 0) {
switch_thread_cond_wait(context->started, context->audio_mutex);
}
switch_mutex_unlock(context->audio_mutex);
switch_mutex_lock(context->audio_mutex); switch_mutex_lock(context->audio_mutex);
switch_buffer_read(context->audio_buffer, data, bytes); read = switch_buffer_read(context->audio_buffer, data, bytes);
switch_mutex_unlock(context->audio_mutex); switch_mutex_unlock(context->audio_mutex);
if (!read && (status == 5 || status == 6)) {
return SWITCH_STATUS_FALSE;
} else if (!read) {
read = 2000;
memset(data, 255, read);
}
if (read)
*len = read/2;
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
@ -171,6 +203,14 @@ static switch_status_t vlc_file_close(switch_file_handle_t *handle)
libvlc_media_player_stop(context->mp); libvlc_media_player_stop(context->mp);
libvlc_media_release(context->m); libvlc_media_release(context->m);
context->playing = 0;
if( context->mp )
libvlc_media_player_stop(context->mp);
if( context->m )
libvlc_media_release(context->m);
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
@ -190,9 +230,10 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_vlc_load)
file_interface->file_open = vlc_file_open; file_interface->file_open = vlc_file_open;
file_interface->file_close = vlc_file_close; file_interface->file_close = vlc_file_close;
file_interface->file_read = vlc_file_read; file_interface->file_read = vlc_file_read;
file_interface->file_write = vlc_file_write;
/* load the vlc engine. */ /* load the vlc engine. */
inst = libvlc_new(1, &vlc_args); read_inst = libvlc_new(1, &vlc_args);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Initialized VLC instance\n"); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Initialized VLC instance\n");
@ -205,7 +246,10 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_vlc_load)
Macro expands to: switch_status_t mod_vlc_shutdown() */ Macro expands to: switch_status_t mod_vlc_shutdown() */
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_vlc_shutdown) SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_vlc_shutdown)
{ {
libvlc_release(inst); if ( read_inst != NULL )
libvlc_release(read_inst);
if ( inst_out != NULL )
libvlc_release(inst_out);
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }