]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
FS-8914 #resolve [recording mp4 cuts off the end in some cases]
authorAnthony Minessale <anthm@freeswitch.org>
Wed, 9 Mar 2016 00:53:55 +0000 (18:53 -0600)
committerAnthony Minessale <anthm@freeswitch.org>
Wed, 9 Mar 2016 00:53:55 +0000 (18:53 -0600)
src/include/switch_core_media.h
src/include/switch_types.h
src/mod/applications/mod_av/avformat.c
src/switch_core_media.c
src/switch_ivr_play_say.c

index 65c400ea33d65e2f5cb1f6d3e1df5a0049620861..3a09b3163fdfa40797d3908329f6034d3db20935 100644 (file)
@@ -348,6 +348,7 @@ SWITCH_DECLARE(switch_bool_t) switch_core_session_in_video_thread(switch_core_se
 SWITCH_DECLARE(switch_bool_t) switch_core_media_check_dtls(switch_core_session_t *session, switch_media_type_t type);
 SWITCH_DECLARE(switch_status_t) switch_core_media_set_outgoing_bitrate(switch_core_session_t *session, switch_media_type_t type, uint32_t bitrate);
 SWITCH_DECLARE(switch_status_t) switch_core_media_reset_jb(switch_core_session_t *session, switch_media_type_t type);
+SWITCH_DECLARE(switch_status_t) switch_core_session_wait_for_video_input_params(switch_core_session_t *session, uint32_t timeout_ms);
                                                                                                                                
 SWITCH_END_EXTERN_C
 #endif
index 31f4ebfc31fe79cac40b96e628ba8bfa4aa25ee9..08832855876df4a4e2a288212ed389ac017659bb 100644 (file)
@@ -1517,8 +1517,9 @@ typedef enum {
 } switch_channel_flag_t;
 
 typedef struct switch_vid_params_s {
-       int width;
-       int height;
+       uint32_t width;
+       uint32_t height;
+       uint32_t fps;
 } switch_vid_params_t;
 
 
index 190a23456f44f0ecabbef6771943bfbc03180818..2df8e951e9ae0200b5b65329c524225d7dfdb535 100644 (file)
@@ -143,6 +143,7 @@ typedef struct record_helper_s {
        switch_queue_t *video_queue;
        switch_thread_t *video_thread;
        switch_mm_t *mm;
+       int finalize;
 } record_helper_t;
 
 static void log_packet(const AVFormatContext *fmt_ctx, const AVPacket *pkt)
@@ -514,6 +515,7 @@ static void *SWITCH_THREAD_FUNC video_thread_run(switch_thread_t *thread, void *
        switch_image_t *img = NULL, *tmp_img = NULL;
        int d_w = eh->video_st->width, d_h = eh->video_st->height;
        int size = 0, skip = 0, skip_freq = 0, skip_count = 0, skip_total = 0, skip_total_count = 0;
+       uint64_t delta = 0, last_ts = 0;
 
        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "video thread start\n");
        
@@ -557,7 +559,7 @@ static void *SWITCH_THREAD_FUNC video_thread_run(switch_thread_t *thread, void *
                
                        size = switch_queue_size(eh->video_queue);
                        
-                       if (size > 5) {
+                       if (size > 5 && !eh->finalize) {
                                skip = size;
 
                                if (size > 10) {
@@ -585,14 +587,25 @@ static void *SWITCH_THREAD_FUNC video_thread_run(switch_thread_t *thread, void *
                fill_avframe(eh->video_st->frame, img);
                switch_core_timer_sync(eh->timer);
                
-               if (eh->video_st->frame->pts == eh->timer->samplecount) {
+               if (eh->finalize && delta) {
+                       eh->video_st->frame->pts += delta;
+               } else if (eh->video_st->frame->pts == eh->timer->samplecount) {
                        // never use the same pts, or the encoder coughs
                        eh->video_st->frame->pts++;
                } else {
+                       uint64_t delta_tmp = eh->timer->samplecount - last_ts;
+
+                       if (delta_tmp > 1) {
+                               delta = delta_tmp;
+                       }
+
                        eh->video_st->frame->pts = eh->timer->samplecount;
                }
-               // eh->video_st->frame->pts = switch_time_now() / 1000 - eh->video_st->next_pts;
-               // switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "pts: %lld\n", eh->video_st->frame->pts);
+               
+               last_ts = eh->video_st->frame->pts;
+
+               //eh->video_st->frame->pts = switch_time_now() / 1000 - eh->video_st->next_pts;
+               //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "pts: %ld\n", eh->video_st->frame->pts);
 
                /* encode the image */
                ret = avcodec_encode_video2(eh->video_st->st->codec, &pkt, eh->video_st->frame, &got_packet);
@@ -1573,7 +1586,7 @@ static switch_status_t av_file_open(switch_file_handle_t *handle, const char *pa
        if (fmt->video_codec != AV_CODEC_ID_NONE) {
                const AVCodecDescriptor *desc;
 
-               if (handle->stream_name && (!strcasecmp(handle->stream_name, "rtmp") || !strcasecmp(handle->stream_name, "youtube"))) {
+               if ((handle->stream_name && (!strcasecmp(handle->stream_name, "rtmp") || !strcasecmp(handle->stream_name, "youtube"))) || !strcasecmp(ext, "mp4")) {
                        if (fmt->video_codec != AV_CODEC_ID_H264 ) {
                                fmt->video_codec = AV_CODEC_ID_H264; // force H264
                        }
@@ -1608,7 +1621,7 @@ static switch_status_t av_file_open(switch_file_handle_t *handle, const char *pa
                                }
                        }
 
-                       if (handle->mm.fps > 0.0f) {
+                       if (handle->stream_name && handle->mm.fps > 0.0f) {
                                handle->mm.keyint = (int) 2.0f * handle->mm.fps;
                        }
                }
@@ -1684,6 +1697,7 @@ static switch_status_t av_file_write(switch_file_handle_t *handle, void *data, s
        }
 
        if (!context->vid_ready) {
+               switch_buffer_zero(context->audio_buffer);
                return status;
        }
 
@@ -1793,16 +1807,39 @@ static switch_status_t av_file_close(switch_file_handle_t *handle)
        switch_status_t status;
 
        context->closed = 1;
+       context->eh.finalize = 1;
 
        if (context->eh.video_queue) {
+
+
+               if (switch_test_flag(handle, SWITCH_FILE_FLAG_WRITE)) {
+                       switch_rgb_color_t bgcolor;
+                       int x;
+                       
+                       switch_color_set_rgb(&bgcolor, "#000000");
+                       x = (int)handle->mm.fps * 1;
+
+                       if (x <= 0) x = 100;
+                       
+                       while(handle->mm.vw && x-- > 0) {
+                               switch_image_t *blank_img = NULL;
+                               if ((blank_img = switch_img_alloc(NULL, SWITCH_IMG_FMT_I420, handle->mm.vw, handle->mm.vh, 1))) {
+                                       switch_img_fill(blank_img, 0, 0, blank_img->d_w, blank_img->d_h, &bgcolor);
+                                       switch_queue_push(context->eh.video_queue, blank_img);
+                               }
+                       }
+
+               }
                switch_queue_push(context->eh.video_queue, NULL);
        }
 
+       if (switch_test_flag(handle, SWITCH_FILE_FLAG_WRITE)) {
+               av_file_write(handle, NULL, NULL);
+       }
+
        if (context->eh.video_thread) {
                switch_thread_join(&status, context->eh.video_thread);
        }
-       
-       av_file_write(handle, NULL, NULL);
 
        if (context->file_read_thread_running && context->file_read_thread) {
                context->file_read_thread_running = 0;
@@ -1857,7 +1894,6 @@ static switch_status_t av_file_read(switch_file_handle_t *handle, void *data, si
        }
 
        switch_mutex_lock(context->mutex);
-
        size = switch_buffer_read(context->audio_buffer, data, need);
        switch_mutex_unlock(context->mutex);
 
index a3dba3cfd1bf829c81dae8b9d40f7e28f8cec1ba..84c16a6ce6c0cd83b926f24f3a29d7ffa0a105bb 100644 (file)
@@ -2044,6 +2044,7 @@ static void check_jb_sync(switch_core_session_t *session)
 
        if (fps) {
                video_globals.fps = fps;
+               smh->vid_params.fps = fps;
        }
 
        switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session),
@@ -11171,6 +11172,44 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_write_video_frame(switch_cor
        return status;
 }
 
+SWITCH_DECLARE(switch_status_t) switch_core_session_wait_for_video_input_params(switch_core_session_t *session, uint32_t timeout_ms)
+{
+       switch_media_handle_t *smh;
+       switch_codec_implementation_t read_impl = { 0 };
+
+       switch_assert(session != NULL);
+
+       if (!(smh = session->media_handle)) {
+               return SWITCH_STATUS_FALSE;
+       }
+       
+       if (!switch_channel_test_flag(session->channel, CF_VIDEO_DECODED_READ)) {
+               return SWITCH_STATUS_GENERR;;
+       }
+
+       switch_core_session_get_read_impl(session, &read_impl);
+               
+       while(switch_channel_ready(session->channel) && timeout_ms > 0) {
+               switch_frame_t *read_frame;
+               switch_status_t status;
+               
+               status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
+
+               if (!SWITCH_READ_ACCEPTABLE(status)) {
+                       break;
+               }
+
+               if (switch_channel_test_flag(session->channel, CF_VIDEO_READY) && smh->vid_params.width && smh->vid_params.height && smh->vid_params.fps) {
+                       return SWITCH_STATUS_SUCCESS;
+               }
+
+               timeout_ms -= (read_impl.microseconds_per_packet / 1000);
+       }
+
+       return SWITCH_STATUS_TIMEOUT;
+       
+}
+
 SWITCH_DECLARE(switch_status_t) switch_core_session_read_video_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags,
                                                                                                                                         int stream_id)
 {
@@ -11252,7 +11291,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_video_frame(switch_core
 
                decode_status = switch_core_codec_decode_video((*frame)->codec, *frame);
                
-               if ((*frame)->img && switch_channel_test_flag(session->channel, CF_VIDEO_DEBUG_READ)) {
+               if ((*frame)->img) {//((*frame)->img && switch_channel_test_flag(session->channel, CF_VIDEO_DEBUG_READ)) {
                        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "IMAGE %dx%d %dx%d\n", 
                                                          (*frame)->img->w, (*frame)->img->h, (*frame)->img->d_w, (*frame)->img->d_h);
                }
index a99690d95f0df4ab298d7a7b92c336b0324372e7..3c8465885ae6cf3f04eae05ecd925fa365ca0131 100644 (file)
@@ -536,10 +536,11 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_record_file(switch_core_session_t *se
 
                file_flags |= SWITCH_FILE_FLAG_VIDEO;
                switch_channel_set_flag_recursive(channel, CF_VIDEO_DECODED_READ);
-               fh->mm.fps = switch_core_media_get_video_fps(session);
+               switch_core_session_wait_for_video_input_params(session, 10000);
                switch_core_media_get_vid_params(session, &vid_params);
                fh->mm.vw = vid_params.width;
                fh->mm.vh = vid_params.height;
+               fh->mm.fps = vid_params.fps;
        }
 
        if (switch_core_file_open(fh, file, fh->channels, read_impl.actual_samples_per_second, file_flags, NULL) != SWITCH_STATUS_SUCCESS) {
@@ -579,7 +580,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_record_file(switch_core_session_t *se
                        switch_channel_set_flag_recursive(channel, CF_VIDEO_DECODED_READ);
                        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);