Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
6147 serge 1
/*
2
 * Intel MediaSDK QSV based H.264 / HEVC decoder
3
 *
4
 * copyright (c) 2013 Luca Barbato
5
 * copyright (c) 2015 Anton Khirnov
6
 *
7
 * This file is part of FFmpeg.
8
 *
9
 * FFmpeg is free software; you can redistribute it and/or
10
 * modify it under the terms of the GNU Lesser General Public
11
 * License as published by the Free Software Foundation; either
12
 * version 2.1 of the License, or (at your option) any later version.
13
 *
14
 * FFmpeg is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17
 * Lesser General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU Lesser General Public
20
 * License along with FFmpeg; if not, write to the Free Software
21
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22
 */
23
 
24
 
25
#include 
26
#include 
27
 
28
#include 
29
 
30
#include "libavutil/common.h"
31
#include "libavutil/fifo.h"
32
#include "libavutil/opt.h"
33
 
34
#include "avcodec.h"
35
#include "internal.h"
36
#include "qsvdec.h"
37
 
38
enum LoadPlugin {
39
    LOAD_PLUGIN_NONE,
40
    LOAD_PLUGIN_HEVC_SW,
41
};
42
 
43
typedef struct QSVH2645Context {
44
    AVClass *class;
45
    QSVContext qsv;
46
 
47
    int load_plugin;
48
 
49
    // the filter for converting to Annex B
50
    AVBitStreamFilterContext *bsf;
51
 
52
} QSVH2645Context;
53
 
54
static av_cold int qsv_decode_close(AVCodecContext *avctx)
55
{
56
    QSVH2645Context *s = avctx->priv_data;
57
 
58
    ff_qsv_decode_close(&s->qsv);
59
 
60
    av_bitstream_filter_close(s->bsf);
61
 
62
    return 0;
63
}
64
 
65
static av_cold int qsv_decode_init(AVCodecContext *avctx)
66
{
67
    QSVH2645Context *s = avctx->priv_data;
68
    int ret;
69
 
70
    if (avctx->codec_id == AV_CODEC_ID_HEVC && s->load_plugin != LOAD_PLUGIN_NONE) {
71
        static const char *uid_hevcenc_sw = "15dd936825ad475ea34e35f3f54217a6";
72
 
73
        if (s->qsv.load_plugins[0]) {
74
            av_log(avctx, AV_LOG_WARNING,
75
                   "load_plugins is not empty, but load_plugin is not set to 'none'."
76
                   "The load_plugin value will be ignored.\n");
77
        } else {
78
            av_freep(&s->qsv.load_plugins);
79
            s->qsv.load_plugins = av_strdup(uid_hevcenc_sw);
80
            if (!s->qsv.load_plugins)
81
                return AVERROR(ENOMEM);
82
        }
83
    }
84
 
85
    if (avctx->codec_id == AV_CODEC_ID_H264)
86
        s->bsf = av_bitstream_filter_init("h264_mp4toannexb");
87
    else
88
        s->bsf = av_bitstream_filter_init("hevc_mp4toannexb");
89
    if (!s->bsf) {
90
        ret = AVERROR(ENOMEM);
91
        goto fail;
92
    }
93
 
94
    return 0;
95
fail:
96
    qsv_decode_close(avctx);
97
    return ret;
98
}
99
 
100
static int qsv_decode_frame(AVCodecContext *avctx, void *data,
101
                            int *got_frame, AVPacket *avpkt)
102
{
103
    QSVH2645Context *s = avctx->priv_data;
104
    AVFrame *frame    = data;
105
    int ret;
106
    uint8_t *p_filtered = NULL;
107
    int      n_filtered = NULL;
108
    AVPacket pkt_filtered = { 0 };
109
 
110
    if (avpkt->size) {
111
        if (avpkt->size > 3 && !avpkt->data[0] &&
112
            !avpkt->data[1] && !avpkt->data[2] && 1==avpkt->data[3]) {
113
            /* we already have annex-b prefix */
114
            return ff_qsv_decode(avctx, &s->qsv, frame, got_frame, avpkt);
115
 
116
        } else {
117
            /* no annex-b prefix. try to restore: */
118
            ret = av_bitstream_filter_filter(s->bsf, avctx, "private_spspps_buf",
119
                                         &p_filtered, &n_filtered,
120
                                         avpkt->data, avpkt->size, 0);
121
            if (ret>=0) {
122
                pkt_filtered.pts  = avpkt->pts;
123
                pkt_filtered.data = p_filtered;
124
                pkt_filtered.size = n_filtered;
125
 
126
                ret = ff_qsv_decode(avctx, &s->qsv, frame, got_frame, &pkt_filtered);
127
 
128
                if (p_filtered != avpkt->data)
129
                    av_free(p_filtered);
130
                return ret > 0 ? avpkt->size : ret;
131
            }
132
        }
133
    }
134
 
135
    return ff_qsv_decode(avctx, &s->qsv, frame, got_frame, avpkt);
136
}
137
 
