summaryrefslogtreecommitdiff
path: root/toxav/video.c
diff options
context:
space:
mode:
Diffstat (limited to 'toxav/video.c')
-rw-r--r--toxav/video.c292
1 files changed, 233 insertions, 59 deletions
diff --git a/toxav/video.c b/toxav/video.c
index eee542a2..0014dbb6 100644
--- a/toxav/video.c
+++ b/toxav/video.c
@@ -33,8 +33,124 @@
33#include <assert.h> 33#include <assert.h>
34#include <stdlib.h> 34#include <stdlib.h>
35 35
36#define MAX_DECODE_TIME_US 0 /* Good quality encode. */ 36/**
37#define VIDEO_DECODE_BUFFER_SIZE 20 37 * Soft deadline the decoder should attempt to meet, in "us" (microseconds).
38 * Set to zero for unlimited.
39 *
40 * By convention, the value 1 is used to mean "return as fast as possible."
41 */
42// TODO: don't hardcode this, let the application choose it
43#define WANTED_MAX_DECODER_FPS 40
44
45/**
46 * VPX_DL_REALTIME (1)
47 * deadline parameter analogous to VPx REALTIME mode.
48 *
49 * VPX_DL_GOOD_QUALITY (1000000)
50 * deadline parameter analogous to VPx GOOD QUALITY mode.
51 *
52 * VPX_DL_BEST_QUALITY (0)
53 * deadline parameter analogous to VPx BEST QUALITY mode.
54 */
55#define MAX_DECODE_TIME_US (1000000 / WANTED_MAX_DECODER_FPS) // to allow x fps
56
57/**
58 * Codec control function to set encoder internal speed settings. Changes in
59 * this value influences, among others, the encoder's selection of motion
60 * estimation methods. Values greater than 0 will increase encoder speed at the
61 * expense of quality.
62 *
63 * Note Valid range for VP8: -16..16
64 */
65#define VP8E_SET_CPUUSED_VALUE 16
66
67/**
68 * Initialize encoder with this value. Target bandwidth to use for this stream, in kilobits per second.
69 */
70#define VIDEO_BITRATE_INITIAL_VALUE 5000
71#define VIDEO_DECODE_BUFFER_SIZE 5 // this buffer has normally max. 1 entry
72
73#define VIDEO_CODEC_DECODER_INTERFACE (vpx_codec_vp8_dx())
74#define VIDEO_CODEC_ENCODER_INTERFACE (vpx_codec_vp8_cx())
75
76#define VIDEO_CODEC_DECODER_MAX_WIDTH 800 // its a dummy value, because the struct needs a value there
77#define VIDEO_CODEC_DECODER_MAX_HEIGHT 600 // its a dummy value, because the struct needs a value there
78
79#define VPX_MAX_DIST_NORMAL 40
80#define VPX_MAX_DIST_START 40
81
82#define VPX_MAX_ENCODER_THREADS 4
83#define VPX_MAX_DECODER_THREADS 4
84#define VIDEO__VP8_DECODER_POST_PROCESSING_ENABLED 0
85
86void vc_init_encoder_cfg(Logger *log, vpx_codec_enc_cfg_t *cfg, int16_t kf_max_dist)
87{
88 vpx_codec_err_t rc = vpx_codec_enc_config_default(VIDEO_CODEC_ENCODER_INTERFACE, cfg, 0);
89
90 if (rc != VPX_CODEC_OK) {
91 LOGGER_ERROR(log, "vc_init_encoder_cfg:Failed to get config: %s", vpx_codec_err_to_string(rc));
92 }
93
94 /* Target bandwidth to use for this stream, in kilobits per second */
95 cfg->rc_target_bitrate = VIDEO_BITRATE_INITIAL_VALUE;
96 cfg->g_w = VIDEO_CODEC_DECODER_MAX_WIDTH;
97 cfg->g_h = VIDEO_CODEC_DECODER_MAX_HEIGHT;
98 cfg->g_pass = VPX_RC_ONE_PASS;
99 cfg->g_error_resilient = VPX_ERROR_RESILIENT_DEFAULT | VPX_ERROR_RESILIENT_PARTITIONS;
100 cfg->g_lag_in_frames = 0;
101
102 /* Allow lagged encoding
103 *
104 * If set, this value allows the encoder to consume a number of input
105 * frames before producing output frames. This allows the encoder to
106 * base decisions for the current frame on future frames. This does
107 * increase the latency of the encoding pipeline, so it is not appropriate
108 * in all situations (ex: realtime encoding).
109 *
110 * Note that this is a maximum value -- the encoder may produce frames
111 * sooner than the given limit. Set this value to 0 to disable this
112 * feature.
113 */
114 cfg->kf_min_dist = 0;
115 cfg->kf_mode = VPX_KF_AUTO; // Encoder determines optimal placement automatically
116 cfg->rc_end_usage = VPX_VBR; // what quality mode?
117
118 /*
119 * VPX_VBR Variable Bit Rate (VBR) mode
120 * VPX_CBR Constant Bit Rate (CBR) mode
121 * VPX_CQ Constrained Quality (CQ) mode -> give codec a hint that we may be on low bandwidth connection
122 * VPX_Q Constant Quality (Q) mode
123 */
124 if (kf_max_dist > 1) {
125 cfg->kf_max_dist = kf_max_dist; // a full frame every x frames minimum (can be more often, codec decides automatically)
126 LOGGER_DEBUG(log, "kf_max_dist=%d (1)", cfg->kf_max_dist);
127 } else {
128 cfg->kf_max_dist = VPX_MAX_DIST_START;
129 LOGGER_DEBUG(log, "kf_max_dist=%d (2)", cfg->kf_max_dist);
130 }
131
132 cfg->g_threads = VPX_MAX_ENCODER_THREADS; // Maximum number of threads to use
133 /* TODO: set these to something reasonable */
134 // cfg->g_timebase.num = 1;
135 // cfg->g_timebase.den = 60; // 60 fps
136 cfg->rc_resize_allowed = 1; // allow encoder to resize to smaller resolution
137 cfg->rc_resize_up_thresh = 40;
138 cfg->rc_resize_down_thresh = 5;
139
140 /* TODO: make quality setting an API call, but start with normal quality */
141#if 0
142 /* Highest-resolution encoder settings */
143 cfg->rc_dropframe_thresh = 0;
144 cfg->rc_resize_allowed = 0;
145 cfg->rc_min_quantizer = 2;
146 cfg->rc_max_quantizer = 56;
147 cfg->rc_undershoot_pct = 100;
148 cfg->rc_overshoot_pct = 15;
149 cfg->rc_buf_initial_sz = 500;
150 cfg->rc_buf_optimal_sz = 600;
151 cfg->rc_buf_sz = 1000;
152#endif
153}
38 154
39VCSession *vc_new(Logger *log, ToxAV *av, uint32_t friend_number, toxav_video_receive_frame_cb *cb, void *cb_data) 155VCSession *vc_new(Logger *log, ToxAV *av, uint32_t friend_number, toxav_video_receive_frame_cb *cb, void *cb_data)
40{ 156{
@@ -52,49 +168,72 @@ VCSession *vc_new(Logger *log, ToxAV *av, uint32_t friend_number, toxav_video_re
52 return nullptr; 168 return nullptr;
53 } 169 }
54 170
171 int cpu_used_value = VP8E_SET_CPUUSED_VALUE;
172
55 if (!(vc->vbuf_raw = rb_new(VIDEO_DECODE_BUFFER_SIZE))) { 173 if (!(vc->vbuf_raw = rb_new(VIDEO_DECODE_BUFFER_SIZE))) {
56 goto BASE_CLEANUP; 174 goto BASE_CLEANUP;
57 } 175 }
58 176
59 rc = vpx_codec_dec_init(vc->decoder, VIDEO_CODEC_DECODER_INTERFACE, nullptr, 0); 177 /*
178 * VPX_CODEC_USE_FRAME_THREADING
179 * Enable frame-based multi-threading
180 *
181 * VPX_CODEC_USE_ERROR_CONCEALMENT
182 * Conceal errors in decoded frames
183 */
184 vpx_codec_dec_cfg_t dec_cfg;
185 dec_cfg.threads = VPX_MAX_DECODER_THREADS; // Maximum number of threads to use
186 dec_cfg.w = VIDEO_CODEC_DECODER_MAX_WIDTH;
187 dec_cfg.h = VIDEO_CODEC_DECODER_MAX_HEIGHT;
188
189 LOGGER_DEBUG(log, "Using VP8 codec for decoder (0)");
190 rc = vpx_codec_dec_init(vc->decoder, VIDEO_CODEC_DECODER_INTERFACE, &dec_cfg,
191 VPX_CODEC_USE_FRAME_THREADING | VPX_CODEC_USE_POSTPROC);
192
193 if (rc == VPX_CODEC_INCAPABLE) {
194 LOGGER_WARNING(log, "Postproc not supported by this decoder (0)");
195 rc = vpx_codec_dec_init(vc->decoder, VIDEO_CODEC_DECODER_INTERFACE, &dec_cfg, VPX_CODEC_USE_FRAME_THREADING);
196 }
60 197
61 if (rc != VPX_CODEC_OK) { 198 if (rc != VPX_CODEC_OK) {
62 LOGGER_ERROR(log, "Init video_decoder failed: %s", vpx_codec_err_to_string(rc)); 199 LOGGER_ERROR(log, "Init video_decoder failed: %s", vpx_codec_err_to_string(rc));
63 goto BASE_CLEANUP; 200 goto BASE_CLEANUP;
64 } 201 }
65 202
66 /* Set encoder to some initial values 203 if (VIDEO__VP8_DECODER_POST_PROCESSING_ENABLED == 1) {
67 */ 204 vp8_postproc_cfg_t pp = {VP8_DEBLOCK, 1, 0};
68 vpx_codec_enc_cfg_t cfg; 205 vpx_codec_err_t cc_res = vpx_codec_control(vc->decoder, VP8_SET_POSTPROC, &pp);
69 rc = vpx_codec_enc_config_default(VIDEO_CODEC_ENCODER_INTERFACE, &cfg, 0);
70 206
71 if (rc != VPX_CODEC_OK) { 207 if (cc_res != VPX_CODEC_OK) {
72 LOGGER_ERROR(log, "Failed to get config: %s", vpx_codec_err_to_string(rc)); 208 LOGGER_WARNING(log, "Failed to turn on postproc");
73 goto BASE_CLEANUP_1; 209 } else {
210 LOGGER_DEBUG(log, "turn on postproc: OK");
211 }
212 } else {
213 vp8_postproc_cfg_t pp = {0, 0, 0};
214 vpx_codec_err_t cc_res = vpx_codec_control(vc->decoder, VP8_SET_POSTPROC, &pp);
215
216 if (cc_res != VPX_CODEC_OK) {
217 LOGGER_WARNING(log, "Failed to turn OFF postproc");
218 } else {
219 LOGGER_DEBUG(log, "Disable postproc: OK");
220 }
74 } 221 }
75 222
76 cfg.rc_target_bitrate = 500000; 223 /* Set encoder to some initial values
77 cfg.g_w = 800; 224 */
78 cfg.g_h = 600; 225 vpx_codec_enc_cfg_t cfg;
79 cfg.g_pass = VPX_RC_ONE_PASS; 226 vc_init_encoder_cfg(log, &cfg, 1);
80 /* TODO(mannol): If we set error resilience the app will crash due to bug in vp8.
81 Perhaps vp9 has solved it?*/
82#if 0
83 cfg.g_error_resilient = VPX_ERROR_RESILIENT_DEFAULT | VPX_ERROR_RESILIENT_PARTITIONS;
84#endif
85 cfg.g_lag_in_frames = 0;
86 cfg.kf_min_dist = 0;
87 cfg.kf_max_dist = 48;
88 cfg.kf_mode = VPX_KF_AUTO;
89 227
90 rc = vpx_codec_enc_init(vc->encoder, VIDEO_CODEC_ENCODER_INTERFACE, &cfg, 0); 228 LOGGER_DEBUG(log, "Using VP8 codec for encoder (0.1)");
229 rc = vpx_codec_enc_init(vc->encoder, VIDEO_CODEC_ENCODER_INTERFACE, &cfg, VPX_CODEC_USE_FRAME_THREADING);
91 230
92 if (rc != VPX_CODEC_OK) { 231 if (rc != VPX_CODEC_OK) {
93 LOGGER_ERROR(log, "Failed to initialize encoder: %s", vpx_codec_err_to_string(rc)); 232 LOGGER_ERROR(log, "Failed to initialize encoder: %s", vpx_codec_err_to_string(rc));
94 goto BASE_CLEANUP_1; 233 goto BASE_CLEANUP_1;
95 } 234 }
96 235
97 rc = vpx_codec_control(vc->encoder, VP8E_SET_CPUUSED, 8); 236 rc = vpx_codec_control(vc->encoder, VP8E_SET_CPUUSED, cpu_used_value);
98 237
99 if (rc != VPX_CODEC_OK) { 238 if (rc != VPX_CODEC_OK) {
100 LOGGER_ERROR(log, "Failed to set encoder control setting: %s", vpx_codec_err_to_string(rc)); 239 LOGGER_ERROR(log, "Failed to set encoder control setting: %s", vpx_codec_err_to_string(rc));
@@ -102,6 +241,20 @@ VCSession *vc_new(Logger *log, ToxAV *av, uint32_t friend_number, toxav_video_re
102 goto BASE_CLEANUP_1; 241 goto BASE_CLEANUP_1;
103 } 242 }
104 243
244 /*
245 VPX_CTRL_USE_TYPE(VP8E_SET_NOISE_SENSITIVITY, unsigned int)
246 control function to set noise sensitivity
247 0: off, 1: OnYOnly, 2: OnYUV, 3: OnYUVAggressive, 4: Adaptive
248 */
249 /*
250 rc = vpx_codec_control(vc->encoder, VP8E_SET_NOISE_SENSITIVITY, 2);
251
252 if (rc != VPX_CODEC_OK) {
253 LOGGER_ERROR(log, "Failed to set encoder control setting: %s", vpx_codec_err_to_string(rc));
254 vpx_codec_destroy(vc->encoder);
255 goto BASE_CLEANUP_1;
256 }
257 */
105 vc->linfts = current_time_monotonic(); 258 vc->linfts = current_time_monotonic();
106 vc->lcfd = 60; 259 vc->lcfd = 60;
107 vc->vcb.first = cb; 260 vc->vcb.first = cb;
@@ -109,9 +262,7 @@ VCSession *vc_new(Logger *log, ToxAV *av, uint32_t friend_number, toxav_video_re
109 vc->friend_number = friend_number; 262 vc->friend_number = friend_number;
110 vc->av = av; 263 vc->av = av;
111 vc->log = log; 264 vc->log = log;
112
113 return vc; 265 return vc;
114
115BASE_CLEANUP_1: 266BASE_CLEANUP_1:
116 vpx_codec_destroy(vc->decoder); 267 vpx_codec_destroy(vc->decoder);
117BASE_CLEANUP: 268BASE_CLEANUP:
@@ -120,6 +271,7 @@ BASE_CLEANUP:
120 free(vc); 271 free(vc);
121 return nullptr; 272 return nullptr;
122} 273}
274
123void vc_kill(VCSession *vc) 275void vc_kill(VCSession *vc)
124{ 276{
125 if (!vc) { 277 if (!vc) {
@@ -128,7 +280,6 @@ void vc_kill(VCSession *vc)
128 280
129 vpx_codec_destroy(vc->encoder); 281 vpx_codec_destroy(vc->encoder);
130 vpx_codec_destroy(vc->decoder); 282 vpx_codec_destroy(vc->decoder);
131
132 void *p; 283 void *p;
133 284
134 while (rb_read((RingBuffer *)vc->vbuf_raw, &p)) { 285 while (rb_read((RingBuffer *)vc->vbuf_raw, &p)) {
@@ -136,12 +287,11 @@ void vc_kill(VCSession *vc)
136 } 287 }
137 288
138 rb_kill((RingBuffer *)vc->vbuf_raw); 289 rb_kill((RingBuffer *)vc->vbuf_raw);
139
140 pthread_mutex_destroy(vc->queue_mutex); 290 pthread_mutex_destroy(vc->queue_mutex);
141
142 LOGGER_DEBUG(vc->log, "Terminated video handler: %p", vc); 291 LOGGER_DEBUG(vc->log, "Terminated video handler: %p", vc);
143 free(vc); 292 free(vc);
144} 293}
294
145void vc_iterate(VCSession *vc) 295void vc_iterate(VCSession *vc)
146{ 296{
147 if (!vc) { 297 if (!vc) {
@@ -154,45 +304,63 @@ void vc_iterate(VCSession *vc)
154 304
155 pthread_mutex_lock(vc->queue_mutex); 305 pthread_mutex_lock(vc->queue_mutex);
156 306
307 uint32_t full_data_len;
308
157 if (rb_read((RingBuffer *)vc->vbuf_raw, (void **)&p)) { 309 if (rb_read((RingBuffer *)vc->vbuf_raw, (void **)&p)) {
158 pthread_mutex_unlock(vc->queue_mutex); 310 pthread_mutex_unlock(vc->queue_mutex);
311 const struct RTPHeader *const header = &p->header;
312
313 if (header->flags & RTP_LARGE_FRAME) {
314 full_data_len = header->data_length_full;
315 LOGGER_DEBUG(vc->log, "vc_iterate:001:full_data_len=%d", (int)full_data_len);
316 } else {
317 full_data_len = p->len;
318 LOGGER_DEBUG(vc->log, "vc_iterate:002");
319 }
159 320
160 rc = vpx_codec_decode(vc->decoder, p->data, p->len, nullptr, MAX_DECODE_TIME_US); 321 LOGGER_DEBUG(vc->log, "vc_iterate: rb_read p->len=%d p->header.xe=%d", (int)full_data_len, p->header.xe);
322 LOGGER_DEBUG(vc->log, "vc_iterate: rb_read rb size=%d", (int)rb_size((RingBuffer *)vc->vbuf_raw));
323 rc = vpx_codec_decode(vc->decoder, p->data, full_data_len, nullptr, MAX_DECODE_TIME_US);
161 free(p); 324 free(p);
162 325
163 if (rc != VPX_CODEC_OK) { 326 if (rc != VPX_CODEC_OK) {
164 LOGGER_ERROR(vc->log, "Error decoding video: %s", vpx_codec_err_to_string(rc)); 327 LOGGER_ERROR(vc->log, "Error decoding video: %d %s", (int)rc, vpx_codec_err_to_string(rc));
165 } else { 328 } else {
329 /* Play decoded images */
166 vpx_codec_iter_t iter = nullptr; 330 vpx_codec_iter_t iter = nullptr;
167 vpx_image_t *dest = vpx_codec_get_frame(vc->decoder, &iter); 331 vpx_image_t *dest = nullptr;
168 332
169 /* Play decoded images */ 333 while ((dest = vpx_codec_get_frame(vc->decoder, &iter)) != nullptr) {
170 for (; dest; dest = vpx_codec_get_frame(vc->decoder, &iter)) {
171 if (vc->vcb.first) { 334 if (vc->vcb.first) {
172 vc->vcb.first(vc->av, vc->friend_number, dest->d_w, dest->d_h, 335 vc->vcb.first(vc->av, vc->friend_number, dest->d_w, dest->d_h,
173 (const uint8_t *)dest->planes[0], (const uint8_t *)dest->planes[1], (const uint8_t *)dest->planes[2], 336 (const uint8_t *)dest->planes[0], (const uint8_t *)dest->planes[1], (const uint8_t *)dest->planes[2],
174 dest->stride[0], dest->stride[1], dest->stride[2], vc->vcb.second); 337 dest->stride[0], dest->stride[1], dest->stride[2], vc->vcb.second);
175 } 338 }
176 339
177 vpx_img_free(dest); 340 vpx_img_free(dest); // is this needed? none of the VPx examples show that
178 } 341 }
179 } 342 }
180 343
181 return; 344 return;
345 } else {
346 LOGGER_TRACE(vc->log, "no Video frame data available");
182 } 347 }
183 348
184 pthread_mutex_unlock(vc->queue_mutex); 349 pthread_mutex_unlock(vc->queue_mutex);
185} 350}
351
186int vc_queue_message(void *vcp, struct RTPMessage *msg) 352int vc_queue_message(void *vcp, struct RTPMessage *msg)
187{ 353{
188 /* This function does the reconstruction of video packets. 354 /* This function is called with complete messages
189 * See more info about video splitting in docs 355 * they have already been assembled.
356 * this function gets called from handle_rtp_packet() and handle_rtp_packet_v3()
190 */ 357 */
191 if (!vcp || !msg) { 358 if (!vcp || !msg) {
192 return -1; 359 return -1;
193 } 360 }
194 361
195 VCSession *vc = (VCSession *)vcp; 362 VCSession *vc = (VCSession *)vcp;
363 const struct RTPHeader *const header = &msg->header;
196 364
197 if (msg->header.pt == (rtp_TypeVideo + 2) % 128) { 365 if (msg->header.pt == (rtp_TypeVideo + 2) % 128) {
198 LOGGER_WARNING(vc->log, "Got dummy!"); 366 LOGGER_WARNING(vc->log, "Got dummy!");
@@ -201,41 +369,45 @@ int vc_queue_message(void *vcp, struct RTPMessage *msg)
201 } 369 }
202 370
203 if (msg->header.pt != rtp_TypeVideo % 128) { 371 if (msg->header.pt != rtp_TypeVideo % 128) {
204 LOGGER_WARNING(vc->log, "Invalid payload type!"); 372 LOGGER_WARNING(vc->log, "Invalid payload type! pt=%d", (int)msg->header.pt);
205 free(msg); 373 free(msg);
206 return -1; 374 return -1;
207 } 375 }
208 376
209 pthread_mutex_lock(vc->queue_mutex); 377 pthread_mutex_lock(vc->queue_mutex);
210 free(rb_write((RingBuffer *)vc->vbuf_raw, msg)); 378
211 { 379 if ((header->flags & RTP_LARGE_FRAME) && header->pt == rtp_TypeVideo % 128) {
212 /* Calculate time took for peer to send us this frame */ 380 LOGGER_DEBUG(vc->log, "rb_write msg->len=%d b0=%d b1=%d", (int)msg->len, (int)msg->data[0], (int)msg->data[1]);
213 uint32_t t_lcfd = current_time_monotonic() - vc->linfts;
214 vc->lcfd = t_lcfd > 100 ? vc->lcfd : t_lcfd;
215 vc->linfts = current_time_monotonic();
216 } 381 }
217 pthread_mutex_unlock(vc->queue_mutex);
218 382
383 free(rb_write((RingBuffer *)vc->vbuf_raw, msg));
384
385 /* Calculate time it took for peer to send us this frame */
386 uint32_t t_lcfd = current_time_monotonic() - vc->linfts;
387 vc->lcfd = t_lcfd > 100 ? vc->lcfd : t_lcfd;
388 vc->linfts = current_time_monotonic();
389 pthread_mutex_unlock(vc->queue_mutex);
219 return 0; 390 return 0;
220} 391}
221int vc_reconfigure_encoder(VCSession *vc, uint32_t bit_rate, uint16_t width, uint16_t height) 392
393int vc_reconfigure_encoder(VCSession *vc, uint32_t bit_rate, uint16_t width, uint16_t height, int16_t kf_max_dist)
222{ 394{
223 if (!vc) { 395 if (!vc) {
224 return -1; 396 return -1;
225 } 397 }
226 398
227 vpx_codec_enc_cfg_t cfg = *vc->encoder->config.enc; 399 vpx_codec_enc_cfg_t cfg2 = *vc->encoder->config.enc;
228 vpx_codec_err_t rc; 400 vpx_codec_err_t rc;
229 401
230 if (cfg.rc_target_bitrate == bit_rate && cfg.g_w == width && cfg.g_h == height) { 402 if (cfg2.rc_target_bitrate == bit_rate && cfg2.g_w == width && cfg2.g_h == height && kf_max_dist == -1) {
231 return 0; /* Nothing changed */ 403 return 0; /* Nothing changed */
232 } 404 }
233 405
234 if (cfg.g_w == width && cfg.g_h == height) { 406 if (cfg2.g_w == width && cfg2.g_h == height && kf_max_dist == -1) {
235 /* Only bit rate changed */ 407 /* Only bit rate changed */
236 cfg.rc_target_bitrate = bit_rate; 408 LOGGER_INFO(vc->log, "bitrate change from: %u to: %u", (uint32_t)cfg2.rc_target_bitrate, (uint32_t)bit_rate);
237 409 cfg2.rc_target_bitrate = bit_rate;
238 rc = vpx_codec_enc_config_set(vc->encoder, &cfg); 410 rc = vpx_codec_enc_config_set(vc->encoder, &cfg2);
239 411
240 if (rc != VPX_CODEC_OK) { 412 if (rc != VPX_CODEC_OK) {
241 LOGGER_ERROR(vc->log, "Failed to set encoder control setting: %s", vpx_codec_err_to_string(rc)); 413 LOGGER_ERROR(vc->log, "Failed to set encoder control setting: %s", vpx_codec_err_to_string(rc));
@@ -245,23 +417,25 @@ int vc_reconfigure_encoder(VCSession *vc, uint32_t bit_rate, uint16_t width, uin
245 /* Resolution is changed, must reinitialize encoder since libvpx v1.4 doesn't support 417 /* Resolution is changed, must reinitialize encoder since libvpx v1.4 doesn't support
246 * reconfiguring encoder to use resolutions greater than initially set. 418 * reconfiguring encoder to use resolutions greater than initially set.
247 */ 419 */
248
249 LOGGER_DEBUG(vc->log, "Have to reinitialize vpx encoder on session %p", vc); 420 LOGGER_DEBUG(vc->log, "Have to reinitialize vpx encoder on session %p", vc);
250 421 vpx_codec_ctx_t new_c;
422 vpx_codec_enc_cfg_t cfg;
423 vc_init_encoder_cfg(vc->log, &cfg, kf_max_dist);
251 cfg.rc_target_bitrate = bit_rate; 424 cfg.rc_target_bitrate = bit_rate;
252 cfg.g_w = width; 425 cfg.g_w = width;
253 cfg.g_h = height; 426 cfg.g_h = height;
254 427
255 vpx_codec_ctx_t new_c; 428 LOGGER_DEBUG(vc->log, "Using VP8 codec for encoder");
256 429 rc = vpx_codec_enc_init(&new_c, VIDEO_CODEC_ENCODER_INTERFACE, &cfg, VPX_CODEC_USE_FRAME_THREADING);
257 rc = vpx_codec_enc_init(&new_c, VIDEO_CODEC_ENCODER_INTERFACE, &cfg, 0);
258 430
259 if (rc != VPX_CODEC_OK) { 431 if (rc != VPX_CODEC_OK) {
260 LOGGER_ERROR(vc->log, "Failed to initialize encoder: %s", vpx_codec_err_to_string(rc)); 432 LOGGER_ERROR(vc->log, "Failed to initialize encoder: %s", vpx_codec_err_to_string(rc));
261 return -1; 433 return -1;
262 } 434 }
263 435
264 rc = vpx_codec_control(&new_c, VP8E_SET_CPUUSED, 8); 436 int cpu_used_value = VP8E_SET_CPUUSED_VALUE;
437
438 rc = vpx_codec_control(&new_c, VP8E_SET_CPUUSED, cpu_used_value);
265 439
266 if (rc != VPX_CODEC_OK) { 440 if (rc != VPX_CODEC_OK) {
267 LOGGER_ERROR(vc->log, "Failed to set encoder control setting: %s", vpx_codec_err_to_string(rc)); 441 LOGGER_ERROR(vc->log, "Failed to set encoder control setting: %s", vpx_codec_err_to_string(rc));