Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4349 Serge 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 "dxva2_internal.h"
24
 
25
void *ff_dxva2_get_surface(const Picture *picture)
26
{
27
    return picture->f.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, Picture *pic,
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 = { 0 };
90
    int      result;
91
 
92
    if (FAILED(IDirectXVideoDecoder_BeginFrame(ctx->decoder,
93
                                               ff_dxva2_get_surface(pic),
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
    exec.NumCompBuffers      = buffer_count;
136
    exec.pCompressedBuffers  = buffer;
137
    exec.pExtensionData      = NULL;
138
    if (FAILED(IDirectXVideoDecoder_Execute(ctx->decoder, &exec))) {
139
        av_log(avctx, AV_LOG_ERROR, "Failed to execute\n");
140
        result = -1;
141
    }
142
 
143
end:
144
    if (FAILED(IDirectXVideoDecoder_EndFrame(ctx->decoder, NULL))) {
145
        av_log(avctx, AV_LOG_ERROR, "Failed to end frame\n");
146
        result = -1;
147
    }
148
 
149
    return result;
150
}