138
static void qsv_decode_flush(AVCodecContext *avctx)
139
{
140
//    QSVH2645Context *s = avctx->priv_data;
141
    /* TODO: flush qsv engine if necessary */
142
}
143
 
144
#define OFFSET(x) offsetof(QSVH2645Context, x)
145
#define VD AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM
146
 
147
#if CONFIG_HEVC_QSV_DECODER
148
AVHWAccel ff_hevc_qsv_hwaccel = {
149
    .name           = "hevc_qsv",
150
    .type           = AVMEDIA_TYPE_VIDEO,
151
    .id             = AV_CODEC_ID_HEVC,
152
    .pix_fmt        = AV_PIX_FMT_QSV,
153
};
154
 
155
static const AVOption hevc_options[] = {
156
    { "async_depth", "Internal parallelization depth, the higher the value the higher the latency.", OFFSET(qsv.async_depth), AV_OPT_TYPE_INT, { .i64 = ASYNC_DEPTH_DEFAULT }, 0, INT_MAX, VD },
157
 
158
    { "load_plugin", "A user plugin to load in an internal session", OFFSET(load_plugin), AV_OPT_TYPE_INT, { .i64 = LOAD_PLUGIN_HEVC_SW }, LOAD_PLUGIN_NONE, LOAD_PLUGIN_HEVC_SW, VD, "load_plugin" },
159
    { "none",     NULL, 0, AV_OPT_TYPE_CONST, { .i64 = LOAD_PLUGIN_NONE },    0, 0, VD, "load_plugin" },
160
    { "hevc_sw",  NULL, 0, AV_OPT_TYPE_CONST, { .i64 = LOAD_PLUGIN_HEVC_SW }, 0, 0, VD, "load_plugin" },
161
 
162
    { "load_plugins", "A :-separate list of hexadecimal plugin UIDs to load in an internal session",
163
        OFFSET(qsv.load_plugins), AV_OPT_TYPE_STRING, { .str = "" }, 0, 0, VD },
164
    { NULL },
165
};
166
 
167
static const AVClass hevc_class = {
168
    .class_name = "hevc_qsv",
169
    .item_name  = av_default_item_name,
170
    .option     = hevc_options,
171
    .version    = LIBAVUTIL_VERSION_INT,
172
};
173
 
174
AVCodec ff_hevc_qsv_decoder = {
175
    .name           = "hevc_qsv",
176
    .long_name      = NULL_IF_CONFIG_SMALL("HEVC (Intel Quick Sync Video acceleration)"),
177
    .priv_data_size = sizeof(QSVH2645Context),
178
    .type           = AVMEDIA_TYPE_VIDEO,
179
    .id             = AV_CODEC_ID_HEVC,
180
    .init           = qsv_decode_init,
181
    .decode         = qsv_decode_frame,
182
    .flush          = qsv_decode_flush,
183
    .close          = qsv_decode_close,
184
    .capabilities   = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1,
185
    .priv_class     = &hevc_class,
186
};
187
#endif
188
 
189
#if CONFIG_H264_QSV_DECODER
190
AVHWAccel ff_h264_qsv_hwaccel = {
191
    .name           = "h264_qsv",
192
    .type           = AVMEDIA_TYPE_VIDEO,
193
    .id             = AV_CODEC_ID_H264,
194
    .pix_fmt        = AV_PIX_FMT_QSV,
195
};
196
 
197
static const AVOption options[] = {
198
    { "async_depth", "Internal parallelization depth, the higher the value the higher the latency.", OFFSET(qsv.async_depth), AV_OPT_TYPE_INT, { .i64 = ASYNC_DEPTH_DEFAULT }, 0, INT_MAX, VD },
199
    { NULL },
200
};
201
 
202
static const AVClass class = {
203
    .class_name = "h264_qsv",
204
    .item_name  = av_default_item_name,
205
    .option     = options,
206
    .version    = LIBAVUTIL_VERSION_INT,
207
};
208
 
209
AVCodec ff_h264_qsv_decoder = {
210
    .name           = "h264_qsv",
211
    .long_name      = NULL_IF_CONFIG_SMALL("H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 (Intel Quick Sync Video acceleration)"),
212
    .priv_data_size = sizeof(QSVH2645Context),
213
    .type           = AVMEDIA_TYPE_VIDEO,
214
    .id             = AV_CODEC_ID_H264,
215
    .init           = qsv_decode_init,
216
    .decode         = qsv_decode_frame,
217
    .flush          = qsv_decode_flush,
218
    .close          = qsv_decode_close,
219
    .capabilities   = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1,
220
    .priv_class     = &class,
221
};
222
#endif