You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

288 lines
9.5KB

  1. /*
  2. * DXVA2 HW acceleration.
  3. *
  4. * copyright (c) 2010 Laurent Aimar
  5. *
  6. * This file is part of Libav.
  7. *
  8. * Libav 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. * Libav 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 Libav; if not, write to the Free Software
  20. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  21. */
  22. #include <assert.h>
  23. #include <string.h>
  24. #include "libavutil/log.h"
  25. #include "libavutil/time.h"
  26. #include "avcodec.h"
  27. #include "dxva2_internal.h"
  28. void *ff_dxva2_get_surface(const AVFrame *frame)
  29. {
  30. return frame->data[3];
  31. }
  32. unsigned ff_dxva2_get_surface_index(const AVCodecContext *avctx,
  33. const AVDXVAContext *ctx,
  34. const AVFrame *frame)
  35. {
  36. void *surface = ff_dxva2_get_surface(frame);
  37. unsigned i;
  38. for (i = 0; i < DXVA_CONTEXT_COUNT(avctx, ctx); i++)
  39. if (DXVA_CONTEXT_SURFACE(avctx, ctx, i) == surface)
  40. return i;
  41. assert(0);
  42. return 0;
  43. }
  44. int ff_dxva2_commit_buffer(AVCodecContext *avctx,
  45. AVDXVAContext *ctx,
  46. DECODER_BUFFER_DESC *dsc,
  47. unsigned type, const void *data, unsigned size,
  48. unsigned mb_count)
  49. {
  50. void *dxva_data;
  51. unsigned dxva_size;
  52. int result;
  53. HRESULT hr;
  54. #if CONFIG_D3D11VA
  55. if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD)
  56. hr = ID3D11VideoContext_GetDecoderBuffer(D3D11VA_CONTEXT(ctx)->video_context,
  57. D3D11VA_CONTEXT(ctx)->decoder,
  58. type,
  59. &dxva_size, &dxva_data);
  60. #endif
  61. #if CONFIG_DXVA2
  62. if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD)
  63. hr = IDirectXVideoDecoder_GetBuffer(DXVA2_CONTEXT(ctx)->decoder, type,
  64. &dxva_data, &dxva_size);
  65. #endif
  66. if (FAILED(hr)) {
  67. av_log(avctx, AV_LOG_ERROR, "Failed to get a buffer for %u: 0x%lx\n",
  68. type, hr);
  69. return -1;
  70. }
  71. if (size <= dxva_size) {
  72. memcpy(dxva_data, data, size);
  73. #if CONFIG_D3D11VA
  74. if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) {
  75. D3D11_VIDEO_DECODER_BUFFER_DESC *dsc11 = dsc;
  76. memset(dsc11, 0, sizeof(*dsc11));
  77. dsc11->BufferType = type;
  78. dsc11->DataSize = size;
  79. dsc11->NumMBsInBuffer = mb_count;
  80. }
  81. #endif
  82. #if CONFIG_DXVA2
  83. if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) {
  84. DXVA2_DecodeBufferDesc *dsc2 = dsc;
  85. memset(dsc2, 0, sizeof(*dsc2));
  86. dsc2->CompressedBufferType = type;
  87. dsc2->DataSize = size;
  88. dsc2->NumMBsInBuffer = mb_count;
  89. }
  90. #endif
  91. result = 0;
  92. } else {
  93. av_log(avctx, AV_LOG_ERROR, "Buffer for type %u was too small\n", type);
  94. result = -1;
  95. }
  96. #if CONFIG_D3D11VA
  97. if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD)
  98. hr = ID3D11VideoContext_ReleaseDecoderBuffer(D3D11VA_CONTEXT(ctx)->video_context, D3D11VA_CONTEXT(ctx)->decoder, type);
  99. #endif
  100. #if CONFIG_DXVA2
  101. if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD)
  102. hr = IDirectXVideoDecoder_ReleaseBuffer(DXVA2_CONTEXT(ctx)->decoder, type);
  103. #endif
  104. if (FAILED(hr)) {
  105. av_log(avctx, AV_LOG_ERROR,
  106. "Failed to release buffer type %u: 0x%lx\n",
  107. type, hr);
  108. result = -1;
  109. }
  110. return result;
  111. }
  112. int ff_dxva2_common_end_frame(AVCodecContext *avctx, AVFrame *frame,
  113. const void *pp, unsigned pp_size,
  114. const void *qm, unsigned qm_size,
  115. int (*commit_bs_si)(AVCodecContext *,
  116. DECODER_BUFFER_DESC *bs,
  117. DECODER_BUFFER_DESC *slice))
  118. {
  119. AVDXVAContext *ctx = avctx->hwaccel_context;
  120. unsigned buffer_count = 0;
  121. #if CONFIG_D3D11VA
  122. D3D11_VIDEO_DECODER_BUFFER_DESC buffer11[4];
  123. #endif
  124. #if CONFIG_DXVA2
  125. DXVA2_DecodeBufferDesc buffer2[4];
  126. #endif
  127. DECODER_BUFFER_DESC *buffer,*buffer_slice;
  128. int result, runs = 0;
  129. HRESULT hr;
  130. unsigned type;
  131. do {
  132. #if CONFIG_D3D11VA
  133. if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) {
  134. if (D3D11VA_CONTEXT(ctx)->context_mutex != INVALID_HANDLE_VALUE)
  135. WaitForSingleObjectEx(D3D11VA_CONTEXT(ctx)->context_mutex, INFINITE, FALSE);
  136. hr = ID3D11VideoContext_DecoderBeginFrame(D3D11VA_CONTEXT(ctx)->video_context, D3D11VA_CONTEXT(ctx)->decoder,
  137. ff_dxva2_get_surface(frame),
  138. 0, NULL);
  139. }
  140. #endif
  141. #if CONFIG_DXVA2
  142. if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD)
  143. hr = IDirectXVideoDecoder_BeginFrame(DXVA2_CONTEXT(ctx)->decoder,
  144. ff_dxva2_get_surface(frame),
  145. NULL);
  146. #endif
  147. if (hr == E_PENDING)
  148. av_usleep(2000);
  149. } while (hr == E_PENDING && ++runs < 50);
  150. if (FAILED(hr)) {
  151. av_log(avctx, AV_LOG_ERROR, "Failed to begin frame: 0x%lx\n", hr);
  152. #if CONFIG_D3D11VA
  153. if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD)
  154. if (D3D11VA_CONTEXT(ctx)->context_mutex != INVALID_HANDLE_VALUE)
  155. ReleaseMutex(D3D11VA_CONTEXT(ctx)->context_mutex);
  156. #endif
  157. return -1;
  158. }
  159. #if CONFIG_D3D11VA
  160. if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) {
  161. buffer = &buffer11[buffer_count];
  162. type = D3D11_VIDEO_DECODER_BUFFER_PICTURE_PARAMETERS;
  163. }
  164. #endif
  165. #if CONFIG_DXVA2
  166. if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) {
  167. buffer = &buffer2[buffer_count];
  168. type = DXVA2_PictureParametersBufferType;
  169. }
  170. #endif
  171. result = ff_dxva2_commit_buffer(avctx, ctx, buffer,
  172. type,
  173. pp, pp_size, 0);
  174. if (result) {
  175. av_log(avctx, AV_LOG_ERROR,
  176. "Failed to add picture parameter buffer\n");
  177. goto end;
  178. }
  179. buffer_count++;
  180. if (qm_size > 0) {
  181. #if CONFIG_D3D11VA
  182. if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) {
  183. buffer = &buffer11[buffer_count];
  184. type = D3D11_VIDEO_DECODER_BUFFER_INVERSE_QUANTIZATION_MATRIX;
  185. }
  186. #endif
  187. #if CONFIG_DXVA2
  188. if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) {
  189. buffer = &buffer2[buffer_count];
  190. type = DXVA2_InverseQuantizationMatrixBufferType;
  191. }
  192. #endif
  193. result = ff_dxva2_commit_buffer(avctx, ctx, buffer,
  194. type,
  195. qm, qm_size, 0);
  196. if (result) {
  197. av_log(avctx, AV_LOG_ERROR,
  198. "Failed to add inverse quantization matrix buffer\n");
  199. goto end;
  200. }
  201. buffer_count++;
  202. }
  203. #if CONFIG_D3D11VA
  204. if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) {
  205. buffer = &buffer11[buffer_count + 0];
  206. buffer_slice = &buffer11[buffer_count + 1];
  207. }
  208. #endif
  209. #if CONFIG_DXVA2
  210. if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) {
  211. buffer = &buffer2[buffer_count + 0];
  212. buffer_slice = &buffer2[buffer_count + 1];
  213. }
  214. #endif
  215. result = commit_bs_si(avctx,
  216. buffer,
  217. buffer_slice);
  218. if (result) {
  219. av_log(avctx, AV_LOG_ERROR,
  220. "Failed to add bitstream or slice control buffer\n");
  221. goto end;
  222. }
  223. buffer_count += 2;
  224. /* TODO Film Grain when possible */
  225. assert(buffer_count == 1 + (qm_size > 0) + 2);
  226. #if CONFIG_D3D11VA
  227. if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD)
  228. hr = ID3D11VideoContext_SubmitDecoderBuffers(D3D11VA_CONTEXT(ctx)->video_context,
  229. D3D11VA_CONTEXT(ctx)->decoder,
  230. buffer_count, buffer11);
  231. #endif
  232. #if CONFIG_DXVA2
  233. if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) {
  234. DXVA2_DecodeExecuteParams exec = {
  235. .NumCompBuffers = buffer_count,
  236. .pCompressedBuffers = buffer2,
  237. .pExtensionData = NULL,
  238. };
  239. hr = IDirectXVideoDecoder_Execute(DXVA2_CONTEXT(ctx)->decoder, &exec);
  240. }
  241. #endif
  242. if (FAILED(hr)) {
  243. av_log(avctx, AV_LOG_ERROR, "Failed to execute: 0x%lx\n", hr);
  244. result = -1;
  245. }
  246. end:
  247. #if CONFIG_D3D11VA
  248. if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) {
  249. hr = ID3D11VideoContext_DecoderEndFrame(D3D11VA_CONTEXT(ctx)->video_context, D3D11VA_CONTEXT(ctx)->decoder);
  250. if (D3D11VA_CONTEXT(ctx)->context_mutex != INVALID_HANDLE_VALUE)
  251. ReleaseMutex(D3D11VA_CONTEXT(ctx)->context_mutex);
  252. }
  253. #endif
  254. #if CONFIG_DXVA2
  255. if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD)
  256. hr = IDirectXVideoDecoder_EndFrame(DXVA2_CONTEXT(ctx)->decoder, NULL);
  257. #endif
  258. if (FAILED(hr)) {
  259. av_log(avctx, AV_LOG_ERROR, "Failed to end frame: 0x%lx\n", hr);
  260. result = -1;
  261. }
  262. return result;
  263. }