Libav 0.7.1
|
00001 /* 00002 * DXVA2 HW acceleration. 00003 * 00004 * copyright (c) 2010 Laurent Aimar 00005 * 00006 * This file is part of Libav. 00007 * 00008 * Libav is free software; you can redistribute it and/or 00009 * modify it under the terms of the GNU Lesser General Public 00010 * License as published by the Free Software Foundation; either 00011 * version 2.1 of the License, or (at your option) any later version. 00012 * 00013 * Libav is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00016 * Lesser General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU Lesser General Public 00019 * License along with Libav; if not, write to the Free Software 00020 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00021 */ 00022 00023 #include "dxva2_internal.h" 00024 00025 void *ff_dxva2_get_surface(const Picture *picture) 00026 { 00027 return picture->data[3]; 00028 } 00029 00030 unsigned ff_dxva2_get_surface_index(const struct dxva_context *ctx, 00031 const Picture *picture) 00032 { 00033 void *surface = ff_dxva2_get_surface(picture); 00034 unsigned i; 00035 00036 for (i = 0; i < ctx->surface_count; i++) 00037 if (ctx->surface[i] == surface) 00038 return i; 00039 00040 assert(0); 00041 return 0; 00042 } 00043 00044 int ff_dxva2_commit_buffer(AVCodecContext *avctx, 00045 struct dxva_context *ctx, 00046 DXVA2_DecodeBufferDesc *dsc, 00047 unsigned type, const void *data, unsigned size, 00048 unsigned mb_count) 00049 { 00050 void *dxva_data; 00051 unsigned dxva_size; 00052 int result; 00053 00054 if (FAILED(IDirectXVideoDecoder_GetBuffer(ctx->decoder, type, 00055 &dxva_data, &dxva_size))) { 00056 av_log(avctx, AV_LOG_ERROR, "Failed to get a buffer for %d\n", type); 00057 return -1; 00058 } 00059 if (size <= dxva_size) { 00060 memcpy(dxva_data, data, size); 00061 00062 memset(dsc, 0, sizeof(*dsc)); 00063 dsc->CompressedBufferType = type; 00064 dsc->DataSize = size; 00065 dsc->NumMBsInBuffer = mb_count; 00066 00067 result = 0; 00068 } else { 00069 av_log(avctx, AV_LOG_ERROR, "Buffer for type %d was too small\n", type); 00070 result = -1; 00071 } 00072 if (FAILED(IDirectXVideoDecoder_ReleaseBuffer(ctx->decoder, type))) { 00073 av_log(avctx, AV_LOG_ERROR, "Failed to release buffer type %d\n", type); 00074 result = -1; 00075 } 00076 return result; 00077 } 00078 00079 int ff_dxva2_common_end_frame(AVCodecContext *avctx, MpegEncContext *s, 00080 const void *pp, unsigned pp_size, 00081 const void *qm, unsigned qm_size, 00082 int (*commit_bs_si)(AVCodecContext *, 00083 DXVA2_DecodeBufferDesc *bs, 00084 DXVA2_DecodeBufferDesc *slice)) 00085 { 00086 struct dxva_context *ctx = avctx->hwaccel_context; 00087 unsigned buffer_count = 0; 00088 DXVA2_DecodeBufferDesc buffer[4]; 00089 DXVA2_DecodeExecuteParams exec; 00090 int result; 00091 00092 if (FAILED(IDirectXVideoDecoder_BeginFrame(ctx->decoder, 00093 ff_dxva2_get_surface(s->current_picture_ptr), 00094 NULL))) { 00095 av_log(avctx, AV_LOG_ERROR, "Failed to begin frame\n"); 00096 return -1; 00097 } 00098 00099 result = ff_dxva2_commit_buffer(avctx, ctx, &buffer[buffer_count], 00100 DXVA2_PictureParametersBufferType, 00101 pp, pp_size, 0); 00102 if (result) { 00103 av_log(avctx, AV_LOG_ERROR, 00104 "Failed to add picture parameter buffer\n"); 00105 goto end; 00106 } 00107 buffer_count++; 00108 00109 if (qm_size > 0) { 00110 result = ff_dxva2_commit_buffer(avctx, ctx, &buffer[buffer_count], 00111 DXVA2_InverseQuantizationMatrixBufferType, 00112 qm, qm_size, 0); 00113 if (result) { 00114 av_log(avctx, AV_LOG_ERROR, 00115 "Failed to add inverse quantization matrix buffer\n"); 00116 goto end; 00117 } 00118 buffer_count++; 00119 } 00120 00121 result = commit_bs_si(avctx, 00122 &buffer[buffer_count + 0], 00123 &buffer[buffer_count + 1]); 00124 if (result) { 00125 av_log(avctx, AV_LOG_ERROR, 00126 "Failed to add bitstream or slice control buffer\n"); 00127 goto end; 00128 } 00129 buffer_count += 2; 00130 00131 /* TODO Film Grain when possible */ 00132 00133 assert(buffer_count == 1 + (qm_size > 0) + 2); 00134 00135 memset(&exec, 0, sizeof(exec)); 00136 exec.NumCompBuffers = buffer_count; 00137 exec.pCompressedBuffers = buffer; 00138 exec.pExtensionData = NULL; 00139 if (FAILED(IDirectXVideoDecoder_Execute(ctx->decoder, &exec))) { 00140 av_log(avctx, AV_LOG_ERROR, "Failed to execute\n"); 00141 result = -1; 00142 } 00143 00144 end: 00145 if (FAILED(IDirectXVideoDecoder_EndFrame(ctx->decoder, NULL))) { 00146 av_log(avctx, AV_LOG_ERROR, "Failed to end frame\n"); 00147 result = -1; 00148 } 00149 00150 if (!result) 00151 ff_draw_horiz_band(s, 0, s->avctx->height); 00152 return result; 00153 } 00154