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 |