From 185318bbce339f1ee908a46c3f4acfdae93a9198 Mon Sep 17 00:00:00 2001 From: Mikhael-Danilov Date: Mon, 18 Jul 2016 20:46:11 +0300 Subject: [PATCH 1/3] * vpx_image_t input_frame in VCSession to avoid alloc|free pair for each frame * input_frame allocated with align 0 so copy here is unnecessary --- toxav/toxav.c | 18 +----------------- toxav/video.c | 34 ++++++++++++++++++++++++++++++++-- toxav/video.h | 3 +++ 3 files changed, 36 insertions(+), 19 deletions(-) diff --git a/toxav/toxav.c b/toxav/toxav.c index 814c4f2659..137e1fd920 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..dd0193f62f 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,27 @@ 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 + */ + vc->input_frame.planes[VPX_PLANE_Y] = y; + vc->input_frame.planes[VPX_PLANE_U] = u; + vc->input_frame.planes[VPX_PLANE_V] = v; + + return vpx_codec_encode(vc->encoder, &vc->input_frame, + vc->frame_counter, 1, 0, MAX_ENCODE_TIME_US); +} \ No newline at end of file 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 */ From e71902a29063ed75382abe85253c42fc3ee24615 Mon Sep 17 00:00:00 2001 From: Mikhael-Danilov Date: Wed, 27 Jul 2016 16:02:37 -0400 Subject: [PATCH 2/3] fix pointer type mismatch (tests passes now) --- toxav/toxav.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/toxav/toxav.c b/toxav/toxav.c index 137e1fd920..83de5f4b28 100644 --- a/toxav/toxav.c +++ b/toxav/toxav.c @@ -785,7 +785,7 @@ bool toxav_video_send_frame(ToxAV *av, uint32_t friend_number, uint16_t width, u } { /* Encode */ - int vrc = vc_encode_frame(&call->video.second, y, u, v); + int vrc = vc_encode_frame(call->video.second, y, u, v); if (vrc != VPX_CODEC_OK) { pthread_mutex_unlock(call->mutex_video); From e3776b41afd91a31ea8fb2825c9decb14cb7a0d4 Mon Sep 17 00:00:00 2001 From: Mikhael-Danilov Date: Thu, 28 Jul 2016 07:02:10 -0400 Subject: [PATCH 3/3] still need frame data copy here (or we get memory leak on each image size change) --- toxav/video.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/toxav/video.c b/toxav/video.c index dd0193f62f..89c99a7e49 100644 --- a/toxav/video.c +++ b/toxav/video.c @@ -285,10 +285,16 @@ int vc_encode_frame(VCSession *vc, const uint8_t *y, const uint8_t *u, const uin /* I420 "It comprises an NxM Y plane followed by (N/2)x(M/2) V and U planes." * http://fourcc.org/yuv.php#IYUV */ - vc->input_frame.planes[VPX_PLANE_Y] = y; - vc->input_frame.planes[VPX_PLANE_U] = u; - vc->input_frame.planes[VPX_PLANE_V] = v; + + vpx_image_t *img = &vc->input_frame; + + int plane_bytes_y = img->w * img->h; + int plane_bytes_uv = plane_bytes_y / 4; - return vpx_codec_encode(vc->encoder, &vc->input_frame, + 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); -} \ No newline at end of file +}