diff --git a/toxav/toxav.c b/toxav/toxav.c index 814c4f2659..83de5f4b28 100644 --- a/toxav/toxav.c +++ b/toxav/toxav.c @@ -34,8 +34,6 @@ #include #include -#define MAX_ENCODE_TIME_US ((1000 / 24) * 1000) - typedef struct ToxAVCall_s { ToxAV *av; @@ -787,21 +785,7 @@ bool toxav_video_send_frame(ToxAV *av, uint32_t friend_number, uint16_t width, u } { /* Encode */ - vpx_image_t img; - img.w = img.h = img.d_w = img.d_h = 0; - vpx_img_alloc(&img, VPX_IMG_FMT_I420, width, height, 0); - - /* I420 "It comprises an NxM Y plane followed by (N/2)x(M/2) V and U planes." - * http://fourcc.org/yuv.php#IYUV - */ - memcpy(img.planes[VPX_PLANE_Y], y, width * height); - memcpy(img.planes[VPX_PLANE_U], u, (width / 2) * (height / 2)); - memcpy(img.planes[VPX_PLANE_V], v, (width / 2) * (height / 2)); - - int vrc = vpx_codec_encode(call->video.second->encoder, &img, - call->video.second->frame_counter, 1, 0, MAX_ENCODE_TIME_US); - - vpx_img_free(&img); + int vrc = vc_encode_frame(call->video.second, y, u, v); if (vrc != VPX_CODEC_OK) { pthread_mutex_unlock(call->mutex_video); diff --git a/toxav/video.c b/toxav/video.c index 8a832201c5..89c99a7e49 100644 --- a/toxav/video.c +++ b/toxav/video.c @@ -34,6 +34,8 @@ #include "../toxcore/network.h" #define MAX_DECODE_TIME_US 0 /* Good quality encode. */ +#define MAX_ENCODE_TIME_US ((1000 / 24) * 1000) + #define VIDEO_DECODE_BUFFER_SIZE 20 VCSession *vc_new(ToxAV *av, uint32_t friend_number, toxav_video_receive_frame_cb *cb, void *cb_data) @@ -97,7 +99,13 @@ VCSession *vc_new(ToxAV *av, uint32_t friend_number, toxav_video_receive_frame_c vpx_codec_destroy(vc->encoder); goto BASE_CLEANUP_1; } - + + vc->input_frame.w = vc->input_frame.h = vc->input_frame.d_w = vc->input_frame.d_h = 0; + if(!vpx_img_alloc(&vc->input_frame, VPX_IMG_FMT_I420, cfg.g_w, cfg.g_h, 0)) { + LOGGER_WARNING("Allocation failed! Application might misbehave!"); + goto BASE_CLEANUP_1; + } + vc->linfts = current_time_monotonic(); vc->lcfd = 60; vc->vcb.first = cb; @@ -123,6 +131,8 @@ void vc_kill(VCSession *vc) vpx_codec_destroy(vc->encoder); vpx_codec_destroy(vc->decoder); + vpx_img_free(&vc->input_frame); + void *p; while (rb_read(vc->vbuf_raw, (void **)&p)) @@ -247,7 +257,7 @@ int vc_reconfigure_encoder(VCSession *vc, uint32_t bit_rate, uint16_t width, uin LOGGER_ERROR("Failed to initialize encoder: %s", vpx_codec_err_to_string(rc)); return -1; } - + rc = vpx_codec_control(&new_c, VP8E_SET_CPUUSED, 8); if (rc != VPX_CODEC_OK) { @@ -258,7 +268,33 @@ int vc_reconfigure_encoder(VCSession *vc, uint32_t bit_rate, uint16_t width, uin vpx_codec_destroy(vc->encoder); memcpy(vc->encoder, &new_c, sizeof(new_c)); + + vpx_img_free(&vc->input_frame); + vc->input_frame.w = vc->input_frame.h = vc->input_frame.d_w = vc->input_frame.d_h = 0; + if(!vpx_img_alloc(&vc->input_frame, VPX_IMG_FMT_I420, cfg.g_w, cfg.g_h, 0)) { + LOGGER_ERROR("Failed to allocate frame"); + return -1; + } } return 0; } + +int vc_encode_frame(VCSession *vc, const uint8_t *y, const uint8_t *u, const uint8_t *v) +{ + /* I420 "It comprises an NxM Y plane followed by (N/2)x(M/2) V and U planes." + * http://fourcc.org/yuv.php#IYUV + */ + + vpx_image_t *img = &vc->input_frame; + + int plane_bytes_y = img->w * img->h; + int plane_bytes_uv = plane_bytes_y / 4; + + memcpy( img->planes[VPX_PLANE_Y], y, plane_bytes_y); + memcpy( img->planes[VPX_PLANE_U], u, plane_bytes_uv); + memcpy( img->planes[VPX_PLANE_V], v, plane_bytes_uv); + + return vpx_codec_encode(vc->encoder, img, + vc->frame_counter, 1, 0, MAX_ENCODE_TIME_US); +} diff --git a/toxav/video.h b/toxav/video.h index fb836a3549..6e4f47599f 100644 --- a/toxav/video.h +++ b/toxav/video.h @@ -56,6 +56,8 @@ typedef struct VCSession_s { PAIR(toxav_video_receive_frame_cb *, void *) vcb; /* Video frame receive callback */ pthread_mutex_t queue_mutex[1]; + + vpx_image_t input_frame; } VCSession; VCSession *vc_new(ToxAV *av, uint32_t friend_number, toxav_video_receive_frame_cb *cb, void *cb_data); @@ -63,5 +65,6 @@ void vc_kill(VCSession *vc); void vc_iterate(VCSession *vc); int vc_queue_message(void *vcp, struct RTPMessage *msg); int vc_reconfigure_encoder(VCSession *vc, uint32_t bit_rate, uint16_t width, uint16_t height); +int vc_encode_frame(VCSession *vc, const uint8_t *y, const uint8_t *u, const uint8_t *v); #endif /* VIDEO_H */