|
|
|
@@ -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); |
|
|
|
|