2 * VP9 HW decode acceleration through NVDEC
4 * Copyright (c) 2016 Timo Rothenpieler
6 * This file is part of FFmpeg.
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.
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.
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
23 #include "libavutil/pixdesc.h"
28 #include "hwaccel_internal.h"
30 #include "vp9shared.h"
32 static int nvdec_vp9_start_frame(AVCodecContext
*avctx
, const uint8_t *buffer
, uint32_t size
)
34 VP9SharedContext
*h
= avctx
->priv_data
;
35 const AVPixFmtDescriptor
*pixdesc
= av_pix_fmt_desc_get(avctx
->sw_pix_fmt
);
37 NVDECContext
*ctx
= avctx
->internal
->hwaccel_priv_data
;
38 CUVIDPICPARAMS
*pp
= &ctx
->pic_params
;
39 CUVIDVP9PICPARAMS
*ppc
= &pp
->CodecSpecific
.vp9
;
42 AVFrame
*cur_frame
= h
->frames
[CUR_FRAME
].tf
.f
;
46 ret
= ff_nvdec_start_frame(avctx
, cur_frame
);
50 fdd
= (FrameDecodeData
*)cur_frame
->private_ref
->data
;
51 cf
= (NVDECFrame
*)fdd
->hwaccel_priv
;
53 *pp
= (CUVIDPICPARAMS
) {
54 .PicWidthInMbs
= (cur_frame
->width
+ 15) / 16,
55 .FrameHeightInMbs
= (cur_frame
->height
+ 15) / 16,
56 .CurrPicIdx
= cf
->idx
,
58 .CodecSpecific
.vp9
= {
59 .width
= cur_frame
->width
,
60 .height
= cur_frame
->height
,
62 .LastRefIdx
= ff_nvdec_get_ref_idx(h
->refs
[h
->h
.refidx
[0]].f
),
63 .GoldenRefIdx
= ff_nvdec_get_ref_idx(h
->refs
[h
->h
.refidx
[1]].f
),
64 .AltRefIdx
= ff_nvdec_get_ref_idx(h
->refs
[h
->h
.refidx
[2]].f
),
66 .profile
= h
->h
.profile
,
67 .frameContextIdx
= h
->h
.framectxid
,
68 .frameType
= !h
->h
.keyframe
,
69 .showFrame
= !h
->h
.invisible
,
70 .errorResilient
= h
->h
.errorres
,
71 .frameParallelDecoding
= h
->h
.parallelmode
,
72 .subSamplingX
= pixdesc
->log2_chroma_w
,
73 .subSamplingY
= pixdesc
->log2_chroma_h
,
74 .intraOnly
= h
->h
.intraonly
,
75 .allow_high_precision_mv
= h
->h
.keyframe
? 0 : h
->h
.highprecisionmvs
,
76 .refreshEntropyProbs
= h
->h
.refreshctx
,
78 .bitDepthMinus8Luma
= pixdesc
->comp
[0].depth
- 8,
79 .bitDepthMinus8Chroma
= pixdesc
->comp
[1].depth
- 8,
81 .loopFilterLevel
= h
->h
.filter
.level
,
82 .loopFilterSharpness
= h
->h
.filter
.sharpness
,
83 .modeRefLfEnabled
= h
->h
.lf_delta
.enabled
,
85 .log2_tile_columns
= h
->h
.tiling
.log2_tile_cols
,
86 .log2_tile_rows
= h
->h
.tiling
.log2_tile_rows
,
88 .segmentEnabled
= h
->h
.segmentation
.enabled
,
89 .segmentMapUpdate
= h
->h
.segmentation
.update_map
,
90 .segmentMapTemporalUpdate
= h
->h
.segmentation
.temporal
,
91 .segmentFeatureMode
= h
->h
.segmentation
.absolute_vals
,
94 .qpYDc
= h
->h
.ydc_qdelta
,
95 .qpChDc
= h
->h
.uvdc_qdelta
,
96 .qpChAc
= h
->h
.uvac_qdelta
,
98 .resetFrameContext
= h
->h
.resetctx
,
99 .mcomp_filter_type
= h
->h
.filtermode
^ (h
->h
.filtermode
<= 1),
101 .frameTagSize
= h
->h
.uncompressed_header_size
,
102 .offsetToDctParts
= h
->h
.compressed_header_size
,
104 .refFrameSignBias
[0] = 0,
108 for (i
= 0; i
< 2; i
++)
109 ppc
->mbModeLfDelta
[i
] = h
->h
.lf_delta
.mode
[i
];
111 for (i
= 0; i
< 4; i
++)
112 ppc
->mbRefLfDelta
[i
] = h
->h
.lf_delta
.ref
[i
];
114 for (i
= 0; i
< 7; i
++)
115 ppc
->mb_segment_tree_probs
[i
] = h
->h
.segmentation
.prob
[i
];
117 for (i
= 0; i
< 3; i
++) {
118 ppc
->activeRefIdx
[i
] = h
->h
.refidx
[i
];
119 ppc
->segment_pred_probs
[i
] = h
->h
.segmentation
.pred_prob
[i
];
120 ppc
->refFrameSignBias
[i
+ 1] = h
->h
.signbias
[i
];
123 for (i
= 0; i
< 8; i
++) {
124 ppc
->segmentFeatureEnable
[i
][0] = h
->h
.segmentation
.feat
[i
].q_enabled
;
125 ppc
->segmentFeatureEnable
[i
][1] = h
->h
.segmentation
.feat
[i
].lf_enabled
;
126 ppc
->segmentFeatureEnable
[i
][2] = h
->h
.segmentation
.feat
[i
].ref_enabled
;
127 ppc
->segmentFeatureEnable
[i
][3] = h
->h
.segmentation
.feat
[i
].skip_enabled
;
129 ppc
->segmentFeatureData
[i
][0] = h
->h
.segmentation
.feat
[i
].q_val
;
130 ppc
->segmentFeatureData
[i
][1] = h
->h
.segmentation
.feat
[i
].lf_val
;
131 ppc
->segmentFeatureData
[i
][2] = h
->h
.segmentation
.feat
[i
].ref_val
;
132 ppc
->segmentFeatureData
[i
][3] = 0;
135 switch (avctx
->colorspace
) {
137 case AVCOL_SPC_UNSPECIFIED
:
140 case AVCOL_SPC_BT470BG
:
143 case AVCOL_SPC_BT709
:
146 case AVCOL_SPC_SMPTE170M
:
149 case AVCOL_SPC_SMPTE240M
:
152 case AVCOL_SPC_BT2020_NCL
:
155 case AVCOL_SPC_RESERVED
:
166 static int nvdec_vp9_frame_params(AVCodecContext
*avctx
,
167 AVBufferRef
*hw_frames_ctx
)
169 // VP9 uses a fixed size pool of 8 possible reference frames
170 return ff_nvdec_frame_params(avctx
, hw_frames_ctx
, 8, 0);
173 const FFHWAccel ff_vp9_nvdec_hwaccel
= {
174 .p
.name
= "vp9_nvdec",
175 .p
.type
= AVMEDIA_TYPE_VIDEO
,
176 .p
.id
= AV_CODEC_ID_VP9
,
177 .p
.pix_fmt
= AV_PIX_FMT_CUDA
,
178 .start_frame
= nvdec_vp9_start_frame
,
179 .end_frame
= ff_nvdec_simple_end_frame
,
180 .decode_slice
= ff_nvdec_simple_decode_slice
,
181 .frame_params
= nvdec_vp9_frame_params
,
182 .init
= ff_nvdec_decode_init
,
183 .uninit
= ff_nvdec_decode_uninit
,
184 .priv_data_size
= sizeof(NVDECContext
),