1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * Videotoolbox hardware acceleration 3cabdff1aSopenharmony_ci * 4cabdff1aSopenharmony_ci * copyright (c) 2012 Sebastien Zwickert 5cabdff1aSopenharmony_ci * 6cabdff1aSopenharmony_ci * This file is part of FFmpeg. 7cabdff1aSopenharmony_ci * 8cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 9cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 10cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 11cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 12cabdff1aSopenharmony_ci * 13cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 14cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 15cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16cabdff1aSopenharmony_ci * Lesser General Public License for more details. 17cabdff1aSopenharmony_ci * 18cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 19cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 20cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 21cabdff1aSopenharmony_ci */ 22cabdff1aSopenharmony_ci 23cabdff1aSopenharmony_ci#include "config.h" 24cabdff1aSopenharmony_ci#include "config_components.h" 25cabdff1aSopenharmony_ci#include "videotoolbox.h" 26cabdff1aSopenharmony_ci#include "libavutil/hwcontext_videotoolbox.h" 27cabdff1aSopenharmony_ci#include "vt_internal.h" 28cabdff1aSopenharmony_ci#include "libavutil/avutil.h" 29cabdff1aSopenharmony_ci#include "libavutil/hwcontext.h" 30cabdff1aSopenharmony_ci#include "libavutil/pixdesc.h" 31cabdff1aSopenharmony_ci#include "bytestream.h" 32cabdff1aSopenharmony_ci#include "decode.h" 33cabdff1aSopenharmony_ci#include "internal.h" 34cabdff1aSopenharmony_ci#include "h264dec.h" 35cabdff1aSopenharmony_ci#include "hevcdec.h" 36cabdff1aSopenharmony_ci#include "mpegvideo.h" 37cabdff1aSopenharmony_ci#include "proresdec.h" 38cabdff1aSopenharmony_ci#include <Availability.h> 39cabdff1aSopenharmony_ci#include <AvailabilityMacros.h> 40cabdff1aSopenharmony_ci#include <TargetConditionals.h> 41cabdff1aSopenharmony_ci 42cabdff1aSopenharmony_ci#ifndef kVTVideoDecoderSpecification_RequireHardwareAcceleratedVideoDecoder 43cabdff1aSopenharmony_ci# define kVTVideoDecoderSpecification_RequireHardwareAcceleratedVideoDecoder CFSTR("RequireHardwareAcceleratedVideoDecoder") 44cabdff1aSopenharmony_ci#endif 45cabdff1aSopenharmony_ci#ifndef kVTVideoDecoderSpecification_EnableHardwareAcceleratedVideoDecoder 46cabdff1aSopenharmony_ci# define kVTVideoDecoderSpecification_EnableHardwareAcceleratedVideoDecoder CFSTR("EnableHardwareAcceleratedVideoDecoder") 47cabdff1aSopenharmony_ci#endif 48cabdff1aSopenharmony_ci 49cabdff1aSopenharmony_ci#if !HAVE_KCMVIDEOCODECTYPE_HEVC 50cabdff1aSopenharmony_cienum { kCMVideoCodecType_HEVC = 'hvc1' }; 51cabdff1aSopenharmony_ci#endif 52cabdff1aSopenharmony_ci 53cabdff1aSopenharmony_ci#if !HAVE_KCMVIDEOCODECTYPE_VP9 54cabdff1aSopenharmony_cienum { kCMVideoCodecType_VP9 = 'vp09' }; 55cabdff1aSopenharmony_ci#endif 56cabdff1aSopenharmony_ci 57cabdff1aSopenharmony_ci#define VIDEOTOOLBOX_ESDS_EXTRADATA_PADDING 12 58cabdff1aSopenharmony_ci 59cabdff1aSopenharmony_citypedef struct VTHWFrame { 60cabdff1aSopenharmony_ci CVPixelBufferRef pixbuf; 61cabdff1aSopenharmony_ci AVBufferRef *hw_frames_ctx; 62cabdff1aSopenharmony_ci} VTHWFrame; 63cabdff1aSopenharmony_ci 64cabdff1aSopenharmony_cistatic void videotoolbox_buffer_release(void *opaque, uint8_t *data) 65cabdff1aSopenharmony_ci{ 66cabdff1aSopenharmony_ci VTHWFrame *ref = (VTHWFrame *)data; 67cabdff1aSopenharmony_ci av_buffer_unref(&ref->hw_frames_ctx); 68cabdff1aSopenharmony_ci CVPixelBufferRelease(ref->pixbuf); 69cabdff1aSopenharmony_ci 70cabdff1aSopenharmony_ci av_free(data); 71cabdff1aSopenharmony_ci} 72cabdff1aSopenharmony_ci 73cabdff1aSopenharmony_ciint ff_videotoolbox_buffer_copy(VTContext *vtctx, 74cabdff1aSopenharmony_ci const uint8_t *buffer, 75cabdff1aSopenharmony_ci uint32_t size) 76cabdff1aSopenharmony_ci{ 77cabdff1aSopenharmony_ci void *tmp; 78cabdff1aSopenharmony_ci 79cabdff1aSopenharmony_ci tmp = av_fast_realloc(vtctx->bitstream, 80cabdff1aSopenharmony_ci &vtctx->allocated_size, 81cabdff1aSopenharmony_ci size); 82cabdff1aSopenharmony_ci 83cabdff1aSopenharmony_ci if (!tmp) 84cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 85cabdff1aSopenharmony_ci 86cabdff1aSopenharmony_ci vtctx->bitstream = tmp; 87cabdff1aSopenharmony_ci memcpy(vtctx->bitstream, buffer, size); 88cabdff1aSopenharmony_ci vtctx->bitstream_size = size; 89cabdff1aSopenharmony_ci 90cabdff1aSopenharmony_ci return 0; 91cabdff1aSopenharmony_ci} 92cabdff1aSopenharmony_ci 93cabdff1aSopenharmony_cistatic int videotoolbox_postproc_frame(void *avctx, AVFrame *frame) 94cabdff1aSopenharmony_ci{ 95cabdff1aSopenharmony_ci int ret; 96cabdff1aSopenharmony_ci VTHWFrame *ref = (VTHWFrame *)frame->buf[0]->data; 97cabdff1aSopenharmony_ci 98cabdff1aSopenharmony_ci if (!ref->pixbuf) { 99cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "No frame decoded?\n"); 100cabdff1aSopenharmony_ci av_frame_unref(frame); 101cabdff1aSopenharmony_ci return AVERROR_EXTERNAL; 102cabdff1aSopenharmony_ci } 103cabdff1aSopenharmony_ci 104cabdff1aSopenharmony_ci frame->crop_right = 0; 105cabdff1aSopenharmony_ci frame->crop_left = 0; 106cabdff1aSopenharmony_ci frame->crop_top = 0; 107cabdff1aSopenharmony_ci frame->crop_bottom = 0; 108cabdff1aSopenharmony_ci 109cabdff1aSopenharmony_ci if ((ret = av_vt_pixbuf_set_attachments(avctx, ref->pixbuf, frame)) < 0) 110cabdff1aSopenharmony_ci return ret; 111cabdff1aSopenharmony_ci 112cabdff1aSopenharmony_ci frame->data[3] = (uint8_t*)ref->pixbuf; 113cabdff1aSopenharmony_ci 114cabdff1aSopenharmony_ci if (ref->hw_frames_ctx) { 115cabdff1aSopenharmony_ci av_buffer_unref(&frame->hw_frames_ctx); 116cabdff1aSopenharmony_ci frame->hw_frames_ctx = av_buffer_ref(ref->hw_frames_ctx); 117cabdff1aSopenharmony_ci if (!frame->hw_frames_ctx) 118cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 119cabdff1aSopenharmony_ci } 120cabdff1aSopenharmony_ci 121cabdff1aSopenharmony_ci return 0; 122cabdff1aSopenharmony_ci} 123cabdff1aSopenharmony_ci 124cabdff1aSopenharmony_ciint ff_videotoolbox_alloc_frame(AVCodecContext *avctx, AVFrame *frame) 125cabdff1aSopenharmony_ci{ 126cabdff1aSopenharmony_ci size_t size = sizeof(VTHWFrame); 127cabdff1aSopenharmony_ci uint8_t *data = NULL; 128cabdff1aSopenharmony_ci AVBufferRef *buf = NULL; 129cabdff1aSopenharmony_ci int ret = ff_attach_decode_data(frame); 130cabdff1aSopenharmony_ci FrameDecodeData *fdd; 131cabdff1aSopenharmony_ci if (ret < 0) 132cabdff1aSopenharmony_ci return ret; 133cabdff1aSopenharmony_ci 134cabdff1aSopenharmony_ci data = av_mallocz(size); 135cabdff1aSopenharmony_ci if (!data) 136cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 137cabdff1aSopenharmony_ci buf = av_buffer_create(data, size, videotoolbox_buffer_release, NULL, 0); 138cabdff1aSopenharmony_ci if (!buf) { 139cabdff1aSopenharmony_ci av_freep(&data); 140cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 141cabdff1aSopenharmony_ci } 142cabdff1aSopenharmony_ci frame->buf[0] = buf; 143cabdff1aSopenharmony_ci 144cabdff1aSopenharmony_ci fdd = (FrameDecodeData*)frame->private_ref->data; 145cabdff1aSopenharmony_ci fdd->post_process = videotoolbox_postproc_frame; 146cabdff1aSopenharmony_ci 147cabdff1aSopenharmony_ci frame->width = avctx->width; 148cabdff1aSopenharmony_ci frame->height = avctx->height; 149cabdff1aSopenharmony_ci frame->format = avctx->pix_fmt; 150cabdff1aSopenharmony_ci 151cabdff1aSopenharmony_ci return 0; 152cabdff1aSopenharmony_ci} 153cabdff1aSopenharmony_ci 154cabdff1aSopenharmony_ci#define AV_W8(p, v) *(p) = (v) 155cabdff1aSopenharmony_ci 156cabdff1aSopenharmony_cistatic int escape_ps(uint8_t* dst, const uint8_t* src, int src_size) 157cabdff1aSopenharmony_ci{ 158cabdff1aSopenharmony_ci int i; 159cabdff1aSopenharmony_ci int size = src_size; 160cabdff1aSopenharmony_ci uint8_t* p = dst; 161cabdff1aSopenharmony_ci 162cabdff1aSopenharmony_ci for (i = 0; i < src_size; i++) { 163cabdff1aSopenharmony_ci if (i + 2 < src_size && 164cabdff1aSopenharmony_ci src[i] == 0x00 && 165cabdff1aSopenharmony_ci src[i + 1] == 0x00 && 166cabdff1aSopenharmony_ci src[i + 2] <= 0x03) { 167cabdff1aSopenharmony_ci if (dst) { 168cabdff1aSopenharmony_ci *p++ = src[i++]; 169cabdff1aSopenharmony_ci *p++ = src[i]; 170cabdff1aSopenharmony_ci *p++ = 0x03; 171cabdff1aSopenharmony_ci } else { 172cabdff1aSopenharmony_ci i++; 173cabdff1aSopenharmony_ci } 174cabdff1aSopenharmony_ci size++; 175cabdff1aSopenharmony_ci } else if (dst) 176cabdff1aSopenharmony_ci *p++ = src[i]; 177cabdff1aSopenharmony_ci } 178cabdff1aSopenharmony_ci 179cabdff1aSopenharmony_ci if (dst) 180cabdff1aSopenharmony_ci av_assert0((p - dst) == size); 181cabdff1aSopenharmony_ci 182cabdff1aSopenharmony_ci return size; 183cabdff1aSopenharmony_ci} 184cabdff1aSopenharmony_ci 185cabdff1aSopenharmony_ciCFDataRef ff_videotoolbox_avcc_extradata_create(AVCodecContext *avctx) 186cabdff1aSopenharmony_ci{ 187cabdff1aSopenharmony_ci VTContext *vtctx = avctx->internal->hwaccel_priv_data; 188cabdff1aSopenharmony_ci H264Context *h = avctx->priv_data; 189cabdff1aSopenharmony_ci CFDataRef data = NULL; 190cabdff1aSopenharmony_ci uint8_t *p; 191cabdff1aSopenharmony_ci int sps_size = escape_ps(NULL, h->ps.sps->data, h->ps.sps->data_size); 192cabdff1aSopenharmony_ci int pps_size = escape_ps(NULL, h->ps.pps->data, h->ps.pps->data_size); 193cabdff1aSopenharmony_ci int vt_extradata_size; 194cabdff1aSopenharmony_ci uint8_t *vt_extradata; 195cabdff1aSopenharmony_ci 196cabdff1aSopenharmony_ci vt_extradata_size = 6 + 2 + sps_size + 3 + pps_size; 197cabdff1aSopenharmony_ci vt_extradata = av_malloc(vt_extradata_size); 198cabdff1aSopenharmony_ci 199cabdff1aSopenharmony_ci if (!vt_extradata) 200cabdff1aSopenharmony_ci return NULL; 201cabdff1aSopenharmony_ci 202cabdff1aSopenharmony_ci p = vt_extradata; 203cabdff1aSopenharmony_ci 204cabdff1aSopenharmony_ci AV_W8(p + 0, 1); /* version */ 205cabdff1aSopenharmony_ci AV_W8(p + 1, h->ps.sps->data[1]); /* profile */ 206cabdff1aSopenharmony_ci AV_W8(p + 2, h->ps.sps->data[2]); /* profile compat */ 207cabdff1aSopenharmony_ci AV_W8(p + 3, h->ps.sps->data[3]); /* level */ 208cabdff1aSopenharmony_ci AV_W8(p + 4, 0xff); /* 6 bits reserved (111111) + 2 bits nal size length - 3 (11) */ 209cabdff1aSopenharmony_ci AV_W8(p + 5, 0xe1); /* 3 bits reserved (111) + 5 bits number of sps (00001) */ 210cabdff1aSopenharmony_ci AV_WB16(p + 6, sps_size); 211cabdff1aSopenharmony_ci p += 8; 212cabdff1aSopenharmony_ci p += escape_ps(p, h->ps.sps->data, h->ps.sps->data_size); 213cabdff1aSopenharmony_ci AV_W8(p + 0, 1); /* number of pps */ 214cabdff1aSopenharmony_ci AV_WB16(p + 1, pps_size); 215cabdff1aSopenharmony_ci p += 3; 216cabdff1aSopenharmony_ci p += escape_ps(p, h->ps.pps->data, h->ps.pps->data_size); 217cabdff1aSopenharmony_ci 218cabdff1aSopenharmony_ci av_assert0(p - vt_extradata == vt_extradata_size); 219cabdff1aSopenharmony_ci 220cabdff1aSopenharmony_ci // save sps header (profile/level) used to create decoder session, 221cabdff1aSopenharmony_ci // so we can detect changes and recreate it. 222cabdff1aSopenharmony_ci if (vtctx) 223cabdff1aSopenharmony_ci memcpy(vtctx->sps, h->ps.sps->data + 1, 3); 224cabdff1aSopenharmony_ci 225cabdff1aSopenharmony_ci data = CFDataCreate(kCFAllocatorDefault, vt_extradata, vt_extradata_size); 226cabdff1aSopenharmony_ci av_free(vt_extradata); 227cabdff1aSopenharmony_ci return data; 228cabdff1aSopenharmony_ci} 229cabdff1aSopenharmony_ci 230cabdff1aSopenharmony_ciCFDataRef ff_videotoolbox_hvcc_extradata_create(AVCodecContext *avctx) 231cabdff1aSopenharmony_ci{ 232cabdff1aSopenharmony_ci HEVCContext *h = avctx->priv_data; 233cabdff1aSopenharmony_ci int i, num_vps = 0, num_sps = 0, num_pps = 0; 234cabdff1aSopenharmony_ci const HEVCVPS *vps = h->ps.vps; 235cabdff1aSopenharmony_ci const HEVCSPS *sps = h->ps.sps; 236cabdff1aSopenharmony_ci const HEVCPPS *pps = h->ps.pps; 237cabdff1aSopenharmony_ci PTLCommon ptlc = vps->ptl.general_ptl; 238cabdff1aSopenharmony_ci VUI vui = sps->vui; 239cabdff1aSopenharmony_ci uint8_t parallelismType; 240cabdff1aSopenharmony_ci CFDataRef data = NULL; 241cabdff1aSopenharmony_ci uint8_t *p; 242cabdff1aSopenharmony_ci int vt_extradata_size = 23 + 3 + 3 + 3; 243cabdff1aSopenharmony_ci uint8_t *vt_extradata; 244cabdff1aSopenharmony_ci 245cabdff1aSopenharmony_ci#define COUNT_SIZE_PS(T, t) \ 246cabdff1aSopenharmony_ci for (i = 0; i < HEVC_MAX_##T##PS_COUNT; i++) { \ 247cabdff1aSopenharmony_ci if (h->ps.t##ps_list[i]) { \ 248cabdff1aSopenharmony_ci const HEVC##T##PS *lps = (const HEVC##T##PS *)h->ps.t##ps_list[i]->data; \ 249cabdff1aSopenharmony_ci vt_extradata_size += 2 + escape_ps(NULL, lps->data, lps->data_size); \ 250cabdff1aSopenharmony_ci num_##t##ps++; \ 251cabdff1aSopenharmony_ci } \ 252cabdff1aSopenharmony_ci } 253cabdff1aSopenharmony_ci 254cabdff1aSopenharmony_ci COUNT_SIZE_PS(V, v) 255cabdff1aSopenharmony_ci COUNT_SIZE_PS(S, s) 256cabdff1aSopenharmony_ci COUNT_SIZE_PS(P, p) 257cabdff1aSopenharmony_ci 258cabdff1aSopenharmony_ci vt_extradata = av_malloc(vt_extradata_size); 259cabdff1aSopenharmony_ci if (!vt_extradata) 260cabdff1aSopenharmony_ci return NULL; 261cabdff1aSopenharmony_ci p = vt_extradata; 262cabdff1aSopenharmony_ci 263cabdff1aSopenharmony_ci /* unsigned int(8) configurationVersion = 1; */ 264cabdff1aSopenharmony_ci AV_W8(p + 0, 1); 265cabdff1aSopenharmony_ci 266cabdff1aSopenharmony_ci /* 267cabdff1aSopenharmony_ci * unsigned int(2) general_profile_space; 268cabdff1aSopenharmony_ci * unsigned int(1) general_tier_flag; 269cabdff1aSopenharmony_ci * unsigned int(5) general_profile_idc; 270cabdff1aSopenharmony_ci */ 271cabdff1aSopenharmony_ci AV_W8(p + 1, ptlc.profile_space << 6 | 272cabdff1aSopenharmony_ci ptlc.tier_flag << 5 | 273cabdff1aSopenharmony_ci ptlc.profile_idc); 274cabdff1aSopenharmony_ci 275cabdff1aSopenharmony_ci /* unsigned int(32) general_profile_compatibility_flags; */ 276cabdff1aSopenharmony_ci for (i = 0; i < 4; i++) { 277cabdff1aSopenharmony_ci AV_W8(p + 2 + i, ptlc.profile_compatibility_flag[i * 8] << 7 | 278cabdff1aSopenharmony_ci ptlc.profile_compatibility_flag[i * 8 + 1] << 6 | 279cabdff1aSopenharmony_ci ptlc.profile_compatibility_flag[i * 8 + 2] << 5 | 280cabdff1aSopenharmony_ci ptlc.profile_compatibility_flag[i * 8 + 3] << 4 | 281cabdff1aSopenharmony_ci ptlc.profile_compatibility_flag[i * 8 + 4] << 3 | 282cabdff1aSopenharmony_ci ptlc.profile_compatibility_flag[i * 8 + 5] << 2 | 283cabdff1aSopenharmony_ci ptlc.profile_compatibility_flag[i * 8 + 6] << 1 | 284cabdff1aSopenharmony_ci ptlc.profile_compatibility_flag[i * 8 + 7]); 285cabdff1aSopenharmony_ci } 286cabdff1aSopenharmony_ci 287cabdff1aSopenharmony_ci /* unsigned int(48) general_constraint_indicator_flags; */ 288cabdff1aSopenharmony_ci AV_W8(p + 6, ptlc.progressive_source_flag << 7 | 289cabdff1aSopenharmony_ci ptlc.interlaced_source_flag << 6 | 290cabdff1aSopenharmony_ci ptlc.non_packed_constraint_flag << 5 | 291cabdff1aSopenharmony_ci ptlc.frame_only_constraint_flag << 4); 292cabdff1aSopenharmony_ci AV_W8(p + 7, 0); 293cabdff1aSopenharmony_ci AV_WN32(p + 8, 0); 294cabdff1aSopenharmony_ci 295cabdff1aSopenharmony_ci /* unsigned int(8) general_level_idc; */ 296cabdff1aSopenharmony_ci AV_W8(p + 12, ptlc.level_idc); 297cabdff1aSopenharmony_ci 298cabdff1aSopenharmony_ci /* 299cabdff1aSopenharmony_ci * bit(4) reserved = ‘1111’b; 300cabdff1aSopenharmony_ci * unsigned int(12) min_spatial_segmentation_idc; 301cabdff1aSopenharmony_ci */ 302cabdff1aSopenharmony_ci AV_W8(p + 13, 0xf0 | (vui.min_spatial_segmentation_idc >> 4)); 303cabdff1aSopenharmony_ci AV_W8(p + 14, vui.min_spatial_segmentation_idc & 0xff); 304cabdff1aSopenharmony_ci 305cabdff1aSopenharmony_ci /* 306cabdff1aSopenharmony_ci * bit(6) reserved = ‘111111’b; 307cabdff1aSopenharmony_ci * unsigned int(2) parallelismType; 308cabdff1aSopenharmony_ci */ 309cabdff1aSopenharmony_ci if (!vui.min_spatial_segmentation_idc) 310cabdff1aSopenharmony_ci parallelismType = 0; 311cabdff1aSopenharmony_ci else if (pps->entropy_coding_sync_enabled_flag && pps->tiles_enabled_flag) 312cabdff1aSopenharmony_ci parallelismType = 0; 313cabdff1aSopenharmony_ci else if (pps->entropy_coding_sync_enabled_flag) 314cabdff1aSopenharmony_ci parallelismType = 3; 315cabdff1aSopenharmony_ci else if (pps->tiles_enabled_flag) 316cabdff1aSopenharmony_ci parallelismType = 2; 317cabdff1aSopenharmony_ci else 318cabdff1aSopenharmony_ci parallelismType = 1; 319cabdff1aSopenharmony_ci AV_W8(p + 15, 0xfc | parallelismType); 320cabdff1aSopenharmony_ci 321cabdff1aSopenharmony_ci /* 322cabdff1aSopenharmony_ci * bit(6) reserved = ‘111111’b; 323cabdff1aSopenharmony_ci * unsigned int(2) chromaFormat; 324cabdff1aSopenharmony_ci */ 325cabdff1aSopenharmony_ci AV_W8(p + 16, sps->chroma_format_idc | 0xfc); 326cabdff1aSopenharmony_ci 327cabdff1aSopenharmony_ci /* 328cabdff1aSopenharmony_ci * bit(5) reserved = ‘11111’b; 329cabdff1aSopenharmony_ci * unsigned int(3) bitDepthLumaMinus8; 330cabdff1aSopenharmony_ci */ 331cabdff1aSopenharmony_ci AV_W8(p + 17, (sps->bit_depth - 8) | 0xf8); 332cabdff1aSopenharmony_ci 333cabdff1aSopenharmony_ci /* 334cabdff1aSopenharmony_ci * bit(5) reserved = ‘11111’b; 335cabdff1aSopenharmony_ci * unsigned int(3) bitDepthChromaMinus8; 336cabdff1aSopenharmony_ci */ 337cabdff1aSopenharmony_ci AV_W8(p + 18, (sps->bit_depth_chroma - 8) | 0xf8); 338cabdff1aSopenharmony_ci 339cabdff1aSopenharmony_ci /* bit(16) avgFrameRate; */ 340cabdff1aSopenharmony_ci AV_WB16(p + 19, 0); 341cabdff1aSopenharmony_ci 342cabdff1aSopenharmony_ci /* 343cabdff1aSopenharmony_ci * bit(2) constantFrameRate; 344cabdff1aSopenharmony_ci * bit(3) numTemporalLayers; 345cabdff1aSopenharmony_ci * bit(1) temporalIdNested; 346cabdff1aSopenharmony_ci * unsigned int(2) lengthSizeMinusOne; 347cabdff1aSopenharmony_ci */ 348cabdff1aSopenharmony_ci AV_W8(p + 21, 0 << 6 | 349cabdff1aSopenharmony_ci sps->max_sub_layers << 3 | 350cabdff1aSopenharmony_ci sps->temporal_id_nesting_flag << 2 | 351cabdff1aSopenharmony_ci 3); 352cabdff1aSopenharmony_ci 353cabdff1aSopenharmony_ci /* unsigned int(8) numOfArrays; */ 354cabdff1aSopenharmony_ci AV_W8(p + 22, 3); 355cabdff1aSopenharmony_ci 356cabdff1aSopenharmony_ci p += 23; 357cabdff1aSopenharmony_ci 358cabdff1aSopenharmony_ci#define APPEND_PS(T, t) \ 359cabdff1aSopenharmony_ci /* \ 360cabdff1aSopenharmony_ci * bit(1) array_completeness; \ 361cabdff1aSopenharmony_ci * unsigned int(1) reserved = 0; \ 362cabdff1aSopenharmony_ci * unsigned int(6) NAL_unit_type; \ 363cabdff1aSopenharmony_ci */ \ 364cabdff1aSopenharmony_ci AV_W8(p, 1 << 7 | \ 365cabdff1aSopenharmony_ci HEVC_NAL_##T##PS & 0x3f); \ 366cabdff1aSopenharmony_ci /* unsigned int(16) numNalus; */ \ 367cabdff1aSopenharmony_ci AV_WB16(p + 1, num_##t##ps); \ 368cabdff1aSopenharmony_ci p += 3; \ 369cabdff1aSopenharmony_ci for (i = 0; i < HEVC_MAX_##T##PS_COUNT; i++) { \ 370cabdff1aSopenharmony_ci if (h->ps.t##ps_list[i]) { \ 371cabdff1aSopenharmony_ci const HEVC##T##PS *lps = (const HEVC##T##PS *)h->ps.t##ps_list[i]->data; \ 372cabdff1aSopenharmony_ci int size = escape_ps(p + 2, lps->data, lps->data_size); \ 373cabdff1aSopenharmony_ci /* unsigned int(16) nalUnitLength; */ \ 374cabdff1aSopenharmony_ci AV_WB16(p, size); \ 375cabdff1aSopenharmony_ci /* bit(8*nalUnitLength) nalUnit; */ \ 376cabdff1aSopenharmony_ci p += 2 + size; \ 377cabdff1aSopenharmony_ci } \ 378cabdff1aSopenharmony_ci } 379cabdff1aSopenharmony_ci 380cabdff1aSopenharmony_ci APPEND_PS(V, v) 381cabdff1aSopenharmony_ci APPEND_PS(S, s) 382cabdff1aSopenharmony_ci APPEND_PS(P, p) 383cabdff1aSopenharmony_ci 384cabdff1aSopenharmony_ci av_assert0(p - vt_extradata == vt_extradata_size); 385cabdff1aSopenharmony_ci 386cabdff1aSopenharmony_ci data = CFDataCreate(kCFAllocatorDefault, vt_extradata, vt_extradata_size); 387cabdff1aSopenharmony_ci av_free(vt_extradata); 388cabdff1aSopenharmony_ci return data; 389cabdff1aSopenharmony_ci} 390cabdff1aSopenharmony_ci 391cabdff1aSopenharmony_ciint ff_videotoolbox_h264_start_frame(AVCodecContext *avctx, 392cabdff1aSopenharmony_ci const uint8_t *buffer, 393cabdff1aSopenharmony_ci uint32_t size) 394cabdff1aSopenharmony_ci{ 395cabdff1aSopenharmony_ci VTContext *vtctx = avctx->internal->hwaccel_priv_data; 396cabdff1aSopenharmony_ci H264Context *h = avctx->priv_data; 397cabdff1aSopenharmony_ci 398cabdff1aSopenharmony_ci if (h->is_avc == 1) { 399cabdff1aSopenharmony_ci return ff_videotoolbox_buffer_copy(vtctx, buffer, size); 400cabdff1aSopenharmony_ci } 401cabdff1aSopenharmony_ci 402cabdff1aSopenharmony_ci return 0; 403cabdff1aSopenharmony_ci} 404cabdff1aSopenharmony_ci 405cabdff1aSopenharmony_cistatic int videotoolbox_h264_decode_params(AVCodecContext *avctx, 406cabdff1aSopenharmony_ci int type, 407cabdff1aSopenharmony_ci const uint8_t *buffer, 408cabdff1aSopenharmony_ci uint32_t size) 409cabdff1aSopenharmony_ci{ 410cabdff1aSopenharmony_ci VTContext *vtctx = avctx->internal->hwaccel_priv_data; 411cabdff1aSopenharmony_ci H264Context *h = avctx->priv_data; 412cabdff1aSopenharmony_ci 413cabdff1aSopenharmony_ci // save sps header (profile/level) used to create decoder session 414cabdff1aSopenharmony_ci if (!vtctx->sps[0]) 415cabdff1aSopenharmony_ci memcpy(vtctx->sps, h->ps.sps->data + 1, 3); 416cabdff1aSopenharmony_ci 417cabdff1aSopenharmony_ci if (type == H264_NAL_SPS) { 418cabdff1aSopenharmony_ci if (size > 4 && memcmp(vtctx->sps, buffer + 1, 3) != 0) { 419cabdff1aSopenharmony_ci vtctx->reconfig_needed = true; 420cabdff1aSopenharmony_ci memcpy(vtctx->sps, buffer + 1, 3); 421cabdff1aSopenharmony_ci } 422cabdff1aSopenharmony_ci } 423cabdff1aSopenharmony_ci 424cabdff1aSopenharmony_ci // pass-through SPS/PPS changes to the decoder 425cabdff1aSopenharmony_ci return ff_videotoolbox_h264_decode_slice(avctx, buffer, size); 426cabdff1aSopenharmony_ci} 427cabdff1aSopenharmony_ci 428cabdff1aSopenharmony_cistatic int videotoolbox_common_decode_slice(AVCodecContext *avctx, 429cabdff1aSopenharmony_ci const uint8_t *buffer, 430cabdff1aSopenharmony_ci uint32_t size) 431cabdff1aSopenharmony_ci{ 432cabdff1aSopenharmony_ci VTContext *vtctx = avctx->internal->hwaccel_priv_data; 433cabdff1aSopenharmony_ci void *tmp; 434cabdff1aSopenharmony_ci 435cabdff1aSopenharmony_ci tmp = av_fast_realloc(vtctx->bitstream, 436cabdff1aSopenharmony_ci &vtctx->allocated_size, 437cabdff1aSopenharmony_ci vtctx->bitstream_size+size+4); 438cabdff1aSopenharmony_ci if (!tmp) 439cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 440cabdff1aSopenharmony_ci 441cabdff1aSopenharmony_ci vtctx->bitstream = tmp; 442cabdff1aSopenharmony_ci 443cabdff1aSopenharmony_ci AV_WB32(vtctx->bitstream + vtctx->bitstream_size, size); 444cabdff1aSopenharmony_ci memcpy(vtctx->bitstream + vtctx->bitstream_size + 4, buffer, size); 445cabdff1aSopenharmony_ci 446cabdff1aSopenharmony_ci vtctx->bitstream_size += size + 4; 447cabdff1aSopenharmony_ci 448cabdff1aSopenharmony_ci return 0; 449cabdff1aSopenharmony_ci} 450cabdff1aSopenharmony_ci 451cabdff1aSopenharmony_ciint ff_videotoolbox_h264_decode_slice(AVCodecContext *avctx, 452cabdff1aSopenharmony_ci const uint8_t *buffer, 453cabdff1aSopenharmony_ci uint32_t size) 454cabdff1aSopenharmony_ci{ 455cabdff1aSopenharmony_ci H264Context *h = avctx->priv_data; 456cabdff1aSopenharmony_ci 457cabdff1aSopenharmony_ci if (h->is_avc == 1) 458cabdff1aSopenharmony_ci return 0; 459cabdff1aSopenharmony_ci 460cabdff1aSopenharmony_ci return videotoolbox_common_decode_slice(avctx, buffer, size); 461cabdff1aSopenharmony_ci} 462cabdff1aSopenharmony_ci 463cabdff1aSopenharmony_ci#if CONFIG_VIDEOTOOLBOX 464cabdff1aSopenharmony_ci// Return the AVVideotoolboxContext that matters currently. Where it comes from 465cabdff1aSopenharmony_ci// depends on the API used. 466cabdff1aSopenharmony_cistatic AVVideotoolboxContext *videotoolbox_get_context(AVCodecContext *avctx) 467cabdff1aSopenharmony_ci{ 468cabdff1aSopenharmony_ci // Somewhat tricky because the user can call av_videotoolbox_default_free() 469cabdff1aSopenharmony_ci // at any time, even when the codec is closed. 470cabdff1aSopenharmony_ci if (avctx->internal && avctx->internal->hwaccel_priv_data) { 471cabdff1aSopenharmony_ci VTContext *vtctx = avctx->internal->hwaccel_priv_data; 472cabdff1aSopenharmony_ci if (vtctx->vt_ctx) 473cabdff1aSopenharmony_ci return vtctx->vt_ctx; 474cabdff1aSopenharmony_ci } 475cabdff1aSopenharmony_ci return avctx->hwaccel_context; 476cabdff1aSopenharmony_ci} 477cabdff1aSopenharmony_ci 478cabdff1aSopenharmony_cistatic void videotoolbox_stop(AVCodecContext *avctx) 479cabdff1aSopenharmony_ci{ 480cabdff1aSopenharmony_ci AVVideotoolboxContext *videotoolbox = videotoolbox_get_context(avctx); 481cabdff1aSopenharmony_ci if (!videotoolbox) 482cabdff1aSopenharmony_ci return; 483cabdff1aSopenharmony_ci 484cabdff1aSopenharmony_ci if (videotoolbox->cm_fmt_desc) { 485cabdff1aSopenharmony_ci CFRelease(videotoolbox->cm_fmt_desc); 486cabdff1aSopenharmony_ci videotoolbox->cm_fmt_desc = NULL; 487cabdff1aSopenharmony_ci } 488cabdff1aSopenharmony_ci 489cabdff1aSopenharmony_ci if (videotoolbox->session) { 490cabdff1aSopenharmony_ci VTDecompressionSessionInvalidate(videotoolbox->session); 491cabdff1aSopenharmony_ci CFRelease(videotoolbox->session); 492cabdff1aSopenharmony_ci videotoolbox->session = NULL; 493cabdff1aSopenharmony_ci } 494cabdff1aSopenharmony_ci} 495cabdff1aSopenharmony_ci 496cabdff1aSopenharmony_ciint ff_videotoolbox_uninit(AVCodecContext *avctx) 497cabdff1aSopenharmony_ci{ 498cabdff1aSopenharmony_ci VTContext *vtctx = avctx->internal->hwaccel_priv_data; 499cabdff1aSopenharmony_ci if (!vtctx) 500cabdff1aSopenharmony_ci return 0; 501cabdff1aSopenharmony_ci 502cabdff1aSopenharmony_ci av_freep(&vtctx->bitstream); 503cabdff1aSopenharmony_ci if (vtctx->frame) 504cabdff1aSopenharmony_ci CVPixelBufferRelease(vtctx->frame); 505cabdff1aSopenharmony_ci 506cabdff1aSopenharmony_ci if (vtctx->vt_ctx) 507cabdff1aSopenharmony_ci videotoolbox_stop(avctx); 508cabdff1aSopenharmony_ci 509cabdff1aSopenharmony_ci av_buffer_unref(&vtctx->cached_hw_frames_ctx); 510cabdff1aSopenharmony_ci av_freep(&vtctx->vt_ctx); 511cabdff1aSopenharmony_ci 512cabdff1aSopenharmony_ci return 0; 513cabdff1aSopenharmony_ci} 514cabdff1aSopenharmony_ci 515cabdff1aSopenharmony_cistatic int videotoolbox_buffer_create(AVCodecContext *avctx, AVFrame *frame) 516cabdff1aSopenharmony_ci{ 517cabdff1aSopenharmony_ci VTContext *vtctx = avctx->internal->hwaccel_priv_data; 518cabdff1aSopenharmony_ci CVPixelBufferRef pixbuf = (CVPixelBufferRef)vtctx->frame; 519cabdff1aSopenharmony_ci OSType pixel_format = CVPixelBufferGetPixelFormatType(pixbuf); 520cabdff1aSopenharmony_ci enum AVPixelFormat sw_format = av_map_videotoolbox_format_to_pixfmt(pixel_format); 521cabdff1aSopenharmony_ci int width = CVPixelBufferGetWidth(pixbuf); 522cabdff1aSopenharmony_ci int height = CVPixelBufferGetHeight(pixbuf); 523cabdff1aSopenharmony_ci AVHWFramesContext *cached_frames; 524cabdff1aSopenharmony_ci VTHWFrame *ref; 525cabdff1aSopenharmony_ci int ret; 526cabdff1aSopenharmony_ci 527cabdff1aSopenharmony_ci if (!frame->buf[0] || frame->data[3]) { 528cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "videotoolbox: invalid state\n"); 529cabdff1aSopenharmony_ci av_frame_unref(frame); 530cabdff1aSopenharmony_ci return AVERROR_EXTERNAL; 531cabdff1aSopenharmony_ci } 532cabdff1aSopenharmony_ci 533cabdff1aSopenharmony_ci ref = (VTHWFrame *)frame->buf[0]->data; 534cabdff1aSopenharmony_ci 535cabdff1aSopenharmony_ci if (ref->pixbuf) 536cabdff1aSopenharmony_ci CVPixelBufferRelease(ref->pixbuf); 537cabdff1aSopenharmony_ci ref->pixbuf = vtctx->frame; 538cabdff1aSopenharmony_ci vtctx->frame = NULL; 539cabdff1aSopenharmony_ci 540cabdff1aSopenharmony_ci // Old API code path. 541cabdff1aSopenharmony_ci if (!vtctx->cached_hw_frames_ctx) 542cabdff1aSopenharmony_ci return 0; 543cabdff1aSopenharmony_ci 544cabdff1aSopenharmony_ci cached_frames = (AVHWFramesContext*)vtctx->cached_hw_frames_ctx->data; 545cabdff1aSopenharmony_ci 546cabdff1aSopenharmony_ci if (cached_frames->sw_format != sw_format || 547cabdff1aSopenharmony_ci cached_frames->width != width || 548cabdff1aSopenharmony_ci cached_frames->height != height) { 549cabdff1aSopenharmony_ci AVBufferRef *hw_frames_ctx = av_hwframe_ctx_alloc(cached_frames->device_ref); 550cabdff1aSopenharmony_ci AVHWFramesContext *hw_frames; 551cabdff1aSopenharmony_ci if (!hw_frames_ctx) 552cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 553cabdff1aSopenharmony_ci 554cabdff1aSopenharmony_ci hw_frames = (AVHWFramesContext*)hw_frames_ctx->data; 555cabdff1aSopenharmony_ci hw_frames->format = cached_frames->format; 556cabdff1aSopenharmony_ci hw_frames->sw_format = sw_format; 557cabdff1aSopenharmony_ci hw_frames->width = width; 558cabdff1aSopenharmony_ci hw_frames->height = height; 559cabdff1aSopenharmony_ci 560cabdff1aSopenharmony_ci ret = av_hwframe_ctx_init(hw_frames_ctx); 561cabdff1aSopenharmony_ci if (ret < 0) { 562cabdff1aSopenharmony_ci av_buffer_unref(&hw_frames_ctx); 563cabdff1aSopenharmony_ci return ret; 564cabdff1aSopenharmony_ci } 565cabdff1aSopenharmony_ci 566cabdff1aSopenharmony_ci av_buffer_unref(&vtctx->cached_hw_frames_ctx); 567cabdff1aSopenharmony_ci vtctx->cached_hw_frames_ctx = hw_frames_ctx; 568cabdff1aSopenharmony_ci } 569cabdff1aSopenharmony_ci 570cabdff1aSopenharmony_ci av_buffer_unref(&ref->hw_frames_ctx); 571cabdff1aSopenharmony_ci ref->hw_frames_ctx = av_buffer_ref(vtctx->cached_hw_frames_ctx); 572cabdff1aSopenharmony_ci if (!ref->hw_frames_ctx) 573cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 574cabdff1aSopenharmony_ci 575cabdff1aSopenharmony_ci return 0; 576cabdff1aSopenharmony_ci} 577cabdff1aSopenharmony_ci 578cabdff1aSopenharmony_cistatic void videotoolbox_write_mp4_descr_length(PutByteContext *pb, int length) 579cabdff1aSopenharmony_ci{ 580cabdff1aSopenharmony_ci int i; 581cabdff1aSopenharmony_ci uint8_t b; 582cabdff1aSopenharmony_ci 583cabdff1aSopenharmony_ci for (i = 3; i >= 0; i--) { 584cabdff1aSopenharmony_ci b = (length >> (i * 7)) & 0x7F; 585cabdff1aSopenharmony_ci if (i != 0) 586cabdff1aSopenharmony_ci b |= 0x80; 587cabdff1aSopenharmony_ci 588cabdff1aSopenharmony_ci bytestream2_put_byteu(pb, b); 589cabdff1aSopenharmony_ci } 590cabdff1aSopenharmony_ci} 591cabdff1aSopenharmony_ci 592cabdff1aSopenharmony_cistatic CFDataRef videotoolbox_esds_extradata_create(AVCodecContext *avctx) 593cabdff1aSopenharmony_ci{ 594cabdff1aSopenharmony_ci CFDataRef data; 595cabdff1aSopenharmony_ci uint8_t *rw_extradata; 596cabdff1aSopenharmony_ci PutByteContext pb; 597cabdff1aSopenharmony_ci int full_size = 3 + 5 + 13 + 5 + avctx->extradata_size + 3; 598cabdff1aSopenharmony_ci // ES_DescrTag data + DecoderConfigDescrTag + data + DecSpecificInfoTag + size + SLConfigDescriptor 599cabdff1aSopenharmony_ci int config_size = 13 + 5 + avctx->extradata_size; 600cabdff1aSopenharmony_ci int s; 601cabdff1aSopenharmony_ci 602cabdff1aSopenharmony_ci if (!(rw_extradata = av_mallocz(full_size + VIDEOTOOLBOX_ESDS_EXTRADATA_PADDING))) 603cabdff1aSopenharmony_ci return NULL; 604cabdff1aSopenharmony_ci 605cabdff1aSopenharmony_ci bytestream2_init_writer(&pb, rw_extradata, full_size + VIDEOTOOLBOX_ESDS_EXTRADATA_PADDING); 606cabdff1aSopenharmony_ci bytestream2_put_byteu(&pb, 0); // version 607cabdff1aSopenharmony_ci bytestream2_put_ne24(&pb, 0); // flags 608cabdff1aSopenharmony_ci 609cabdff1aSopenharmony_ci // elementary stream descriptor 610cabdff1aSopenharmony_ci bytestream2_put_byteu(&pb, 0x03); // ES_DescrTag 611cabdff1aSopenharmony_ci videotoolbox_write_mp4_descr_length(&pb, full_size); 612cabdff1aSopenharmony_ci bytestream2_put_ne16(&pb, 0); // esid 613cabdff1aSopenharmony_ci bytestream2_put_byteu(&pb, 0); // stream priority (0-32) 614cabdff1aSopenharmony_ci 615cabdff1aSopenharmony_ci // decoder configuration descriptor 616cabdff1aSopenharmony_ci bytestream2_put_byteu(&pb, 0x04); // DecoderConfigDescrTag 617cabdff1aSopenharmony_ci videotoolbox_write_mp4_descr_length(&pb, config_size); 618cabdff1aSopenharmony_ci bytestream2_put_byteu(&pb, 32); // object type indication. 32 = AV_CODEC_ID_MPEG4 619cabdff1aSopenharmony_ci bytestream2_put_byteu(&pb, 0x11); // stream type 620cabdff1aSopenharmony_ci bytestream2_put_ne24(&pb, 0); // buffer size 621cabdff1aSopenharmony_ci bytestream2_put_ne32(&pb, 0); // max bitrate 622cabdff1aSopenharmony_ci bytestream2_put_ne32(&pb, 0); // avg bitrate 623cabdff1aSopenharmony_ci 624cabdff1aSopenharmony_ci // decoder specific descriptor 625cabdff1aSopenharmony_ci bytestream2_put_byteu(&pb, 0x05); ///< DecSpecificInfoTag 626cabdff1aSopenharmony_ci videotoolbox_write_mp4_descr_length(&pb, avctx->extradata_size); 627cabdff1aSopenharmony_ci 628cabdff1aSopenharmony_ci bytestream2_put_buffer(&pb, avctx->extradata, avctx->extradata_size); 629cabdff1aSopenharmony_ci 630cabdff1aSopenharmony_ci // SLConfigDescriptor 631cabdff1aSopenharmony_ci bytestream2_put_byteu(&pb, 0x06); // SLConfigDescrTag 632cabdff1aSopenharmony_ci bytestream2_put_byteu(&pb, 0x01); // length 633cabdff1aSopenharmony_ci bytestream2_put_byteu(&pb, 0x02); // 634cabdff1aSopenharmony_ci 635cabdff1aSopenharmony_ci s = bytestream2_size_p(&pb); 636cabdff1aSopenharmony_ci 637cabdff1aSopenharmony_ci data = CFDataCreate(kCFAllocatorDefault, rw_extradata, s); 638cabdff1aSopenharmony_ci 639cabdff1aSopenharmony_ci av_freep(&rw_extradata); 640cabdff1aSopenharmony_ci return data; 641cabdff1aSopenharmony_ci} 642cabdff1aSopenharmony_ci 643cabdff1aSopenharmony_cistatic CMSampleBufferRef videotoolbox_sample_buffer_create(CMFormatDescriptionRef fmt_desc, 644cabdff1aSopenharmony_ci void *buffer, 645cabdff1aSopenharmony_ci int size) 646cabdff1aSopenharmony_ci{ 647cabdff1aSopenharmony_ci OSStatus status; 648cabdff1aSopenharmony_ci CMBlockBufferRef block_buf; 649cabdff1aSopenharmony_ci CMSampleBufferRef sample_buf; 650cabdff1aSopenharmony_ci 651cabdff1aSopenharmony_ci block_buf = NULL; 652cabdff1aSopenharmony_ci sample_buf = NULL; 653cabdff1aSopenharmony_ci 654cabdff1aSopenharmony_ci status = CMBlockBufferCreateWithMemoryBlock(kCFAllocatorDefault,// structureAllocator 655cabdff1aSopenharmony_ci buffer, // memoryBlock 656cabdff1aSopenharmony_ci size, // blockLength 657cabdff1aSopenharmony_ci kCFAllocatorNull, // blockAllocator 658cabdff1aSopenharmony_ci NULL, // customBlockSource 659cabdff1aSopenharmony_ci 0, // offsetToData 660cabdff1aSopenharmony_ci size, // dataLength 661cabdff1aSopenharmony_ci 0, // flags 662cabdff1aSopenharmony_ci &block_buf); 663cabdff1aSopenharmony_ci 664cabdff1aSopenharmony_ci if (!status) { 665cabdff1aSopenharmony_ci status = CMSampleBufferCreate(kCFAllocatorDefault, // allocator 666cabdff1aSopenharmony_ci block_buf, // dataBuffer 667cabdff1aSopenharmony_ci TRUE, // dataReady 668cabdff1aSopenharmony_ci 0, // makeDataReadyCallback 669cabdff1aSopenharmony_ci 0, // makeDataReadyRefcon 670cabdff1aSopenharmony_ci fmt_desc, // formatDescription 671cabdff1aSopenharmony_ci 1, // numSamples 672cabdff1aSopenharmony_ci 0, // numSampleTimingEntries 673cabdff1aSopenharmony_ci NULL, // sampleTimingArray 674cabdff1aSopenharmony_ci 0, // numSampleSizeEntries 675cabdff1aSopenharmony_ci NULL, // sampleSizeArray 676cabdff1aSopenharmony_ci &sample_buf); 677cabdff1aSopenharmony_ci } 678cabdff1aSopenharmony_ci 679cabdff1aSopenharmony_ci if (block_buf) 680cabdff1aSopenharmony_ci CFRelease(block_buf); 681cabdff1aSopenharmony_ci 682cabdff1aSopenharmony_ci return sample_buf; 683cabdff1aSopenharmony_ci} 684cabdff1aSopenharmony_ci 685cabdff1aSopenharmony_cistatic void videotoolbox_decoder_callback(void *opaque, 686cabdff1aSopenharmony_ci void *sourceFrameRefCon, 687cabdff1aSopenharmony_ci OSStatus status, 688cabdff1aSopenharmony_ci VTDecodeInfoFlags flags, 689cabdff1aSopenharmony_ci CVImageBufferRef image_buffer, 690cabdff1aSopenharmony_ci CMTime pts, 691cabdff1aSopenharmony_ci CMTime duration) 692cabdff1aSopenharmony_ci{ 693cabdff1aSopenharmony_ci VTContext *vtctx = opaque; 694cabdff1aSopenharmony_ci 695cabdff1aSopenharmony_ci if (vtctx->frame) { 696cabdff1aSopenharmony_ci CVPixelBufferRelease(vtctx->frame); 697cabdff1aSopenharmony_ci vtctx->frame = NULL; 698cabdff1aSopenharmony_ci } 699cabdff1aSopenharmony_ci 700cabdff1aSopenharmony_ci if (!image_buffer) { 701cabdff1aSopenharmony_ci av_log(vtctx->logctx, status ? AV_LOG_WARNING : AV_LOG_DEBUG, 702cabdff1aSopenharmony_ci "vt decoder cb: output image buffer is null: %i\n", status); 703cabdff1aSopenharmony_ci return; 704cabdff1aSopenharmony_ci } 705cabdff1aSopenharmony_ci 706cabdff1aSopenharmony_ci vtctx->frame = CVPixelBufferRetain(image_buffer); 707cabdff1aSopenharmony_ci} 708cabdff1aSopenharmony_ci 709cabdff1aSopenharmony_cistatic OSStatus videotoolbox_session_decode_frame(AVCodecContext *avctx) 710cabdff1aSopenharmony_ci{ 711cabdff1aSopenharmony_ci OSStatus status; 712cabdff1aSopenharmony_ci CMSampleBufferRef sample_buf; 713cabdff1aSopenharmony_ci AVVideotoolboxContext *videotoolbox = videotoolbox_get_context(avctx); 714cabdff1aSopenharmony_ci VTContext *vtctx = avctx->internal->hwaccel_priv_data; 715cabdff1aSopenharmony_ci 716cabdff1aSopenharmony_ci sample_buf = videotoolbox_sample_buffer_create(videotoolbox->cm_fmt_desc, 717cabdff1aSopenharmony_ci vtctx->bitstream, 718cabdff1aSopenharmony_ci vtctx->bitstream_size); 719cabdff1aSopenharmony_ci 720cabdff1aSopenharmony_ci if (!sample_buf) 721cabdff1aSopenharmony_ci return -1; 722cabdff1aSopenharmony_ci 723cabdff1aSopenharmony_ci status = VTDecompressionSessionDecodeFrame(videotoolbox->session, 724cabdff1aSopenharmony_ci sample_buf, 725cabdff1aSopenharmony_ci 0, // decodeFlags 726cabdff1aSopenharmony_ci NULL, // sourceFrameRefCon 727cabdff1aSopenharmony_ci 0); // infoFlagsOut 728cabdff1aSopenharmony_ci if (status == noErr) 729cabdff1aSopenharmony_ci status = VTDecompressionSessionWaitForAsynchronousFrames(videotoolbox->session); 730cabdff1aSopenharmony_ci 731cabdff1aSopenharmony_ci CFRelease(sample_buf); 732cabdff1aSopenharmony_ci 733cabdff1aSopenharmony_ci return status; 734cabdff1aSopenharmony_ci} 735cabdff1aSopenharmony_ci 736cabdff1aSopenharmony_cistatic CMVideoFormatDescriptionRef videotoolbox_format_desc_create(CMVideoCodecType codec_type, 737cabdff1aSopenharmony_ci CFDictionaryRef decoder_spec, 738cabdff1aSopenharmony_ci int width, 739cabdff1aSopenharmony_ci int height) 740cabdff1aSopenharmony_ci{ 741cabdff1aSopenharmony_ci CMFormatDescriptionRef cm_fmt_desc; 742cabdff1aSopenharmony_ci OSStatus status; 743cabdff1aSopenharmony_ci 744cabdff1aSopenharmony_ci status = CMVideoFormatDescriptionCreate(kCFAllocatorDefault, 745cabdff1aSopenharmony_ci codec_type, 746cabdff1aSopenharmony_ci width, 747cabdff1aSopenharmony_ci height, 748cabdff1aSopenharmony_ci decoder_spec, // Dictionary of extension 749cabdff1aSopenharmony_ci &cm_fmt_desc); 750cabdff1aSopenharmony_ci 751cabdff1aSopenharmony_ci if (status) 752cabdff1aSopenharmony_ci return NULL; 753cabdff1aSopenharmony_ci 754cabdff1aSopenharmony_ci return cm_fmt_desc; 755cabdff1aSopenharmony_ci} 756cabdff1aSopenharmony_ci 757cabdff1aSopenharmony_cistatic CFDictionaryRef videotoolbox_buffer_attributes_create(int width, 758cabdff1aSopenharmony_ci int height, 759cabdff1aSopenharmony_ci OSType pix_fmt) 760cabdff1aSopenharmony_ci{ 761cabdff1aSopenharmony_ci CFMutableDictionaryRef buffer_attributes; 762cabdff1aSopenharmony_ci CFMutableDictionaryRef io_surface_properties; 763cabdff1aSopenharmony_ci CFNumberRef cv_pix_fmt; 764cabdff1aSopenharmony_ci CFNumberRef w; 765cabdff1aSopenharmony_ci CFNumberRef h; 766cabdff1aSopenharmony_ci 767cabdff1aSopenharmony_ci w = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &width); 768cabdff1aSopenharmony_ci h = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &height); 769cabdff1aSopenharmony_ci cv_pix_fmt = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &pix_fmt); 770cabdff1aSopenharmony_ci 771cabdff1aSopenharmony_ci buffer_attributes = CFDictionaryCreateMutable(kCFAllocatorDefault, 772cabdff1aSopenharmony_ci 4, 773cabdff1aSopenharmony_ci &kCFTypeDictionaryKeyCallBacks, 774cabdff1aSopenharmony_ci &kCFTypeDictionaryValueCallBacks); 775cabdff1aSopenharmony_ci io_surface_properties = CFDictionaryCreateMutable(kCFAllocatorDefault, 776cabdff1aSopenharmony_ci 0, 777cabdff1aSopenharmony_ci &kCFTypeDictionaryKeyCallBacks, 778cabdff1aSopenharmony_ci &kCFTypeDictionaryValueCallBacks); 779cabdff1aSopenharmony_ci 780cabdff1aSopenharmony_ci if (pix_fmt) 781cabdff1aSopenharmony_ci CFDictionarySetValue(buffer_attributes, kCVPixelBufferPixelFormatTypeKey, cv_pix_fmt); 782cabdff1aSopenharmony_ci CFDictionarySetValue(buffer_attributes, kCVPixelBufferIOSurfacePropertiesKey, io_surface_properties); 783cabdff1aSopenharmony_ci CFDictionarySetValue(buffer_attributes, kCVPixelBufferWidthKey, w); 784cabdff1aSopenharmony_ci CFDictionarySetValue(buffer_attributes, kCVPixelBufferHeightKey, h); 785cabdff1aSopenharmony_ci#if TARGET_OS_IPHONE 786cabdff1aSopenharmony_ci CFDictionarySetValue(buffer_attributes, kCVPixelBufferOpenGLESCompatibilityKey, kCFBooleanTrue); 787cabdff1aSopenharmony_ci#else 788cabdff1aSopenharmony_ci CFDictionarySetValue(buffer_attributes, kCVPixelBufferIOSurfaceOpenGLTextureCompatibilityKey, kCFBooleanTrue); 789cabdff1aSopenharmony_ci#endif 790cabdff1aSopenharmony_ci 791cabdff1aSopenharmony_ci CFRelease(io_surface_properties); 792cabdff1aSopenharmony_ci CFRelease(cv_pix_fmt); 793cabdff1aSopenharmony_ci CFRelease(w); 794cabdff1aSopenharmony_ci CFRelease(h); 795cabdff1aSopenharmony_ci 796cabdff1aSopenharmony_ci return buffer_attributes; 797cabdff1aSopenharmony_ci} 798cabdff1aSopenharmony_ci 799cabdff1aSopenharmony_cistatic CFDictionaryRef videotoolbox_decoder_config_create(CMVideoCodecType codec_type, 800cabdff1aSopenharmony_ci AVCodecContext *avctx) 801cabdff1aSopenharmony_ci{ 802cabdff1aSopenharmony_ci CFMutableDictionaryRef config_info = CFDictionaryCreateMutable(kCFAllocatorDefault, 803cabdff1aSopenharmony_ci 0, 804cabdff1aSopenharmony_ci &kCFTypeDictionaryKeyCallBacks, 805cabdff1aSopenharmony_ci &kCFTypeDictionaryValueCallBacks); 806cabdff1aSopenharmony_ci 807cabdff1aSopenharmony_ci CFDictionarySetValue(config_info, 808cabdff1aSopenharmony_ci codec_type == kCMVideoCodecType_HEVC ? 809cabdff1aSopenharmony_ci kVTVideoDecoderSpecification_EnableHardwareAcceleratedVideoDecoder : 810cabdff1aSopenharmony_ci kVTVideoDecoderSpecification_RequireHardwareAcceleratedVideoDecoder, 811cabdff1aSopenharmony_ci kCFBooleanTrue); 812cabdff1aSopenharmony_ci 813cabdff1aSopenharmony_ci CFMutableDictionaryRef avc_info; 814cabdff1aSopenharmony_ci CFDataRef data = NULL; 815cabdff1aSopenharmony_ci 816cabdff1aSopenharmony_ci avc_info = CFDictionaryCreateMutable(kCFAllocatorDefault, 817cabdff1aSopenharmony_ci 1, 818cabdff1aSopenharmony_ci &kCFTypeDictionaryKeyCallBacks, 819cabdff1aSopenharmony_ci &kCFTypeDictionaryValueCallBacks); 820cabdff1aSopenharmony_ci 821cabdff1aSopenharmony_ci switch (codec_type) { 822cabdff1aSopenharmony_ci case kCMVideoCodecType_MPEG4Video : 823cabdff1aSopenharmony_ci if (avctx->extradata_size) 824cabdff1aSopenharmony_ci data = videotoolbox_esds_extradata_create(avctx); 825cabdff1aSopenharmony_ci if (data) 826cabdff1aSopenharmony_ci CFDictionarySetValue(avc_info, CFSTR("esds"), data); 827cabdff1aSopenharmony_ci break; 828cabdff1aSopenharmony_ci case kCMVideoCodecType_H264 : 829cabdff1aSopenharmony_ci data = ff_videotoolbox_avcc_extradata_create(avctx); 830cabdff1aSopenharmony_ci if (data) 831cabdff1aSopenharmony_ci CFDictionarySetValue(avc_info, CFSTR("avcC"), data); 832cabdff1aSopenharmony_ci break; 833cabdff1aSopenharmony_ci case kCMVideoCodecType_HEVC : 834cabdff1aSopenharmony_ci data = ff_videotoolbox_hvcc_extradata_create(avctx); 835cabdff1aSopenharmony_ci if (data) 836cabdff1aSopenharmony_ci CFDictionarySetValue(avc_info, CFSTR("hvcC"), data); 837cabdff1aSopenharmony_ci break; 838cabdff1aSopenharmony_ci#if CONFIG_VP9_VIDEOTOOLBOX_HWACCEL 839cabdff1aSopenharmony_ci case kCMVideoCodecType_VP9 : 840cabdff1aSopenharmony_ci data = ff_videotoolbox_vpcc_extradata_create(avctx); 841cabdff1aSopenharmony_ci if (data) 842cabdff1aSopenharmony_ci CFDictionarySetValue(avc_info, CFSTR("vpcC"), data); 843cabdff1aSopenharmony_ci break; 844cabdff1aSopenharmony_ci#endif 845cabdff1aSopenharmony_ci default: 846cabdff1aSopenharmony_ci break; 847cabdff1aSopenharmony_ci } 848cabdff1aSopenharmony_ci 849cabdff1aSopenharmony_ci CFDictionarySetValue(config_info, 850cabdff1aSopenharmony_ci kCMFormatDescriptionExtension_SampleDescriptionExtensionAtoms, 851cabdff1aSopenharmony_ci avc_info); 852cabdff1aSopenharmony_ci 853cabdff1aSopenharmony_ci if (data) 854cabdff1aSopenharmony_ci CFRelease(data); 855cabdff1aSopenharmony_ci 856cabdff1aSopenharmony_ci CFRelease(avc_info); 857cabdff1aSopenharmony_ci return config_info; 858cabdff1aSopenharmony_ci} 859cabdff1aSopenharmony_ci 860cabdff1aSopenharmony_cistatic int videotoolbox_start(AVCodecContext *avctx) 861cabdff1aSopenharmony_ci{ 862cabdff1aSopenharmony_ci AVVideotoolboxContext *videotoolbox = videotoolbox_get_context(avctx); 863cabdff1aSopenharmony_ci OSStatus status; 864cabdff1aSopenharmony_ci VTDecompressionOutputCallbackRecord decoder_cb; 865cabdff1aSopenharmony_ci CFDictionaryRef decoder_spec; 866cabdff1aSopenharmony_ci CFDictionaryRef buf_attr; 867cabdff1aSopenharmony_ci 868cabdff1aSopenharmony_ci if (!videotoolbox) { 869cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "hwaccel context is not set\n"); 870cabdff1aSopenharmony_ci return -1; 871cabdff1aSopenharmony_ci } 872cabdff1aSopenharmony_ci 873cabdff1aSopenharmony_ci switch( avctx->codec_id ) { 874cabdff1aSopenharmony_ci case AV_CODEC_ID_H263 : 875cabdff1aSopenharmony_ci videotoolbox->cm_codec_type = kCMVideoCodecType_H263; 876cabdff1aSopenharmony_ci break; 877cabdff1aSopenharmony_ci case AV_CODEC_ID_H264 : 878cabdff1aSopenharmony_ci videotoolbox->cm_codec_type = kCMVideoCodecType_H264; 879cabdff1aSopenharmony_ci break; 880cabdff1aSopenharmony_ci case AV_CODEC_ID_HEVC : 881cabdff1aSopenharmony_ci videotoolbox->cm_codec_type = kCMVideoCodecType_HEVC; 882cabdff1aSopenharmony_ci break; 883cabdff1aSopenharmony_ci case AV_CODEC_ID_MPEG1VIDEO : 884cabdff1aSopenharmony_ci videotoolbox->cm_codec_type = kCMVideoCodecType_MPEG1Video; 885cabdff1aSopenharmony_ci break; 886cabdff1aSopenharmony_ci case AV_CODEC_ID_MPEG2VIDEO : 887cabdff1aSopenharmony_ci videotoolbox->cm_codec_type = kCMVideoCodecType_MPEG2Video; 888cabdff1aSopenharmony_ci break; 889cabdff1aSopenharmony_ci case AV_CODEC_ID_MPEG4 : 890cabdff1aSopenharmony_ci videotoolbox->cm_codec_type = kCMVideoCodecType_MPEG4Video; 891cabdff1aSopenharmony_ci break; 892cabdff1aSopenharmony_ci case AV_CODEC_ID_PRORES : 893cabdff1aSopenharmony_ci switch (avctx->codec_tag) { 894cabdff1aSopenharmony_ci default: 895cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_WARNING, "Unknown prores profile %d\n", avctx->codec_tag); 896cabdff1aSopenharmony_ci // fall-through 897cabdff1aSopenharmony_ci case MKTAG('a','p','c','o'): // kCMVideoCodecType_AppleProRes422Proxy 898cabdff1aSopenharmony_ci case MKTAG('a','p','c','s'): // kCMVideoCodecType_AppleProRes422LT 899cabdff1aSopenharmony_ci case MKTAG('a','p','c','n'): // kCMVideoCodecType_AppleProRes422 900cabdff1aSopenharmony_ci case MKTAG('a','p','c','h'): // kCMVideoCodecType_AppleProRes422HQ 901cabdff1aSopenharmony_ci case MKTAG('a','p','4','h'): // kCMVideoCodecType_AppleProRes4444 902cabdff1aSopenharmony_ci case MKTAG('a','p','4','x'): // kCMVideoCodecType_AppleProRes4444XQ 903cabdff1aSopenharmony_ci videotoolbox->cm_codec_type = av_bswap32(avctx->codec_tag); 904cabdff1aSopenharmony_ci break; 905cabdff1aSopenharmony_ci } 906cabdff1aSopenharmony_ci break; 907cabdff1aSopenharmony_ci case AV_CODEC_ID_VP9 : 908cabdff1aSopenharmony_ci videotoolbox->cm_codec_type = kCMVideoCodecType_VP9; 909cabdff1aSopenharmony_ci break; 910cabdff1aSopenharmony_ci default : 911cabdff1aSopenharmony_ci break; 912cabdff1aSopenharmony_ci } 913cabdff1aSopenharmony_ci 914cabdff1aSopenharmony_ci#if defined(MAC_OS_X_VERSION_10_9) && !TARGET_OS_IPHONE && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9) && AV_HAS_BUILTIN(__builtin_available) 915cabdff1aSopenharmony_ci if (avctx->codec_id == AV_CODEC_ID_PRORES) { 916cabdff1aSopenharmony_ci if (__builtin_available(macOS 10.9, *)) { 917cabdff1aSopenharmony_ci VTRegisterProfessionalVideoWorkflowVideoDecoders(); 918cabdff1aSopenharmony_ci } 919cabdff1aSopenharmony_ci } 920cabdff1aSopenharmony_ci#endif 921cabdff1aSopenharmony_ci 922cabdff1aSopenharmony_ci#if defined(MAC_OS_VERSION_11_0) && !TARGET_OS_IPHONE && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_VERSION_11_0) && AV_HAS_BUILTIN(__builtin_available) 923cabdff1aSopenharmony_ci if (__builtin_available(macOS 11.0, *)) { 924cabdff1aSopenharmony_ci VTRegisterSupplementalVideoDecoderIfAvailable(videotoolbox->cm_codec_type); 925cabdff1aSopenharmony_ci } 926cabdff1aSopenharmony_ci#endif 927cabdff1aSopenharmony_ci 928cabdff1aSopenharmony_ci decoder_spec = videotoolbox_decoder_config_create(videotoolbox->cm_codec_type, avctx); 929cabdff1aSopenharmony_ci 930cabdff1aSopenharmony_ci if (!decoder_spec) { 931cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "decoder specification creation failed\n"); 932cabdff1aSopenharmony_ci return -1; 933cabdff1aSopenharmony_ci } 934cabdff1aSopenharmony_ci 935cabdff1aSopenharmony_ci videotoolbox->cm_fmt_desc = videotoolbox_format_desc_create(videotoolbox->cm_codec_type, 936cabdff1aSopenharmony_ci decoder_spec, 937cabdff1aSopenharmony_ci avctx->width, 938cabdff1aSopenharmony_ci avctx->height); 939cabdff1aSopenharmony_ci if (!videotoolbox->cm_fmt_desc) { 940cabdff1aSopenharmony_ci if (decoder_spec) 941cabdff1aSopenharmony_ci CFRelease(decoder_spec); 942cabdff1aSopenharmony_ci 943cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "format description creation failed\n"); 944cabdff1aSopenharmony_ci return -1; 945cabdff1aSopenharmony_ci } 946cabdff1aSopenharmony_ci 947cabdff1aSopenharmony_ci buf_attr = videotoolbox_buffer_attributes_create(avctx->width, 948cabdff1aSopenharmony_ci avctx->height, 949cabdff1aSopenharmony_ci videotoolbox->cv_pix_fmt_type); 950cabdff1aSopenharmony_ci 951cabdff1aSopenharmony_ci decoder_cb.decompressionOutputCallback = videotoolbox_decoder_callback; 952cabdff1aSopenharmony_ci decoder_cb.decompressionOutputRefCon = avctx->internal->hwaccel_priv_data; 953cabdff1aSopenharmony_ci 954cabdff1aSopenharmony_ci status = VTDecompressionSessionCreate(NULL, // allocator 955cabdff1aSopenharmony_ci videotoolbox->cm_fmt_desc, // videoFormatDescription 956cabdff1aSopenharmony_ci decoder_spec, // videoDecoderSpecification 957cabdff1aSopenharmony_ci buf_attr, // destinationImageBufferAttributes 958cabdff1aSopenharmony_ci &decoder_cb, // outputCallback 959cabdff1aSopenharmony_ci &videotoolbox->session); // decompressionSessionOut 960cabdff1aSopenharmony_ci 961cabdff1aSopenharmony_ci if (decoder_spec) 962cabdff1aSopenharmony_ci CFRelease(decoder_spec); 963cabdff1aSopenharmony_ci if (buf_attr) 964cabdff1aSopenharmony_ci CFRelease(buf_attr); 965cabdff1aSopenharmony_ci 966cabdff1aSopenharmony_ci switch (status) { 967cabdff1aSopenharmony_ci case kVTVideoDecoderNotAvailableNowErr: 968cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_VERBOSE, "VideoToolbox session not available.\n"); 969cabdff1aSopenharmony_ci return AVERROR(ENOSYS); 970cabdff1aSopenharmony_ci case kVTVideoDecoderUnsupportedDataFormatErr: 971cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_VERBOSE, "VideoToolbox does not support this format.\n"); 972cabdff1aSopenharmony_ci return AVERROR(ENOSYS); 973cabdff1aSopenharmony_ci case kVTCouldNotFindVideoDecoderErr: 974cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_VERBOSE, "VideoToolbox decoder for this format not found.\n"); 975cabdff1aSopenharmony_ci return AVERROR(ENOSYS); 976cabdff1aSopenharmony_ci case kVTVideoDecoderMalfunctionErr: 977cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_VERBOSE, "VideoToolbox malfunction.\n"); 978cabdff1aSopenharmony_ci return AVERROR(EINVAL); 979cabdff1aSopenharmony_ci case kVTVideoDecoderBadDataErr: 980cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_VERBOSE, "VideoToolbox reported invalid data.\n"); 981cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 982cabdff1aSopenharmony_ci case 0: 983cabdff1aSopenharmony_ci return 0; 984cabdff1aSopenharmony_ci default: 985cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_VERBOSE, "Unknown VideoToolbox session creation error %d\n", (int)status); 986cabdff1aSopenharmony_ci return AVERROR_UNKNOWN; 987cabdff1aSopenharmony_ci } 988cabdff1aSopenharmony_ci} 989cabdff1aSopenharmony_ci 990cabdff1aSopenharmony_cistatic const char *videotoolbox_error_string(OSStatus status) 991cabdff1aSopenharmony_ci{ 992cabdff1aSopenharmony_ci switch (status) { 993cabdff1aSopenharmony_ci case kVTVideoDecoderBadDataErr: 994cabdff1aSopenharmony_ci return "bad data"; 995cabdff1aSopenharmony_ci case kVTVideoDecoderMalfunctionErr: 996cabdff1aSopenharmony_ci return "decoder malfunction"; 997cabdff1aSopenharmony_ci case kVTInvalidSessionErr: 998cabdff1aSopenharmony_ci return "invalid session"; 999cabdff1aSopenharmony_ci } 1000cabdff1aSopenharmony_ci return "unknown"; 1001cabdff1aSopenharmony_ci} 1002cabdff1aSopenharmony_ci 1003cabdff1aSopenharmony_ciint ff_videotoolbox_common_end_frame(AVCodecContext *avctx, AVFrame *frame) 1004cabdff1aSopenharmony_ci{ 1005cabdff1aSopenharmony_ci OSStatus status; 1006cabdff1aSopenharmony_ci AVVideotoolboxContext *videotoolbox = videotoolbox_get_context(avctx); 1007cabdff1aSopenharmony_ci VTContext *vtctx = avctx->internal->hwaccel_priv_data; 1008cabdff1aSopenharmony_ci 1009cabdff1aSopenharmony_ci if (vtctx->reconfig_needed == true) { 1010cabdff1aSopenharmony_ci vtctx->reconfig_needed = false; 1011cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_VERBOSE, "VideoToolbox decoder needs reconfig, restarting..\n"); 1012cabdff1aSopenharmony_ci videotoolbox_stop(avctx); 1013cabdff1aSopenharmony_ci if (videotoolbox_start(avctx) != 0) { 1014cabdff1aSopenharmony_ci return AVERROR_EXTERNAL; 1015cabdff1aSopenharmony_ci } 1016cabdff1aSopenharmony_ci } 1017cabdff1aSopenharmony_ci 1018cabdff1aSopenharmony_ci if (!videotoolbox->session || !vtctx->bitstream || !vtctx->bitstream_size) 1019cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 1020cabdff1aSopenharmony_ci 1021cabdff1aSopenharmony_ci status = videotoolbox_session_decode_frame(avctx); 1022cabdff1aSopenharmony_ci if (status != noErr) { 1023cabdff1aSopenharmony_ci if (status == kVTVideoDecoderMalfunctionErr || status == kVTInvalidSessionErr) 1024cabdff1aSopenharmony_ci vtctx->reconfig_needed = true; 1025cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Failed to decode frame (%s, %d)\n", videotoolbox_error_string(status), (int)status); 1026cabdff1aSopenharmony_ci return AVERROR_UNKNOWN; 1027cabdff1aSopenharmony_ci } 1028cabdff1aSopenharmony_ci 1029cabdff1aSopenharmony_ci if (!vtctx->frame) { 1030cabdff1aSopenharmony_ci vtctx->reconfig_needed = true; 1031cabdff1aSopenharmony_ci return AVERROR_UNKNOWN; 1032cabdff1aSopenharmony_ci } 1033cabdff1aSopenharmony_ci 1034cabdff1aSopenharmony_ci return videotoolbox_buffer_create(avctx, frame); 1035cabdff1aSopenharmony_ci} 1036cabdff1aSopenharmony_ci 1037cabdff1aSopenharmony_cistatic int videotoolbox_h264_end_frame(AVCodecContext *avctx) 1038cabdff1aSopenharmony_ci{ 1039cabdff1aSopenharmony_ci H264Context *h = avctx->priv_data; 1040cabdff1aSopenharmony_ci AVFrame *frame = h->cur_pic_ptr->f; 1041cabdff1aSopenharmony_ci VTContext *vtctx = avctx->internal->hwaccel_priv_data; 1042cabdff1aSopenharmony_ci int ret = ff_videotoolbox_common_end_frame(avctx, frame); 1043cabdff1aSopenharmony_ci vtctx->bitstream_size = 0; 1044cabdff1aSopenharmony_ci return ret; 1045cabdff1aSopenharmony_ci} 1046cabdff1aSopenharmony_ci 1047cabdff1aSopenharmony_cistatic int videotoolbox_hevc_start_frame(AVCodecContext *avctx, 1048cabdff1aSopenharmony_ci const uint8_t *buffer, 1049cabdff1aSopenharmony_ci uint32_t size) 1050cabdff1aSopenharmony_ci{ 1051cabdff1aSopenharmony_ci return 0; 1052cabdff1aSopenharmony_ci} 1053cabdff1aSopenharmony_ci 1054cabdff1aSopenharmony_cistatic int videotoolbox_hevc_decode_slice(AVCodecContext *avctx, 1055cabdff1aSopenharmony_ci const uint8_t *buffer, 1056cabdff1aSopenharmony_ci uint32_t size) 1057cabdff1aSopenharmony_ci{ 1058cabdff1aSopenharmony_ci return videotoolbox_common_decode_slice(avctx, buffer, size); 1059cabdff1aSopenharmony_ci} 1060cabdff1aSopenharmony_ci 1061cabdff1aSopenharmony_ci 1062cabdff1aSopenharmony_cistatic int videotoolbox_hevc_decode_params(AVCodecContext *avctx, 1063cabdff1aSopenharmony_ci int type, 1064cabdff1aSopenharmony_ci const uint8_t *buffer, 1065cabdff1aSopenharmony_ci uint32_t size) 1066cabdff1aSopenharmony_ci{ 1067cabdff1aSopenharmony_ci return videotoolbox_common_decode_slice(avctx, buffer, size); 1068cabdff1aSopenharmony_ci} 1069cabdff1aSopenharmony_ci 1070cabdff1aSopenharmony_cistatic int videotoolbox_hevc_end_frame(AVCodecContext *avctx) 1071cabdff1aSopenharmony_ci{ 1072cabdff1aSopenharmony_ci HEVCContext *h = avctx->priv_data; 1073cabdff1aSopenharmony_ci AVFrame *frame = h->ref->frame; 1074cabdff1aSopenharmony_ci VTContext *vtctx = avctx->internal->hwaccel_priv_data; 1075cabdff1aSopenharmony_ci 1076cabdff1aSopenharmony_ci h->output_frame->crop_right = 0; 1077cabdff1aSopenharmony_ci h->output_frame->crop_left = 0; 1078cabdff1aSopenharmony_ci h->output_frame->crop_top = 0; 1079cabdff1aSopenharmony_ci h->output_frame->crop_bottom = 0; 1080cabdff1aSopenharmony_ci 1081cabdff1aSopenharmony_ci int ret = ff_videotoolbox_common_end_frame(avctx, frame); 1082cabdff1aSopenharmony_ci vtctx->bitstream_size = 0; 1083cabdff1aSopenharmony_ci return ret; 1084cabdff1aSopenharmony_ci} 1085cabdff1aSopenharmony_ci 1086cabdff1aSopenharmony_cistatic int videotoolbox_mpeg_start_frame(AVCodecContext *avctx, 1087cabdff1aSopenharmony_ci const uint8_t *buffer, 1088cabdff1aSopenharmony_ci uint32_t size) 1089cabdff1aSopenharmony_ci{ 1090cabdff1aSopenharmony_ci VTContext *vtctx = avctx->internal->hwaccel_priv_data; 1091cabdff1aSopenharmony_ci 1092cabdff1aSopenharmony_ci return ff_videotoolbox_buffer_copy(vtctx, buffer, size); 1093cabdff1aSopenharmony_ci} 1094cabdff1aSopenharmony_ci 1095cabdff1aSopenharmony_cistatic int videotoolbox_mpeg_decode_slice(AVCodecContext *avctx, 1096cabdff1aSopenharmony_ci const uint8_t *buffer, 1097cabdff1aSopenharmony_ci uint32_t size) 1098cabdff1aSopenharmony_ci{ 1099cabdff1aSopenharmony_ci return 0; 1100cabdff1aSopenharmony_ci} 1101cabdff1aSopenharmony_ci 1102cabdff1aSopenharmony_cistatic int videotoolbox_mpeg_end_frame(AVCodecContext *avctx) 1103cabdff1aSopenharmony_ci{ 1104cabdff1aSopenharmony_ci MpegEncContext *s = avctx->priv_data; 1105cabdff1aSopenharmony_ci AVFrame *frame = s->current_picture_ptr->f; 1106cabdff1aSopenharmony_ci 1107cabdff1aSopenharmony_ci return ff_videotoolbox_common_end_frame(avctx, frame); 1108cabdff1aSopenharmony_ci} 1109cabdff1aSopenharmony_ci 1110cabdff1aSopenharmony_cistatic int videotoolbox_prores_start_frame(AVCodecContext *avctx, 1111cabdff1aSopenharmony_ci const uint8_t *buffer, 1112cabdff1aSopenharmony_ci uint32_t size) 1113cabdff1aSopenharmony_ci{ 1114cabdff1aSopenharmony_ci return 0; 1115cabdff1aSopenharmony_ci} 1116cabdff1aSopenharmony_ci 1117cabdff1aSopenharmony_cistatic int videotoolbox_prores_decode_slice(AVCodecContext *avctx, 1118cabdff1aSopenharmony_ci const uint8_t *buffer, 1119cabdff1aSopenharmony_ci uint32_t size) 1120cabdff1aSopenharmony_ci{ 1121cabdff1aSopenharmony_ci VTContext *vtctx = avctx->internal->hwaccel_priv_data; 1122cabdff1aSopenharmony_ci 1123cabdff1aSopenharmony_ci return ff_videotoolbox_buffer_copy(vtctx, buffer, size); 1124cabdff1aSopenharmony_ci} 1125cabdff1aSopenharmony_ci 1126cabdff1aSopenharmony_cistatic int videotoolbox_prores_end_frame(AVCodecContext *avctx) 1127cabdff1aSopenharmony_ci{ 1128cabdff1aSopenharmony_ci ProresContext *ctx = avctx->priv_data; 1129cabdff1aSopenharmony_ci AVFrame *frame = ctx->frame; 1130cabdff1aSopenharmony_ci 1131cabdff1aSopenharmony_ci return ff_videotoolbox_common_end_frame(avctx, frame); 1132cabdff1aSopenharmony_ci} 1133cabdff1aSopenharmony_ci 1134cabdff1aSopenharmony_cistatic enum AVPixelFormat videotoolbox_best_pixel_format(AVCodecContext *avctx) { 1135cabdff1aSopenharmony_ci const AVPixFmtDescriptor *descriptor = av_pix_fmt_desc_get(avctx->sw_pix_fmt); 1136cabdff1aSopenharmony_ci if (!descriptor) 1137cabdff1aSopenharmony_ci return AV_PIX_FMT_NV12; // same as av_videotoolbox_alloc_context() 1138cabdff1aSopenharmony_ci 1139cabdff1aSopenharmony_ci int depth = descriptor->comp[0].depth; 1140cabdff1aSopenharmony_ci 1141cabdff1aSopenharmony_ci if (descriptor->flags & AV_PIX_FMT_FLAG_ALPHA) 1142cabdff1aSopenharmony_ci return AV_PIX_FMT_AYUV64; 1143cabdff1aSopenharmony_ci 1144cabdff1aSopenharmony_ci#if HAVE_KCVPIXELFORMATTYPE_444YPCBCR16BIPLANARVIDEORANGE 1145cabdff1aSopenharmony_ci if (depth > 10) 1146cabdff1aSopenharmony_ci return descriptor->log2_chroma_w == 0 ? AV_PIX_FMT_P416 : AV_PIX_FMT_P216; 1147cabdff1aSopenharmony_ci#endif 1148cabdff1aSopenharmony_ci 1149cabdff1aSopenharmony_ci#if HAVE_KCVPIXELFORMATTYPE_444YPCBCR10BIPLANARVIDEORANGE 1150cabdff1aSopenharmony_ci if (descriptor->log2_chroma_w == 0) { 1151cabdff1aSopenharmony_ci#if HAVE_KCVPIXELFORMATTYPE_444YPCBCR8BIPLANARVIDEORANGE 1152cabdff1aSopenharmony_ci if (depth <= 8) 1153cabdff1aSopenharmony_ci return AV_PIX_FMT_NV24; 1154cabdff1aSopenharmony_ci#endif 1155cabdff1aSopenharmony_ci return AV_PIX_FMT_P410; 1156cabdff1aSopenharmony_ci } 1157cabdff1aSopenharmony_ci#endif 1158cabdff1aSopenharmony_ci#if HAVE_KCVPIXELFORMATTYPE_422YPCBCR10BIPLANARVIDEORANGE 1159cabdff1aSopenharmony_ci if (descriptor->log2_chroma_h == 0) { 1160cabdff1aSopenharmony_ci#if HAVE_KCVPIXELFORMATTYPE_422YPCBCR8BIPLANARVIDEORANGE 1161cabdff1aSopenharmony_ci if (depth <= 8) 1162cabdff1aSopenharmony_ci return AV_PIX_FMT_NV16; 1163cabdff1aSopenharmony_ci#endif 1164cabdff1aSopenharmony_ci return AV_PIX_FMT_P210; 1165cabdff1aSopenharmony_ci } 1166cabdff1aSopenharmony_ci#endif 1167cabdff1aSopenharmony_ci#if HAVE_KCVPIXELFORMATTYPE_420YPCBCR10BIPLANARVIDEORANGE 1168cabdff1aSopenharmony_ci if (depth > 8) { 1169cabdff1aSopenharmony_ci return AV_PIX_FMT_P010; 1170cabdff1aSopenharmony_ci } 1171cabdff1aSopenharmony_ci#endif 1172cabdff1aSopenharmony_ci 1173cabdff1aSopenharmony_ci return AV_PIX_FMT_NV12; 1174cabdff1aSopenharmony_ci} 1175cabdff1aSopenharmony_ci 1176cabdff1aSopenharmony_ciint ff_videotoolbox_common_init(AVCodecContext *avctx) 1177cabdff1aSopenharmony_ci{ 1178cabdff1aSopenharmony_ci VTContext *vtctx = avctx->internal->hwaccel_priv_data; 1179cabdff1aSopenharmony_ci AVHWFramesContext *hw_frames; 1180cabdff1aSopenharmony_ci int err; 1181cabdff1aSopenharmony_ci 1182cabdff1aSopenharmony_ci vtctx->logctx = avctx; 1183cabdff1aSopenharmony_ci 1184cabdff1aSopenharmony_ci // Old API - do nothing. 1185cabdff1aSopenharmony_ci if (avctx->hwaccel_context) 1186cabdff1aSopenharmony_ci return 0; 1187cabdff1aSopenharmony_ci 1188cabdff1aSopenharmony_ci if (!avctx->hw_frames_ctx && !avctx->hw_device_ctx) { 1189cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, 1190cabdff1aSopenharmony_ci "Either hw_frames_ctx or hw_device_ctx must be set.\n"); 1191cabdff1aSopenharmony_ci return AVERROR(EINVAL); 1192cabdff1aSopenharmony_ci } 1193cabdff1aSopenharmony_ci 1194cabdff1aSopenharmony_ci vtctx->vt_ctx = av_videotoolbox_alloc_context(); 1195cabdff1aSopenharmony_ci if (!vtctx->vt_ctx) { 1196cabdff1aSopenharmony_ci err = AVERROR(ENOMEM); 1197cabdff1aSopenharmony_ci goto fail; 1198cabdff1aSopenharmony_ci } 1199cabdff1aSopenharmony_ci 1200cabdff1aSopenharmony_ci if (avctx->hw_frames_ctx) { 1201cabdff1aSopenharmony_ci hw_frames = (AVHWFramesContext*)avctx->hw_frames_ctx->data; 1202cabdff1aSopenharmony_ci } else { 1203cabdff1aSopenharmony_ci avctx->hw_frames_ctx = av_hwframe_ctx_alloc(avctx->hw_device_ctx); 1204cabdff1aSopenharmony_ci if (!avctx->hw_frames_ctx) { 1205cabdff1aSopenharmony_ci err = AVERROR(ENOMEM); 1206cabdff1aSopenharmony_ci goto fail; 1207cabdff1aSopenharmony_ci } 1208cabdff1aSopenharmony_ci 1209cabdff1aSopenharmony_ci hw_frames = (AVHWFramesContext*)avctx->hw_frames_ctx->data; 1210cabdff1aSopenharmony_ci hw_frames->format = AV_PIX_FMT_VIDEOTOOLBOX; 1211cabdff1aSopenharmony_ci hw_frames->sw_format = videotoolbox_best_pixel_format(avctx); 1212cabdff1aSopenharmony_ci hw_frames->width = avctx->width; 1213cabdff1aSopenharmony_ci hw_frames->height = avctx->height; 1214cabdff1aSopenharmony_ci 1215cabdff1aSopenharmony_ci err = av_hwframe_ctx_init(avctx->hw_frames_ctx); 1216cabdff1aSopenharmony_ci if (err < 0) { 1217cabdff1aSopenharmony_ci av_buffer_unref(&avctx->hw_frames_ctx); 1218cabdff1aSopenharmony_ci goto fail; 1219cabdff1aSopenharmony_ci } 1220cabdff1aSopenharmony_ci } 1221cabdff1aSopenharmony_ci 1222cabdff1aSopenharmony_ci vtctx->cached_hw_frames_ctx = av_buffer_ref(avctx->hw_frames_ctx); 1223cabdff1aSopenharmony_ci if (!vtctx->cached_hw_frames_ctx) { 1224cabdff1aSopenharmony_ci err = AVERROR(ENOMEM); 1225cabdff1aSopenharmony_ci goto fail; 1226cabdff1aSopenharmony_ci } 1227cabdff1aSopenharmony_ci 1228cabdff1aSopenharmony_ci bool full_range = avctx->color_range == AVCOL_RANGE_JPEG; 1229cabdff1aSopenharmony_ci vtctx->vt_ctx->cv_pix_fmt_type = 1230cabdff1aSopenharmony_ci av_map_videotoolbox_format_from_pixfmt2(hw_frames->sw_format, full_range); 1231cabdff1aSopenharmony_ci if (!vtctx->vt_ctx->cv_pix_fmt_type) { 1232cabdff1aSopenharmony_ci const AVPixFmtDescriptor *attempted_format = 1233cabdff1aSopenharmony_ci av_pix_fmt_desc_get(hw_frames->sw_format); 1234cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, 1235cabdff1aSopenharmony_ci "Failed to map underlying FFmpeg pixel format %s (%s range) to " 1236cabdff1aSopenharmony_ci "a VideoToolbox format!\n", 1237cabdff1aSopenharmony_ci attempted_format ? attempted_format->name : "<unknown>", 1238cabdff1aSopenharmony_ci av_color_range_name(avctx->color_range)); 1239cabdff1aSopenharmony_ci err = AVERROR(EINVAL); 1240cabdff1aSopenharmony_ci goto fail; 1241cabdff1aSopenharmony_ci } 1242cabdff1aSopenharmony_ci 1243cabdff1aSopenharmony_ci err = videotoolbox_start(avctx); 1244cabdff1aSopenharmony_ci if (err < 0) 1245cabdff1aSopenharmony_ci goto fail; 1246cabdff1aSopenharmony_ci 1247cabdff1aSopenharmony_ci return 0; 1248cabdff1aSopenharmony_ci 1249cabdff1aSopenharmony_cifail: 1250cabdff1aSopenharmony_ci ff_videotoolbox_uninit(avctx); 1251cabdff1aSopenharmony_ci return err; 1252cabdff1aSopenharmony_ci} 1253cabdff1aSopenharmony_ci 1254cabdff1aSopenharmony_ciint ff_videotoolbox_frame_params(AVCodecContext *avctx, 1255cabdff1aSopenharmony_ci AVBufferRef *hw_frames_ctx) 1256cabdff1aSopenharmony_ci{ 1257cabdff1aSopenharmony_ci AVHWFramesContext *frames_ctx = (AVHWFramesContext*)hw_frames_ctx->data; 1258cabdff1aSopenharmony_ci 1259cabdff1aSopenharmony_ci frames_ctx->format = AV_PIX_FMT_VIDEOTOOLBOX; 1260cabdff1aSopenharmony_ci frames_ctx->width = avctx->coded_width; 1261cabdff1aSopenharmony_ci frames_ctx->height = avctx->coded_height; 1262cabdff1aSopenharmony_ci frames_ctx->sw_format = videotoolbox_best_pixel_format(avctx); 1263cabdff1aSopenharmony_ci 1264cabdff1aSopenharmony_ci return 0; 1265cabdff1aSopenharmony_ci} 1266cabdff1aSopenharmony_ci 1267cabdff1aSopenharmony_ciconst AVHWAccel ff_h263_videotoolbox_hwaccel = { 1268cabdff1aSopenharmony_ci .name = "h263_videotoolbox", 1269cabdff1aSopenharmony_ci .type = AVMEDIA_TYPE_VIDEO, 1270cabdff1aSopenharmony_ci .id = AV_CODEC_ID_H263, 1271cabdff1aSopenharmony_ci .pix_fmt = AV_PIX_FMT_VIDEOTOOLBOX, 1272cabdff1aSopenharmony_ci .alloc_frame = ff_videotoolbox_alloc_frame, 1273cabdff1aSopenharmony_ci .start_frame = videotoolbox_mpeg_start_frame, 1274cabdff1aSopenharmony_ci .decode_slice = videotoolbox_mpeg_decode_slice, 1275cabdff1aSopenharmony_ci .end_frame = videotoolbox_mpeg_end_frame, 1276cabdff1aSopenharmony_ci .frame_params = ff_videotoolbox_frame_params, 1277cabdff1aSopenharmony_ci .init = ff_videotoolbox_common_init, 1278cabdff1aSopenharmony_ci .uninit = ff_videotoolbox_uninit, 1279cabdff1aSopenharmony_ci .priv_data_size = sizeof(VTContext), 1280cabdff1aSopenharmony_ci}; 1281cabdff1aSopenharmony_ci 1282cabdff1aSopenharmony_ciconst AVHWAccel ff_hevc_videotoolbox_hwaccel = { 1283cabdff1aSopenharmony_ci .name = "hevc_videotoolbox", 1284cabdff1aSopenharmony_ci .type = AVMEDIA_TYPE_VIDEO, 1285cabdff1aSopenharmony_ci .id = AV_CODEC_ID_HEVC, 1286cabdff1aSopenharmony_ci .pix_fmt = AV_PIX_FMT_VIDEOTOOLBOX, 1287cabdff1aSopenharmony_ci .alloc_frame = ff_videotoolbox_alloc_frame, 1288cabdff1aSopenharmony_ci .start_frame = videotoolbox_hevc_start_frame, 1289cabdff1aSopenharmony_ci .decode_slice = videotoolbox_hevc_decode_slice, 1290cabdff1aSopenharmony_ci .decode_params = videotoolbox_hevc_decode_params, 1291cabdff1aSopenharmony_ci .end_frame = videotoolbox_hevc_end_frame, 1292cabdff1aSopenharmony_ci .frame_params = ff_videotoolbox_frame_params, 1293cabdff1aSopenharmony_ci .init = ff_videotoolbox_common_init, 1294cabdff1aSopenharmony_ci .uninit = ff_videotoolbox_uninit, 1295cabdff1aSopenharmony_ci .priv_data_size = sizeof(VTContext), 1296cabdff1aSopenharmony_ci}; 1297cabdff1aSopenharmony_ci 1298cabdff1aSopenharmony_ciconst AVHWAccel ff_h264_videotoolbox_hwaccel = { 1299cabdff1aSopenharmony_ci .name = "h264_videotoolbox", 1300cabdff1aSopenharmony_ci .type = AVMEDIA_TYPE_VIDEO, 1301cabdff1aSopenharmony_ci .id = AV_CODEC_ID_H264, 1302cabdff1aSopenharmony_ci .pix_fmt = AV_PIX_FMT_VIDEOTOOLBOX, 1303cabdff1aSopenharmony_ci .alloc_frame = ff_videotoolbox_alloc_frame, 1304cabdff1aSopenharmony_ci .start_frame = ff_videotoolbox_h264_start_frame, 1305cabdff1aSopenharmony_ci .decode_slice = ff_videotoolbox_h264_decode_slice, 1306cabdff1aSopenharmony_ci .decode_params = videotoolbox_h264_decode_params, 1307cabdff1aSopenharmony_ci .end_frame = videotoolbox_h264_end_frame, 1308cabdff1aSopenharmony_ci .frame_params = ff_videotoolbox_frame_params, 1309cabdff1aSopenharmony_ci .init = ff_videotoolbox_common_init, 1310cabdff1aSopenharmony_ci .uninit = ff_videotoolbox_uninit, 1311cabdff1aSopenharmony_ci .priv_data_size = sizeof(VTContext), 1312cabdff1aSopenharmony_ci}; 1313cabdff1aSopenharmony_ci 1314cabdff1aSopenharmony_ciconst AVHWAccel ff_mpeg1_videotoolbox_hwaccel = { 1315cabdff1aSopenharmony_ci .name = "mpeg1_videotoolbox", 1316cabdff1aSopenharmony_ci .type = AVMEDIA_TYPE_VIDEO, 1317cabdff1aSopenharmony_ci .id = AV_CODEC_ID_MPEG1VIDEO, 1318cabdff1aSopenharmony_ci .pix_fmt = AV_PIX_FMT_VIDEOTOOLBOX, 1319cabdff1aSopenharmony_ci .alloc_frame = ff_videotoolbox_alloc_frame, 1320cabdff1aSopenharmony_ci .start_frame = videotoolbox_mpeg_start_frame, 1321cabdff1aSopenharmony_ci .decode_slice = videotoolbox_mpeg_decode_slice, 1322cabdff1aSopenharmony_ci .end_frame = videotoolbox_mpeg_end_frame, 1323cabdff1aSopenharmony_ci .frame_params = ff_videotoolbox_frame_params, 1324cabdff1aSopenharmony_ci .init = ff_videotoolbox_common_init, 1325cabdff1aSopenharmony_ci .uninit = ff_videotoolbox_uninit, 1326cabdff1aSopenharmony_ci .priv_data_size = sizeof(VTContext), 1327cabdff1aSopenharmony_ci}; 1328cabdff1aSopenharmony_ci 1329cabdff1aSopenharmony_ciconst AVHWAccel ff_mpeg2_videotoolbox_hwaccel = { 1330cabdff1aSopenharmony_ci .name = "mpeg2_videotoolbox", 1331cabdff1aSopenharmony_ci .type = AVMEDIA_TYPE_VIDEO, 1332cabdff1aSopenharmony_ci .id = AV_CODEC_ID_MPEG2VIDEO, 1333cabdff1aSopenharmony_ci .pix_fmt = AV_PIX_FMT_VIDEOTOOLBOX, 1334cabdff1aSopenharmony_ci .alloc_frame = ff_videotoolbox_alloc_frame, 1335cabdff1aSopenharmony_ci .start_frame = videotoolbox_mpeg_start_frame, 1336cabdff1aSopenharmony_ci .decode_slice = videotoolbox_mpeg_decode_slice, 1337cabdff1aSopenharmony_ci .end_frame = videotoolbox_mpeg_end_frame, 1338cabdff1aSopenharmony_ci .frame_params = ff_videotoolbox_frame_params, 1339cabdff1aSopenharmony_ci .init = ff_videotoolbox_common_init, 1340cabdff1aSopenharmony_ci .uninit = ff_videotoolbox_uninit, 1341cabdff1aSopenharmony_ci .priv_data_size = sizeof(VTContext), 1342cabdff1aSopenharmony_ci}; 1343cabdff1aSopenharmony_ci 1344cabdff1aSopenharmony_ciconst AVHWAccel ff_mpeg4_videotoolbox_hwaccel = { 1345cabdff1aSopenharmony_ci .name = "mpeg4_videotoolbox", 1346cabdff1aSopenharmony_ci .type = AVMEDIA_TYPE_VIDEO, 1347cabdff1aSopenharmony_ci .id = AV_CODEC_ID_MPEG4, 1348cabdff1aSopenharmony_ci .pix_fmt = AV_PIX_FMT_VIDEOTOOLBOX, 1349cabdff1aSopenharmony_ci .alloc_frame = ff_videotoolbox_alloc_frame, 1350cabdff1aSopenharmony_ci .start_frame = videotoolbox_mpeg_start_frame, 1351cabdff1aSopenharmony_ci .decode_slice = videotoolbox_mpeg_decode_slice, 1352cabdff1aSopenharmony_ci .end_frame = videotoolbox_mpeg_end_frame, 1353cabdff1aSopenharmony_ci .frame_params = ff_videotoolbox_frame_params, 1354cabdff1aSopenharmony_ci .init = ff_videotoolbox_common_init, 1355cabdff1aSopenharmony_ci .uninit = ff_videotoolbox_uninit, 1356cabdff1aSopenharmony_ci .priv_data_size = sizeof(VTContext), 1357cabdff1aSopenharmony_ci}; 1358cabdff1aSopenharmony_ci 1359cabdff1aSopenharmony_ciconst AVHWAccel ff_prores_videotoolbox_hwaccel = { 1360cabdff1aSopenharmony_ci .name = "prores_videotoolbox", 1361cabdff1aSopenharmony_ci .type = AVMEDIA_TYPE_VIDEO, 1362cabdff1aSopenharmony_ci .id = AV_CODEC_ID_PRORES, 1363cabdff1aSopenharmony_ci .pix_fmt = AV_PIX_FMT_VIDEOTOOLBOX, 1364cabdff1aSopenharmony_ci .alloc_frame = ff_videotoolbox_alloc_frame, 1365cabdff1aSopenharmony_ci .start_frame = videotoolbox_prores_start_frame, 1366cabdff1aSopenharmony_ci .decode_slice = videotoolbox_prores_decode_slice, 1367cabdff1aSopenharmony_ci .end_frame = videotoolbox_prores_end_frame, 1368cabdff1aSopenharmony_ci .frame_params = ff_videotoolbox_frame_params, 1369cabdff1aSopenharmony_ci .init = ff_videotoolbox_common_init, 1370cabdff1aSopenharmony_ci .uninit = ff_videotoolbox_uninit, 1371cabdff1aSopenharmony_ci .priv_data_size = sizeof(VTContext), 1372cabdff1aSopenharmony_ci}; 1373cabdff1aSopenharmony_ci 1374cabdff1aSopenharmony_cistatic AVVideotoolboxContext *av_videotoolbox_alloc_context_with_pix_fmt(enum AVPixelFormat pix_fmt, 1375cabdff1aSopenharmony_ci bool full_range) 1376cabdff1aSopenharmony_ci{ 1377cabdff1aSopenharmony_ci AVVideotoolboxContext *ret = av_mallocz(sizeof(*ret)); 1378cabdff1aSopenharmony_ci 1379cabdff1aSopenharmony_ci if (ret) { 1380cabdff1aSopenharmony_ci ret->output_callback = videotoolbox_decoder_callback; 1381cabdff1aSopenharmony_ci 1382cabdff1aSopenharmony_ci OSType cv_pix_fmt_type = av_map_videotoolbox_format_from_pixfmt2(pix_fmt, full_range); 1383cabdff1aSopenharmony_ci if (cv_pix_fmt_type == 0) { 1384cabdff1aSopenharmony_ci cv_pix_fmt_type = kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange; 1385cabdff1aSopenharmony_ci } 1386cabdff1aSopenharmony_ci ret->cv_pix_fmt_type = cv_pix_fmt_type; 1387cabdff1aSopenharmony_ci } 1388cabdff1aSopenharmony_ci 1389cabdff1aSopenharmony_ci return ret; 1390cabdff1aSopenharmony_ci} 1391cabdff1aSopenharmony_ci 1392cabdff1aSopenharmony_ciAVVideotoolboxContext *av_videotoolbox_alloc_context(void) 1393cabdff1aSopenharmony_ci{ 1394cabdff1aSopenharmony_ci return av_videotoolbox_alloc_context_with_pix_fmt(AV_PIX_FMT_NONE, false); 1395cabdff1aSopenharmony_ci} 1396cabdff1aSopenharmony_ci 1397cabdff1aSopenharmony_ciint av_videotoolbox_default_init(AVCodecContext *avctx) 1398cabdff1aSopenharmony_ci{ 1399cabdff1aSopenharmony_ci return av_videotoolbox_default_init2(avctx, NULL); 1400cabdff1aSopenharmony_ci} 1401cabdff1aSopenharmony_ci 1402cabdff1aSopenharmony_ciint av_videotoolbox_default_init2(AVCodecContext *avctx, AVVideotoolboxContext *vtctx) 1403cabdff1aSopenharmony_ci{ 1404cabdff1aSopenharmony_ci enum AVPixelFormat pix_fmt = videotoolbox_best_pixel_format(avctx); 1405cabdff1aSopenharmony_ci bool full_range = avctx->color_range == AVCOL_RANGE_JPEG; 1406cabdff1aSopenharmony_ci avctx->hwaccel_context = vtctx ?: av_videotoolbox_alloc_context_with_pix_fmt(pix_fmt, full_range); 1407cabdff1aSopenharmony_ci if (!avctx->hwaccel_context) 1408cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 1409cabdff1aSopenharmony_ci return videotoolbox_start(avctx); 1410cabdff1aSopenharmony_ci} 1411cabdff1aSopenharmony_ci 1412cabdff1aSopenharmony_civoid av_videotoolbox_default_free(AVCodecContext *avctx) 1413cabdff1aSopenharmony_ci{ 1414cabdff1aSopenharmony_ci 1415cabdff1aSopenharmony_ci videotoolbox_stop(avctx); 1416cabdff1aSopenharmony_ci av_freep(&avctx->hwaccel_context); 1417cabdff1aSopenharmony_ci} 1418cabdff1aSopenharmony_ci#endif /* CONFIG_VIDEOTOOLBOX */ 1419