24 #if CONFIG_VIDEOTOOLBOX
37 #include <TargetConditionals.h>
39 #ifndef kVTVideoDecoderSpecification_RequireHardwareAcceleratedVideoDecoder
40 # define kVTVideoDecoderSpecification_RequireHardwareAcceleratedVideoDecoder CFSTR("RequireHardwareAcceleratedVideoDecoder")
43 #if !HAVE_KCMVIDEOCODECTYPE_HEVC
47 #define VIDEOTOOLBOX_ESDS_EXTRADATA_PADDING 12
51 CVPixelBufferRef cv_buffer = (CVImageBufferRef)data;
52 CVPixelBufferRelease(cv_buffer);
88 #define AV_W8(p, v) *(p) = (v)
116 av_assert0(p - vt_extradata == vt_extradata_size);
118 data = CFDataCreate(kCFAllocatorDefault, vt_extradata, vt_extradata_size);
135 int vt_extradata_size = 23 + 5 + vps->
data_size + 5 + sps->data_size + 3;
146 vt_extradata =
av_malloc(vt_extradata_size);
198 AV_W8(p + 15, 0xfc | parallelismType);
204 AV_W8(p + 16, sps->chroma_format_idc | 0xfc);
210 AV_W8(p + 17, (sps->bit_depth - 8) | 0xfc);
216 AV_W8(p + 18, (sps->bit_depth_chroma - 8) | 0xfc);
227 AV_W8(p + 21, 0 << 6 |
228 sps->max_sub_layers << 3 |
229 sps->temporal_id_nesting_flag << 2 |
256 AV_WB16(p + 3, sps->data_size);
257 memcpy(p + 5, sps->data, sps->data_size);
258 p += 5 + sps->data_size;
274 av_assert0(p - vt_extradata == vt_extradata_size);
276 data = CFDataCreate(kCFAllocatorDefault, vt_extradata, vt_extradata_size);
286 sizeof(vtctx->
frame),
290 if (!frame->
buf[0]) {
349 CVPixelBufferRelease(vtctx->
frame);
355 #if CONFIG_VIDEOTOOLBOX
373 CVPixelBufferRef pixbuf = (CVPixelBufferRef)vtctx->
frame;
374 OSType pixel_format = CVPixelBufferGetPixelFormatType(pixbuf);
376 int width = CVPixelBufferGetWidth(pixbuf);
377 int height = CVPixelBufferGetHeight(pixbuf);
392 cached_frames->
width != width ||
393 cached_frames->
height != height) {
402 hw_frames->
width = width;
403 hw_frames->
height = height;
428 for (i = 3; i >= 0; i--) {
429 b = (length >> (i * 7)) & 0x7F;
433 bytestream2_put_byteu(pb, b);
437 static CFDataRef videotoolbox_esds_extradata_create(
AVCodecContext *avctx)
451 bytestream2_put_byteu(&pb, 0);
455 bytestream2_put_byteu(&pb, 0x03);
456 videotoolbox_write_mp4_descr_length(&pb, full_size);
458 bytestream2_put_byteu(&pb, 0);
461 bytestream2_put_byteu(&pb, 0x04);
462 videotoolbox_write_mp4_descr_length(&pb, config_size);
463 bytestream2_put_byteu(&pb, 32);
464 bytestream2_put_byteu(&pb, 0x11);
470 bytestream2_put_byteu(&pb, 0x05);
476 bytestream2_put_byteu(&pb, 0x06);
477 bytestream2_put_byteu(&pb, 0x01);
478 bytestream2_put_byteu(&pb, 0x02);
482 data = CFDataCreate(kCFAllocatorDefault, rw_extradata, s);
488 static CMSampleBufferRef videotoolbox_sample_buffer_create(CMFormatDescriptionRef fmt_desc,
493 CMBlockBufferRef block_buf;
494 CMSampleBufferRef sample_buf;
499 status = CMBlockBufferCreateWithMemoryBlock(kCFAllocatorDefault,
510 status = CMSampleBufferCreate(kCFAllocatorDefault,
525 CFRelease(block_buf);
530 static void videotoolbox_decoder_callback(
void *opaque,
531 void *sourceFrameRefCon,
533 VTDecodeInfoFlags
flags,
534 CVImageBufferRef image_buffer,
542 CVPixelBufferRelease(vtctx->
frame);
551 vtctx->
frame = CVPixelBufferRetain(image_buffer);
554 static OSStatus videotoolbox_session_decode_frame(
AVCodecContext *avctx)
557 CMSampleBufferRef sample_buf;
561 sample_buf = videotoolbox_sample_buffer_create(videotoolbox->
cm_fmt_desc,
568 status = VTDecompressionSessionDecodeFrame(videotoolbox->
session,
574 status = VTDecompressionSessionWaitForAsynchronousFrames(videotoolbox->
session);
576 CFRelease(sample_buf);
590 status = videotoolbox_session_decode_frame(avctx);
600 return videotoolbox_buffer_create(avctx, frame);
608 return videotoolbox_common_end_frame(avctx, frame);
618 ret = videotoolbox_common_end_frame(avctx, frame);
644 return videotoolbox_common_end_frame(avctx, frame);
647 static CFDictionaryRef videotoolbox_decoder_config_create(CMVideoCodecType
codec_type,
650 CFMutableDictionaryRef config_info = CFDictionaryCreateMutable(kCFAllocatorDefault,
652 &kCFTypeDictionaryKeyCallBacks,
653 &kCFTypeDictionaryValueCallBacks);
655 CFDictionarySetValue(config_info,
660 CFMutableDictionaryRef avc_info;
661 CFDataRef data =
NULL;
663 avc_info = CFDictionaryCreateMutable(kCFAllocatorDefault,
665 &kCFTypeDictionaryKeyCallBacks,
666 &kCFTypeDictionaryValueCallBacks);
668 switch (codec_type) {
669 case kCMVideoCodecType_MPEG4Video :
670 data = videotoolbox_esds_extradata_create(avctx);
672 CFDictionarySetValue(avc_info, CFSTR(
"esds"), data);
674 case kCMVideoCodecType_H264 :
677 CFDictionarySetValue(avc_info, CFSTR(
"avcC"), data);
682 CFDictionarySetValue(avc_info, CFSTR(
"hvcC"), data);
688 CFDictionarySetValue(config_info,
689 kCMFormatDescriptionExtension_SampleDescriptionExtensionAtoms,
700 static CFDictionaryRef videotoolbox_buffer_attributes_create(
int width,
704 CFMutableDictionaryRef buffer_attributes;
705 CFMutableDictionaryRef io_surface_properties;
706 CFNumberRef cv_pix_fmt;
710 w = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &width);
711 h = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &height);
712 cv_pix_fmt = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &pix_fmt);
714 buffer_attributes = CFDictionaryCreateMutable(kCFAllocatorDefault,
716 &kCFTypeDictionaryKeyCallBacks,
717 &kCFTypeDictionaryValueCallBacks);
718 io_surface_properties = CFDictionaryCreateMutable(kCFAllocatorDefault,
720 &kCFTypeDictionaryKeyCallBacks,
721 &kCFTypeDictionaryValueCallBacks);
724 CFDictionarySetValue(buffer_attributes, kCVPixelBufferPixelFormatTypeKey, cv_pix_fmt);
725 CFDictionarySetValue(buffer_attributes, kCVPixelBufferIOSurfacePropertiesKey, io_surface_properties);
726 CFDictionarySetValue(buffer_attributes, kCVPixelBufferWidthKey, w);
727 CFDictionarySetValue(buffer_attributes, kCVPixelBufferHeightKey, h);
729 CFDictionarySetValue(buffer_attributes, kCVPixelBufferOpenGLESCompatibilityKey, kCFBooleanTrue);
731 CFDictionarySetValue(buffer_attributes, kCVPixelBufferIOSurfaceOpenGLTextureCompatibilityKey, kCFBooleanTrue);
734 CFRelease(io_surface_properties);
735 CFRelease(cv_pix_fmt);
739 return buffer_attributes;
742 static CMVideoFormatDescriptionRef videotoolbox_format_desc_create(CMVideoCodecType codec_type,
743 CFDictionaryRef decoder_spec,
747 CMFormatDescriptionRef cm_fmt_desc;
750 status = CMVideoFormatDescriptionCreate(kCFAllocatorDefault,
767 VTDecompressionOutputCallbackRecord decoder_cb;
768 CFDictionaryRef decoder_spec;
769 CFDictionaryRef buf_attr;
799 decoder_spec = videotoolbox_decoder_config_create(videotoolbox->
cm_codec_type, avctx);
807 CFRelease(decoder_spec);
813 buf_attr = videotoolbox_buffer_attributes_create(avctx->
width,
817 decoder_cb.decompressionOutputCallback = videotoolbox_decoder_callback;
818 decoder_cb.decompressionOutputRefCon = avctx;
820 status = VTDecompressionSessionCreate(
NULL,
828 CFRelease(decoder_spec);
833 case kVTVideoDecoderNotAvailableNowErr:
836 case kVTVideoDecoderUnsupportedDataFormatErr:
839 case kVTVideoDecoderMalfunctionErr:
842 case kVTVideoDecoderBadDataErr :
848 av_log(avctx,
AV_LOG_VERBOSE,
"Unknown VideoToolbox session creation error %u\n", (
unsigned)status);
862 VTDecompressionSessionInvalidate(videotoolbox->
session);
863 CFRelease(videotoolbox->
session);
877 videotoolbox_default_free(avctx);
897 "Either hw_frames_ctx or hw_device_ctx must be set.\n");
943 err = videotoolbox_default_init(avctx);
954 AVHWAccel ff_h263_videotoolbox_hwaccel = {
955 .
name =
"h263_videotoolbox",
960 .start_frame = videotoolbox_mpeg_start_frame,
961 .decode_slice = videotoolbox_mpeg_decode_slice,
962 .end_frame = videotoolbox_mpeg_end_frame,
963 .init = videotoolbox_common_init,
968 AVHWAccel ff_hevc_videotoolbox_hwaccel = {
969 .
name =
"hevc_videotoolbox",
976 .end_frame = videotoolbox_hevc_end_frame,
977 .init = videotoolbox_common_init,
982 AVHWAccel ff_h264_videotoolbox_hwaccel = {
983 .
name =
"h264_videotoolbox",
990 .end_frame = videotoolbox_h264_end_frame,
991 .init = videotoolbox_common_init,
996 AVHWAccel ff_mpeg1_videotoolbox_hwaccel = {
997 .
name =
"mpeg1_videotoolbox",
1002 .start_frame = videotoolbox_mpeg_start_frame,
1003 .decode_slice = videotoolbox_mpeg_decode_slice,
1004 .end_frame = videotoolbox_mpeg_end_frame,
1005 .init = videotoolbox_common_init,
1010 AVHWAccel ff_mpeg2_videotoolbox_hwaccel = {
1011 .
name =
"mpeg2_videotoolbox",
1016 .start_frame = videotoolbox_mpeg_start_frame,
1017 .decode_slice = videotoolbox_mpeg_decode_slice,
1018 .end_frame = videotoolbox_mpeg_end_frame,
1019 .init = videotoolbox_common_init,
1024 AVHWAccel ff_mpeg4_videotoolbox_hwaccel = {
1025 .
name =
"mpeg4_videotoolbox",
1030 .start_frame = videotoolbox_mpeg_start_frame,
1031 .decode_slice = videotoolbox_mpeg_decode_slice,
1032 .end_frame = videotoolbox_mpeg_end_frame,
1033 .init = videotoolbox_common_init,
1044 ret->
cv_pix_fmt_type = kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange;
1060 return videotoolbox_default_init(avctx);
1066 videotoolbox_default_free(avctx);
int min_spatial_segmentation_idc
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
static enum AVPixelFormat pix_fmt
void av_buffer_unref(AVBufferRef **buf)
Free a given reference and automatically free the buffer if there are no more references to it...
This structure describes decoded (raw) audio or video data.
AVBufferRef * vps_list[HEVC_MAX_VPS_COUNT]
ptrdiff_t const GLvoid * data
int cm_codec_type
CoreMedia codec type that Videotoolbox will use to create the decompression session.
AVBufferRef * buf[AV_NUM_DATA_POINTERS]
AVBuffer references backing the data for this frame.
hardware decoding through Videotoolbox
static av_always_inline void bytestream2_init_writer(PutByteContext *p, uint8_t *buf, int buf_size)
uint32_t av_map_videotoolbox_format_from_pixfmt(enum AVPixelFormat pix_fmt)
Convert an AVPixelFormat to a VideoToolbox (actually CoreVideo) format.
int width
The allocated dimensions of the frames in this pool.
enum AVMediaType codec_type
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Convenience header that includes libavutil's core.
int is_avc
Used to parse AVC variant of H.264.
enum AVPixelFormat format
The pixel format identifying the underlying HW surface type.
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
uint8_t entropy_coding_sync_enabled_flag
AVBufferRef * hw_frames_ctx
For hwaccel-format frames, this should be a reference to the AVHWFramesContext describing the frame...
#define av_assert0(cond)
assert() equivalent, that is always enabled.
AVBufferRef * sps_list[HEVC_MAX_SPS_COUNT]
uint8_t profile_compatibility_flag[32]
void * hwaccel_context
Hardware accelerator context.
An API-specific header for AV_HWDEVICE_TYPE_VIDEOTOOLBOX.
uint8_t * extradata
some codecs need / can use extradata like Huffman tables.
#define AV_LOG_VERBOSE
Detailed information.
AVBufferRef * pps_list[HEVC_MAX_PPS_COUNT]
#define AV_BUFFER_FLAG_READONLY
Always treat the buffer as read-only, even when it has only one reference.
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
uint8_t frame_only_constraint_flag
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
planar YUV 4:2:0, 12bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (firs...
AVBufferRef * av_buffer_create(uint8_t *data, int size, void(*free)(void *opaque, uint8_t *data), void *opaque, int flags)
Create an AVBuffer from an existing array.
VTDecompressionSessionRef session
Videotoolbox decompression session object.
int av_hwframe_ctx_init(AVBufferRef *ref)
Finalize the context before use.
uint8_t tiles_enabled_flag
const char * name
Name of the hardware accelerated codec.
int width
picture width / height.
AVBufferRef * hw_frames_ctx
A reference to the AVHWFramesContext describing the input (for encoding) or output (decoding) frames...
Picture * current_picture_ptr
pointer to the current picture
H.264 / AVC / MPEG-4 part10 codec.
void * av_fast_realloc(void *ptr, unsigned int *size, size_t min_size)
Reallocate the given buffer if it is not large enough, otherwise do nothing.
static av_always_inline unsigned int bytestream2_put_buffer(PutByteContext *p, const uint8_t *src, unsigned int size)
preferred ID for MPEG-1/2 video decoding
int format
format of the frame, -1 if unknown or unset Values correspond to enum AVPixelFormat for video frames...
AVBufferRef * av_buffer_alloc(int size)
Allocate an AVBuffer of the given size using av_malloc().
Public libavcodec VDA header.
#define bytestream2_put_ne24
main external API structure.
uint8_t * data
The data buffer.
CMVideoFormatDescriptionRef cm_fmt_desc
CoreMedia Format Description that Videotoolbox will use to create the decompression session...
This struct describes a set or pool of "hardware" frames (i.e.
H264Picture * cur_pic_ptr
OSType cv_pix_fmt_type
CVPixelBuffer Format Type that Videotoolbox will use for decoded frames.
static int64_t pts
Global timestamp for the audio frames.
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
AVBufferRef * device_ref
A reference to the parent AVHWDeviceContext.
A reference to a data buffer.
VTDecompressionOutputCallback output_callback
The output callback that must be passed to the session.
AVBufferRef * av_hwframe_ctx_alloc(AVBufferRef *device_ref_in)
Allocate an AVHWFramesContext tied to a given device context.
void * hwaccel_priv_data
hwaccel-specific private data
AVBufferRef * av_buffer_ref(AVBufferRef *buf)
Create a new reference to an AVBuffer.
struct AVVideotoolboxContext * vt_ctx
#define AVERROR_UNKNOWN
Unknown error, typically from an external library.
enum AVPixelFormat av_map_videotoolbox_format_to_pixfmt(uint32_t cv_fmt)
Convert a VideoToolbox (actually CoreVideo) format to AVPixelFormat.
struct AVCodecInternal * internal
Private context used for internal data.
struct AVBufferRef * cached_hw_frames_ctx
#define bytestream2_put_ne32
uint8_t progressive_source_flag
#define bytestream2_put_ne16
AVBufferRef * hw_device_ctx
A reference to the AVHWDeviceContext describing the device which will be used by a hardware encoder/d...
uint8_t non_packed_constraint_flag
enum AVPixelFormat sw_format
The pixel format identifying the actual data layout of the hardware frames.
AVPixelFormat
Pixel format.
uint8_t interlaced_source_flag
This struct holds all the information that needs to be passed between the caller and libavcodec for i...
static av_always_inline int bytestream2_size_p(PutByteContext *p)