24 #if CONFIG_VIDEOTOOLBOX
35 #ifndef kVTVideoDecoderSpecification_EnableHardwareAcceleratedVideoDecoder
36 # define kVTVideoDecoderSpecification_EnableHardwareAcceleratedVideoDecoder CFSTR("EnableHardwareAcceleratedVideoDecoder")
39 #define VIDEOTOOLBOX_ESDS_EXTRADATA_PADDING 12
43 CVPixelBufferRef cv_buffer = (CVImageBufferRef)data;
44 CVPixelBufferRelease(cv_buffer);
93 rw_extradata[4] |= 0x03;
95 data = CFDataCreate(kCFAllocatorDefault, rw_extradata, avctx->
extradata_size);
110 sizeof(vtctx->
frame),
114 if (!frame->
buf[0]) {
173 CVPixelBufferRelease(vtctx->
frame);
179 #if CONFIG_VIDEOTOOLBOX
185 for (i = 3; i >= 0; i--) {
186 b = (length >> (i * 7)) & 0x7F;
190 bytestream2_put_byteu(pb, b);
194 static CFDataRef videotoolbox_esds_extradata_create(
AVCodecContext *avctx)
208 bytestream2_put_byteu(&pb, 0);
212 bytestream2_put_byteu(&pb, 0x03);
213 videotoolbox_write_mp4_descr_length(&pb, full_size);
215 bytestream2_put_byteu(&pb, 0);
218 bytestream2_put_byteu(&pb, 0x04);
219 videotoolbox_write_mp4_descr_length(&pb, config_size);
220 bytestream2_put_byteu(&pb, 32);
221 bytestream2_put_byteu(&pb, 0x11);
227 bytestream2_put_byteu(&pb, 0x05);
233 bytestream2_put_byteu(&pb, 0x06);
234 bytestream2_put_byteu(&pb, 0x01);
235 bytestream2_put_byteu(&pb, 0x02);
239 data = CFDataCreate(kCFAllocatorDefault, rw_extradata, s);
245 static CMSampleBufferRef videotoolbox_sample_buffer_create(CMFormatDescriptionRef fmt_desc,
250 CMBlockBufferRef block_buf;
251 CMSampleBufferRef sample_buf;
256 status = CMBlockBufferCreateWithMemoryBlock(kCFAllocatorDefault,
267 status = CMSampleBufferCreate(kCFAllocatorDefault,
282 CFRelease(block_buf);
287 static void videotoolbox_decoder_callback(
void *opaque,
288 void *sourceFrameRefCon,
290 VTDecodeInfoFlags
flags,
291 CVImageBufferRef image_buffer,
299 CVPixelBufferRelease(vtctx->
frame);
308 vtctx->
frame = CVPixelBufferRetain(image_buffer);
311 static OSStatus videotoolbox_session_decode_frame(
AVCodecContext *avctx)
314 CMSampleBufferRef sample_buf;
318 sample_buf = videotoolbox_sample_buffer_create(videotoolbox->
cm_fmt_desc,
325 status = VTDecompressionSessionDecodeFrame(videotoolbox->
session,
331 status = VTDecompressionSessionWaitForAsynchronousFrames(videotoolbox->
session);
333 CFRelease(sample_buf);
347 status = videotoolbox_session_decode_frame(avctx);
365 return videotoolbox_common_end_frame(avctx, frame);
389 return videotoolbox_common_end_frame(avctx, frame);
392 static CFDictionaryRef videotoolbox_decoder_config_create(CMVideoCodecType
codec_type,
395 CFMutableDictionaryRef config_info = CFDictionaryCreateMutable(kCFAllocatorDefault,
397 &kCFTypeDictionaryKeyCallBacks,
398 &kCFTypeDictionaryValueCallBacks);
400 CFDictionarySetValue(config_info,
405 CFMutableDictionaryRef avc_info;
406 CFDataRef data =
NULL;
408 avc_info = CFDictionaryCreateMutable(kCFAllocatorDefault,
410 &kCFTypeDictionaryKeyCallBacks,
411 &kCFTypeDictionaryValueCallBacks);
413 switch (codec_type) {
414 case kCMVideoCodecType_MPEG4Video :
415 data = videotoolbox_esds_extradata_create(avctx);
417 CFDictionarySetValue(avc_info, CFSTR(
"esds"), data);
419 case kCMVideoCodecType_H264 :
422 CFDictionarySetValue(avc_info, CFSTR(
"avcC"), data);
428 CFDictionarySetValue(config_info,
429 kCMFormatDescriptionExtension_SampleDescriptionExtensionAtoms,
440 static CFDictionaryRef videotoolbox_buffer_attributes_create(
int width,
444 CFMutableDictionaryRef buffer_attributes;
445 CFMutableDictionaryRef io_surface_properties;
446 CFNumberRef cv_pix_fmt;
450 w = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &width);
451 h = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &height);
452 cv_pix_fmt = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &pix_fmt);
454 buffer_attributes = CFDictionaryCreateMutable(kCFAllocatorDefault,
456 &kCFTypeDictionaryKeyCallBacks,
457 &kCFTypeDictionaryValueCallBacks);
458 io_surface_properties = CFDictionaryCreateMutable(kCFAllocatorDefault,
460 &kCFTypeDictionaryKeyCallBacks,
461 &kCFTypeDictionaryValueCallBacks);
463 CFDictionarySetValue(buffer_attributes, kCVPixelBufferPixelFormatTypeKey, cv_pix_fmt);
464 CFDictionarySetValue(buffer_attributes, kCVPixelBufferIOSurfacePropertiesKey, io_surface_properties);
465 CFDictionarySetValue(buffer_attributes, kCVPixelBufferWidthKey, w);
466 CFDictionarySetValue(buffer_attributes, kCVPixelBufferHeightKey, h);
468 CFRelease(io_surface_properties);
469 CFRelease(cv_pix_fmt);
473 return buffer_attributes;
476 static CMVideoFormatDescriptionRef videotoolbox_format_desc_create(CMVideoCodecType codec_type,
477 CFDictionaryRef decoder_spec,
481 CMFormatDescriptionRef cm_fmt_desc;
484 status = CMVideoFormatDescriptionCreate(kCFAllocatorDefault,
501 VTDecompressionOutputCallbackRecord decoder_cb;
502 CFDictionaryRef decoder_spec;
503 CFDictionaryRef buf_attr;
533 decoder_spec = videotoolbox_decoder_config_create(videotoolbox->
cm_codec_type, avctx);
541 CFRelease(decoder_spec);
547 buf_attr = videotoolbox_buffer_attributes_create(avctx->
width,
551 decoder_cb.decompressionOutputCallback = videotoolbox_decoder_callback;
552 decoder_cb.decompressionOutputRefCon = avctx;
554 status = VTDecompressionSessionCreate(
NULL,
562 CFRelease(decoder_spec);
567 case kVTVideoDecoderNotAvailableNowErr:
568 case kVTVideoDecoderUnsupportedDataFormatErr:
570 case kVTVideoDecoderMalfunctionErr:
572 case kVTVideoDecoderBadDataErr :
590 VTDecompressionSessionInvalidate(videotoolbox->
session);
594 AVHWAccel ff_h263_videotoolbox_hwaccel = {
595 .
name =
"h263_videotoolbox",
600 .start_frame = videotoolbox_mpeg_start_frame,
601 .decode_slice = videotoolbox_mpeg_decode_slice,
602 .end_frame = videotoolbox_mpeg_end_frame,
607 AVHWAccel ff_h264_videotoolbox_hwaccel = {
608 .
name =
"h264_videotoolbox",
615 .end_frame = videotoolbox_h264_end_frame,
620 AVHWAccel ff_mpeg1_videotoolbox_hwaccel = {
621 .
name =
"mpeg1_videotoolbox",
626 .start_frame = videotoolbox_mpeg_start_frame,
627 .decode_slice = videotoolbox_mpeg_decode_slice,
628 .end_frame = videotoolbox_mpeg_end_frame,
633 AVHWAccel ff_mpeg2_videotoolbox_hwaccel = {
634 .
name =
"mpeg2_videotoolbox",
639 .start_frame = videotoolbox_mpeg_start_frame,
640 .decode_slice = videotoolbox_mpeg_decode_slice,
641 .end_frame = videotoolbox_mpeg_end_frame,
646 AVHWAccel ff_mpeg4_videotoolbox_hwaccel = {
647 .
name =
"mpeg4_videotoolbox",
652 .start_frame = videotoolbox_mpeg_start_frame,
653 .decode_slice = videotoolbox_mpeg_decode_slice,
654 .end_frame = videotoolbox_mpeg_end_frame,
665 ret->
cv_pix_fmt_type = kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange;
681 return videotoolbox_default_init(avctx);
687 videotoolbox_default_free(avctx);
#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.
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)
enum AVMediaType codec_type
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
int is_avc
Used to parse AVC variant of h264.
void * hwaccel_context
Hardware accelerator context.
uint8_t * extradata
some codecs need / can use extradata like Huffman tables.
#define AV_BUFFER_FLAG_READONLY
Always treat the buffer as read-only, even when it has only one reference.
H.264 / AVC / MPEG4 part10 codec.
int width
width and height of the video frame
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
void * av_fast_realloc(void *ptr, unsigned int *size, size_t min_size)
Reallocate the given block if it is not large enough, otherwise do nothing.
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
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.
const char * name
Name of the hardware accelerated codec.
int width
picture width / height.
Picture * current_picture_ptr
pointer to the current picture
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
void * av_memdup(const void *p, size_t size)
Duplicate the buffer p.
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.
CMVideoFormatDescriptionRef cm_fmt_desc
CoreMedia Format Description that Videotoolbox will use to create the decompression session...
BYTE int const BYTE int int int height
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.
VTDecompressionOutputCallback output_callback
The output callback that must be passed to the session.
void * hwaccel_priv_data
hwaccel-specific private data
#define AVERROR_UNKNOWN
Unknown error, typically from an external library.
struct AVCodecInternal * internal
Private context used for internal data.
#define bytestream2_put_ne32
#define bytestream2_put_ne16
This struct holds all the information that needs to be passed between the caller and libavcodec for i...
void * av_mallocz(size_t size)
Allocate a block of size bytes with alignment suitable for all memory accesses (including vectors if ...
static av_always_inline int bytestream2_size_p(PutByteContext *p)