From 6cc2b37b3ac93b165e65a9f3ca2b9627c9b5dbfa Mon Sep 17 00:00:00 2001 From: Green Sky Date: Fri, 28 Mar 2025 10:16:29 +0100 Subject: [PATCH] fix(toxav): remove extra copy of video frame on encode Tested and works, but there might be alignment issues and other stuff. --- toxav/toxav.c | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/toxav/toxav.c b/toxav/toxav.c index f98e69cd61..e7d9230447 100644 --- a/toxav/toxav.c +++ b/toxav/toxav.c @@ -1072,24 +1072,28 @@ bool toxav_video_send_frame(ToxAV *av, uint32_t friend_number, uint16_t width, u { /* Encode */ vpx_image_t img; - img.w = 0; - img.h = 0; - img.d_w = 0; - img.d_h = 0; - if (vpx_img_alloc(&img, VPX_IMG_FMT_I420, width, height, 0) == nullptr) { - pthread_mutex_unlock(call->mutex_video); - LOGGER_ERROR(av->log, "Could not allocate image for frame"); - rc = TOXAV_ERR_SEND_FRAME_INVALID; - goto RETURN; + // TODO(Green-Sky): figure out stride_align + // TODO(Green-Sky): check memory alignment? + if (vpx_img_wrap(&img, VPX_IMG_FMT_I420, width, height, 0, (uint8_t *)y) != nullptr) { + // vpx_img_wrap assumes contigues memory, so we fix that + img.planes[VPX_PLANE_U] = (uint8_t *)u; + img.planes[VPX_PLANE_V] = (uint8_t *)v; + } else { + // call to wrap failed, falling back to copy + img.w = 0; + img.h = 0; + img.d_w = 0; + 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)); } - /* 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)); - const vpx_codec_err_t vrc = vpx_codec_encode(call->video->encoder, &img, call->video->frame_counter, 1, vpx_encode_flags, MAX_ENCODE_TIME_US);