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_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
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user