diff --git a/html5/verto/video_demo/index.html b/html5/verto/video_demo/index.html index 5378d4b6a8..cece37d0b1 100644 --- a/html5/verto/video_demo/index.html +++ b/html5/verto/video_demo/index.html @@ -99,6 +99,7 @@ <button data-inline="true" id="hold">HOLD</button> <button data-inline="true" id="hupbtn">End Call</button> + <button data-inline="true" id="mutebtn">Toggle Audio Mute</button> <!-- <button data-inline="true" class="startxferbtn">Transfer</button>--> <span class="sharediv"> <button data-inline="true" id="sharebtn">Share</button> @@ -109,7 +110,8 @@ <button data-inline="true" id="smallerbtn">Smaller - </button> <button data-inline="true" id="biggerbtn">Bigger +</button> <button data-inline="true" id="fullbtn">Full Screen</button> - </span> + <button data-inline="true" id="vmutebtn">Toggle Video Mute</button> + </span> <div id="media"> <video id="webcam" autoplay="autoplay"></video> @@ -168,8 +170,12 @@ FreeSWITCH Verto™ Video Transcoding Demo </div> <br> - <a target="_CC2104" href="https://www.cluecon.com"><img border="0" width="300" src="img/cc_banner.gif"></a> - +<center> <table width="1024" border="0"> +<tr><td> <center><a target="_CC2104" href="https://www.cluecon.com"><img border="0" width="300" src="img/cc_banner.gif"></a></center></td> +<td><center> <img src="img/verto_black_web.gif" width="300"></center> + </td></tr> + </table></center><br><br> + <div id="offline"> <div id="errordisplay" style="font-weight:bold;font-size:18px;color:#ae0000"></div> @@ -234,20 +240,60 @@ function dial(ext) <div id="online" align="center" style="width:75%"> <div class="ui-field-contain"> -<div id="devices"> +<script> +function toggle_demo() { + +if ($('#demos').is(':visible')) { + $('#demos').hide(); + $('#showdemo').text("Show Demo Extensions"); +} else { + $('#devices').hide();$('#showdevices').show();$('#demos').show(); + $('#showdemo').text("Hide Demo Extensions"); +} + +} + +function toggle_device() { + +if ($('#devices').is(':visible')) { + $('#devices').hide(); + $('#showdevices').text("View Device Settings"); +} else { + $('#devices').show();$('#demos').hide(); + $('#showdevices').text("Hide Device Settings"); +} + +} + +</script> + +<button data-inline="true" id="showdemo" onclick="toggle_demo();">View Demo Extensions</button> +<button data-inline="true" id="showdevices" onclick="toggle_device();">View Device Settings</button> + <button data-inline="true"id="logoutbtn">Log Out</button> +<br><br> + + +<div id="devices" style="border-style:outset;border-width:2px"> <div id="camdiv"> -<legend><b>Camera</b>:</legend><select data-theme="a" data-overlay-theme="a" data-native-menu="false" id="usecamera"></select> + + <legend><b>Camera</b>:</legend><select data-theme="a" data-overlay-theme="a" data-native-menu="false" id="usecamera"></select> <br><br></div> <legend><b>Microphone</b>:</legend><select data-theme="a" data-overlay-theme="a" data-native-menu="false" id="usemic"></select> <Br clear="all"><Br> -<center><button data-inline="true" id="refreshbtn">Refresh Device List</button> -<button data-inline="true" id="hidedevices" onclick="$('#devices').hide();$('#showdevices').show()">Save Device Settings</button> -</center> -<Br clear="all"><hr><br> +<div style="xvisibility:hidden"> + <label><input id="use_vid" type="checkbox" value="foo" > Use Video</label> + <label><input id="use_stereo" type="checkbox" value="foo" > Stereo Audio</label> + <label><input id="use_stun" type="checkbox" value="foo" > Use STUN</label> +<!-- <label><input id="local_video" type="checkbox" value="foo" > Local Video</label>--> +</div> + + +<Br clear="all"> +<br><br> <div > <fieldset data-role="controlgroup" data-type="horizontal"> <legend><b>Video Quality</b>:</legend> @@ -336,12 +382,16 @@ function dial(ext) </fieldset> </div><br clear="all"><br> +<br><br> +<center><button data-inline="true" id="refreshbtn">Refresh Device List</button> +<button data-inline="true" id="hidedevices" onclick="$('#devices').hide();$('#showdevices').show()">Save Device Settings</button> + +</center> +<Br clear="all"><br> </div> - <button data-inline="true" id="showdemo" onclick="$('#demos').show();$('#showdemo').hide()">View Demo Extensions</button> -<button data-inline="true" id="showdevices" onclick="$('#devices').show();$('#showdevices').hide()">View Device Settings</button> <br><br> <div id="demos" style="border-style:outset"> @@ -371,14 +421,13 @@ function dial(ext) <div style="border-style:inset;border-width:1px;background-color:#eeeeee"> <button class="vidbtn" data-inline="true" onclick="dial('decode')">Video from your Webcam decoded then re-encoded w/ MOH</button> <button class="vidbtn" data-inline="true" onclick="dial('3500')">Video Transcoded Conference</button> - <button class="vidbtn" id="hidedemo" data-inline="true" onclick="$('#demos').hide();$('#showdemo').show();">Hide Demos</button> </div> </div> -<br><br><br> +<br><br><br><hr><br> <div class="ui-field-contain" style="text-align:right;"> <label for="name">Name</label> <input type="text" size="30" id="cidname"/> @@ -392,20 +441,15 @@ function dial(ext) <input type="text" id="ext""/> </div> <button data-inline="true" id="callbtn">Call Extension</button> - <br><br> +<br> +<hr> +<br><br> <div style="color:blue" id="main_info"> </div><br><br> - <img src="img/verto_black_web.gif" width="300"><br><br> - <button data-inline="true"id="logoutbtn">Log Out</button> + </div> + + <br> - -<div style="xvisibility:hidden"> - <label><input id="use_vid" type="checkbox" value="foo" > Use Video</label> - <label><input id="use_stereo" type="checkbox" value="foo" > Stereo Audio</label> - <label><input id="use_stun" type="checkbox" value="foo" > Use STUN</label> -<!-- <label><input id="local_video" type="checkbox" value="foo" > Local Video</label>--> -</div> - <br> <!-- <b>TEXT</b><br>To: <input type="text" size="20" id="textto"/> MSG: <input type="text" size="40" id="textmsg"/> diff --git a/html5/verto/video_demo/verto.js b/html5/verto/video_demo/verto.js index c827f9f553..71f6a7763d 100644 --- a/html5/verto/video_demo/verto.js +++ b/html5/verto/video_demo/verto.js @@ -509,6 +509,14 @@ $("#hupbtn").click(function() { cur_call = null; }); +$("#mutebtn").click(function() { + cur_call.dtmf("0"); +}); + +$("#vmutebtn").click(function() { + cur_call.dtmf("*0"); +}); + $("#fullbtn").click(function() { full_screen("webcam"); }); diff --git a/src/mod/applications/mod_fsv/mod_fsv.c b/src/mod/applications/mod_fsv/mod_fsv.c index d57d316e57..cbcb2c0d7c 100644 --- a/src/mod/applications/mod_fsv/mod_fsv.c +++ b/src/mod/applications/mod_fsv/mod_fsv.c @@ -498,18 +498,15 @@ SWITCH_STANDARD_APP(play_yuv_function) switch_image_t *img = NULL; switch_byte_t *yuv = NULL; int argc; - char *argv[3] = { 0 }; + int to = 0; + char *argv[5] = { 0 }; char *mydata = switch_core_session_strdup(session, data); uint32_t loops = 0; + switch_time_t done = 0; + int nots = 0; switch_channel_answer(channel); - while (switch_channel_ready(channel) && !switch_channel_test_flag(channel, CF_VIDEO)) { - if ((++loops % 100) == 0) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Waiting for video......\n"); - switch_ivr_sleep(session, 20, SWITCH_TRUE, NULL); - continue; - } - switch_channel_audio_sync(channel); switch_core_session_raw_read(session); @@ -522,6 +519,23 @@ SWITCH_STANDARD_APP(play_yuv_function) if (argc > 1) width = atoi(argv[1]); if (argc > 2) height = atoi(argv[2]); + if (argc > 3) to = atoi(argv[3]); + if (argc > 4) nots = atoi(argv[4]); + + done = switch_micro_time_now() + (to * 1000); + + + while (switch_channel_ready(channel) && !switch_channel_test_flag(channel, CF_VIDEO)) { + if ((++loops % 100) == 0) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Waiting for video......\n"); + switch_ivr_sleep(session, 20, SWITCH_TRUE, NULL); + + if (switch_micro_time_now() > done) { + goto done; + } + continue; + } + + width = width ? width : 352; height = height ? height : 288; @@ -568,6 +582,9 @@ SWITCH_STANDARD_APP(play_yuv_function) switch_set_flag((&vid_frame), SFF_RAW_RTP); // switch_set_flag((&vid_frame), SFF_PROXY_PACKET); + switch_core_session_request_video_refresh(session); + switch_core_media_gen_key_frame(session); + while (switch_channel_ready(channel)) { char ts_str[64]; @@ -578,6 +595,11 @@ SWITCH_STANDARD_APP(play_yuv_function) break; } + if (switch_micro_time_now() > done) { + goto done; + } + + switch_ivr_parse_all_events(session); //check for dtmf interrupts @@ -597,10 +619,14 @@ SWITCH_STANDARD_APP(play_yuv_function) } } + memset(read_frame->data, 0, read_frame->datalen); if (read_frame) switch_core_session_write_frame(session, read_frame, SWITCH_IO_FLAG_NONE, 0); - sprintf(ts_str, "%" SWITCH_TIME_T_FMT, switch_micro_time_now() / 1000); - switch_img_add_text(img->planes[SWITCH_PLANE_PACKED], width, 20, 20, ts_str); + if (!nots) { + sprintf(ts_str, "%" SWITCH_TIME_T_FMT, switch_micro_time_now() / 1000); + switch_img_add_text(img->planes[SWITCH_PLANE_PACKED], width, 20, 20, ts_str); + } + vid_frame.img = img; switch_core_session_write_video_frame(session, &vid_frame, SWITCH_IO_FLAG_NONE, 0); } diff --git a/src/mod/formats/mod_vlc/mod_vlc.c b/src/mod/formats/mod_vlc/mod_vlc.c index dd3513a21c..db03b1108e 100644 --- a/src/mod/formats/mod_vlc/mod_vlc.c +++ b/src/mod/formats/mod_vlc/mod_vlc.c @@ -81,6 +81,7 @@ struct vlc_file_context { switch_memory_pool_t *pool; switch_buffer_t *audio_buffer; switch_mutex_t *audio_mutex; + switch_mutex_t *cond_mutex; switch_thread_cond_t *cond; char *path; int samples; @@ -102,6 +103,7 @@ struct vlc_video_context { libvlc_media_player_t *mp; libvlc_media_t *m; switch_mutex_t *audio_mutex; + switch_mutex_t *cond_mutex; switch_file_handle_t fh; switch_memory_pool_t *pool; switch_thread_cond_t *cond; @@ -183,9 +185,9 @@ 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); if (status == libvlc_Error) { context->err = 1; - if (switch_mutex_lock(context->audio_mutex) == SWITCH_STATUS_SUCCESS) { + if (switch_mutex_lock(context->cond_mutex) == SWITCH_STATUS_SUCCESS) { switch_thread_cond_signal(context->cond); - switch_mutex_unlock(context->audio_mutex); + switch_mutex_unlock(context->cond_mutex); } } } @@ -197,9 +199,9 @@ 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); if (new_state == libvlc_Ended || new_state == libvlc_Error) { - if (switch_mutex_lock(context->audio_mutex) == SWITCH_STATUS_SUCCESS) { + if (switch_mutex_lock(context->cond_mutex) == SWITCH_STATUS_SUCCESS) { switch_thread_cond_signal(context->cond); - switch_mutex_unlock(context->audio_mutex); + switch_mutex_unlock(context->cond_mutex); } } } @@ -208,28 +210,54 @@ static void vlc_media_state_callback(const libvlc_event_t * event, void * data) static void vlc_mediaplayer_av_error_callback(const libvlc_event_t * event, void * data) { - vlc_video_context_t *context = (vlc_video_context_t *) data; - int status = libvlc_media_get_state(context->m); + vlc_file_context_t *acontext = (vlc_file_context_t *) data; + vlc_video_context_t *vcontext = acontext->vcontext; + + int status = libvlc_media_get_state(vcontext->m); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Got a libvlc_MediaPlayerEncounteredError callback. mediaPlayer Status: %d\n", status); if (status == libvlc_Error) { - context->err = 1; - if (switch_mutex_lock(context->audio_mutex) == SWITCH_STATUS_SUCCESS) { - switch_thread_cond_signal(context->cond); - switch_mutex_unlock(context->audio_mutex); + vcontext->err = 1; + + if (vcontext && vcontext->video_queue) { + switch_queue_push(vcontext->video_queue, NULL); + } + + if (vcontext && vcontext->video_queue) { + switch_queue_push(vcontext->video_queue, NULL); + } + if (switch_mutex_lock(acontext->cond_mutex) == SWITCH_STATUS_SUCCESS) { + switch_thread_cond_signal(acontext->cond); + switch_mutex_unlock(acontext->cond_mutex); + } + if (switch_mutex_lock(vcontext->cond_mutex) == SWITCH_STATUS_SUCCESS) { + switch_thread_cond_signal(vcontext->cond); + switch_mutex_unlock(vcontext->cond_mutex); } } } static void vlc_media_av_state_callback(const libvlc_event_t * event, void * data) { - vlc_video_context_t *context = (vlc_video_context_t *) data; + vlc_file_context_t *acontext = (vlc_file_context_t *) data; + vlc_video_context_t *vcontext = acontext->vcontext; int new_state = event->u.media_state_changed.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 (switch_mutex_lock(context->audio_mutex) == SWITCH_STATUS_SUCCESS) { - switch_thread_cond_signal(context->cond); - switch_mutex_unlock(context->audio_mutex); + if (new_state == libvlc_Ended || new_state == libvlc_Error || new_state == 6) { + vcontext->err = 1; + + if (vcontext && vcontext->video_queue) { + switch_queue_push(vcontext->video_queue, NULL); + } + + if (switch_mutex_lock(acontext->cond_mutex) == SWITCH_STATUS_SUCCESS) { + switch_thread_cond_signal(acontext->cond); + switch_mutex_unlock(acontext->cond_mutex); + } + + if (switch_mutex_lock(vcontext->cond_mutex) == SWITCH_STATUS_SUCCESS) { + switch_thread_cond_signal(vcontext->cond); + switch_mutex_unlock(vcontext->cond_mutex); } } } @@ -249,7 +277,10 @@ void vlc_auto_play_callback(void *data, const void *samples, unsigned count, int if(!context->playing ) { context->playing = 1; - switch_thread_cond_signal(context->cond); + if (switch_mutex_trylock(context->cond_mutex) == SWITCH_STATUS_SUCCESS) { + switch_thread_cond_signal(context->cond); + switch_mutex_unlock(context->cond_mutex); + } } switch_mutex_unlock(context->audio_mutex); } @@ -257,25 +288,64 @@ void vlc_auto_play_callback(void *data, const void *samples, unsigned count, int #define FORCE_SPLIT 1 void vlc_play_audio_callback(void *data, const void *samples, unsigned count, int64_t pts) { - vlc_video_context_t *context = (vlc_video_context_t *) data; + vlc_video_context_t *vcontext = (vlc_video_context_t *) data; switch_size_t bytes; - switch_mutex_lock(context->audio_mutex); + switch_mutex_lock(vcontext->audio_mutex); - bytes = switch_buffer_inuse(context->audio_buffer); + bytes = switch_buffer_inuse(vcontext->audio_buffer); if (bytes > 2000000) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Buffer overflow %d\n", (int)bytes); - switch_buffer_zero(context->audio_buffer); + switch_buffer_zero(vcontext->audio_buffer); } - switch_buffer_write(context->audio_buffer, samples, count * 2 * context->channels); + switch_buffer_write(vcontext->audio_buffer, samples, count * 2 * vcontext->channels); - if (!context->playing) { - context->playing = 1; - if (context->cond) switch_thread_cond_signal(context->cond); + switch_mutex_unlock(vcontext->audio_mutex); + + if (!vcontext->playing) { + vcontext->playing = 1; + + if (switch_mutex_trylock(vcontext->cond_mutex) == SWITCH_STATUS_SUCCESS) { + switch_thread_cond_signal(vcontext->cond); + switch_mutex_unlock(vcontext->cond_mutex); + } } - switch_mutex_unlock(context->audio_mutex); + + + // switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "VLC callback, play audio: %d \n", count); +} + + +void vlc_file_play_audio_callback(void *data, const void *samples, unsigned count, int64_t pts) { + vlc_file_context_t *acontext = (vlc_file_context_t *) data; + vlc_video_context_t *vcontext = acontext->vcontext; + + switch_size_t bytes; + + switch_mutex_lock(vcontext->audio_mutex); + + bytes = switch_buffer_inuse(vcontext->audio_buffer); + if (bytes > 2000000) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Buffer overflow %d\n", (int)bytes); + switch_buffer_zero(vcontext->audio_buffer); + } + + switch_buffer_write(vcontext->audio_buffer, samples, count * 2 * vcontext->channels); + + switch_mutex_unlock(vcontext->audio_mutex); + + if (!vcontext->playing) { + vcontext->playing = 1; + + if (switch_mutex_trylock(acontext->cond_mutex) == SWITCH_STATUS_SUCCESS) { + switch_thread_cond_signal(acontext->cond); + switch_mutex_unlock(acontext->cond_mutex); + } + } + + // switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "VLC callback, play audio: %d \n", count); } @@ -386,6 +456,15 @@ unsigned video_format_setup_callback(void **opaque, char *chroma, unsigned *widt *height = context->force_height; } + if (*height == 738) { + *height = 720; + } + + if (*height == 1090) { + *height = 1080; + } + + *pitches = (*width) * 2; *lines = (*height); @@ -500,10 +579,12 @@ static switch_status_t av_init_handle(switch_file_handle_t *handle, switch_image switch_buffer_create_dynamic(&(vcontext->audio_buffer), VLC_BUFFER_SIZE, VLC_BUFFER_SIZE * 8, 0); switch_mutex_init(&vcontext->audio_mutex, SWITCH_MUTEX_NESTED, vcontext->pool); + switch_mutex_init(&vcontext->cond_mutex, SWITCH_MUTEX_NESTED, vcontext->pool); + switch_mutex_init(&acontext->cond_mutex, SWITCH_MUTEX_NESTED, acontext->pool); switch_mutex_init(&vcontext->video_mutex, SWITCH_MUTEX_NESTED, vcontext->pool); switch_thread_cond_create(&vcontext->cond, vcontext->pool); switch_thread_cond_create(&acontext->cond, acontext->pool); - + switch_core_timer_init(&vcontext->timer, "soft", 1, 1000, vcontext->pool); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "VLC open %s for writing\n", acontext->path); @@ -632,7 +713,12 @@ static switch_status_t vlc_file_av_open(switch_file_handle_t *handle, const char switch_mutex_init(&vcontext->audio_mutex, SWITCH_MUTEX_NESTED, vcontext->pool); switch_mutex_init(&vcontext->video_mutex, SWITCH_MUTEX_NESTED, vcontext->pool); + switch_mutex_init(&vcontext->cond_mutex, SWITCH_MUTEX_NESTED, vcontext->pool); + switch_mutex_init(&acontext->audio_mutex, SWITCH_MUTEX_NESTED, acontext->pool); + switch_mutex_init(&acontext->cond_mutex, SWITCH_MUTEX_NESTED, acontext->pool); + switch_queue_create(&vcontext->video_queue, SWITCH_CORE_QUEUE_LEN, vcontext->pool); + switch_thread_cond_create(&acontext->cond, acontext->pool); switch_thread_cond_create(&vcontext->cond, vcontext->pool); switch_buffer_create_dynamic(&vcontext->audio_buffer, VLC_BUFFER_SIZE, VLC_BUFFER_SIZE * 8, 0); @@ -642,13 +728,13 @@ static switch_status_t vlc_file_av_open(switch_file_handle_t *handle, const char libvlc_audio_set_format(vcontext->mp, "S16N", vcontext->samplerate, handle->channels); m_event_manager = libvlc_media_event_manager(vcontext->m); - libvlc_event_attach(m_event_manager, libvlc_MediaStateChanged, vlc_media_av_state_callback, (void *) vcontext); + libvlc_event_attach(m_event_manager, libvlc_MediaStateChanged, vlc_media_av_state_callback, (void *) acontext); mp_event_manager = libvlc_media_player_event_manager(vcontext->mp); - libvlc_event_attach(mp_event_manager, libvlc_MediaPlayerEncounteredError, vlc_mediaplayer_av_error_callback, (void *) vcontext); + libvlc_event_attach(mp_event_manager, libvlc_MediaPlayerEncounteredError, vlc_mediaplayer_av_error_callback, (void *) acontext); - libvlc_audio_set_callbacks(vcontext->mp, vlc_play_audio_callback, NULL,NULL,NULL,NULL, (void *) vcontext); - + libvlc_audio_set_callbacks(vcontext->mp, vlc_file_play_audio_callback, NULL,NULL,NULL,NULL, (void *) acontext); + libvlc_video_set_format_callbacks(vcontext->mp, video_format_setup_callback, video_format_clean_callback); libvlc_video_set_callbacks(vcontext->mp, vlc_video_lock_callback, vlc_video_av_unlock_callback, vlc_video_display_callback, vcontext); @@ -680,6 +766,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_mutex_init(&context->audio_mutex, SWITCH_MUTEX_NESTED, context->pool); switch_thread_cond_create(&(context->cond), context->pool); + switch_mutex_init(&context->cond_mutex, SWITCH_MUTEX_NESTED, context->pool); } handle->private_info = context; @@ -800,28 +887,30 @@ static switch_status_t vlc_file_av_read(switch_file_handle_t *handle, void *data return SWITCH_STATUS_GENERR; } - switch_mutex_lock(vcontext->audio_mutex); + while (vcontext->playing == 0 && status != libvlc_Ended && status != libvlc_Error) { - switch_thread_cond_wait(vcontext->cond, vcontext->audio_mutex); + switch_mutex_lock(acontext->cond_mutex); + switch_thread_cond_wait(acontext->cond, acontext->cond_mutex); + switch_mutex_unlock(acontext->cond_mutex); status = libvlc_media_get_state(vcontext->m); } if (vcontext->err == 1) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "VLC error\n"); - switch_mutex_unlock(vcontext->audio_mutex); return SWITCH_STATUS_FALSE; } - switch_mutex_unlock(vcontext->audio_mutex); if (!vcontext->vid_ready) { - switch_mutex_lock(vcontext->audio_mutex); + switch_mutex_lock(vcontext->cond_mutex); if (!vcontext->vid_ready) { - switch_thread_cond_wait(vcontext->cond, vcontext->audio_mutex); + switch_thread_cond_wait(vcontext->cond, vcontext->cond_mutex); } - switch_mutex_unlock(vcontext->audio_mutex); + switch_mutex_unlock(vcontext->cond_mutex); } + while(!switch_buffer_inuse(vcontext->audio_buffer) && !vcontext->err && vcontext->playing) { + switch_cond_next(); + } switch_mutex_lock(vcontext->audio_mutex); read = switch_buffer_read(vcontext->audio_buffer, data, bytes); @@ -869,18 +958,19 @@ static switch_status_t vlc_file_read(switch_file_handle_t *handle, void *data, s return SWITCH_STATUS_GENERR; } - switch_mutex_lock(context->audio_mutex); + switch_mutex_lock(context->cond_mutex); while (context->playing == 0 && status != libvlc_Ended && status != libvlc_Error) { - switch_thread_cond_wait(context->cond, context->audio_mutex); + switch_thread_cond_wait(context->cond, context->cond_mutex); status = libvlc_media_get_state(context->m); } + switch_mutex_lock(context->cond_mutex); if (context->err == 1) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "VLC error\n"); - switch_mutex_unlock(context->audio_mutex); return SWITCH_STATUS_FALSE; } + switch_mutex_lock(context->audio_mutex); read = switch_buffer_read(context->audio_buffer, data, bytes); switch_mutex_unlock(context->audio_mutex); @@ -914,9 +1004,9 @@ static switch_status_t vlc_file_read_video(switch_file_handle_t *handle, switch_ if (!vcontext->vid_ready) { vcontext->vid_ready = 1; - if (switch_mutex_trylock(vcontext->audio_mutex) == SWITCH_STATUS_SUCCESS) { + if (switch_mutex_trylock(vcontext->cond_mutex) == SWITCH_STATUS_SUCCESS) { switch_thread_cond_signal(vcontext->cond); - switch_mutex_unlock(vcontext->audio_mutex); + switch_mutex_unlock(vcontext->cond_mutex); } } @@ -964,9 +1054,9 @@ static switch_status_t vlc_file_write_video(switch_file_handle_t *handle, switch if (!vcontext->vid_ready) { vcontext->vid_ready = 1; - if (switch_mutex_trylock(vcontext->audio_mutex) == SWITCH_STATUS_SUCCESS) { + if (switch_mutex_trylock(vcontext->cond_mutex) == SWITCH_STATUS_SUCCESS) { switch_thread_cond_signal(vcontext->cond); - switch_mutex_unlock(vcontext->audio_mutex); + switch_mutex_unlock(vcontext->cond_mutex); } } @@ -1004,11 +1094,11 @@ static switch_status_t vlc_file_av_write(switch_file_handle_t *handle, void *dat } if (!vcontext->vid_ready) { - switch_mutex_lock(vcontext->audio_mutex); + switch_mutex_lock(vcontext->cond_mutex); if (!vcontext->vid_ready) { - switch_thread_cond_wait(vcontext->cond, vcontext->audio_mutex); + switch_thread_cond_wait(vcontext->cond, vcontext->cond_mutex); } - switch_mutex_unlock(vcontext->audio_mutex); + switch_mutex_unlock(vcontext->cond_mutex); } switch_mutex_lock(vcontext->audio_mutex); @@ -1065,14 +1155,14 @@ static switch_status_t vlc_file_av_close(switch_file_handle_t *handle) if (switch_test_flag(handle, SWITCH_FILE_FLAG_WRITE) && switch_test_flag(handle, SWITCH_FILE_FLAG_VIDEO)) { - if (vcontext->cond && switch_mutex_trylock(vcontext->video_mutex) == SWITCH_STATUS_SUCCESS) { + if (vcontext->cond && switch_mutex_trylock(vcontext->cond_mutex) == SWITCH_STATUS_SUCCESS) { switch_thread_cond_signal(vcontext->cond); - switch_mutex_unlock(vcontext->video_mutex); + switch_mutex_unlock(vcontext->cond_mutex); } - if (acontext->cond && switch_mutex_trylock(vcontext->audio_mutex) == SWITCH_STATUS_SUCCESS) { + if (acontext->cond && switch_mutex_trylock(acontext->cond_mutex) == SWITCH_STATUS_SUCCESS) { switch_thread_cond_signal(acontext->cond); - switch_mutex_unlock(vcontext->audio_mutex); + switch_mutex_unlock(acontext->cond_mutex); } while(switch_buffer_inuse(vcontext->audio_buffer) || switch_queue_size(vcontext->video_queue)) { @@ -1212,6 +1302,8 @@ SWITCH_STANDARD_APP(play_video_function) 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->audio_mutex, SWITCH_MUTEX_NESTED, context->pool); + switch_mutex_init(&context->cond_mutex, SWITCH_MUTEX_NESTED, context->pool); switch_thread_cond_create(&(context->cond), context->pool); @@ -1349,11 +1441,11 @@ int vlc_write_video_imem_get_callback(void *data, const char *cookie, int64_t * int r = 0; if (!context->ending) { - switch_mutex_lock(context->video_mutex); + switch_mutex_lock(context->cond_mutex); if (!switch_queue_size(context->video_queue)) { - switch_thread_cond_wait(context->cond, context->video_mutex); + switch_thread_cond_wait(context->cond, context->cond_mutex); } - switch_mutex_unlock(context->video_mutex); + switch_mutex_unlock(context->cond_mutex); } if (*cookie == 'v') { @@ -1464,9 +1556,9 @@ static switch_status_t video_read_callback(switch_core_session_t *session, switc 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) { + if (switch_mutex_trylock(context->cond_mutex) == SWITCH_STATUS_SUCCESS) { switch_thread_cond_signal(context->cond); - switch_mutex_unlock(context->video_mutex); + switch_mutex_unlock(context->cond_mutex); } } } @@ -1537,6 +1629,7 @@ SWITCH_STANDARD_APP(capture_video_function) 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->video_mutex, SWITCH_MUTEX_NESTED, context->pool); + switch_mutex_init(&context->cond_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); @@ -1678,9 +1771,9 @@ SWITCH_STANDARD_APP(capture_video_function) switch_core_session_set_video_read_callback(session, NULL, NULL); context->ending = 1; - if (switch_mutex_trylock(context->video_mutex) == SWITCH_STATUS_SUCCESS) { + if (switch_mutex_trylock(context->cond_mutex) == SWITCH_STATUS_SUCCESS) { switch_thread_cond_signal(context->cond); - switch_mutex_unlock(context->video_mutex); + switch_mutex_unlock(context->cond_mutex); } while(switch_buffer_inuse(context->audio_buffer) || switch_queue_size(context->video_queue)) { @@ -1843,6 +1936,9 @@ static switch_status_t setup_tech_pvt(switch_core_session_t *osession, switch_co 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->cond_mutex, SWITCH_MUTEX_NESTED, context->pool); + + switch_thread_cond_create(&(context->cond), context->pool); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "VLC open %s for reading\n", path); diff --git a/src/switch_core_session.c b/src/switch_core_session.c index 5f0d126157..e1ebce14d6 100644 --- a/src/switch_core_session.c +++ b/src/switch_core_session.c @@ -2691,6 +2691,9 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_execute_application_get_flag switch_application_interface_t *application_interface; switch_status_t status = SWITCH_STATUS_SUCCESS; + switch_core_session_request_video_refresh(session); + switch_core_media_gen_key_frame(session); + if (switch_channel_down_nosig(session->channel)) { char *p; if (!arg && (p = strstr(app, "::"))) { diff --git a/src/switch_core_state_machine.c b/src/switch_core_state_machine.c index 534da052dd..c066cd00b7 100644 --- a/src/switch_core_state_machine.c +++ b/src/switch_core_state_machine.c @@ -361,7 +361,8 @@ void switch_core_state_machine_init(switch_memory_pool_t *pool) if (state < CS_HANGUP && switch_channel_get_callstate(session->channel) == CCS_UNHELD) { \ switch_channel_set_callstate(session->channel, CCS_ACTIVE); \ } \ - switch_core_session_request_video_refresh(session); \ + switch_core_session_request_video_refresh(session); \ + switch_core_media_gen_key_frame(session); \ if (!driver_state_handler->on_##__STATE || (driver_state_handler->on_##__STATE(session) == SWITCH_STATUS_SUCCESS \ )) { \ while (do_extra_handlers && (application_state_handler = switch_channel_get_state_handler(session->channel, index++)) != 0) { \