mirror of
https://github.com/librempeg/librempeg
synced 2024-11-23 19:58:59 +00:00
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@gmail.com>
This commit is contained in:
parent
e320f9576a
commit
a259501e5a
@ -35,6 +35,7 @@
|
|||||||
#include "libavutil/internal.h"
|
#include "libavutil/internal.h"
|
||||||
#include "libavutil/parseutils.h"
|
#include "libavutil/parseutils.h"
|
||||||
#include "libavutil/time.h"
|
#include "libavutil/time.h"
|
||||||
|
#include "libavutil/imgutils.h"
|
||||||
#include "avdevice.h"
|
#include "avdevice.h"
|
||||||
|
|
||||||
static const int avf_time_base = 1000000;
|
static const int avf_time_base = 1000000;
|
||||||
@ -892,6 +893,49 @@ fail:
|
|||||||
return AVERROR(EIO);
|
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)
|
static int avf_read_packet(AVFormatContext *s, AVPacket *pkt)
|
||||||
{
|
{
|
||||||
AVFContext* ctx = (AVFContext*)s->priv_data;
|
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);
|
image_buffer = CMSampleBufferGetImageBuffer(ctx->current_frame);
|
||||||
|
|
||||||
if (ctx->current_frame != nil) {
|
if (ctx->current_frame != nil) {
|
||||||
void *data;
|
int status;
|
||||||
if (av_new_packet(pkt, (int)CVPixelBufferGetDataSize(image_buffer)) < 0) {
|
if (av_new_packet(pkt, (int)CVPixelBufferGetDataSize(image_buffer)) < 0) {
|
||||||
return AVERROR(EIO);
|
return AVERROR(EIO);
|
||||||
}
|
}
|
||||||
@ -919,14 +963,12 @@ static int avf_read_packet(AVFormatContext *s, AVPacket *pkt)
|
|||||||
pkt->stream_index = ctx->video_stream_index;
|
pkt->stream_index = ctx->video_stream_index;
|
||||||
pkt->flags |= AV_PKT_FLAG_KEY;
|
pkt->flags |= AV_PKT_FLAG_KEY;
|
||||||
|
|
||||||
CVPixelBufferLockBaseAddress(image_buffer, 0);
|
status = copy_cvpixelbuffer(s, image_buffer, pkt);
|
||||||
|
|
||||||
data = CVPixelBufferGetBaseAddress(image_buffer);
|
|
||||||
memcpy(pkt->data, data, pkt->size);
|
|
||||||
|
|
||||||
CVPixelBufferUnlockBaseAddress(image_buffer, 0);
|
|
||||||
CFRelease(ctx->current_frame);
|
CFRelease(ctx->current_frame);
|
||||||
ctx->current_frame = nil;
|
ctx->current_frame = nil;
|
||||||
|
|
||||||
|
if (status < 0)
|
||||||
|
return status;
|
||||||
} else if (ctx->current_audio_frame != nil) {
|
} else if (ctx->current_audio_frame != nil) {
|
||||||
CMBlockBufferRef block_buffer = CMSampleBufferGetDataBuffer(ctx->current_audio_frame);
|
CMBlockBufferRef block_buffer = CMSampleBufferGetDataBuffer(ctx->current_audio_frame);
|
||||||
int block_buffer_size = CMBlockBufferGetDataLength(block_buffer);
|
int block_buffer_size = CMBlockBufferGetDataLength(block_buffer);
|
||||||
|
Loading…
Reference in New Issue
Block a user