|
@@ -42,6 +42,9 @@ enum { kCMVideoCodecType_HEVC = 'hvc1' }; |
|
|
|
|
|
|
|
|
#define VIDEOTOOLBOX_ESDS_EXTRADATA_PADDING 12 |
|
|
#define VIDEOTOOLBOX_ESDS_EXTRADATA_PADDING 12 |
|
|
|
|
|
|
|
|
|
|
|
static void videotoolbox_stop(AVCodecContext *avctx); |
|
|
|
|
|
static int videotoolbox_start(AVCodecContext *avctx); |
|
|
|
|
|
|
|
|
static void videotoolbox_buffer_release(void *opaque, uint8_t *data) |
|
|
static void videotoolbox_buffer_release(void *opaque, uint8_t *data) |
|
|
{ |
|
|
{ |
|
|
CVPixelBufferRef cv_buffer = (CVImageBufferRef)data; |
|
|
CVPixelBufferRef cv_buffer = (CVImageBufferRef)data; |
|
@@ -307,6 +310,27 @@ int ff_videotoolbox_h264_start_frame(AVCodecContext *avctx, |
|
|
return 0; |
|
|
return 0; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static int videotoolbox_h264_decode_params(AVCodecContext *avctx, |
|
|
|
|
|
int type, |
|
|
|
|
|
const uint8_t *buffer, |
|
|
|
|
|
uint32_t size) |
|
|
|
|
|
{ |
|
|
|
|
|
VTContext *vtctx = avctx->internal->hwaccel_priv_data; |
|
|
|
|
|
|
|
|
|
|
|
if (type == H264_NAL_SPS) { |
|
|
|
|
|
if (!vtctx->sps || vtctx->sps_len != size || memcmp(buffer, vtctx->sps, size) != 0) { |
|
|
|
|
|
vtctx->sps = av_fast_realloc(vtctx->sps, &vtctx->sps_capa, size); |
|
|
|
|
|
if (vtctx->sps) |
|
|
|
|
|
memcpy(vtctx->sps, buffer, size); |
|
|
|
|
|
vtctx->reconfig_needed = true; |
|
|
|
|
|
vtctx->sps_len = size; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// pass-through new PPS to the decoder |
|
|
|
|
|
return ff_videotoolbox_h264_decode_slice(avctx, buffer, size); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
int ff_videotoolbox_h264_decode_slice(AVCodecContext *avctx, |
|
|
int ff_videotoolbox_h264_decode_slice(AVCodecContext *avctx, |
|
|
const uint8_t *buffer, |
|
|
const uint8_t *buffer, |
|
|
uint32_t size) |
|
|
uint32_t size) |
|
@@ -339,6 +363,7 @@ int ff_videotoolbox_uninit(AVCodecContext *avctx) |
|
|
VTContext *vtctx = avctx->internal->hwaccel_priv_data; |
|
|
VTContext *vtctx = avctx->internal->hwaccel_priv_data; |
|
|
if (vtctx) { |
|
|
if (vtctx) { |
|
|
av_freep(&vtctx->bitstream); |
|
|
av_freep(&vtctx->bitstream); |
|
|
|
|
|
av_freep(&vtctx->sps); |
|
|
if (vtctx->frame) |
|
|
if (vtctx->frame) |
|
|
CVPixelBufferRelease(vtctx->frame); |
|
|
CVPixelBufferRelease(vtctx->frame); |
|
|
} |
|
|
} |
|
@@ -591,17 +616,30 @@ static int videotoolbox_common_end_frame(AVCodecContext *avctx, AVFrame *frame) |
|
|
AVVideotoolboxContext *videotoolbox = videotoolbox_get_context(avctx); |
|
|
AVVideotoolboxContext *videotoolbox = videotoolbox_get_context(avctx); |
|
|
VTContext *vtctx = avctx->internal->hwaccel_priv_data; |
|
|
VTContext *vtctx = avctx->internal->hwaccel_priv_data; |
|
|
|
|
|
|
|
|
if (!videotoolbox->session || !vtctx->bitstream) |
|
|
|
|
|
|
|
|
if (vtctx->reconfig_needed == true) { |
|
|
|
|
|
vtctx->reconfig_needed = false; |
|
|
|
|
|
av_log(avctx, AV_LOG_VERBOSE, "VideoToolbox decoder needs reconfig, restarting..\n"); |
|
|
|
|
|
videotoolbox_stop(avctx); |
|
|
|
|
|
if (videotoolbox_start(avctx) != 0) { |
|
|
|
|
|
return AVERROR_EXTERNAL; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (!videotoolbox->session || !vtctx->bitstream || !vtctx->bitstream_size) |
|
|
return AVERROR_INVALIDDATA; |
|
|
return AVERROR_INVALIDDATA; |
|
|
|
|
|
|
|
|
status = videotoolbox_session_decode_frame(avctx); |
|
|
status = videotoolbox_session_decode_frame(avctx); |
|
|
if (status != noErr) { |
|
|
if (status != noErr) { |
|
|
|
|
|
if (status == kVTVideoDecoderMalfunctionErr || status == kVTInvalidSessionErr) |
|
|
|
|
|
vtctx->reconfig_needed = true; |
|
|
av_log(avctx, AV_LOG_ERROR, "Failed to decode frame (%s, %d)\n", videotoolbox_error_string(status), (int)status); |
|
|
av_log(avctx, AV_LOG_ERROR, "Failed to decode frame (%s, %d)\n", videotoolbox_error_string(status), (int)status); |
|
|
return AVERROR_UNKNOWN; |
|
|
return AVERROR_UNKNOWN; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if (!vtctx->frame) |
|
|
|
|
|
|
|
|
if (!vtctx->frame) { |
|
|
|
|
|
vtctx->reconfig_needed = true; |
|
|
return AVERROR_UNKNOWN; |
|
|
return AVERROR_UNKNOWN; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
return videotoolbox_buffer_create(avctx, frame); |
|
|
return videotoolbox_buffer_create(avctx, frame); |
|
|
} |
|
|
} |
|
@@ -1018,6 +1056,7 @@ AVHWAccel ff_h264_videotoolbox_hwaccel = { |
|
|
.alloc_frame = ff_videotoolbox_alloc_frame, |
|
|
.alloc_frame = ff_videotoolbox_alloc_frame, |
|
|
.start_frame = ff_videotoolbox_h264_start_frame, |
|
|
.start_frame = ff_videotoolbox_h264_start_frame, |
|
|
.decode_slice = ff_videotoolbox_h264_decode_slice, |
|
|
.decode_slice = ff_videotoolbox_h264_decode_slice, |
|
|
|
|
|
.decode_params = videotoolbox_h264_decode_params, |
|
|
.end_frame = videotoolbox_h264_end_frame, |
|
|
.end_frame = videotoolbox_h264_end_frame, |
|
|
.frame_params = videotoolbox_frame_params, |
|
|
.frame_params = videotoolbox_frame_params, |
|
|
.init = videotoolbox_common_init, |
|
|
.init = videotoolbox_common_init, |
|
|