diff options
author | Eniz Vukovic <eniz_vukovic@hotmail.com> | 2015-10-23 22:52:32 +0200 |
---|---|---|
committer | Eniz Vukovic <eniz_vukovic@hotmail.com> | 2015-10-23 22:53:56 +0200 |
commit | 90b1ca872731d7911d6318c3a6e05133ea6071b8 (patch) | |
tree | fab45a53e0054a83f9bf9f7bd273ec63e82dd05f | |
parent | b5809f073241c778a97665b2924b85890e52ea1e (diff) |
Fix setting resolution for vpx v1.4 (or newer i suppose)
-rw-r--r-- | toxav/toxav.c | 2 | ||||
-rw-r--r-- | toxav/video.c | 142 | ||||
-rw-r--r-- | toxav/video.h | 2 |
3 files changed, 85 insertions, 61 deletions
diff --git a/toxav/toxav.c b/toxav/toxav.c index 7585206c..a9e8b6f1 100644 --- a/toxav/toxav.c +++ b/toxav/toxav.c | |||
@@ -752,7 +752,7 @@ bool toxav_video_send_frame(ToxAV *av, uint32_t friend_number, uint16_t width, u | |||
752 | goto END; | 752 | goto END; |
753 | } | 753 | } |
754 | 754 | ||
755 | if (vc_reconfigure_encoder(call->video.second->encoder, call->video_bit_rate * 1000, width, height) != 0) { | 755 | if (vc_reconfigure_encoder(call->video.second, call->video_bit_rate * 1000, width, height) != 0) { |
756 | pthread_mutex_unlock(call->mutex_video); | 756 | pthread_mutex_unlock(call->mutex_video); |
757 | rc = TOXAV_ERR_SEND_FRAME_INVALID; | 757 | rc = TOXAV_ERR_SEND_FRAME_INVALID; |
758 | goto END; | 758 | goto END; |
diff --git a/toxav/video.c b/toxav/video.c index 919e3c81..acc1852b 100644 --- a/toxav/video.c +++ b/toxav/video.c | |||
@@ -36,9 +36,6 @@ | |||
36 | #define MAX_DECODE_TIME_US 0 /* Good quality encode. */ | 36 | #define MAX_DECODE_TIME_US 0 /* Good quality encode. */ |
37 | #define VIDEO_DECODE_BUFFER_SIZE 20 | 37 | #define VIDEO_DECODE_BUFFER_SIZE 20 |
38 | 38 | ||
39 | |||
40 | bool create_video_encoder (vpx_codec_ctx_t *dest, int32_t bit_rate); | ||
41 | |||
42 | VCSession *vc_new(ToxAV *av, uint32_t friend_number, toxav_video_receive_frame_cb *cb, void *cb_data) | 39 | VCSession *vc_new(ToxAV *av, uint32_t friend_number, toxav_video_receive_frame_cb *cb, void *cb_data) |
43 | { | 40 | { |
44 | VCSession *vc = calloc(sizeof(VCSession), 1); | 41 | VCSession *vc = calloc(sizeof(VCSession), 1); |
@@ -64,9 +61,41 @@ VCSession *vc_new(ToxAV *av, uint32_t friend_number, toxav_video_receive_frame_c | |||
64 | goto BASE_CLEANUP; | 61 | goto BASE_CLEANUP; |
65 | } | 62 | } |
66 | 63 | ||
67 | if (!create_video_encoder(vc->encoder, 500000)) { | 64 | /* Set encoder to some initial values |
68 | vpx_codec_destroy(vc->decoder); | 65 | */ |
69 | goto BASE_CLEANUP; | 66 | vpx_codec_enc_cfg_t cfg; |
67 | rc = vpx_codec_enc_config_default(VIDEO_CODEC_ENCODER_INTERFACE, &cfg, 0); | ||
68 | |||
69 | if (rc != VPX_CODEC_OK) { | ||
70 | LOGGER_ERROR("Failed to get config: %s", vpx_codec_err_to_string(rc)); | ||
71 | goto BASE_CLEANUP_1; | ||
72 | } | ||
73 | |||
74 | cfg.rc_target_bitrate = 500000; | ||
75 | cfg.g_w = 800; | ||
76 | cfg.g_h = 600; | ||
77 | cfg.g_pass = VPX_RC_ONE_PASS; | ||
78 | /* FIXME If we set error resilience the app will crash due to bug in vp8. | ||
79 | Perhaps vp9 has solved it?*/ | ||
80 | // cfg.g_error_resilient = VPX_ERROR_RESILIENT_DEFAULT | VPX_ERROR_RESILIENT_PARTITIONS; | ||
81 | cfg.g_lag_in_frames = 0; | ||
82 | cfg.kf_min_dist = 0; | ||
83 | cfg.kf_max_dist = 48; | ||
84 | cfg.kf_mode = VPX_KF_AUTO; | ||
85 | |||
86 | rc = vpx_codec_enc_init(vc->encoder, VIDEO_CODEC_ENCODER_INTERFACE, &cfg, 0); | ||
87 | |||
88 | if (rc != VPX_CODEC_OK) { | ||
89 | LOGGER_ERROR("Failed to initialize encoder: %s", vpx_codec_err_to_string(rc)); | ||
90 | goto BASE_CLEANUP_1; | ||
91 | } | ||
92 | |||
93 | rc = vpx_codec_control(vc->encoder, VP8E_SET_CPUUSED, 8); | ||
94 | |||
95 | if (rc != VPX_CODEC_OK) { | ||
96 | LOGGER_ERROR("Failed to set encoder control setting: %s", vpx_codec_err_to_string(rc)); | ||
97 | vpx_codec_destroy(vc->encoder); | ||
98 | goto BASE_CLEANUP_1; | ||
70 | } | 99 | } |
71 | 100 | ||
72 | vc->linfts = current_time_monotonic(); | 101 | vc->linfts = current_time_monotonic(); |
@@ -78,6 +107,8 @@ VCSession *vc_new(ToxAV *av, uint32_t friend_number, toxav_video_receive_frame_c | |||
78 | 107 | ||
79 | return vc; | 108 | return vc; |
80 | 109 | ||
110 | BASE_CLEANUP_1: | ||
111 | vpx_codec_destroy(vc->decoder); | ||
81 | BASE_CLEANUP: | 112 | BASE_CLEANUP: |
82 | pthread_mutex_destroy(vc->queue_mutex); | 113 | pthread_mutex_destroy(vc->queue_mutex); |
83 | rb_kill(vc->vbuf_raw); | 114 | rb_kill(vc->vbuf_raw); |
@@ -176,68 +207,61 @@ int vc_queue_message(void *vcp, struct RTPMessage *msg) | |||
176 | 207 | ||
177 | return 0; | 208 | return 0; |
178 | } | 209 | } |
179 | int vc_reconfigure_encoder(vpx_codec_ctx_t *vccdc, uint32_t bit_rate, uint16_t width, uint16_t height) | 210 | int vc_reconfigure_encoder(VCSession* vc, uint32_t bit_rate, uint16_t width, uint16_t height) |
180 | { | 211 | { |
181 | if (!vccdc) | 212 | if (!vc) |
182 | return -1; | 213 | return -1; |
183 | 214 | ||
184 | vpx_codec_enc_cfg_t cfg = *vccdc->config.enc; | 215 | vpx_codec_enc_cfg_t cfg = *vc->encoder->config.enc; |
185 | 216 | int rc; | |
217 | |||
186 | if (cfg.rc_target_bitrate == bit_rate && cfg.g_w == width && cfg.g_h == height) | 218 | if (cfg.rc_target_bitrate == bit_rate && cfg.g_w == width && cfg.g_h == height) |
187 | return 0; /* Nothing changed */ | 219 | return 0; /* Nothing changed */ |
188 | 220 | ||
189 | cfg.rc_target_bitrate = bit_rate; | 221 | if (cfg.g_w == width && cfg.g_h == height) |
190 | cfg.g_w = width; | 222 | { |
191 | cfg.g_h = height; | 223 | /* Only bit rate changed */ |
192 | 224 | cfg.rc_target_bitrate = bit_rate; | |
193 | int rc = vpx_codec_enc_config_set(vccdc, &cfg); | 225 | |
194 | 226 | rc = vpx_codec_enc_config_set(vc->encoder, &cfg); | |
195 | if (rc != VPX_CODEC_OK) { | 227 | |
196 | LOGGER_ERROR("Failed to set encoder control setting: %s", vpx_codec_err_to_string(rc)); | 228 | if (rc != VPX_CODEC_OK) { |
197 | return -1; | 229 | LOGGER_ERROR("Failed to set encoder control setting: %s", vpx_codec_err_to_string(rc)); |
198 | } | 230 | return -1; |
199 | 231 | } | |
200 | return 0; | ||
201 | } | ||
202 | |||
203 | |||
204 | bool create_video_encoder (vpx_codec_ctx_t *dest, int32_t bit_rate) | ||
205 | { | ||
206 | assert(dest); | ||
207 | |||
208 | vpx_codec_enc_cfg_t cfg; | ||
209 | int rc = vpx_codec_enc_config_default(VIDEO_CODEC_ENCODER_INTERFACE, &cfg, 0); | ||
210 | |||
211 | if (rc != VPX_CODEC_OK) { | ||
212 | LOGGER_ERROR("Failed to get config: %s", vpx_codec_err_to_string(rc)); | ||
213 | return false; | ||
214 | } | ||
215 | |||
216 | cfg.rc_target_bitrate = bit_rate; | ||
217 | cfg.g_w = 800; | ||
218 | cfg.g_h = 600; | ||
219 | cfg.g_pass = VPX_RC_ONE_PASS; | ||
220 | /* FIXME If we set error resilience the app will crash due to bug in vp8. | ||
221 | Perhaps vp9 has solved it?*/ | ||
222 | // cfg.g_error_resilient = VPX_ERROR_RESILIENT_DEFAULT | VPX_ERROR_RESILIENT_PARTITIONS; | ||
223 | cfg.g_lag_in_frames = 0; | ||
224 | cfg.kf_min_dist = 0; | ||
225 | cfg.kf_max_dist = 48; | ||
226 | cfg.kf_mode = VPX_KF_AUTO; | ||
227 | |||
228 | rc = vpx_codec_enc_init(dest, VIDEO_CODEC_ENCODER_INTERFACE, &cfg, 0); | ||
229 | |||
230 | if (rc != VPX_CODEC_OK) { | ||
231 | LOGGER_ERROR("Failed to initialize encoder: %s", vpx_codec_err_to_string(rc)); | ||
232 | return false; | ||
233 | } | 232 | } |
233 | else | ||
234 | { | ||
235 | /* Resolution is changed, must reinitialize encoder since libvpx v1.4 doesn't support | ||
236 | * reconfiguring encoder to use resolutions greater than initially set. | ||
237 | */ | ||
238 | |||
239 | LOGGER_DEBUG("Have to reinitialize vpx encoder on session %p", vc); | ||
240 | |||
241 | cfg.rc_target_bitrate = bit_rate; | ||
242 | cfg.g_w = width; | ||
243 | cfg.g_h = height; | ||
244 | |||
245 | vpx_codec_ctx_t new_c; | ||
246 | |||
247 | rc = vpx_codec_enc_init(&new_c, VIDEO_CODEC_ENCODER_INTERFACE, &cfg, 0); | ||
248 | |||
249 | if (rc != VPX_CODEC_OK) { | ||
250 | LOGGER_ERROR("Failed to initialize encoder: %s", vpx_codec_err_to_string(rc)); | ||
251 | return -1; | ||
252 | } | ||
234 | 253 | ||
235 | rc = vpx_codec_control(dest, VP8E_SET_CPUUSED, 8); | 254 | rc = vpx_codec_control(&new_c, VP8E_SET_CPUUSED, 8); |
236 | 255 | ||
237 | if (rc != VPX_CODEC_OK) { | 256 | if (rc != VPX_CODEC_OK) { |
238 | LOGGER_ERROR("Failed to set encoder control setting: %s", vpx_codec_err_to_string(rc)); | 257 | LOGGER_ERROR("Failed to set encoder control setting: %s", vpx_codec_err_to_string(rc)); |
239 | vpx_codec_destroy(dest); | 258 | vpx_codec_destroy(&new_c); |
259 | return -1; | ||
260 | } | ||
261 | |||
262 | vpx_codec_destroy(vc->encoder); | ||
263 | memcpy(vc->encoder, &new_c, sizeof(new_c)); | ||
240 | } | 264 | } |
241 | 265 | ||
242 | return true; | 266 | return 0; |
243 | } | 267 | } |
diff --git a/toxav/video.h b/toxav/video.h index 1ad1f6f5..51f34318 100644 --- a/toxav/video.h +++ b/toxav/video.h | |||
@@ -62,6 +62,6 @@ VCSession *vc_new(ToxAV* av, uint32_t friend_number, toxav_video_receive_frame_c | |||
62 | void vc_kill(VCSession *vc); | 62 | void vc_kill(VCSession *vc); |
63 | void vc_iterate(VCSession *vc); | 63 | void vc_iterate(VCSession *vc); |
64 | int vc_queue_message(void *vcp, struct RTPMessage *msg); | 64 | int vc_queue_message(void *vcp, struct RTPMessage *msg); |
65 | int vc_reconfigure_encoder(vpx_codec_ctx_t *vccdc, uint32_t bit_rate, uint16_t width, uint16_t height); | 65 | int vc_reconfigure_encoder(VCSession *vc, uint32_t bit_rate, uint16_t width, uint16_t height); |
66 | 66 | ||
67 | #endif /* VIDEO_H */ | 67 | #endif /* VIDEO_H */ |