//Not used on OSX - frame is never copied.
static int copy_avframe_to_pixel_buffer(AVCodecContext *avctx,
const AVFrame *frame,
CVPixelBufferRef cv_img,
const size_t *plane_strides,
const size_t *plane_rows)
{
int i, j;
size_t plane_count;
int status;
int rows;
int src_stride;
int dst_stride;
uint8_t *src_addr;
uint8_t *dst_addr;
size_t copy_bytes;
status = CVPixelBufferLockBaseAddress(cv_img, 0);
if (status) {
av_log(
avctx,
AV_LOG_ERROR,
"Error: Could not lock base address of CVPixelBuffer: %d.\n",
status
);
}
if (CVPixelBufferIsPlanar(cv_img)) {
plane_count = CVPixelBufferGetPlaneCount(cv_img);
for (i = 0; frame->data[i]; i++) {
if (i == plane_count) {
CVPixelBufferUnlockBaseAddress(cv_img, 0);
av_log(avctx,
AV_LOG_ERROR,
"Error: different number of planes in AVFrame and CVPixelBuffer.\n"
);
return AVERROR_EXTERNAL;
}
dst_addr = (uint8_t*)CVPixelBufferGetBaseAddressOfPlane(cv_img, i);
src_addr = (uint8_t*)frame->data[i];
dst_stride = CVPixelBufferGetBytesPerRowOfPlane(cv_img, i);
src_stride = plane_strides[i];
rows = plane_rows[i];
if (dst_stride == src_stride) {
memcpy(dst_addr, src_addr, src_stride * rows);
} else {
copy_bytes = dst_stride < src_stride ? dst_stride : src_stride;
for (j = 0; j < rows; j++) {
memcpy(dst_addr + j * dst_stride, src_addr + j * src_stride, copy_bytes);
}
}
}
} else {
if (frame->data[1]) {
CVPixelBufferUnlockBaseAddress(cv_img, 0);
av_log(avctx,
AV_LOG_ERROR,
"Error: different number of planes in AVFrame and non-planar CVPixelBuffer.\n"
);
return AVERROR_EXTERNAL;
}
dst_addr = (uint8_t*)CVPixelBufferGetBaseAddress(cv_img);
src_addr = (uint8_t*)frame->data[0];
dst_stride = CVPixelBufferGetBytesPerRow(cv_img);
src_stride = plane_strides[0];
rows = plane_rows[0];
if (dst_stride == src_stride) {
memcpy(dst_addr, src_addr, src_stride * rows);
} else {
copy_bytes = dst_stride < src_stride ? dst_stride : src_stride;
for (j = 0; j < rows; j++) {
memcpy(dst_addr + j * dst_stride, src_addr + j * src_stride, copy_bytes);
}
}
}
status = CVPixelBufferUnlockBaseAddress(cv_img, 0);
if (status) {
av_log(avctx, AV_LOG_ERROR, "Error: Could not unlock CVPixelBuffer base address: %d.\n", status);
return AVERROR_EXTERNAL;
}
return 0;
}