1/* 2 * Videotoolbox hardware acceleration for VP9 3 * 4 * copyright (c) 2021 rcombs 5 * 6 * This file is part of FFmpeg. 7 * 8 * FFmpeg is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU Lesser General Public 10 * License as published by the Free Software Foundation; either 11 * version 2.1 of the License, or (at your option) any later version. 12 * 13 * FFmpeg is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * Lesser General Public License for more details. 17 * 18 * You should have received a copy of the GNU Lesser General Public 19 * License along with FFmpeg; if not, write to the Free Software 20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 21 */ 22 23#include "config.h" 24#include "videotoolbox.h" 25#include "libavutil/hwcontext_videotoolbox.h" 26#include "vt_internal.h" 27#include "libavutil/avutil.h" 28#include "libavutil/frame.h" 29#include "libavutil/hwcontext.h" 30#include "libavutil/intreadwrite.h" 31#include "libavutil/pixdesc.h" 32#include "decode.h" 33#include "internal.h" 34#include "vp9shared.h" 35 36enum VPX_CHROMA_SUBSAMPLING 37{ 38 VPX_SUBSAMPLING_420_VERTICAL = 0, 39 VPX_SUBSAMPLING_420_COLLOCATED_WITH_LUMA = 1, 40 VPX_SUBSAMPLING_422 = 2, 41 VPX_SUBSAMPLING_444 = 3, 42}; 43 44static int get_vpx_chroma_subsampling(enum AVPixelFormat pixel_format, 45 enum AVChromaLocation chroma_location) 46{ 47 int chroma_w, chroma_h; 48 if (av_pix_fmt_get_chroma_sub_sample(pixel_format, &chroma_w, &chroma_h) == 0) { 49 if (chroma_w == 1 && chroma_h == 1) { 50 return (chroma_location == AVCHROMA_LOC_LEFT) 51 ? VPX_SUBSAMPLING_420_VERTICAL 52 : VPX_SUBSAMPLING_420_COLLOCATED_WITH_LUMA; 53 } else if (chroma_w == 1 && chroma_h == 0) { 54 return VPX_SUBSAMPLING_422; 55 } else if (chroma_w == 0 && chroma_h == 0) { 56 return VPX_SUBSAMPLING_444; 57 } 58 } 59 return -1; 60} 61 62CFDataRef ff_videotoolbox_vpcc_extradata_create(AVCodecContext *avctx) 63{ 64 const VP9SharedContext *h = avctx->priv_data; 65 CFDataRef data = NULL; 66 uint8_t *p; 67 int vt_extradata_size; 68 uint8_t *vt_extradata; 69 int subsampling = get_vpx_chroma_subsampling(avctx->sw_pix_fmt, avctx->chroma_sample_location); 70 71 vt_extradata_size = 1 + 3 + 6 + 2; 72 vt_extradata = av_malloc(vt_extradata_size); 73 74 if (subsampling < 0) 75 return NULL; 76 77 if (!vt_extradata) 78 return NULL; 79 80 p = vt_extradata; 81 82 *p++ = 1; /* version */ 83 AV_WB24(p + 1, 0); /* flags */ 84 p += 3; 85 86 *p++ = h->h.profile; 87 *p++ = avctx->level; 88 *p++ = (h->h.bpp << 4) | (subsampling << 1) | (avctx->color_range == AVCOL_RANGE_JPEG); 89 *p++ = avctx->color_primaries; 90 *p++ = avctx->color_trc; 91 *p++ = avctx->colorspace; 92 93 AV_WB16(p + 0, 0); 94 p += 2; 95 96 av_assert0(p - vt_extradata == vt_extradata_size); 97 98 data = CFDataCreate(kCFAllocatorDefault, vt_extradata, vt_extradata_size); 99 av_free(vt_extradata); 100 return data; 101} 102 103static int videotoolbox_vp9_start_frame(AVCodecContext *avctx, 104 const uint8_t *buffer, 105 uint32_t size) 106{ 107 return 0; 108} 109 110static int videotoolbox_vp9_decode_slice(AVCodecContext *avctx, 111 const uint8_t *buffer, 112 uint32_t size) 113{ 114 VTContext *vtctx = avctx->internal->hwaccel_priv_data; 115 116 return ff_videotoolbox_buffer_copy(vtctx, buffer, size); 117} 118 119static int videotoolbox_vp9_end_frame(AVCodecContext *avctx) 120{ 121 const VP9SharedContext *h = avctx->priv_data; 122 AVFrame *frame = h->frames[CUR_FRAME].tf.f; 123 124 return ff_videotoolbox_common_end_frame(avctx, frame); 125} 126 127const AVHWAccel ff_vp9_videotoolbox_hwaccel = { 128 .name = "vp9_videotoolbox", 129 .type = AVMEDIA_TYPE_VIDEO, 130 .id = AV_CODEC_ID_VP9, 131 .pix_fmt = AV_PIX_FMT_VIDEOTOOLBOX, 132 .alloc_frame = ff_videotoolbox_alloc_frame, 133 .start_frame = videotoolbox_vp9_start_frame, 134 .decode_slice = videotoolbox_vp9_decode_slice, 135 .end_frame = videotoolbox_vp9_end_frame, 136 .frame_params = ff_videotoolbox_frame_params, 137 .init = ff_videotoolbox_common_init, 138 .uninit = ff_videotoolbox_uninit, 139 .priv_data_size = sizeof(VTContext), 140}; 141