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.

304 lines
10KB

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