FFmpeg
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
d3d12va_mpeg2.c
Go to the documentation of this file.
1 /*
2  * Direct3D12 MPEG-2 HW acceleration
3  *
4  * copyright (c) 2022-2023 Wu Jianhua <toqsxw@outlook.com>
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 #include "libavutil/avassert.h"
26 #include "mpegutils.h"
27 #include "mpegvideodec.h"
28 #include "d3d12va_decode.h"
29 #include "dxva2_internal.h"
30 
31 #define MAX_SLICES 1024
32 #define INVALID_REF 0xffff
33 
34 typedef struct D3D12DecodePictureContext {
35  DXVA_PictureParameters pp;
36  DXVA_QmatrixData qm;
37  unsigned slice_count;
38  DXVA_SliceInfo slices[MAX_SLICES];
39  const uint8_t *bitstream;
40  unsigned bitstream_size;
42 
44  av_unused const AVBufferRef *buffer_ref,
45  av_unused const uint8_t *buffer,
46  av_unused uint32_t size)
47 {
48  const MpegEncContext *s = avctx->priv_data;
50  D3D12DecodePictureContext *ctx_pic = s->cur_pic.ptr->hwaccel_picture_private;
51 
52  if (!ctx)
53  return -1;
54 
55  av_assert0(ctx_pic);
56 
57  ctx->used_mask = 0;
58 
61 
62  // Post processing operations are not supported in D3D12 Video
63  ctx_pic->pp.wDeblockedPictureIndex = INVALID_REF;
64 
65  ctx_pic->bitstream = NULL;
66  ctx_pic->bitstream_size = 0;
67  ctx_pic->slice_count = 0;
68 
69  return 0;
70 }
71 
72 static int d3d12va_mpeg2_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size)
73 {
74  const MpegEncContext *s = avctx->priv_data;
75  D3D12DecodePictureContext *ctx_pic = s->cur_pic.ptr->hwaccel_picture_private;
76 
77  if (ctx_pic->slice_count >= MAX_SLICES) {
78  return AVERROR(ERANGE);
79  }
80 
81  if (!ctx_pic->bitstream)
82  ctx_pic->bitstream = buffer;
83  ctx_pic->bitstream_size += size;
84 
85  ff_dxva2_mpeg2_fill_slice(avctx, &ctx_pic->slices[ctx_pic->slice_count++],
86  buffer - ctx_pic->bitstream, buffer, size);
87 
88  return 0;
89 }
90 
91 static int update_input_arguments(AVCodecContext *avctx, D3D12_VIDEO_DECODE_INPUT_STREAM_ARGUMENTS *input_args, ID3D12Resource *buffer)
92 {
93  const MpegEncContext *s = avctx->priv_data;
94  D3D12DecodePictureContext *ctx_pic = s->cur_pic.ptr->hwaccel_picture_private;
95 
96  const int is_field = s->picture_structure != PICT_FRAME;
97  const unsigned mb_count = s->mb_width * (s->mb_height >> is_field);
98 
99  int i;
100  void *mapped_data = NULL;
101  D3D12_VIDEO_DECODE_FRAME_ARGUMENT *args = &input_args->FrameArguments[input_args->NumFrameArguments++];
102 
103  D3D12_RANGE range = {
104  .Begin = 0,
105  .End = ctx_pic->bitstream_size,
106  };
107 
108  if (FAILED(ID3D12Resource_Map(buffer, 0, &range, &mapped_data))) {
109  av_log(avctx, AV_LOG_ERROR, "Failed to map D3D12 Buffer resource!\n");
110  return AVERROR(EINVAL);
111  }
112 
113  for (i = 0; i < ctx_pic->slice_count; i++) {
114  DXVA_SliceInfo *slice = &ctx_pic->slices[i];
115 
116  if (i < ctx_pic->slice_count - 1)
117  slice->wNumberMBsInSlice = slice[1].wNumberMBsInSlice - slice[0].wNumberMBsInSlice;
118  else
119  slice->wNumberMBsInSlice = mb_count - slice[0].wNumberMBsInSlice;
120  }
121 
122  memcpy(mapped_data, ctx_pic->bitstream, ctx_pic->bitstream_size);
123 
124  ID3D12Resource_Unmap(buffer, 0, &range);
125 
126  args->Type = D3D12_VIDEO_DECODE_ARGUMENT_TYPE_SLICE_CONTROL;
127  args->Size = sizeof(DXVA_SliceInfo) * ctx_pic->slice_count;
128  args->pData = ctx_pic->slices;
129 
130  input_args->CompressedBitstream = (D3D12_VIDEO_DECODE_COMPRESSED_BITSTREAM){
131  .pBuffer = buffer,
132  .Offset = 0,
133  .Size = ctx_pic->bitstream_size,
134  };
135 
136  return 0;
137 }
138 
140 {
141  int ret;
142  MpegEncContext *s = avctx->priv_data;
143  D3D12DecodePictureContext *ctx_pic = s->cur_pic.ptr->hwaccel_picture_private;
144 
145  if (ctx_pic->slice_count <= 0 || ctx_pic->bitstream_size <= 0)
146  return -1;
147 
148  ret = ff_d3d12va_common_end_frame(avctx, s->cur_pic.ptr->f, &ctx_pic->pp, sizeof(ctx_pic->pp),
149  &ctx_pic->qm, sizeof(ctx_pic->qm), update_input_arguments);
150  if (!ret)
151  ff_mpeg_draw_horiz_band(s, 0, avctx->height);
152 
153  return ret;
154 }
155 
157 {
159 
160  ctx->cfg.DecodeProfile = D3D12_VIDEO_DECODE_PROFILE_MPEG2;
161 
162  ctx->max_num_ref = 3;
163 
164  return ff_d3d12va_decode_init(avctx);
165 }
166 
167 #if CONFIG_MPEG2_D3D12VA_HWACCEL
169  .p.name = "mpeg2_d3d12va",
170  .p.type = AVMEDIA_TYPE_VIDEO,
171  .p.id = AV_CODEC_ID_MPEG2VIDEO,
172  .p.pix_fmt = AV_PIX_FMT_D3D12,
174  .uninit = ff_d3d12va_decode_uninit,
175  .start_frame = d3d12va_mpeg2_start_frame,
176  .decode_slice = d3d12va_mpeg2_decode_slice,
177  .end_frame = d3d12va_mpeg2_end_frame,
178  .frame_params = ff_d3d12va_common_frame_params,
179  .frame_priv_data_size = sizeof(D3D12DecodePictureContext),
180  .priv_data_size = sizeof(D3D12VADecodeContext),
181 };
182 #endif
PICT_FRAME
#define PICT_FRAME
Definition: mpegutils.h:33
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
MAX_SLICES
#define MAX_SLICES
Definition: d3d12va_mpeg2.c:31
D3D12DecodePictureContext::bitstream_size
unsigned bitstream_size
Definition: d3d12va_mpeg2.c:40
av_unused
#define av_unused
Definition: attributes.h:131
FFHWAccel::p
AVHWAccel p
The public AVHWAccel.
Definition: hwaccel_internal.h:38
d3d12va_mpeg2_start_frame
static int d3d12va_mpeg2_start_frame(AVCodecContext *avctx, av_unused const AVBufferRef *buffer_ref, av_unused const uint8_t *buffer, av_unused uint32_t size)
Definition: d3d12va_mpeg2.c:43
D3D12DecodePictureContext
Definition: d3d12va_mpeg2.c:34
d3d12va_mpeg2_decode_init
static av_cold int d3d12va_mpeg2_decode_init(AVCodecContext *avctx)
Definition: d3d12va_mpeg2.c:156
INVALID_REF
#define INVALID_REF
Definition: d3d12va_mpeg2.c:32
mpegutils.h
d3d12va_mpeg2_decode_slice
static int d3d12va_mpeg2_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size)
Definition: d3d12va_mpeg2.c:72
FFHWAccel
Definition: hwaccel_internal.h:34
ff_dxva2_mpeg2_fill_quantization_matrices
void ff_dxva2_mpeg2_fill_quantization_matrices(AVCodecContext *avctx, AVDXVAContext *ctx, DXVA_QmatrixData *qm)
Definition: dxva2_mpeg2.c:109
ff_dxva2_mpeg2_fill_picture_parameters
void ff_dxva2_mpeg2_fill_picture_parameters(AVCodecContext *avctx, AVDXVAContext *ctx, DXVA_PictureParameters *pp)
Definition: dxva2_mpeg2.c:43
avassert.h
mpegvideodec.h
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:209
av_cold
#define av_cold
Definition: attributes.h:90
s
#define s(width, name)
Definition: cbs_vp9.c:198
D3D12DecodePictureContext::slices
DXVA_SliceInfo slices[MAX_SLICES]
Definition: d3d12va_mpeg2.c:38
av_assert0
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:40
D3D12DecodePictureContext::pp
DXVA_PictureParameters pp
Definition: d3d12va_mpeg2.c:35
ctx
AVFormatContext * ctx
Definition: movenc.c:49
ff_d3d12va_common_frame_params
int ff_d3d12va_common_frame_params(AVCodecContext *avctx, AVBufferRef *hw_frames_ctx)
d3d12va common frame params
Definition: d3d12va_decode.c:271
dxva2_internal.h
NULL
#define NULL
Definition: coverity.c:32
ff_d3d12va_common_end_frame
int ff_d3d12va_common_end_frame(AVCodecContext *avctx, AVFrame *frame, const void *pp, unsigned pp_size, const void *qm, unsigned qm_size, int(*update_input_arguments)(AVCodecContext *, D3D12_VIDEO_DECODE_INPUT_STREAM_ARGUMENTS *, ID3D12Resource *))
d3d12va common end frame
Definition: d3d12va_decode.c:434
AV_PIX_FMT_D3D12
@ AV_PIX_FMT_D3D12
Hardware surfaces for Direct3D 12.
Definition: pixfmt.h:440
D3D12VA_DECODE_CONTEXT
#define D3D12VA_DECODE_CONTEXT(avctx)
Definition: d3d12va_decode.h:128
D3D12DecodePictureContext::slice_count
unsigned slice_count
Definition: d3d12va_mpeg2.c:37
d3d12va_mpeg2_end_frame
static int d3d12va_mpeg2_end_frame(AVCodecContext *avctx)
Definition: d3d12va_mpeg2.c:139
size
int size
Definition: twinvq_data.h:10344
update_input_arguments
static int update_input_arguments(AVCodecContext *avctx, D3D12_VIDEO_DECODE_INPUT_STREAM_ARGUMENTS *input_args, ID3D12Resource *buffer)
Definition: d3d12va_mpeg2.c:91
ff_mpeg_draw_horiz_band
void ff_mpeg_draw_horiz_band(MpegEncContext *s, int y, int h)
Definition: mpegvideo_dec.c:422
AVDXVAContext
Definition: dxva2_internal.h:74
range
enum AVColorRange range
Definition: mediacodec_wrapper.c:2594
ff_dxva2_mpeg2_fill_slice
void ff_dxva2_mpeg2_fill_slice(AVCodecContext *avctx, DXVA_SliceInfo *slice, unsigned position, const uint8_t *buffer, unsigned size)
Definition: dxva2_mpeg2.c:126
AVHWAccel::name
const char * name
Name of the hardware accelerated codec.
Definition: avcodec.h:2124
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
ff_d3d12va_decode_init
av_cold int ff_d3d12va_decode_init(AVCodecContext *avctx)
init D3D12VADecodeContext
Definition: d3d12va_decode.c:283
D3D12DecodePictureContext::qm
DXVA_QmatrixData qm
Definition: d3d12va_mpeg2.c:36
AVCodecContext::height
int height
Definition: avcodec.h:632
ret
ret
Definition: filter_design.txt:187
ff_mpeg2_d3d12va_hwaccel
const struct FFHWAccel ff_mpeg2_d3d12va_hwaccel
AVCodecContext
main external API structure.
Definition: avcodec.h:451
buffer
the frame and frame reference mechanism is intended to as much as expensive copies of that data while still allowing the filters to produce correct results The data is stored in buffers represented by AVFrame structures Several references can point to the same frame buffer
Definition: filter_design.txt:49
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
AVBufferRef
A reference to a data buffer.
Definition: buffer.h:82
D3D12VADecodeContext
This structure is used to provide the necessary configurations and data to the FFmpeg Direct3D 12 HWA...
Definition: d3d12va_decode.h:37
AVCodecContext::priv_data
void * priv_data
Definition: avcodec.h:478
ff_d3d12va_decode_uninit
av_cold int ff_d3d12va_decode_uninit(AVCodecContext *avctx)
uninit D3D12VADecodeContext
Definition: d3d12va_decode.c:373
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
hwcontext_d3d12va_internal.h
AV_CODEC_ID_MPEG2VIDEO
@ AV_CODEC_ID_MPEG2VIDEO
preferred ID for MPEG-1/2 video decoding
Definition: codec_id.h:54
MpegEncContext
MpegEncContext.
Definition: mpegvideo.h:73
D3D12DecodePictureContext::bitstream
const uint8_t * bitstream
Definition: d3d12va_mpeg2.c:39
d3d12va_decode.h