[FFmpeg-cvslog] lavd/avfoundation: Fix skewed video output
Rick Kern
git at videolan.org
Fri Sep 14 01:28:00 EEST 2018
ffmpeg | branch: master | Rick Kern <kernrj at gmail.com> | Fri Jun 24 11:00:17 2016 -0400| [a259501e5a6ed07d76ce5d615123148b9b68d9f8] | committer: Carl Eugen Hoyos
lavd/avfoundation: Fix skewed video output
Fixes ticket #5654.
The linesize can be greater than the minimum required. This copies the
frame taking linesize into account.
Signed-off-by: Rick Kern <kernrj at gmail.com>
> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=a259501e5a6ed07d76ce5d615123148b9b68d9f8
---
libavdevice/avfoundation.m | 56 ++++++++++++++++++++++++++++++++++++++++------
1 file changed, 49 insertions(+), 7 deletions(-)
diff --git a/libavdevice/avfoundation.m b/libavdevice/avfoundation.m
index a540f6a079..98552ac29d 100644
--- a/libavdevice/avfoundation.m
+++ b/libavdevice/avfoundation.m
@@ -35,6 +35,7 @@
#include "libavutil/internal.h"
#include "libavutil/parseutils.h"
#include "libavutil/time.h"
+#include "libavutil/imgutils.h"
#include "avdevice.h"
static const int avf_time_base = 1000000;
@@ -892,6 +893,49 @@ fail:
return AVERROR(EIO);
}
+static int copy_cvpixelbuffer(AVFormatContext *s,
+ CVPixelBufferRef image_buffer,
+ AVPacket *pkt)
+{
+ AVFContext *ctx = s->priv_data;
+ int src_linesize[4];
+ const uint8_t *src_data[4];
+ int width = CVPixelBufferGetWidth(image_buffer);
+ int height = CVPixelBufferGetHeight(image_buffer);
+ int status;
+
+ memset(src_linesize, 0, sizeof(src_linesize));
+ memset(src_data, 0, sizeof(src_data));
+
+ status = CVPixelBufferLockBaseAddress(image_buffer, 0);
+ if (status != kCVReturnSuccess) {
+ av_log(s, AV_LOG_ERROR, "Could not lock base address: %d\n", status);
+ return AVERROR_EXTERNAL;
+ }
+
+ if (CVPixelBufferIsPlanar(image_buffer)) {
+ size_t plane_count = CVPixelBufferGetPlaneCount(image_buffer);
+ int i;
+ for(i = 0; i < plane_count; i++){
+ src_linesize[i] = CVPixelBufferGetBytesPerRowOfPlane(image_buffer, i);
+ src_data[i] = CVPixelBufferGetBaseAddressOfPlane(image_buffer, i);
+ }
+ } else {
+ src_linesize[0] = CVPixelBufferGetBytesPerRow(image_buffer);
+ src_data[0] = CVPixelBufferGetBaseAddress(image_buffer);
+ }
+
+ status = av_image_copy_to_buffer(pkt->data, pkt->size,
+ src_data, src_linesize,
+ ctx->pixel_format, width, height, 1);
+
+
+
+ CVPixelBufferUnlockBaseAddress(image_buffer, 0);
+
+ return status;
+}
+
static int avf_read_packet(AVFormatContext *s, AVPacket *pkt)
{
AVFContext* ctx = (AVFContext*)s->priv_data;
@@ -903,7 +947,7 @@ static int avf_read_packet(AVFormatContext *s, AVPacket *pkt)
image_buffer = CMSampleBufferGetImageBuffer(ctx->current_frame);
if (ctx->current_frame != nil) {
- void *data;
+ int status;
if (av_new_packet(pkt, (int)CVPixelBufferGetDataSize(image_buffer)) < 0) {
return AVERROR(EIO);
}
@@ -919,14 +963,12 @@ static int avf_read_packet(AVFormatContext *s, AVPacket *pkt)
pkt->stream_index = ctx->video_stream_index;
pkt->flags |= AV_PKT_FLAG_KEY;
- CVPixelBufferLockBaseAddress(image_buffer, 0);
-
- data = CVPixelBufferGetBaseAddress(image_buffer);
- memcpy(pkt->data, data, pkt->size);
-
- CVPixelBufferUnlockBaseAddress(image_buffer, 0);
+ status = copy_cvpixelbuffer(s, image_buffer, pkt);
CFRelease(ctx->current_frame);
ctx->current_frame = nil;
+
+ if (status < 0)
+ return status;
} else if (ctx->current_audio_frame != nil) {
CMBlockBufferRef block_buffer = CMSampleBufferGetDataBuffer(ctx->current_audio_frame);
int block_buffer_size = CMBlockBufferGetDataLength(block_buffer);
More information about the ffmpeg-cvslog
mailing list