FFmpeg
Loading...
Searching...
No Matches
nvdec_h264.c
Go to the documentation of this file.
1/*
2 * MPEG-4 Part 10 / AVC / H.264 HW decode acceleration through NVDEC
3 *
4 * Copyright (c) 2016 Anton Khirnov
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_components.h"
24
25#include <stdint.h>
26#include <string.h>
27
28#include "libavutil/mem.h"
29#include "avcodec.h"
30#include "nvdec.h"
31#include "decode.h"
32#include "internal.h"
33#include "h264dec.h"
34#include "hwaccel_internal.h"
35
36static void dpb_add(const H264Context *h, CUVIDH264DPBENTRY *dst, const H264Picture *src,
37 int frame_idx)
38{
39 FrameDecodeData *fdd = src->f->private_ref;
40 const NVDECFrame *cf = fdd->hwaccel_priv;
41
42 dst->PicIdx = cf ? cf->idx : -1;
43 dst->FrameIdx = frame_idx;
44 dst->is_long_term = src->long_ref;
45 dst->not_existing = 0;
46 dst->used_for_reference = src->reference & 3;
47 dst->FieldOrderCnt[0] = src->field_poc[0];
48 dst->FieldOrderCnt[1] = src->field_poc[1];
49}
50
52 const AVBufferRef *buffer_ref,
53 const uint8_t *buffer, uint32_t size)
54{
55 const H264Context *h = avctx->priv_data;
56 const PPS *pps = h->ps.pps;
57 const SPS *sps = h->ps.sps;
58
60 CUVIDPICPARAMS *pp = &ctx->pic_params;
61 CUVIDH264PICPARAMS *ppc = &pp->CodecSpecific.h264;
62 FrameDecodeData *fdd;
63 NVDECFrame *cf;
64
65 int i, dpb_size, ret;
66
67 ret = ff_nvdec_start_frame(avctx, h->cur_pic_ptr->f);
68 if (ret < 0)
69 return ret;
70
71 fdd = h->cur_pic_ptr->f->private_ref;
72 cf = (NVDECFrame*)fdd->hwaccel_priv;
73
74 *pp = (CUVIDPICPARAMS) {
75 .PicWidthInMbs = h->mb_width,
76 .FrameHeightInMbs = h->mb_height,
77 .CurrPicIdx = cf->idx,
78 .field_pic_flag = FIELD_PICTURE(h),
79 .bottom_field_flag = h->picture_structure == PICT_BOTTOM_FIELD,
80 .second_field = FIELD_PICTURE(h) && !h->first_field,
81 .ref_pic_flag = h->nal_ref_idc != 0,
82 .intra_pic_flag = 1,
83
84 .CodecSpecific.h264 = {
85 .log2_max_frame_num_minus4 = sps->log2_max_frame_num - 4,
86 .pic_order_cnt_type = sps->poc_type,
87 .log2_max_pic_order_cnt_lsb_minus4 = FFMAX(sps->log2_max_poc_lsb - 4, 0),
88 .delta_pic_order_always_zero_flag = sps->delta_pic_order_always_zero_flag,
89 .frame_mbs_only_flag = sps->frame_mbs_only_flag,
90 .direct_8x8_inference_flag = sps->direct_8x8_inference_flag,
91 .num_ref_frames = sps->ref_frame_count,
92 .residual_colour_transform_flag = sps->residual_color_transform_flag,
93 .bit_depth_luma_minus8 = sps->bit_depth_luma - 8,
94 .bit_depth_chroma_minus8 = sps->bit_depth_chroma - 8,
95 .qpprime_y_zero_transform_bypass_flag = sps->transform_bypass,
96
97 .entropy_coding_mode_flag = pps->cabac,
98 .pic_order_present_flag = pps->pic_order_present,
99 .num_ref_idx_l0_active_minus1 = pps->ref_count[0] - 1,
100 .num_ref_idx_l1_active_minus1 = pps->ref_count[1] - 1,
101 .weighted_pred_flag = pps->weighted_pred,
102 .weighted_bipred_idc = pps->weighted_bipred_idc,
103 .pic_init_qp_minus26 = pps->init_qp - 26 - 6 * (sps->bit_depth_luma - 8),
104 .deblocking_filter_control_present_flag = pps->deblocking_filter_parameters_present,
105 .redundant_pic_cnt_present_flag = pps->redundant_pic_cnt_present,
106 .transform_8x8_mode_flag = pps->transform_8x8_mode,
107 .MbaffFrameFlag = sps->mb_aff && !FIELD_PICTURE(h),
108 .constrained_intra_pred_flag = pps->constrained_intra_pred,
109 .chroma_qp_index_offset = pps->chroma_qp_index_offset[0],
110 .second_chroma_qp_index_offset = pps->chroma_qp_index_offset[1],
111 .ref_pic_flag = h->nal_ref_idc != 0,
112 .frame_num = h->poc.frame_num,
113 .CurrFieldOrderCnt[0] = h->cur_pic_ptr->field_poc[0],
114 .CurrFieldOrderCnt[1] = h->cur_pic_ptr->field_poc[1],
115 },
116 };
117
118 memcpy(ppc->WeightScale4x4, pps->scaling_matrix4, sizeof(ppc->WeightScale4x4));
119 memcpy(ppc->WeightScale8x8[0], pps->scaling_matrix8[0], sizeof(ppc->WeightScale8x8[0]));
120 memcpy(ppc->WeightScale8x8[1], pps->scaling_matrix8[3], sizeof(ppc->WeightScale8x8[0]));
121
122 dpb_size = 0;
123 for (i = 0; i < h->short_ref_count; i++)
124 dpb_add(h, &ppc->dpb[dpb_size++], h->short_ref[i], h->short_ref[i]->frame_num);
125 for (i = 0; i < 16; i++) {
126 if (h->long_ref[i])
127 dpb_add(h, &ppc->dpb[dpb_size++], h->long_ref[i], i);
128 }
129
130 for (i = dpb_size; i < FF_ARRAY_ELEMS(ppc->dpb); i++)
131 ppc->dpb[i].PicIdx = -1;
132
133 return 0;
134}
135
136static int nvdec_h264_decode_slice(AVCodecContext *avctx, const uint8_t *buffer,
137 uint32_t size)
138{
140 CUVIDPICPARAMS *pp = &ctx->pic_params;
141 const H264Context *h = avctx->priv_data;
142 const H264SliceContext *sl = &h->slice_ctx[0];
143 void *tmp;
144
145 tmp = av_fast_realloc(ctx->bitstream_internal, &ctx->bitstream_allocated,
146 ctx->bitstream_len + size + 3);
147 if (!tmp)
148 return AVERROR(ENOMEM);
149 ctx->bitstream = ctx->bitstream_internal = tmp;
150
151 tmp = av_fast_realloc(ctx->slice_offsets, &ctx->slice_offsets_allocated,
152 (ctx->nb_slices + 1) * sizeof(*ctx->slice_offsets));
153 if (!tmp)
154 return AVERROR(ENOMEM);
155 ctx->slice_offsets = tmp;
156
157 AV_WB24(ctx->bitstream_internal + ctx->bitstream_len, 1);
158 memcpy(ctx->bitstream_internal + ctx->bitstream_len + 3, buffer, size);
159 ctx->slice_offsets[ctx->nb_slices] = ctx->bitstream_len ;
160 ctx->bitstream_len += size + 3;
161 ctx->nb_slices++;
162
164 pp->intra_pic_flag = 0;
165
166 return 0;
167}
168
170 AVBufferRef *hw_frames_ctx,
171 enum AVPixelFormat hw_format)
172{
173 const H264Context *h = avctx->priv_data;
174 const SPS *sps = h->ps.sps;
175 return ff_nvdec_frame_params(avctx, hw_frames_ctx, hw_format,
176 sps->ref_frame_count + sps->num_reorder_frames, 0);
177}
178
179#if CONFIG_H264_NVDEC_HWACCEL
180static int nvdec_h264_cuda_frame_params(AVCodecContext *avctx,
181 AVBufferRef *hw_frames_ctx)
182{
183 return nvdec_h264_frame_params(avctx, hw_frames_ctx, AV_PIX_FMT_CUDA);
184}
185
187 .p.name = "h264_nvdec",
188 .p.type = AVMEDIA_TYPE_VIDEO,
189 .p.id = AV_CODEC_ID_H264,
190 .p.pix_fmt = AV_PIX_FMT_CUDA,
191 .start_frame = nvdec_h264_start_frame,
192 .end_frame = ff_nvdec_end_frame,
193 .decode_slice = nvdec_h264_decode_slice,
194 .frame_params = nvdec_h264_cuda_frame_params,
195 .init = ff_nvdec_decode_init,
196 .uninit = ff_nvdec_decode_uninit,
197 .priv_data_size = sizeof(NVDECContext),
198};
199#endif
200
201#if CONFIG_H264_NVDEC_CUARRAY_HWACCEL
202static int nvdec_h264_cuarray_frame_params(AVCodecContext *avctx,
203 AVBufferRef *hw_frames_ctx)
204{
205 return nvdec_h264_frame_params(avctx, hw_frames_ctx, AV_PIX_FMT_CUARRAY);
206}
207
209 .p.name = "h264_nvdec_cuarray",
210 .p.type = AVMEDIA_TYPE_VIDEO,
211 .p.id = AV_CODEC_ID_H264,
212 .p.pix_fmt = AV_PIX_FMT_CUARRAY,
213 .start_frame = nvdec_h264_start_frame,
214 .end_frame = ff_nvdec_end_frame,
215 .decode_slice = nvdec_h264_decode_slice,
216 .frame_params = nvdec_h264_cuarray_frame_params,
217 .init = ff_nvdec_decode_init,
218 .uninit = ff_nvdec_decode_uninit,
219 .priv_data_size = sizeof(NVDECContext),
220};
221#endif
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition dsp.h:87
static AVFormatContext * ctx
Libavcodec external API header.
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
static int FUNC sps(CodedBitstreamContext *ctx, RWContext *rw, H264RawSPS *current)
uint64_t pps
Definition dovi_rpuenc.c:36
@ AV_CODEC_ID_H264
Definition codec_id.h:77
#define AVERROR(e)
Definition error.h:45
void * av_fast_realloc(void *ptr, unsigned int *size, size_t min_size)
Reallocate the given buffer if it is not large enough, otherwise do nothing.
Definition mem.c:495
@ AVMEDIA_TYPE_VIDEO
Definition avutil.h:200
@ AV_PICTURE_TYPE_I
Intra.
Definition avutil.h:278
@ AV_PICTURE_TYPE_SI
Switching Intra.
Definition avutil.h:282
H.264 / AVC / MPEG-4 part10 codec.
#define FIELD_PICTURE(h)
Definition h264dec.h:65
const struct FFHWAccel ff_h264_nvdec_hwaccel
const struct FFHWAccel ff_h264_nvdec_cuarray_hwaccel
#define AV_WB24(p, d)
common internal api header.
#define FFMAX(a, b)
Definition macros.h:47
Memory handling functions.
#define PICT_BOTTOM_FIELD
Definition mpegutils.h:32
int ff_nvdec_decode_init(AVCodecContext *avctx)
Definition nvdec.c:404
int ff_nvdec_end_frame(AVCodecContext *avctx)
Definition nvdec.c:1014
int ff_nvdec_start_frame(AVCodecContext *avctx, AVFrame *frame)
Definition nvdec.c:946
int ff_nvdec_decode_uninit(AVCodecContext *avctx)
Definition nvdec.c:297
int ff_nvdec_frame_params(AVCodecContext *avctx, AVBufferRef *hw_frames_ctx, enum AVPixelFormat hw_format, int dpb_size, int supports_444)
Definition nvdec.c:1083
static int nvdec_h264_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size)
Definition nvdec_h264.c:136
static void dpb_add(const H264Context *h, CUVIDH264DPBENTRY *dst, const H264Picture *src, int frame_idx)
Definition nvdec_h264.c:36
static int nvdec_h264_frame_params(AVCodecContext *avctx, AVBufferRef *hw_frames_ctx, enum AVPixelFormat hw_format)
Definition nvdec_h264.c:169
static int nvdec_h264_start_frame(AVCodecContext *avctx, const AVBufferRef *buffer_ref, const uint8_t *buffer, uint32_t size)
Definition nvdec_h264.c:51
AVPixelFormat
Pixel format.
Definition pixfmt.h:71
@ AV_PIX_FMT_CUDA
HW acceleration through CUDA.
Definition pixfmt.h:260
@ AV_PIX_FMT_CUARRAY
hardware decoding through openharmony
Definition pixfmt.h:506
#define FF_ARRAY_ELEMS(a)
A reference to a data buffer.
Definition buffer.h:82
main external API structure.
Definition avcodec.h:443
struct AVCodecInternal * internal
Private context used for internal data.
Definition avcodec.h:478
void * priv_data
Definition avcodec.h:470
void * hwaccel_priv_data
hwaccel-specific private data
Definition internal.h:130
This struct stores per-frame lavc-internal data and is attached to it via private_ref.
Definition decode.h:33
void * hwaccel_priv
Definition decode.h:54
H264Context.
Definition h264dec.h:338
unsigned int idx
Definition nvdec.h:55
Picture parameter set.
Definition h264_ps.h:110
Sequence parameter set.
Definition h264_ps.h:44
static uint8_t tmp[40]
Definition aes_ctr.c:52
#define src
Definition vp8dsp.c:248
int dpb_size
static char buffer[20]
Definition seek.c:32
int size