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)
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");
size = switch_queue_size(eh->video_queue);
- if (size > 5) {
+ if (size > 5 && !eh->finalize) {
skip = size;
if (size > 10) {
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);
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
}
}
}
- if (handle->mm.fps > 0.0f) {
+ if (handle->stream_name && handle->mm.fps > 0.0f) {
handle->mm.keyint = (int) 2.0f * handle->mm.fps;
}
}
}
if (!context->vid_ready) {
+ switch_buffer_zero(context->audio_buffer);
return status;
}
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_mutex_lock(context->mutex);
-
size = switch_buffer_read(context->audio_buffer, data, need);
switch_mutex_unlock(context->mutex);
if (fps) {
video_globals.fps = fps;
+ smh->vid_params.fps = fps;
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session),
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)
{
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);
}
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) {
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);