1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * Videotoolbox hardware acceleration for VP9 3cabdff1aSopenharmony_ci * 4cabdff1aSopenharmony_ci * copyright (c) 2021 rcombs 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 "videotoolbox.h" 25cabdff1aSopenharmony_ci#include "libavutil/hwcontext_videotoolbox.h" 26cabdff1aSopenharmony_ci#include "vt_internal.h" 27cabdff1aSopenharmony_ci#include "libavutil/avutil.h" 28cabdff1aSopenharmony_ci#include "libavutil/frame.h" 29cabdff1aSopenharmony_ci#include "libavutil/hwcontext.h" 30cabdff1aSopenharmony_ci#include "libavutil/intreadwrite.h" 31cabdff1aSopenharmony_ci#include "libavutil/pixdesc.h" 32cabdff1aSopenharmony_ci#include "decode.h" 33cabdff1aSopenharmony_ci#include "internal.h" 34cabdff1aSopenharmony_ci#include "vp9shared.h" 35cabdff1aSopenharmony_ci 36cabdff1aSopenharmony_cienum VPX_CHROMA_SUBSAMPLING 37cabdff1aSopenharmony_ci{ 38cabdff1aSopenharmony_ci VPX_SUBSAMPLING_420_VERTICAL = 0, 39cabdff1aSopenharmony_ci VPX_SUBSAMPLING_420_COLLOCATED_WITH_LUMA = 1, 40cabdff1aSopenharmony_ci VPX_SUBSAMPLING_422 = 2, 41cabdff1aSopenharmony_ci VPX_SUBSAMPLING_444 = 3, 42cabdff1aSopenharmony_ci}; 43cabdff1aSopenharmony_ci 44cabdff1aSopenharmony_cistatic int get_vpx_chroma_subsampling(enum AVPixelFormat pixel_format, 45cabdff1aSopenharmony_ci enum AVChromaLocation chroma_location) 46cabdff1aSopenharmony_ci{ 47cabdff1aSopenharmony_ci int chroma_w, chroma_h; 48cabdff1aSopenharmony_ci if (av_pix_fmt_get_chroma_sub_sample(pixel_format, &chroma_w, &chroma_h) == 0) { 49cabdff1aSopenharmony_ci if (chroma_w == 1 && chroma_h == 1) { 50cabdff1aSopenharmony_ci return (chroma_location == AVCHROMA_LOC_LEFT) 51cabdff1aSopenharmony_ci ? VPX_SUBSAMPLING_420_VERTICAL 52cabdff1aSopenharmony_ci : VPX_SUBSAMPLING_420_COLLOCATED_WITH_LUMA; 53cabdff1aSopenharmony_ci } else if (chroma_w == 1 && chroma_h == 0) { 54cabdff1aSopenharmony_ci return VPX_SUBSAMPLING_422; 55cabdff1aSopenharmony_ci } else if (chroma_w == 0 && chroma_h == 0) { 56cabdff1aSopenharmony_ci return VPX_SUBSAMPLING_444; 57cabdff1aSopenharmony_ci } 58cabdff1aSopenharmony_ci } 59cabdff1aSopenharmony_ci return -1; 60cabdff1aSopenharmony_ci} 61cabdff1aSopenharmony_ci 62cabdff1aSopenharmony_ciCFDataRef ff_videotoolbox_vpcc_extradata_create(AVCodecContext *avctx) 63cabdff1aSopenharmony_ci{ 64cabdff1aSopenharmony_ci const VP9SharedContext *h = avctx->priv_data; 65cabdff1aSopenharmony_ci CFDataRef data = NULL; 66cabdff1aSopenharmony_ci uint8_t *p; 67cabdff1aSopenharmony_ci int vt_extradata_size; 68cabdff1aSopenharmony_ci uint8_t *vt_extradata; 69cabdff1aSopenharmony_ci int subsampling = get_vpx_chroma_subsampling(avctx->sw_pix_fmt, avctx->chroma_sample_location); 70cabdff1aSopenharmony_ci 71cabdff1aSopenharmony_ci vt_extradata_size = 1 + 3 + 6 + 2; 72cabdff1aSopenharmony_ci vt_extradata = av_malloc(vt_extradata_size); 73cabdff1aSopenharmony_ci 74cabdff1aSopenharmony_ci if (subsampling < 0) 75cabdff1aSopenharmony_ci return NULL; 76cabdff1aSopenharmony_ci 77cabdff1aSopenharmony_ci if (!vt_extradata) 78cabdff1aSopenharmony_ci return NULL; 79cabdff1aSopenharmony_ci 80cabdff1aSopenharmony_ci p = vt_extradata; 81cabdff1aSopenharmony_ci 82cabdff1aSopenharmony_ci *p++ = 1; /* version */ 83cabdff1aSopenharmony_ci AV_WB24(p + 1, 0); /* flags */ 84cabdff1aSopenharmony_ci p += 3; 85cabdff1aSopenharmony_ci 86cabdff1aSopenharmony_ci *p++ = h->h.profile; 87cabdff1aSopenharmony_ci *p++ = avctx->level; 88cabdff1aSopenharmony_ci *p++ = (h->h.bpp << 4) | (subsampling << 1) | (avctx->color_range == AVCOL_RANGE_JPEG); 89cabdff1aSopenharmony_ci *p++ = avctx->color_primaries; 90cabdff1aSopenharmony_ci *p++ = avctx->color_trc; 91cabdff1aSopenharmony_ci *p++ = avctx->colorspace; 92cabdff1aSopenharmony_ci 93cabdff1aSopenharmony_ci AV_WB16(p + 0, 0); 94cabdff1aSopenharmony_ci p += 2; 95cabdff1aSopenharmony_ci 96cabdff1aSopenharmony_ci av_assert0(p - vt_extradata == vt_extradata_size); 97cabdff1aSopenharmony_ci 98cabdff1aSopenharmony_ci data = CFDataCreate(kCFAllocatorDefault, vt_extradata, vt_extradata_size); 99cabdff1aSopenharmony_ci av_free(vt_extradata); 100cabdff1aSopenharmony_ci return data; 101cabdff1aSopenharmony_ci} 102cabdff1aSopenharmony_ci 103cabdff1aSopenharmony_cistatic int videotoolbox_vp9_start_frame(AVCodecContext *avctx, 104cabdff1aSopenharmony_ci const uint8_t *buffer, 105cabdff1aSopenharmony_ci uint32_t size) 106cabdff1aSopenharmony_ci{ 107cabdff1aSopenharmony_ci return 0; 108cabdff1aSopenharmony_ci} 109cabdff1aSopenharmony_ci 110cabdff1aSopenharmony_cistatic int videotoolbox_vp9_decode_slice(AVCodecContext *avctx, 111cabdff1aSopenharmony_ci const uint8_t *buffer, 112cabdff1aSopenharmony_ci uint32_t size) 113cabdff1aSopenharmony_ci{ 114cabdff1aSopenharmony_ci VTContext *vtctx = avctx->internal->hwaccel_priv_data; 115cabdff1aSopenharmony_ci 116cabdff1aSopenharmony_ci return ff_videotoolbox_buffer_copy(vtctx, buffer, size); 117cabdff1aSopenharmony_ci} 118cabdff1aSopenharmony_ci 119cabdff1aSopenharmony_cistatic int videotoolbox_vp9_end_frame(AVCodecContext *avctx) 120cabdff1aSopenharmony_ci{ 121cabdff1aSopenharmony_ci const VP9SharedContext *h = avctx->priv_data; 122cabdff1aSopenharmony_ci AVFrame *frame = h->frames[CUR_FRAME].tf.f; 123cabdff1aSopenharmony_ci 124cabdff1aSopenharmony_ci return ff_videotoolbox_common_end_frame(avctx, frame); 125cabdff1aSopenharmony_ci} 126cabdff1aSopenharmony_ci 127cabdff1aSopenharmony_ciconst AVHWAccel ff_vp9_videotoolbox_hwaccel = { 128cabdff1aSopenharmony_ci .name = "vp9_videotoolbox", 129cabdff1aSopenharmony_ci .type = AVMEDIA_TYPE_VIDEO, 130cabdff1aSopenharmony_ci .id = AV_CODEC_ID_VP9, 131cabdff1aSopenharmony_ci .pix_fmt = AV_PIX_FMT_VIDEOTOOLBOX, 132cabdff1aSopenharmony_ci .alloc_frame = ff_videotoolbox_alloc_frame, 133cabdff1aSopenharmony_ci .start_frame = videotoolbox_vp9_start_frame, 134cabdff1aSopenharmony_ci .decode_slice = videotoolbox_vp9_decode_slice, 135cabdff1aSopenharmony_ci .end_frame = videotoolbox_vp9_end_frame, 136cabdff1aSopenharmony_ci .frame_params = ff_videotoolbox_frame_params, 137cabdff1aSopenharmony_ci .init = ff_videotoolbox_common_init, 138cabdff1aSopenharmony_ci .uninit = ff_videotoolbox_uninit, 139cabdff1aSopenharmony_ci .priv_data_size = sizeof(VTContext), 140cabdff1aSopenharmony_ci}; 141