FS-8914 #resolve [recording mp4 cuts off the end in some cases]

This commit is contained in:
Anthony Minessale 2016-03-08 18:53:55 -06:00
parent 11136cbd76
commit 68588e811f
5 changed files with 92 additions and 14 deletions

View 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_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_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_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 SWITCH_END_EXTERN_C
#endif #endif

View File

@ -1517,8 +1517,9 @@ typedef enum {
} switch_channel_flag_t; } switch_channel_flag_t;
typedef struct switch_vid_params_s { typedef struct switch_vid_params_s {
int width; uint32_t width;
int height; uint32_t height;
uint32_t fps;
} switch_vid_params_t; } switch_vid_params_t;

View File

@ -143,6 +143,7 @@ typedef struct record_helper_s {
switch_queue_t *video_queue; switch_queue_t *video_queue;
switch_thread_t *video_thread; switch_thread_t *video_thread;
switch_mm_t *mm; switch_mm_t *mm;
int finalize;
} record_helper_t; } record_helper_t;
static void log_packet(const AVFormatContext *fmt_ctx, const AVPacket *pkt) 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; switch_image_t *img = NULL, *tmp_img = NULL;
int d_w = eh->video_st->width, d_h = eh->video_st->height; 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; 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"); 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); size = switch_queue_size(eh->video_queue);
if (size > 5) { if (size > 5 && !eh->finalize) {
skip = size; skip = size;
if (size > 10) { 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); fill_avframe(eh->video_st->frame, img);
switch_core_timer_sync(eh->timer); 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 // never use the same pts, or the encoder coughs
eh->video_st->frame->pts++; eh->video_st->frame->pts++;
} else { } 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 = 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 */ /* encode the image */
ret = avcodec_encode_video2(eh->video_st->st->codec, &pkt, eh->video_st->frame, &got_packet); 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) { if (fmt->video_codec != AV_CODEC_ID_NONE) {
const AVCodecDescriptor *desc; 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 ) { if (fmt->video_codec != AV_CODEC_ID_H264 ) {
fmt->video_codec = AV_CODEC_ID_H264; // force 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; 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) { if (!context->vid_ready) {
switch_buffer_zero(context->audio_buffer);
return status; return status;
} }
@ -1793,17 +1807,40 @@ static switch_status_t av_file_close(switch_file_handle_t *handle)
switch_status_t status; switch_status_t status;
context->closed = 1; context->closed = 1;
context->eh.finalize = 1;
if (context->eh.video_queue) { 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); 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) { if (context->eh.video_thread) {
switch_thread_join(&status, 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) { if (context->file_read_thread_running && context->file_read_thread) {
context->file_read_thread_running = 0; context->file_read_thread_running = 0;
switch_thread_join(&status, context->file_read_thread); switch_thread_join(&status, context->file_read_thread);
@ -1857,7 +1894,6 @@ static switch_status_t av_file_read(switch_file_handle_t *handle, void *data, si
} }
switch_mutex_lock(context->mutex); switch_mutex_lock(context->mutex);
size = switch_buffer_read(context->audio_buffer, data, need); size = switch_buffer_read(context->audio_buffer, data, need);
switch_mutex_unlock(context->mutex); switch_mutex_unlock(context->mutex);

View File

@ -2044,6 +2044,7 @@ static void check_jb_sync(switch_core_session_t *session)
if (fps) { if (fps) {
video_globals.fps = fps; video_globals.fps = fps;
smh->vid_params.fps = fps;
} }
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), 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; 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, 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) 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); 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", 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); (*frame)->img->w, (*frame)->img->h, (*frame)->img->d_w, (*frame)->img->d_h);
} }

View 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; file_flags |= SWITCH_FILE_FLAG_VIDEO;
switch_channel_set_flag_recursive(channel, CF_VIDEO_DECODED_READ); 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); switch_core_media_get_vid_params(session, &vid_params);
fh->mm.vw = vid_params.width; fh->mm.vw = vid_params.width;
fh->mm.vh = vid_params.height; 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) { if (switch_core_file_open(fh, file, fh->channels, read_impl.actual_samples_per_second, file_flags, NULL) != SWITCH_STATUS_SUCCESS) {