diff --git a/src/include/switch_module_interfaces.h b/src/include/switch_module_interfaces.h index 4a3e8c71f8..04054f6cd4 100644 --- a/src/include/switch_module_interfaces.h +++ b/src/include/switch_module_interfaces.h @@ -301,10 +301,10 @@ struct switch_file_interface { }; typedef enum { - SWITCH_VIDEO_ENCODE_SPEED_DEFAULT, - SWITCH_VIDEO_ENCODE_SPEED_SLOW, + SWITCH_VIDEO_ENCODE_SPEED_DEFAULT = 0, + SWITCH_VIDEO_ENCODE_SPEED_FAST = 0, SWITCH_VIDEO_ENCODE_SPEED_MEDIUM, - SWITCH_VIDEO_ENCODE_SPEED_FAST + SWITCH_VIDEO_ENCODE_SPEED_SLOW } switch_video_encode_speed_t; typedef enum { diff --git a/src/mod/applications/mod_av/avformat.c b/src/mod/applications/mod_av/avformat.c index 6b6b0f7160..8275d56a33 100644 --- a/src/mod/applications/mod_av/avformat.c +++ b/src/mod/applications/mod_av/avformat.c @@ -359,6 +359,14 @@ static switch_status_t add_stream(MediaStream *mst, AVFormatContext *fc, AVCodec if (codec_id == AV_CODEC_ID_H264) { c->ticks_per_frame = 2; + + c->coder_type = 1; // coder = 1 + c->flags|=CODEC_FLAG_LOOP_FILTER; // flags=+loop + c->me_cmp|= 1; // cmp=+chroma, where CHROMA = 1 + c->me_method=ME_HEX; // me_method=hex + c->me_range = 16; // me_range=16 + c->max_b_frames = 3; // bf=3 + switch (mm->vprofile) { case SWITCH_VIDEO_PROFILE_BASELINE: av_opt_set(c->priv_data, "profile", "baseline", 0); @@ -367,10 +375,12 @@ static switch_status_t add_stream(MediaStream *mst, AVFormatContext *fc, AVCodec case SWITCH_VIDEO_PROFILE_MAIN: av_opt_set(c->priv_data, "profile", "main", 0); av_opt_set(c->priv_data, "level", "5", 0); + c->level = 5; break; case SWITCH_VIDEO_PROFILE_HIGH: av_opt_set(c->priv_data, "profile", "high", 0); av_opt_set(c->priv_data, "level", "52", 0); + c->level = 52; break; } @@ -382,6 +392,7 @@ static switch_status_t add_stream(MediaStream *mst, AVFormatContext *fc, AVCodec av_opt_set(c->priv_data, "preset", "medium", 0); break; case SWITCH_VIDEO_ENCODE_SPEED_FAST: + //av_opt_set(c->priv_data, "tune", "zerolatency", 0); av_opt_set(c->priv_data, "preset", "veryfast", 0); break; default: @@ -389,6 +400,17 @@ static switch_status_t add_stream(MediaStream *mst, AVFormatContext *fc, AVCodec } } + c->gop_size = 250; // g=250 + c->keyint_min = 25; // keyint_min=25 + c->scenechange_threshold = 40; // sc_threshold=40 + c->i_quant_factor = 0.71; // i_qfactor=0.71 + c->b_frame_strategy = 1; // b_strategy=1 + c->qcompress = 0.6; // qcomp=0.6 + c->qmin = 10; // qmin=10 + c->qmax = 51; // qmax=51 + c->max_qdiff = 4; // qdiff=4 + + if (codec_id == AV_CODEC_ID_VP8) { av_set_options_string(c, "quality=realtime", "=", ":"); } @@ -567,9 +589,13 @@ 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; + uint64_t hard_delta = 0, delta = 0, last_ts = 0; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "video thread start\n"); + + if (eh->mm->fps) { + hard_delta = 1000 / eh->mm->fps; + } for(;;) { AVPacket pkt = { 0 }; @@ -605,6 +631,7 @@ static void *SWITCH_THREAD_FUNC video_thread_run(switch_thread_t *thread, void * skip_total_count = skip_total; skip_count = 0; skip--; + goto top; } } else { @@ -634,24 +661,33 @@ static void *SWITCH_THREAD_FUNC video_thread_run(switch_thread_t *thread, void * ret = av_frame_make_writable(eh->video_st->frame); } - if (ret < 0) continue; + if (ret < 0) { + continue; + } fill_avframe(eh->video_st->frame, img); - switch_core_timer_sync(eh->timer); - if (eh->finalize && delta) { + if (hard_delta) { + delta = hard_delta; + } + + if ((eh->finalize && delta) || hard_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; + switch_core_timer_sync(eh->timer); + + 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 > 10) { + delta = delta_tmp; + } + + eh->video_st->frame->pts = eh->timer->samplecount; } - - eh->video_st->frame->pts = eh->timer->samplecount; } last_ts = eh->video_st->frame->pts; @@ -1655,14 +1691,17 @@ static switch_status_t av_file_open(switch_file_handle_t *handle, const char *pa handle->mm.ab = 128; } + handle->mm.vb = switch_calc_bitrate(handle->mm.vw, handle->mm.vh, 1, handle->mm.fps); + 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"))) || !strcasecmp(ext, "mp4")) { + if ((handle->stream_name && (!strcasecmp(handle->stream_name, "rtmp") || !strcasecmp(handle->stream_name, "youtube")))) { + if (fmt->video_codec != AV_CODEC_ID_H264 ) { fmt->video_codec = AV_CODEC_ID_H264; // force H264 } - + fmt->audio_codec = AV_CODEC_ID_AAC; handle->samplerate = 44100; handle->mm.samplerate = 44100; @@ -1688,7 +1727,7 @@ static switch_status_t av_file_open(switch_file_handle_t *handle, const char *pa handle->mm.vb = 4500; break; default: - handle->mm.vb = (handle->mm.vw * handle->mm.vh) / 175; + handle->mm.vb = switch_calc_bitrate(handle->mm.vw, handle->mm.vh, 1, handle->mm.fps); break; } } @@ -1708,6 +1747,7 @@ static switch_status_t av_file_open(switch_file_handle_t *handle, const char *pa context->audio_st.sample_rate = handle->samplerate; add_stream(&context->audio_st, context->fc, &context->audio_codec, fmt->audio_codec, &handle->mm); + if (open_audio(context->fc, context->audio_codec, &context->audio_st) != SWITCH_STATUS_SUCCESS) { switch_goto_status(SWITCH_STATUS_GENERR, end); } diff --git a/src/switch_core_media.c b/src/switch_core_media.c index 6c79d8d39e..38979ed2bb 100644 --- a/src/switch_core_media.c +++ b/src/switch_core_media.c @@ -5273,8 +5273,8 @@ static void *SWITCH_THREAD_FUNC video_helper_thread(switch_thread_t *thread, voi unsigned char *buf = NULL; switch_rgb_color_t bgcolor; switch_rtp_engine_t *v_engine = NULL; - const char *var; + int buflen = SWITCH_RTP_MAX_BUF_LEN; if (!(smh = session->media_handle)) { return NULL; @@ -5309,6 +5309,14 @@ static void *SWITCH_THREAD_FUNC video_helper_thread(switch_thread_t *thread, voi switch_channel_get_name(session->channel), switch_channel_test_flag(channel, CF_VIDEO_ECHO) ? "on" : "off"); switch_core_session_request_video_refresh(session); + buf = switch_core_session_alloc(session, buflen); + fr.packet = buf; + fr.packetlen = buflen; + fr.data = buf + 12; + fr.buflen = buflen - 12; + + switch_core_media_gen_key_frame(session); + while (switch_channel_up_nosig(channel)) { int send_blank = 0; @@ -5361,7 +5369,6 @@ static void *SWITCH_THREAD_FUNC video_helper_thread(switch_thread_t *thread, voi } } - //if (!smh->video_write_fh || !switch_channel_test_flag(channel, CF_VIDEO_READY)) { status = switch_core_session_read_video_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0); if (!SWITCH_READ_ACCEPTABLE(status)) { @@ -5369,41 +5376,18 @@ static void *SWITCH_THREAD_FUNC video_helper_thread(switch_thread_t *thread, voi continue; } - //if (switch_test_flag(read_frame, SFF_CNG)) { - // continue; - //} - //} - - //if (vloops < 300 && (vloops % 100) == 0) { - // switch_core_media_gen_key_frame(session); - //switch_core_session_request_video_refresh(session); - //} - vloops++; - - if (!buf) { - int buflen = SWITCH_RTP_MAX_BUF_LEN; - buf = switch_core_session_alloc(session, buflen); - fr.packet = buf; - fr.packetlen = buflen; - fr.data = buf + 12; - fr.buflen = buflen - 12; - switch_core_media_gen_key_frame(session); - } send_blank = 1; - if (switch_channel_test_flag(channel, CF_VIDEO_READY)) { + if (switch_channel_test_flag(channel, CF_VIDEO_READY) && !switch_test_flag(read_frame, SFF_CNG)) { switch_mutex_lock(mh->file_read_mutex); if (smh->video_read_fh && switch_test_flag(smh->video_read_fh, SWITCH_FILE_OPEN) && read_frame->img) { switch_core_file_write_video(smh->video_read_fh, read_frame); - send_blank = 0; } switch_mutex_unlock(mh->file_read_mutex); - //} else if (switch_channel_test_flag(channel, CF_VIDEO_DECODED_READ) || v_engine->smode == SWITCH_MEDIA_FLOW_SENDONLY) { - //send_blank = 1; } - + if (switch_channel_test_flag(channel, CF_VIDEO_WRITING) || session->video_read_callback) { send_blank = 0; } @@ -5417,16 +5401,6 @@ static void *SWITCH_THREAD_FUNC video_helper_thread(switch_thread_t *thread, voi switch_core_session_write_video_frame(session, &fr, SWITCH_IO_FLAG_FORCE, 0); } } -#if 0 - if (blank_img && (send_blank || switch_channel_test_flag(channel, CF_VIDEO_BLANK)) && !session->video_read_callback) { - fr.img = blank_img; - switch_yield(10000); - switch_core_session_write_video_frame(session, &fr, SWITCH_IO_FLAG_FORCE, 0); - } else if (read_frame && (switch_channel_test_flag(channel, CF_VIDEO_ECHO))) { - switch_core_session_write_video_frame(session, read_frame, SWITCH_IO_FLAG_NONE, 0); - } -#endif - } switch_img_free(&blank_img); @@ -11203,6 +11177,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_wait_for_video_input_params( { switch_media_handle_t *smh; switch_codec_implementation_t read_impl = { 0 }; + switch_rtp_engine_t *v_engine = NULL; switch_assert(session != NULL); @@ -11214,6 +11189,12 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_wait_for_video_input_params( return SWITCH_STATUS_GENERR;; } + v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO]; + + if (v_engine->smode == SWITCH_MEDIA_FLOW_SENDONLY) { + return SWITCH_STATUS_NOTIMPL; + } + switch_core_session_get_read_impl(session, &read_impl); while(switch_channel_ready(session->channel) && timeout_ms > 0) { diff --git a/src/switch_ivr_play_say.c b/src/switch_ivr_play_say.c index e6f7f9256b..d856131dd8 100644 --- a/src/switch_ivr_play_say.c +++ b/src/switch_ivr_play_say.c @@ -492,7 +492,12 @@ 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); switch_core_session_request_video_refresh(session); - switch_core_session_wait_for_video_input_params(session, 10000); + if (switch_core_session_wait_for_video_input_params(session, 10000) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Unable to establish inbound video stream\n"); + switch_core_session_reset(session, SWITCH_TRUE, SWITCH_TRUE); + arg_recursion_check_stop(args); + return SWITCH_STATUS_GENERR; + } switch_core_media_get_vid_params(session, &vid_params); fh->mm.vw = vid_params.width; fh->mm.vh = vid_params.height;