mirror of https://github.com/FFmpeg/FFmpeg.git
On M1 Max, this supports profiles 0 and 2, but not 1 and 3.pull/375/head
parent
e3c6cc96cf
commit
a41a2efc85
8 changed files with 171 additions and 3 deletions
@ -0,0 +1,140 @@ |
|||||||
|
/*
|
||||||
|
* Videotoolbox hardware acceleration for VP9 |
||||||
|
* |
||||||
|
* copyright (c) 2021 rcombs |
||||||
|
* |
||||||
|
* This file is part of FFmpeg. |
||||||
|
* |
||||||
|
* FFmpeg is free software; you can redistribute it and/or |
||||||
|
* modify it under the terms of the GNU Lesser General Public |
||||||
|
* License as published by the Free Software Foundation; either |
||||||
|
* version 2.1 of the License, or (at your option) any later version. |
||||||
|
* |
||||||
|
* FFmpeg is distributed in the hope that it will be useful, |
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||||
|
* Lesser General Public License for more details. |
||||||
|
* |
||||||
|
* You should have received a copy of the GNU Lesser General Public |
||||||
|
* License along with FFmpeg; if not, write to the Free Software |
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
||||||
|
*/ |
||||||
|
|
||||||
|
#include "config.h" |
||||||
|
#include "videotoolbox.h" |
||||||
|
#include "libavutil/hwcontext_videotoolbox.h" |
||||||
|
#include "vt_internal.h" |
||||||
|
#include "libavutil/avutil.h" |
||||||
|
#include "libavutil/frame.h" |
||||||
|
#include "libavutil/hwcontext.h" |
||||||
|
#include "libavutil/intreadwrite.h" |
||||||
|
#include "libavutil/pixdesc.h" |
||||||
|
#include "decode.h" |
||||||
|
#include "internal.h" |
||||||
|
#include "vp9shared.h" |
||||||
|
|
||||||
|
enum VPX_CHROMA_SUBSAMPLING |
||||||
|
{ |
||||||
|
VPX_SUBSAMPLING_420_VERTICAL = 0, |
||||||
|
VPX_SUBSAMPLING_420_COLLOCATED_WITH_LUMA = 1, |
||||||
|
VPX_SUBSAMPLING_422 = 2, |
||||||
|
VPX_SUBSAMPLING_444 = 3, |
||||||
|
}; |
||||||
|
|
||||||
|
static int get_vpx_chroma_subsampling(enum AVPixelFormat pixel_format, |
||||||
|
enum AVChromaLocation chroma_location) |
||||||
|
{ |
||||||
|
int chroma_w, chroma_h; |
||||||
|
if (av_pix_fmt_get_chroma_sub_sample(pixel_format, &chroma_w, &chroma_h) == 0) { |
||||||
|
if (chroma_w == 1 && chroma_h == 1) { |
||||||
|
return (chroma_location == AVCHROMA_LOC_LEFT) |
||||||
|
? VPX_SUBSAMPLING_420_VERTICAL |
||||||
|
: VPX_SUBSAMPLING_420_COLLOCATED_WITH_LUMA; |
||||||
|
} else if (chroma_w == 1 && chroma_h == 0) { |
||||||
|
return VPX_SUBSAMPLING_422; |
||||||
|
} else if (chroma_w == 0 && chroma_h == 0) { |
||||||
|
return VPX_SUBSAMPLING_444; |
||||||
|
} |
||||||
|
} |
||||||
|
return -1; |
||||||
|
} |
||||||
|
|
||||||
|
CFDataRef ff_videotoolbox_vpcc_extradata_create(AVCodecContext *avctx) |
||||||
|
{ |
||||||
|
const VP9SharedContext *h = avctx->priv_data; |
||||||
|
CFDataRef data = NULL; |
||||||
|
uint8_t *p; |
||||||
|
int vt_extradata_size; |
||||||
|
uint8_t *vt_extradata; |
||||||
|
int subsampling = get_vpx_chroma_subsampling(avctx->sw_pix_fmt, avctx->chroma_sample_location); |
||||||
|
|
||||||
|
vt_extradata_size = 1 + 3 + 6 + 2; |
||||||
|
vt_extradata = av_malloc(vt_extradata_size); |
||||||
|
|
||||||
|
if (subsampling < 0) |
||||||
|
return NULL; |
||||||
|
|
||||||
|
if (!vt_extradata) |
||||||
|
return NULL; |
||||||
|
|
||||||
|
p = vt_extradata; |
||||||
|
|
||||||
|
*p++ = 1; /* version */ |
||||||
|
AV_WB24(p + 1, 0); /* flags */ |
||||||
|
p += 3; |
||||||
|
|
||||||
|
*p++ = h->h.profile; |
||||||
|
*p++ = avctx->level; |
||||||
|
*p++ = (h->h.bpp << 4) | (subsampling << 1) | (avctx->color_range == AVCOL_RANGE_JPEG); |
||||||
|
*p++ = avctx->color_primaries; |
||||||
|
*p++ = avctx->color_trc; |
||||||
|
*p++ = avctx->colorspace; |
||||||
|
|
||||||
|
AV_WB16(p + 0, 0); |
||||||
|
p += 2; |
||||||
|
|
||||||
|
av_assert0(p - vt_extradata == vt_extradata_size); |
||||||
|
|
||||||
|
data = CFDataCreate(kCFAllocatorDefault, vt_extradata, vt_extradata_size); |
||||||
|
av_free(vt_extradata); |
||||||
|
return data; |
||||||
|
} |
||||||
|
|
||||||
|
static int videotoolbox_vp9_start_frame(AVCodecContext *avctx, |
||||||
|
const uint8_t *buffer, |
||||||
|
uint32_t size) |
||||||
|
{ |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
static int videotoolbox_vp9_decode_slice(AVCodecContext *avctx, |
||||||
|
const uint8_t *buffer, |
||||||
|
uint32_t size) |
||||||
|
{ |
||||||
|
VTContext *vtctx = avctx->internal->hwaccel_priv_data; |
||||||
|
|
||||||
|
return ff_videotoolbox_buffer_copy(vtctx, buffer, size); |
||||||
|
} |
||||||
|
|
||||||
|
static int videotoolbox_vp9_end_frame(AVCodecContext *avctx) |
||||||
|
{ |
||||||
|
const VP9SharedContext *h = avctx->priv_data; |
||||||
|
AVFrame *frame = h->frames[CUR_FRAME].tf.f; |
||||||
|
|
||||||
|
return ff_videotoolbox_common_end_frame(avctx, frame); |
||||||
|
} |
||||||
|
|
||||||
|
const AVHWAccel ff_vp9_videotoolbox_hwaccel = { |
||||||
|
.name = "vp9_videotoolbox", |
||||||
|
.type = AVMEDIA_TYPE_VIDEO, |
||||||
|
.id = AV_CODEC_ID_VP9, |
||||||
|
.pix_fmt = AV_PIX_FMT_VIDEOTOOLBOX, |
||||||
|
.alloc_frame = ff_videotoolbox_alloc_frame, |
||||||
|
.start_frame = videotoolbox_vp9_start_frame, |
||||||
|
.decode_slice = videotoolbox_vp9_decode_slice, |
||||||
|
.end_frame = videotoolbox_vp9_end_frame, |
||||||
|
.frame_params = ff_videotoolbox_frame_params, |
||||||
|
.init = ff_videotoolbox_common_init, |
||||||
|
.uninit = ff_videotoolbox_uninit, |
||||||
|
.priv_data_size = sizeof(VTContext), |
||||||
|
}; |
Loading…
Reference in new issue