FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
dxva2.c
Go to the documentation of this file.
1 /*
2  * DXVA2 HW acceleration.
3  *
4  * copyright (c) 2010 Laurent Aimar
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 <assert.h>
24 #include <string.h>
25 
26 #include "libavutil/log.h"
27 #include "libavutil/time.h"
28 
29 #include "avcodec.h"
30 #include "dxva2_internal.h"
31 
33 {
34  return frame->data[3];
35 }
36 
38  const AVDXVAContext *ctx,
39  const AVFrame *frame)
40 {
41  void *surface = ff_dxva2_get_surface(frame);
42  unsigned i;
43 
44  for (i = 0; i < DXVA_CONTEXT_COUNT(avctx, ctx); i++) {
45 #if CONFIG_D3D11VA
46  if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD && ctx->d3d11va.surface[i] == surface)
47  {
48  D3D11_VIDEO_DECODER_OUTPUT_VIEW_DESC viewDesc;
49  ID3D11VideoDecoderOutputView_GetDesc(ctx->d3d11va.surface[i], &viewDesc);
50  return viewDesc.Texture2D.ArraySlice;
51  }
52 #endif
53 #if CONFIG_DXVA2
54  if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD && ctx->dxva2.surface[i] == surface)
55  return i;
56 #endif
57  }
58 
59  assert(0);
60  return 0;
61 }
62 
66  unsigned type, const void *data, unsigned size,
67  unsigned mb_count)
68 {
69  void *dxva_data;
70  unsigned dxva_size;
71  int result;
72  HRESULT hr = 0;
73 
74 #if CONFIG_D3D11VA
75  if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD)
76  hr = ID3D11VideoContext_GetDecoderBuffer(D3D11VA_CONTEXT(ctx)->video_context,
77  D3D11VA_CONTEXT(ctx)->decoder,
78  type,
79  &dxva_size, &dxva_data);
80 #endif
81 #if CONFIG_DXVA2
82  if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD)
83  hr = IDirectXVideoDecoder_GetBuffer(DXVA2_CONTEXT(ctx)->decoder, type,
84  &dxva_data, &dxva_size);
85 #endif
86  if (FAILED(hr)) {
87  av_log(avctx, AV_LOG_ERROR, "Failed to get a buffer for %u: 0x%lx\n",
88  type, hr);
89  return -1;
90  }
91  if (size <= dxva_size) {
92  memcpy(dxva_data, data, size);
93 
94 #if CONFIG_D3D11VA
95  if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) {
96  D3D11_VIDEO_DECODER_BUFFER_DESC *dsc11 = dsc;
97  memset(dsc11, 0, sizeof(*dsc11));
98  dsc11->BufferType = type;
99  dsc11->DataSize = size;
100  dsc11->NumMBsInBuffer = mb_count;
101  }
102 #endif
103 #if CONFIG_DXVA2
104  if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) {
105  DXVA2_DecodeBufferDesc *dsc2 = dsc;
106  memset(dsc2, 0, sizeof(*dsc2));
107  dsc2->CompressedBufferType = type;
108  dsc2->DataSize = size;
109  dsc2->NumMBsInBuffer = mb_count;
110  }
111 #endif
112 
113  result = 0;
114  } else {
115  av_log(avctx, AV_LOG_ERROR, "Buffer for type %u was too small\n", type);
116  result = -1;
117  }
118 
119 #if CONFIG_D3D11VA
120  if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD)
121  hr = ID3D11VideoContext_ReleaseDecoderBuffer(D3D11VA_CONTEXT(ctx)->video_context, D3D11VA_CONTEXT(ctx)->decoder, type);
122 #endif
123 #if CONFIG_DXVA2
124  if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD)
125  hr = IDirectXVideoDecoder_ReleaseBuffer(DXVA2_CONTEXT(ctx)->decoder, type);
126 #endif
127  if (FAILED(hr)) {
128  av_log(avctx, AV_LOG_ERROR,
129  "Failed to release buffer type %u: 0x%lx\n",
130  type, hr);
131  result = -1;
132  }
133  return result;
134 }
135 
137  const void *pp, unsigned pp_size,
138  const void *qm, unsigned qm_size,
139  int (*commit_bs_si)(AVCodecContext *,
141  DECODER_BUFFER_DESC *slice))
142 {
144  unsigned buffer_count = 0;
145 #if CONFIG_D3D11VA
146  D3D11_VIDEO_DECODER_BUFFER_DESC buffer11[4];
147 #endif
148 #if CONFIG_DXVA2
149  DXVA2_DecodeBufferDesc buffer2[4];
150 #endif
151  DECODER_BUFFER_DESC *buffer = NULL, *buffer_slice = NULL;
152  int result, runs = 0;
153  HRESULT hr;
154  unsigned type;
155 
156  do {
157 #if CONFIG_D3D11VA
158  if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) {
159  if (D3D11VA_CONTEXT(ctx)->context_mutex != INVALID_HANDLE_VALUE)
160  WaitForSingleObjectEx(D3D11VA_CONTEXT(ctx)->context_mutex, INFINITE, FALSE);
161  hr = ID3D11VideoContext_DecoderBeginFrame(D3D11VA_CONTEXT(ctx)->video_context, D3D11VA_CONTEXT(ctx)->decoder,
162  ff_dxva2_get_surface(frame),
163  0, NULL);
164  }
165 #endif
166 #if CONFIG_DXVA2
167  if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD)
168  hr = IDirectXVideoDecoder_BeginFrame(DXVA2_CONTEXT(ctx)->decoder,
169  ff_dxva2_get_surface(frame),
170  NULL);
171 #endif
172  if (hr != E_PENDING || ++runs > 50)
173  break;
174 #if CONFIG_D3D11VA
175  if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD)
176  if (D3D11VA_CONTEXT(ctx)->context_mutex != INVALID_HANDLE_VALUE)
177  ReleaseMutex(D3D11VA_CONTEXT(ctx)->context_mutex);
178 #endif
179  av_usleep(2000);
180  } while(1);
181 
182  if (FAILED(hr)) {
183  av_log(avctx, AV_LOG_ERROR, "Failed to begin frame: 0x%lx\n", hr);
184 #if CONFIG_D3D11VA
185  if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD)
186  if (D3D11VA_CONTEXT(ctx)->context_mutex != INVALID_HANDLE_VALUE)
187  ReleaseMutex(D3D11VA_CONTEXT(ctx)->context_mutex);
188 #endif
189  return -1;
190  }
191 
192 #if CONFIG_D3D11VA
193  if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) {
194  buffer = &buffer11[buffer_count];
195  type = D3D11_VIDEO_DECODER_BUFFER_PICTURE_PARAMETERS;
196  }
197 #endif
198 #if CONFIG_DXVA2
199  if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) {
200  buffer = &buffer2[buffer_count];
201  type = DXVA2_PictureParametersBufferType;
202  }
203 #endif
204  result = ff_dxva2_commit_buffer(avctx, ctx, buffer,
205  type,
206  pp, pp_size, 0);
207  if (result) {
208  av_log(avctx, AV_LOG_ERROR,
209  "Failed to add picture parameter buffer\n");
210  goto end;
211  }
212  buffer_count++;
213 
214  if (qm_size > 0) {
215 #if CONFIG_D3D11VA
216  if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) {
217  buffer = &buffer11[buffer_count];
218  type = D3D11_VIDEO_DECODER_BUFFER_INVERSE_QUANTIZATION_MATRIX;
219  }
220 #endif
221 #if CONFIG_DXVA2
222  if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) {
223  buffer = &buffer2[buffer_count];
224  type = DXVA2_InverseQuantizationMatrixBufferType;
225  }
226 #endif
227  result = ff_dxva2_commit_buffer(avctx, ctx, buffer,
228  type,
229  qm, qm_size, 0);
230  if (result) {
231  av_log(avctx, AV_LOG_ERROR,
232  "Failed to add inverse quantization matrix buffer\n");
233  goto end;
234  }
235  buffer_count++;
236  }
237 
238 #if CONFIG_D3D11VA
239  if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) {
240  buffer = &buffer11[buffer_count + 0];
241  buffer_slice = &buffer11[buffer_count + 1];
242  }
243 #endif
244 #if CONFIG_DXVA2
245  if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) {
246  buffer = &buffer2[buffer_count + 0];
247  buffer_slice = &buffer2[buffer_count + 1];
248  }
249 #endif
250 
251  result = commit_bs_si(avctx,
252  buffer,
253  buffer_slice);
254  if (result) {
255  av_log(avctx, AV_LOG_ERROR,
256  "Failed to add bitstream or slice control buffer\n");
257  goto end;
258  }
259  buffer_count += 2;
260 
261  /* TODO Film Grain when possible */
262 
263  assert(buffer_count == 1 + (qm_size > 0) + 2);
264 
265 #if CONFIG_D3D11VA
266  if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD)
267  hr = ID3D11VideoContext_SubmitDecoderBuffers(D3D11VA_CONTEXT(ctx)->video_context,
268  D3D11VA_CONTEXT(ctx)->decoder,
269  buffer_count, buffer11);
270 #endif
271 #if CONFIG_DXVA2
272  if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) {
273  DXVA2_DecodeExecuteParams exec = {
274  .NumCompBuffers = buffer_count,
275  .pCompressedBuffers = buffer2,
276  .pExtensionData = NULL,
277  };
278  hr = IDirectXVideoDecoder_Execute(DXVA2_CONTEXT(ctx)->decoder, &exec);
279  }
280 #endif
281  if (FAILED(hr)) {
282  av_log(avctx, AV_LOG_ERROR, "Failed to execute: 0x%lx\n", hr);
283  result = -1;
284  }
285 
286 end:
287 #if CONFIG_D3D11VA
288  if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) {
289  hr = ID3D11VideoContext_DecoderEndFrame(D3D11VA_CONTEXT(ctx)->video_context, D3D11VA_CONTEXT(ctx)->decoder);
290  if (D3D11VA_CONTEXT(ctx)->context_mutex != INVALID_HANDLE_VALUE)
291  ReleaseMutex(D3D11VA_CONTEXT(ctx)->context_mutex);
292  }
293 #endif
294 #if CONFIG_DXVA2
295  if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD)
296  hr = IDirectXVideoDecoder_EndFrame(DXVA2_CONTEXT(ctx)->decoder, NULL);
297 #endif
298  if (FAILED(hr)) {
299  av_log(avctx, AV_LOG_ERROR, "Failed to end frame: 0x%lx\n", hr);
300  result = -1;
301  }
302 
303  return result;
304 }
#define NULL
Definition: coverity.c:32
This structure describes decoded (raw) audio or video data.
Definition: frame.h:184
ptrdiff_t const GLvoid * data
Definition: opengl_enc.c:101
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition: avcodec.h:1904
int av_usleep(unsigned usec)
Sleep for a period of time.
Definition: time.c:76
void * ff_dxva2_get_surface(const AVFrame *frame)
Definition: dxva2.c:32
void * hwaccel_context
Hardware accelerator context.
Definition: avcodec.h:3008
static av_cold int end(AVCodecContext *avctx)
Definition: avrndec.c:90
int ff_dxva2_common_end_frame(AVCodecContext *avctx, AVFrame *frame, const void *pp, unsigned pp_size, const void *qm, unsigned qm_size, int(*commit_bs_si)(AVCodecContext *, DECODER_BUFFER_DESC *bs, DECODER_BUFFER_DESC *slice))
Definition: dxva2.c:136
static AVFrame * frame
ptrdiff_t size
Definition: opengl_enc.c:101
#define av_log(a,...)
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
#define FALSE
Definition: windows2linux.h:37
static const chunk_decoder decoder[8]
Definition: dfa.c:327
AVFormatContext * ctx
Definition: movenc.c:48
Libavcodec external API header.
unsigned ff_dxva2_get_surface_index(const AVCodecContext *avctx, const AVDXVAContext *ctx, const AVFrame *frame)
Definition: dxva2.c:37
main external API structure.
Definition: avcodec.h:1676
int ff_dxva2_commit_buffer(AVCodecContext *avctx, AVDXVAContext *ctx, DECODER_BUFFER_DESC *dsc, unsigned type, const void *data, unsigned size, unsigned mb_count)
Definition: dxva2.c:63
GLint GLenum type
Definition: opengl_enc.c:105
void DECODER_BUFFER_DESC
HW decoding through DXVA2, Picture.data[3] contains a LPDIRECT3DSURFACE9 pointer. ...
Definition: pixfmt.h:148
DWORD HRESULT
#define FAILED(hr)
Definition: windows2linux.h:48
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:198
HW decoding through Direct3D11, Picture.data[3] contains a ID3D11VideoDecoderOutputView pointer...
Definition: pixfmt.h:243
#define INVALID_HANDLE_VALUE
Definition: windows2linux.h:47
GLuint buffer
Definition: opengl_enc.c:102