From 65b4c026f4a2aa965f89f28958fe75bceb16475c Mon Sep 17 00:00:00 2001 From: irungentoo Date: Sat, 5 Jul 2014 14:36:19 -0400 Subject: The width and height set during the video encoder initialization is now described as the maximum width and height of images. This is to work around what appears to be a bug in libvpx where the resolution of the stream can be decreased but increasing it above its originally set value introduces memory corruption. --- auto_tests/toxav_basic_test.c | 2 +- toxav/codec.c | 25 +++++++++++++++---------- toxav/codec.h | 3 +++ toxav/toxav.c | 11 ++++++----- toxav/toxav.h | 4 ++-- 5 files changed, 27 insertions(+), 18 deletions(-) diff --git a/auto_tests/toxav_basic_test.c b/auto_tests/toxav_basic_test.c index a1bccd7c..0a710746 100644 --- a/auto_tests/toxav_basic_test.c +++ b/auto_tests/toxav_basic_test.c @@ -199,7 +199,7 @@ START_TEST(test_AV_flows) printf("All set after %llu seconds! Starting call...\n", time(NULL) - cur_time); muhcaps = av_DefaultSettings; - muhcaps.video_height = muhcaps.video_width = 128; + muhcaps.max_video_height = muhcaps.max_video_width = 128; Status status_control = { {none, toxav_new(Alice, 1), NULL, -1}, diff --git a/toxav/codec.c b/toxav/codec.c index ed0c8e54..595c0359 100644 --- a/toxav/codec.c +++ b/toxav/codec.c @@ -217,6 +217,9 @@ int reconfigure_video_encoder_resolution(CodecState *cs, uint16_t width, uint16_ if (cfg.g_w == width && cfg.g_h == height) return 0; + if (width * height > cs->max_width * cs->max_height) + return -1; + LOGGER_DEBUG("New video resolution: %u %u", width, height); cfg.g_w = width; cfg.g_h = height; @@ -249,7 +252,7 @@ int reconfigure_video_encoder_bitrate(CodecState *cs, uint32_t video_bitrate) return 0; } -int init_video_encoder(CodecState *cs, uint16_t width, uint16_t height, uint32_t video_bitrate) +int init_video_encoder(CodecState *cs, uint16_t max_width, uint16_t max_height, uint32_t video_bitrate) { vpx_codec_enc_cfg_t cfg; int rc = vpx_codec_enc_config_default(VIDEO_CODEC_ENCODER_INTERFACE, &cfg, 0); @@ -260,13 +263,18 @@ int init_video_encoder(CodecState *cs, uint16_t width, uint16_t height, uint32_t } cfg.rc_target_bitrate = video_bitrate; - cfg.g_w = 8192; - cfg.g_h = 8192; + cfg.g_w = max_width; + cfg.g_h = max_height; cfg.g_pass = VPX_RC_ONE_PASS; cfg.g_error_resilient = VPX_ERROR_RESILIENT_DEFAULT | VPX_ERROR_RESILIENT_PARTITIONS; cfg.g_lag_in_frames = 0; cfg.kf_min_dist = 0; cfg.kf_max_dist = 300; + cfg.kf_mode = VPX_KF_AUTO; + + cs->max_width = max_width; + cs->max_height = max_height; + cs->bitrate = video_bitrate; rc = vpx_codec_enc_init_ver(&cs->v_encoder, VIDEO_CODEC_ENCODER_INTERFACE, &cfg, 0, VPX_ENCODER_ABI_VERSION); @@ -282,9 +290,6 @@ int init_video_encoder(CodecState *cs, uint16_t width, uint16_t height, uint32_t return -1; } - if (reconfigure_video_encoder_resolution(cs, width, height) != 0) - return -1; - return 0; } @@ -322,8 +327,8 @@ CodecState *codec_init_session ( uint32_t audio_bitrate, uint32_t audio_sample_rate, uint32_t audio_channels, uint32_t audio_VAD_tolerance_ms, - uint16_t video_width, - uint16_t video_height, + uint16_t max_video_width, + uint16_t max_video_height, uint32_t video_bitrate ) { CodecState *retu = calloc(sizeof(CodecState), 1); @@ -334,11 +339,11 @@ CodecState *codec_init_session ( uint32_t audio_bitrate, retu->audio_sample_rate = audio_sample_rate; /* Encoders */ - if (!video_width || !video_height) { /* Disable video */ + if (!max_video_width || !max_video_height) { /* Disable video */ /*video_width = 320; video_height = 240; */ } else { - retu->capabilities |= ( 0 == init_video_encoder(retu, video_width, video_height, video_bitrate) ) ? v_encoding : 0; + retu->capabilities |= ( 0 == init_video_encoder(retu, max_video_width, max_video_height, video_bitrate) ) ? v_encoding : 0; retu->capabilities |= ( 0 == init_video_decoder(retu) ) ? v_decoding : 0; } diff --git a/toxav/codec.h b/toxav/codec.h index d8e9f1a7..a464ec8f 100644 --- a/toxav/codec.h +++ b/toxav/codec.h @@ -56,6 +56,9 @@ typedef struct _CodecState { /* video decoding */ vpx_codec_ctx_t v_decoder; + int bitrate; + int max_width; + int max_height; /* audio encoding */ OpusEncoder *audio_encoder; diff --git a/toxav/toxav.c b/toxav/toxav.c index 9a1c5e3e..606f1370 100644 --- a/toxav/toxav.c +++ b/toxav/toxav.c @@ -81,8 +81,8 @@ struct _ToxAv { const ToxAvCodecSettings av_DefaultSettings = { 500, - 800, - 600, + 1280, + 720, 64000, 20, @@ -350,8 +350,8 @@ int toxav_prepare_transmission ( ToxAv *av, int32_t call_index, ToxAvCodecSettin codec_settings->audio_sample_rate, codec_settings->audio_channels, codec_settings->audio_VAD_tolerance, - codec_settings->video_width, - codec_settings->video_height, + codec_settings->max_video_width, + codec_settings->max_video_height, codec_settings->video_bitrate) )) { if ( pthread_mutex_init(&call->mutex, NULL) != 0 ) goto error; @@ -642,7 +642,8 @@ inline__ int toxav_prepare_video_frame(ToxAv *av, int32_t call_index, uint8_t *d CallSpecific *call = &av->calls[call_index]; pthread_mutex_lock(&call->mutex); - reconfigure_video_encoder_resolution(call->cs, input->d_w, input->d_h); + if (reconfigure_video_encoder_resolution(call->cs, input->d_w, input->d_h) != 0) + return ErrorInternal; int rc = vpx_codec_encode(&call->cs->v_encoder, input, call->cs->frame_counter, 1, 0, MAX_ENCODE_TIME_US); diff --git a/toxav/toxav.h b/toxav/toxav.h index 2e71c4da..b7659441 100644 --- a/toxav/toxav.h +++ b/toxav/toxav.h @@ -120,8 +120,8 @@ typedef enum { */ typedef struct _ToxAvCodecSettings { uint32_t video_bitrate; /* In kbits/s */ - uint16_t video_width; /* In px */ - uint16_t video_height; /* In px */ + uint16_t max_video_width; /* In px */ + uint16_t max_video_height; /* In px */ uint32_t audio_bitrate; /* In bits/s */ uint16_t audio_frame_duration; /* In ms */ -- cgit v1.2.3