]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
FS-8909 #resolve [Add feature to play background video while recording inbound video]
authorAnthony Minessale <anthm@freeswitch.org>
Tue, 8 Mar 2016 01:59:03 +0000 (19:59 -0600)
committerAnthony Minessale <anthm@freeswitch.org>
Tue, 8 Mar 2016 01:59:10 +0000 (19:59 -0600)
src/include/switch_core.h
src/include/switch_core_media.h
src/include/switch_module_interfaces.h
src/include/switch_types.h
src/mod/applications/mod_av/avformat.c
src/mod/formats/mod_vlc/mod_vlc.c
src/switch_core_file.c
src/switch_core_media.c
src/switch_ivr_play_say.c

index 8014e95eae4e632d6c945905447863ba45be34c4..552ea1c62190439c23da8544e3e2cd4861796754 100644 (file)
@@ -1929,6 +1929,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_file_get_string(_In_ switch_file_han
 */
 SWITCH_DECLARE(switch_status_t) switch_core_file_close(_In_ switch_file_handle_t *fh);
 
+SWITCH_DECLARE(switch_status_t) switch_core_file_command(switch_file_handle_t *fh, switch_file_command_t command);
+
 SWITCH_DECLARE(switch_status_t) switch_core_file_truncate(switch_file_handle_t *fh, int64_t offset);
 SWITCH_DECLARE(switch_bool_t) switch_core_file_has_video(switch_file_handle_t *fh);
 
index 4528da03c8ef1edcf15f47dacaa184227d3a97cf..65c400ea33d65e2f5cb1f6d3e1df5a0049620861 100644 (file)
@@ -340,6 +340,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_read_lock_unlock(switch_core_s
 SWITCH_DECLARE(void) switch_core_session_stop_media(switch_core_session_t *session);
 SWITCH_DECLARE(switch_media_flow_t) switch_core_session_media_flow(switch_core_session_t *session, switch_media_type_t type);
 SWITCH_DECLARE(switch_status_t) switch_core_media_get_vid_params(switch_core_session_t *session, switch_vid_params_t *vid_params);
+SWITCH_DECLARE(switch_status_t) switch_core_media_lock_video_file(switch_core_session_t *session, switch_rw_t rw);
+SWITCH_DECLARE(switch_status_t) switch_core_media_unlock_video_file(switch_core_session_t *session, switch_rw_t rw);
 SWITCH_DECLARE(switch_status_t) switch_core_media_set_video_file(switch_core_session_t *session, switch_file_handle_t *fh, switch_rw_t rw);
 SWITCH_DECLARE(switch_file_handle_t *) switch_core_media_get_video_file(switch_core_session_t *session, switch_rw_t rw);
 SWITCH_DECLARE(switch_bool_t) switch_core_session_in_video_thread(switch_core_session_t *session);
index 8621e53d6f67a61888623b38639a8a5dfd93c46f..4a3e8c71f806d72292bdad45e004bd01d369129a 100644 (file)
@@ -289,6 +289,8 @@ struct switch_file_interface {
        switch_status_t (*file_set_string) (switch_file_handle_t *fh, switch_audio_col_t col, const char *string);
        /*! function to get meta data */
        switch_status_t (*file_get_string) (switch_file_handle_t *fh, switch_audio_col_t col, const char **string);
+       /*! function to control the underlying tech of the file  */
+       switch_status_t (*file_command) (switch_file_handle_t *fh, switch_file_command_t command);
        /*! list of supported file extensions */
        char **extens;
        switch_thread_rwlock_t *rwlock;
index d149fb60c081783d59d6c24040b4d928c79e6f1c..31f4ebfc31fe79cac40b96e628ba8bfa4aa25ee9 100644 (file)
@@ -1811,7 +1811,8 @@ typedef enum {
        SWITCH_FILE_WRITE_OVER = (1 << 16),
        SWITCH_FILE_NOMUX = (1 << 17),
        SWITCH_FILE_BREAK_ON_CHANGE = (1 << 18),
-       SWITCH_FILE_FLAG_VIDEO = (1 << 19)
+       SWITCH_FILE_FLAG_VIDEO = (1 << 19),
+       SWITCH_FILE_FLAG_VIDEO_EOF = (1 << 20)
 } switch_file_flag_enum_t;
 typedef uint32_t switch_file_flag_t;
 
@@ -2595,6 +2596,10 @@ typedef enum {
        SPY_DUAL_CROP
 } switch_vid_spy_fmt_t;
 
+typedef enum {
+       SCFC_FLUSH_AUDIO
+} switch_file_command_t;
+
 SWITCH_END_EXTERN_C
 #endif
 /* For Emacs:
index a5faa2e4bc2aee30ab66676f963ed4ef7d0464bc..190a23456f44f0ecabbef6771943bfbc03180818 100644 (file)
@@ -1770,6 +1770,23 @@ static switch_status_t av_file_write(switch_file_handle_t *handle, void *data, s
        return status;
 }
 
+static switch_status_t av_file_command(switch_file_handle_t *handle, switch_file_command_t command)
+{
+       av_file_context_t *context = (av_file_context_t *)handle->private_info;
+
+       switch(command) {
+       case SCFC_FLUSH_AUDIO:
+               switch_mutex_lock(context->mutex);              
+               switch_buffer_zero(context->audio_buffer);
+               switch_mutex_unlock(context->mutex);            
+               break;
+       default:
+               break;
+       }
+
+       return SWITCH_STATUS_SUCCESS;
+}
+
 static switch_status_t av_file_close(switch_file_handle_t *handle)
 {
        av_file_context_t *context = (av_file_context_t *)handle->private_info;
@@ -1840,9 +1857,8 @@ static switch_status_t av_file_read(switch_file_handle_t *handle, void *data, si
        }
 
        switch_mutex_lock(context->mutex);
-       size = switch_buffer_inuse(context->audio_buffer);
-       if (size > *len * context->audio_st.channels * 2) size = *len * context->audio_st.channels * 2;
-       if (size) size = switch_buffer_read(context->audio_buffer, data, size);
+
+       size = switch_buffer_read(context->audio_buffer, data, need);
        switch_mutex_unlock(context->mutex);
 
        if (size == 0) {
@@ -2174,6 +2190,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_avformat_load)
        file_interface->file_seek = av_file_seek;
        file_interface->file_set_string = av_file_set_string;
        file_interface->file_get_string = av_file_get_string;
+       file_interface->file_command = av_file_command;
 
        SWITCH_ADD_API(api_interface, "av_format", "av information", av_format_api_function, "");
 
index e9769fc084dd8cfb3c134bd5aa544e5a6241a4b7..dbacf4e5134d324e6da90fdebb494e1fd4f27c57 100644 (file)
@@ -1340,6 +1340,23 @@ static switch_status_t vlc_file_av_close(switch_file_handle_t *handle)
        return SWITCH_STATUS_SUCCESS;
 }
 
+static switch_status_t vlc_file_command(switch_file_handle_t *handle, switch_file_command_t command)
+{
+       vlc_file_context_t *context = handle->private_info;
+
+       switch(command) {
+       case SCFC_FLUSH_AUDIO:
+               switch_mutex_lock(context->audio_mutex);                
+               switch_buffer_zero(context->audio_buffer);
+               switch_mutex_unlock(context->audio_mutex);              
+               break;
+       default:
+               break;
+       }
+
+       return SWITCH_STATUS_SUCCESS;
+}
+
 static switch_status_t vlc_file_close(switch_file_handle_t *handle)
 {
        vlc_file_context_t *context = handle->private_info;
@@ -2608,6 +2625,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_vlc_load)
        file_interface->extens = vlc_file_supported_formats;
        file_interface->file_open = vlc_file_open;
        file_interface->file_close = vlc_file_close;
+       file_interface->file_command = vlc_file_command;
        file_interface->file_read = vlc_file_read;
        file_interface->file_write = vlc_file_write;
        file_interface->file_read_video = vlc_file_read_video;
index d2998b99071e16d35bbe946c30860a47a3457d6b..fcc21e4491407a60004a350cc8b12502b96e2925 100644 (file)
@@ -735,6 +735,37 @@ SWITCH_DECLARE(switch_status_t) switch_core_file_truncate(switch_file_handle_t *
 
 }
 
+SWITCH_DECLARE(switch_status_t) switch_core_file_command(switch_file_handle_t *fh, switch_file_command_t command)
+{
+       switch_status_t status = SWITCH_STATUS_FALSE;
+       
+       switch_assert(fh != NULL);
+       switch_assert(fh->file_interface != NULL);
+
+       if (!switch_test_flag(fh, SWITCH_FILE_OPEN)) {
+               return SWITCH_STATUS_FALSE;
+       }
+
+       switch(command) {
+       case SCFC_FLUSH_AUDIO:
+               if (fh->pre_buffer) {
+                       switch_buffer_zero(fh->pre_buffer);
+               }
+               break;
+       default:
+               break;
+       }
+
+       if (fh->file_interface->file_command) {
+               switch_mutex_lock(fh->flag_mutex);
+               status = fh->file_interface->file_command(fh, command);
+               switch_mutex_unlock(fh->flag_mutex);
+       }
+
+       return status;
+}
+
+
 SWITCH_DECLARE(switch_status_t) switch_core_file_close(switch_file_handle_t *fh)
 {
        switch_status_t status;
index 9a61980f44be1d927e3761ca3e63169e29e46b74..85bd05b94408eee8ae3509dfe735489072e9aeb0 100644 (file)
@@ -80,7 +80,8 @@ struct media_helper {
        switch_core_session_t *session;
        switch_thread_cond_t *cond;
        switch_mutex_t *cond_mutex;
-       switch_mutex_t *file_mutex;
+       switch_mutex_t *file_read_mutex;
+       switch_mutex_t *file_write_mutex;
        int up;
 };
 
@@ -4952,15 +4953,19 @@ SWITCH_DECLARE(switch_file_handle_t *) switch_core_media_get_video_file(switch_c
 
        v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];      
 
-       switch_mutex_lock(v_engine->mh.file_mutex);
+
 
        if (rw == SWITCH_RW_READ) {
+               switch_mutex_lock(v_engine->mh.file_read_mutex);
                fh = smh->video_read_fh;
+               switch_mutex_unlock(v_engine->mh.file_read_mutex);
        } else {
+               switch_mutex_lock(v_engine->mh.file_write_mutex);
                fh = smh->video_write_fh;
+               switch_mutex_unlock(v_engine->mh.file_write_mutex);
        }
 
-       switch_mutex_unlock(v_engine->mh.file_mutex);
+
 
        return fh;
 }
@@ -5009,24 +5014,29 @@ static void *SWITCH_THREAD_FUNC video_write_thread(switch_thread_t *thread, void
 
        switch_core_timer_init(&timer, "soft", (int)(1000 / fps) , 1, switch_core_session_get_pool(session));
 
-       while (smh->video_write_thread_running > 0 && 
+       while (smh->video_write_thread_running > 0 &&
                   switch_channel_up_nosig(session->channel) && smh->video_write_fh && switch_test_flag(smh->video_write_fh, SWITCH_FILE_OPEN)) {
                switch_status_t wstatus = SWITCH_STATUS_FALSE;
 
                switch_core_timer_next(&timer);
-               switch_mutex_lock(v_engine->mh.file_mutex);
+               switch_mutex_lock(v_engine->mh.file_write_mutex);
 
-               if (smh->video_write_fh) {
-                       wstatus = switch_core_file_read_video(smh->video_write_fh, &fr, SVR_BLOCK);
+               if (smh->video_write_fh->mm.source_fps && smh->video_write_fh->mm.source_fps != fps) {
+                       switch_core_timer_destroy(&timer);
+                       switch_core_timer_init(&timer, "soft", (int)(1000 / fps) , 1, switch_core_session_get_pool(session));
                }
 
-               if (wstatus == SWITCH_STATUS_SUCCESS) {
-                       switch_core_session_write_video_frame(session, &fr, SWITCH_IO_FLAG_NONE, SVR_FLUSH);
-                       switch_img_free(&fr.img);
-               } else if (wstatus != SWITCH_STATUS_BREAK && wstatus != SWITCH_STATUS_IGNORE) {
-                       smh->video_write_fh = NULL;
+               if (smh->video_write_fh && !switch_test_flag(smh->video_write_fh, SWITCH_FILE_FLAG_VIDEO_EOF)) {
+                       wstatus = switch_core_file_read_video(smh->video_write_fh, &fr, SVR_BLOCK);
+
+                       if (wstatus == SWITCH_STATUS_SUCCESS) {
+                               switch_core_session_write_video_frame(session, &fr, SWITCH_IO_FLAG_NONE, SVR_FLUSH);
+                               switch_img_free(&fr.img);
+                       } else if (wstatus != SWITCH_STATUS_BREAK && wstatus != SWITCH_STATUS_IGNORE) {
+                               switch_set_flag_locked(smh->video_write_fh, SWITCH_FILE_FLAG_VIDEO_EOF);
+                       }
                }
-               switch_mutex_unlock(v_engine->mh.file_mutex);
+               switch_mutex_unlock(v_engine->mh.file_write_mutex);
        }
 
        switch_core_timer_destroy(&timer);
@@ -5038,6 +5048,59 @@ static void *SWITCH_THREAD_FUNC video_write_thread(switch_thread_t *thread, void
        return NULL;
 }
 
+SWITCH_DECLARE(switch_status_t) switch_core_media_lock_video_file(switch_core_session_t *session, switch_rw_t rw)
+{
+       switch_media_handle_t *smh;
+       switch_rtp_engine_t *v_engine;
+
+       switch_assert(session);
+
+       if (!switch_channel_test_flag(session->channel, CF_VIDEO)) {
+               return SWITCH_STATUS_FALSE;
+       }
+
+       if (!(smh = session->media_handle)) {
+               return SWITCH_STATUS_FALSE;
+       }
+
+       v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
+
+       if (rw == SWITCH_RW_READ) {
+               switch_mutex_lock(v_engine->mh.file_read_mutex);
+       } else {
+               switch_mutex_lock(v_engine->mh.file_write_mutex);
+       }
+
+       return SWITCH_STATUS_SUCCESS;
+
+}
+
+SWITCH_DECLARE(switch_status_t) switch_core_media_unlock_video_file(switch_core_session_t *session, switch_rw_t rw)
+{
+       switch_media_handle_t *smh;
+       switch_rtp_engine_t *v_engine;
+
+       switch_assert(session);
+
+       if (!switch_channel_test_flag(session->channel, CF_VIDEO)) {
+               return SWITCH_STATUS_FALSE;
+       }
+
+       if (!(smh = session->media_handle)) {
+               return SWITCH_STATUS_FALSE;
+       }
+
+       v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
+
+       if (rw == SWITCH_RW_READ) {
+               switch_mutex_unlock(v_engine->mh.file_read_mutex);
+       } else {
+               switch_mutex_unlock(v_engine->mh.file_write_mutex);
+       }
+
+       return SWITCH_STATUS_SUCCESS;
+}
+
 SWITCH_DECLARE(switch_status_t) switch_core_media_set_video_file(switch_core_session_t *session, switch_file_handle_t *fh, switch_rw_t rw)
 {
        switch_media_handle_t *smh;
@@ -5061,13 +5124,14 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_set_video_file(switch_core_ses
        //      return SWITCH_STATUS_FALSE;
        //}
 
-       switch_mutex_lock(v_engine->mh.file_mutex);
+
 
        if (rw == SWITCH_RW_READ) {
+               switch_mutex_lock(v_engine->mh.file_read_mutex);
 
                if (fh && smh->video_read_fh) {
                        switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "File is already open\n");
-                       switch_mutex_unlock(v_engine->mh.file_mutex);
+                       switch_mutex_unlock(v_engine->mh.file_read_mutex);
                        return SWITCH_STATUS_FALSE; 
                }
 
@@ -5086,12 +5150,16 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_set_video_file(switch_core_ses
 
                smh->video_read_fh = fh;
 
+               switch_mutex_unlock(v_engine->mh.file_read_mutex);
+
        } else {
+               switch_mutex_lock(v_engine->mh.file_write_mutex);
 
                if (fh && smh->video_write_fh) {
-                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "File is already open\n");
-                       switch_mutex_unlock(v_engine->mh.file_mutex);
-                       return SWITCH_STATUS_FALSE; 
+                       //switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "File is already open\n");
+                       smh->video_write_fh = fh;
+                       switch_mutex_unlock(v_engine->mh.file_write_mutex);
+                       return SWITCH_STATUS_SUCCESS; 
                }
 
                if (fh) {
@@ -5111,23 +5179,26 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_set_video_file(switch_core_ses
                        switch_thread_create(&smh->video_write_thread, thd_attr, video_write_thread, session, switch_core_session_get_pool(session));
                }
 
-               smh->video_write_fh = fh;
-
                if (!fh && smh->video_write_thread) {
                        switch_status_t st;
-                       smh->video_write_thread_running = -1;
-                       switch_mutex_unlock(v_engine->mh.file_mutex);
+                       if (smh->video_write_thread_running > 0) {
+                               smh->video_write_thread_running = -1;
+                       }
+                       switch_mutex_unlock(v_engine->mh.file_write_mutex);
                        switch_thread_join(&st, smh->video_write_thread);
-                       switch_mutex_lock(v_engine->mh.file_mutex);
+                       switch_mutex_lock(v_engine->mh.file_write_mutex);
                        smh->video_write_thread = NULL;
                }
                
+               smh->video_write_fh = fh;
+
+               switch_mutex_unlock(v_engine->mh.file_write_mutex);
        }
 
        if (!fh) switch_channel_video_sync(session->channel);
        
        switch_core_session_wake_video_thread(session);
-       switch_mutex_unlock(v_engine->mh.file_mutex);
+
        
        return SWITCH_STATUS_SUCCESS;
 }
@@ -5289,12 +5360,12 @@ static void *SWITCH_THREAD_FUNC video_helper_thread(switch_thread_t *thread, voi
                
 
                if (switch_channel_test_flag(channel, CF_VIDEO_READY)) {
-                       switch_mutex_lock(mh->file_mutex);
+                       switch_mutex_lock(mh->file_read_mutex);
                        if (smh->video_read_fh && switch_test_flag(smh->video_read_fh, SWITCH_FILE_OPEN) && read_frame->img) {
                                switch_core_file_write_video(smh->video_read_fh, read_frame);
                                send_blank = 0;
                        } 
-                       switch_mutex_unlock(mh->file_mutex);
+                       switch_mutex_unlock(mh->file_read_mutex);
                } else if (switch_channel_test_flag(channel, CF_VIDEO_DECODED_READ) || v_engine->smode == SWITCH_MEDIA_FLOW_SENDONLY) {
                        send_blank = 1;
                }
@@ -5355,7 +5426,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_start_video_thread(switch_co
        
        switch_thread_cond_create(&v_engine->mh.cond, pool);
        switch_mutex_init(&v_engine->mh.cond_mutex, SWITCH_MUTEX_NESTED, pool);
-       switch_mutex_init(&v_engine->mh.file_mutex, SWITCH_MUTEX_NESTED, pool);
+       switch_mutex_init(&v_engine->mh.file_read_mutex, SWITCH_MUTEX_NESTED, pool);
+       switch_mutex_init(&v_engine->mh.file_write_mutex, SWITCH_MUTEX_NESTED, pool);
        switch_mutex_init(&smh->read_mutex[SWITCH_MEDIA_TYPE_VIDEO], SWITCH_MUTEX_NESTED, pool);
        switch_mutex_init(&smh->write_mutex[SWITCH_MEDIA_TYPE_VIDEO], SWITCH_MUTEX_NESTED, pool);
        switch_thread_create(&v_engine->media_thread, thd_attr, video_helper_thread, &v_engine->mh, switch_core_session_get_pool(session));
index 023f6add417d711af8ae0f70b1b13695e2cf66bb..9be39f1fd7ffa886d7dd4f131d19253bfc99c1b6 100644 (file)
@@ -359,6 +359,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_record_file(switch_core_session_t *se
        switch_channel_t *channel = switch_core_session_get_channel(session);
        switch_dtmf_t dtmf = { 0 };
        switch_file_handle_t lfh = { 0 };
+       switch_file_handle_t vfh = { 0 };
        switch_frame_t *read_frame;
        switch_codec_t codec, write_codec = { 0 };
        char *codec_name;
@@ -377,8 +378,9 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_record_file(switch_core_session_t *se
        int divisor = 0;
        int file_flags = SWITCH_FILE_FLAG_WRITE | SWITCH_FILE_DATA_SHORT;
        int restart_limit_on_dtmf = 0;
-       const char *prefix, *var;
-       
+       const char *prefix, *var, *video_file = NULL;
+       int vid_play_file_flags = SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT | SWITCH_FILE_FLAG_VIDEO;
+
 
        if (switch_channel_pre_answer(channel) != SWITCH_STATUS_SUCCESS) {
                return SWITCH_STATUS_FALSE;
@@ -548,7 +550,34 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_record_file(switch_core_session_t *se
        }
        
        if (switch_core_file_has_video(fh)) {
-               switch_channel_set_flag(channel, CF_VIDEO_ECHO);
+               switch_core_session_request_video_refresh(session);     
+               
+               if ((p = switch_channel_get_variable(channel, "record_play_video")) || 
+
+                       (fh->params && (p = switch_event_get_header(fh->params, "record_play_video")))) {
+
+                       video_file = switch_core_session_strdup(session, p);
+                       
+                       if (switch_core_file_open(&vfh, video_file, fh->channels, 
+                                                                         read_impl.actual_samples_per_second, vid_play_file_flags, NULL) != SWITCH_STATUS_SUCCESS) {
+                               memset(&vfh, 0, sizeof(vfh));
+                               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Failure opening video playback file.\n");
+                       }
+
+                       if (switch_core_file_has_video(fh)) {
+                               switch_core_media_set_video_file(session, &vfh, SWITCH_RW_WRITE);
+                               switch_core_media_gen_key_frame(session);
+                       } else {
+                               switch_core_file_close(&vfh);
+                               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Video playback file does not contain video\n");
+                               memset(&vfh, 0, sizeof(vfh));
+                       }
+               }
+
+               if (!switch_test_flag(&vfh, SWITCH_FILE_OPEN)) { 
+                       switch_channel_set_flag(channel, CF_VIDEO_ECHO);
+               }
+
                switch_core_media_set_video_file(session, fh, SWITCH_RW_READ);
        } else if (switch_channel_test_flag(channel, CF_VIDEO)) {
                switch_channel_set_flag(channel, CF_VIDEO_BLANK);
@@ -568,42 +597,43 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_record_file(switch_core_session_t *se
 
        restart_limit_on_dtmf = switch_true(switch_channel_get_variable(channel, "record_restart_limit_on_dtmf"));
 
-       if ((p = switch_channel_get_variable(channel, "RECORD_TITLE"))) {
+       if ((p = switch_channel_get_variable(channel, "record_title")) || (fh->params && (p = switch_event_get_header(fh->params, "record_title")))) {
                vval = switch_core_session_strdup(session, p);
                switch_core_file_set_string(fh, SWITCH_AUDIO_COL_STR_TITLE, vval);
-               switch_channel_set_variable(channel, "RECORD_TITLE", NULL);
+               switch_channel_set_variable(channel, "record_title", NULL);
        }
 
-       if ((p = switch_channel_get_variable(channel, "RECORD_COPYRIGHT"))) {
+       if ((p = switch_channel_get_variable(channel, "record_copyright")) || (fh->params && (p = switch_event_get_header(fh->params, "record_copyright")))) {
                vval = switch_core_session_strdup(session, p);
                switch_core_file_set_string(fh, SWITCH_AUDIO_COL_STR_COPYRIGHT, vval);
-               switch_channel_set_variable(channel, "RECORD_COPYRIGHT", NULL);
+               switch_channel_set_variable(channel, "record_copyright", NULL);
        }
 
-       if ((p = switch_channel_get_variable(channel, "RECORD_SOFTWARE"))) {
+       if ((p = switch_channel_get_variable(channel, "record_software")) || (fh->params && (p = switch_event_get_header(fh->params, "record_software")))) {
                vval = switch_core_session_strdup(session, p);
                switch_core_file_set_string(fh, SWITCH_AUDIO_COL_STR_SOFTWARE, vval);
-               switch_channel_set_variable(channel, "RECORD_SOFTWARE", NULL);
+               switch_channel_set_variable(channel, "record_software", NULL);
        }
 
-       if ((p = switch_channel_get_variable(channel, "RECORD_ARTIST"))) {
+       if ((p = switch_channel_get_variable(channel, "record_artist")) || (fh->params && (p = switch_event_get_header(fh->params, "record_artist")))) {
                vval = switch_core_session_strdup(session, p);
                switch_core_file_set_string(fh, SWITCH_AUDIO_COL_STR_ARTIST, vval);
-               switch_channel_set_variable(channel, "RECORD_ARTIST", NULL);
+               switch_channel_set_variable(channel, "record_artist", NULL);
        }
 
-       if ((p = switch_channel_get_variable(channel, "RECORD_COMMENT"))) {
+       if ((p = switch_channel_get_variable(channel, "record_comment")) || (fh->params && (p = switch_event_get_header(fh->params, "record_comment")))) {
                vval = switch_core_session_strdup(session, p);
                switch_core_file_set_string(fh, SWITCH_AUDIO_COL_STR_COMMENT, vval);
-               switch_channel_set_variable(channel, "RECORD_COMMENT", NULL);
+               switch_channel_set_variable(channel, "record_comment", NULL);
        }
 
-       if ((p = switch_channel_get_variable(channel, "RECORD_DATE"))) {
+       if ((p = switch_channel_get_variable(channel, "record_date")) || (fh->params && (p = switch_event_get_header(fh->params, "record_date")))) {
                vval = switch_core_session_strdup(session, p);
                switch_core_file_set_string(fh, SWITCH_AUDIO_COL_STR_DATE, vval);
-               switch_channel_set_variable(channel, "RECORD_DATE", NULL);
+               switch_channel_set_variable(channel, "record_date", NULL);
        }
 
+
        switch_channel_set_variable(channel, "silence_hits_exhausted", "false");
 
        if (!asis) {
@@ -627,6 +657,9 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_record_file(switch_core_session_t *se
                                switch_channel_clear_flag(channel, CF_VIDEO_ECHO);
                                switch_channel_clear_flag_recursive(channel, CF_VIDEO_DECODED_READ);
                                switch_core_media_set_video_file(session, NULL, SWITCH_RW_READ);
+                               if (switch_test_flag(&vfh, SWITCH_FILE_OPEN)) {
+                                       switch_core_media_set_video_file(session, NULL, SWITCH_RW_WRITE);
+                               }
                        }
                        switch_channel_clear_flag(channel, CF_VIDEO_BLANK);
                        switch_core_file_close(fh);
@@ -748,6 +781,39 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_record_file(switch_core_session_t *se
                        }
                }
 
+               if (switch_test_flag(&vfh, SWITCH_FILE_OPEN)) {
+                       switch_core_file_command(&vfh, SCFC_FLUSH_AUDIO);
+
+                       if (switch_test_flag(&vfh, SWITCH_FILE_FLAG_VIDEO_EOF)) {
+
+                               //switch_core_media_set_video_file(session, NULL, SWITCH_RW_WRITE);
+                               
+                               switch_core_media_lock_video_file(session, SWITCH_RW_WRITE);
+
+                               switch_core_file_close(&vfh);
+                               memset(&vfh, 0, sizeof(vfh));
+                               
+                               if (switch_core_file_open(&vfh, video_file, fh->channels, 
+                                                                                 read_impl.actual_samples_per_second, vid_play_file_flags, NULL) != SWITCH_STATUS_SUCCESS) {
+                                       memset(&vfh, 0, sizeof(vfh));
+                                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Failure opening video playback file.\n");
+                               }
+                               
+                               if (switch_core_file_has_video(fh)) {
+                                       //switch_core_media_set_video_file(session, &vfh, SWITCH_RW_WRITE);
+                                       switch_core_media_gen_key_frame(session);
+                               } else {
+                                       switch_core_media_set_video_file(session, NULL, SWITCH_RW_WRITE);
+                                       switch_core_file_close(&vfh);
+                                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Video playback file does not contain video\n");
+                                       memset(&vfh, 0, sizeof(vfh));
+                               }
+
+                               switch_core_media_unlock_video_file(session, SWITCH_RW_WRITE);
+                       }
+
+               }
+
                if (!asis && fh->thresh) {
                        int16_t *fdata = (int16_t *) read_frame->data;
                        uint32_t samples = read_frame->datalen / sizeof(*fdata);
@@ -806,6 +872,9 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_record_file(switch_core_session_t *se
                switch_channel_clear_flag(channel, CF_VIDEO_ECHO);
                switch_channel_clear_flag_recursive(channel, CF_VIDEO_DECODED_READ);
                switch_core_media_set_video_file(session, NULL, SWITCH_RW_READ);
+               if (switch_test_flag(&vfh, SWITCH_FILE_OPEN)) {
+                       switch_core_media_set_video_file(session, NULL, SWITCH_RW_WRITE);
+               }
        }
        switch_channel_clear_flag(channel, CF_VIDEO_BLANK);
        switch_core_file_close(fh);