mirror of
https://github.com/signalwire/freeswitch.git
synced 2025-03-13 12:40:17 +00:00
FS-8914 #resolve [recording mp4 cuts off the end in some cases]
This commit is contained in:
parent
11136cbd76
commit
68588e811f
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
||||
|
@ -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,17 +1807,40 @@ 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;
|
||||
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);
|
||||
|
||||
size = switch_buffer_read(context->audio_buffer, data, need);
|
||||
switch_mutex_unlock(context->mutex);
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user