Statistics
| Branch: | Revision:

ffmpeg / libavcodec / dxva2.c @ 2912e87a

History | View | Annotate | Download (5.03 KB)

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

    
23
#include "dxva2_internal.h"
24

    
25
void *ff_dxva2_get_surface(const Picture *picture)
26
{
27
    return picture->data[3];
28
}
29

    
30
unsigned ff_dxva2_get_surface_index(const struct dxva_context *ctx,
31
                                    const Picture *picture)
32
{
33
    void *surface = ff_dxva2_get_surface(picture);
34
    unsigned i;
35

    
36
    for (i = 0; i < ctx->surface_count; i++)
37
        if (ctx->surface[i] == surface)
38
            return i;
39

    
40
    assert(0);
41
    return 0;
42
}
43

    
44
int ff_dxva2_commit_buffer(AVCodecContext *avctx,
45
                           struct dxva_context *ctx,
46
                           DXVA2_DecodeBufferDesc *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

    
54
    if (FAILED(IDirectXVideoDecoder_GetBuffer(ctx->decoder, type,
55
                                              &dxva_data, &dxva_size))) {
56
        av_log(avctx, AV_LOG_ERROR, "Failed to get a buffer for %d\n", type);
57
        return -1;
58
    }
59
    if (size <= dxva_size) {
60
        memcpy(dxva_data, data, size);
61

    
62
        memset(dsc, 0, sizeof(*dsc));
63
        dsc->CompressedBufferType = type;
64
        dsc->DataSize             = size;
65
        dsc->NumMBsInBuffer       = mb_count;
66

    
67
        result = 0;
68
    } else {
69
        av_log(avctx, AV_LOG_ERROR, "Buffer for type %d was too small\n", type);
70
        result = -1;
71
    }
72
    if (FAILED(IDirectXVideoDecoder_ReleaseBuffer(ctx->decoder, type))) {
73
        av_log(avctx, AV_LOG_ERROR, "Failed to release buffer type %d\n", type);
74
        result = -1;
75
    }
76
    return result;
77
}
78

    
79
int ff_dxva2_common_end_frame(AVCodecContext *avctx, MpegEncContext *s,
80
                              const void *pp, unsigned pp_size,
81
                              const void *qm, unsigned qm_size,
82
                              int (*commit_bs_si)(AVCodecContext *,
83
                                                  DXVA2_DecodeBufferDesc *bs,
84
                                                  DXVA2_DecodeBufferDesc *slice))
85
{
86
    struct dxva_context *ctx = avctx->hwaccel_context;
87
    unsigned               buffer_count = 0;
88
    DXVA2_DecodeBufferDesc buffer[4];
89
    DXVA2_DecodeExecuteParams exec;
90
    int      result;
91

    
92
    if (FAILED(IDirectXVideoDecoder_BeginFrame(ctx->decoder,
93
                                               ff_dxva2_get_surface(s->current_picture_ptr),
94
                                               NULL))) {
95
        av_log(avctx, AV_LOG_ERROR, "Failed to begin frame\n");
96
        return -1;
97
    }
98

    
99
    result = ff_dxva2_commit_buffer(avctx, ctx, &buffer[buffer_count],
100
                                    DXVA2_PictureParametersBufferType,
101
                                    pp, pp_size, 0);
102
    if (result) {
103
        av_log(avctx, AV_LOG_ERROR,
104
               "Failed to add picture parameter buffer\n");
105
        goto end;
106
    }
107
    buffer_count++;
108

    
109
    if (qm_size > 0) {
110
        result = ff_dxva2_commit_buffer(avctx, ctx, &buffer[buffer_count],
111
                                        DXVA2_InverseQuantizationMatrixBufferType,
112
                                        qm, qm_size, 0);
113
        if (result) {
114
            av_log(avctx, AV_LOG_ERROR,
115
                   "Failed to add inverse quantization matrix buffer\n");
116
            goto end;
117
        }
118
        buffer_count++;
119
    }
120

    
121
    result = commit_bs_si(avctx,
122
                          &buffer[buffer_count + 0],
123
                          &buffer[buffer_count + 1]);
124
    if (result) {
125
        av_log(avctx, AV_LOG_ERROR,
126
               "Failed to add bitstream or slice control buffer\n");
127
        goto end;
128
    }
129
    buffer_count += 2;
130

    
131
    /* TODO Film Grain when possible */
132

    
133
    assert(buffer_count == 1 + (qm_size > 0) + 2);
134

    
135
    memset(&exec, 0, sizeof(exec));
136
    exec.NumCompBuffers      = buffer_count;
137
    exec.pCompressedBuffers  = buffer;
138
    exec.pExtensionData      = NULL;
139
    if (FAILED(IDirectXVideoDecoder_Execute(ctx->decoder, &exec))) {
140
        av_log(avctx, AV_LOG_ERROR, "Failed to execute\n");
141
        result = -1;
142
    }
143

    
144
end:
145
    if (FAILED(IDirectXVideoDecoder_EndFrame(ctx->decoder, NULL))) {
146
        av_log(avctx, AV_LOG_ERROR, "Failed to end frame\n");
147
        result = -1;
148
    }
149

    
150
    if (!result)
151
        ff_draw_horiz_band(s, 0, s->avctx->height);
152
    return result;
153
}
154