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