History

avconv: add support for Intel QSV-accelerated transcoding

Anton Khirnov committed 11 years ago

Commit fb472e11 parent dc923bc7 files · +307 −0Browse files

Unified · Split

7 files
  1. Changelog +1 −0
  2. Makefile +1 −0
  3. avconv.c +5 −0
  4. avconv.h +5 −0
  5. avconv_opt.c +3 −0
  6. avconv_qsv.c +268 −0
  7. doc/avconv.texi +24 −0
Changelog+1−0
@@ -44,6 +44,7 @@ version <next>: · 43 unmodified lines
44- Support DNx100 (1440x1080@8)44- Support DNx100 (1440x1080@8)
45- DXV decoding45- DXV decoding
46- Screenpresso SPV1 decoding46- Screenpresso SPV1 decoding
47- zero-copy Intel QSV transcoding in avconv
47 48
48 49
49version 11:50version 11:
Makefile+1−0
@@ -78,6 +78,7 @@ OBJS-avconv += avconv_opt.o avconv_filter.o · 77 unmodified lines
78OBJS-avconv-$(HAVE_VDPAU_X11) += avconv_vdpau.o78OBJS-avconv-$(HAVE_VDPAU_X11) += avconv_vdpau.o
79OBJS-avconv-$(HAVE_DXVA2_LIB) += avconv_dxva2.o79OBJS-avconv-$(HAVE_DXVA2_LIB) += avconv_dxva2.o
80OBJS-avconv-$(CONFIG_VDA) += avconv_vda.o80OBJS-avconv-$(CONFIG_VDA) += avconv_vda.o
81OBJS-avconv-$(CONFIG_LIBMFX) += avconv_qsv.o
81 82
82TESTTOOLS = audiogen videogen rotozoom tiny_psnr base6483TESTTOOLS = audiogen videogen rotozoom tiny_psnr base64
83HOSTPROGS := $(TESTTOOLS:%=tests/%) doc/print_options84HOSTPROGS := $(TESTTOOLS:%=tests/%) doc/print_options
avconv.c+5−0
@@ -1852,6 +1852,11 @@ static int transcode_init(void) · 1851 unmodified lines
1852 }1852 }
1853 }1853 }
1854 1854
1855#if CONFIG_LIBMFX
1856 if (qsv_transcode_init(ost))
1857 exit_program(1);
1858#endif
1859
1855 if (!ost->filter &&1860 if (!ost->filter &&
1856 (enc_ctx->codec_type == AVMEDIA_TYPE_VIDEO ||1861 (enc_ctx->codec_type == AVMEDIA_TYPE_VIDEO ||
1857 enc_ctx->codec_type == AVMEDIA_TYPE_AUDIO)) {1862 enc_ctx->codec_type == AVMEDIA_TYPE_AUDIO)) {
avconv.h+5−0
@@ -54,6 +54,7 @@ enum HWAccelID { · 53 unmodified lines
54 HWACCEL_VDPAU,54 HWACCEL_VDPAU,
55 HWACCEL_DXVA2,55 HWACCEL_DXVA2,
56 HWACCEL_VDA,56 HWACCEL_VDA,
57 HWACCEL_QSV,
57};58};
58 59
59typedef struct HWAccel {60typedef struct HWAccel {
@@ -331,6 +332,8 @@ typedef struct OutputStream { · 271 unmodified lines
331 int64_t max_frames;332 int64_t max_frames;
332 AVFrame *filtered_frame;333 AVFrame *filtered_frame;
333 334
335 void *hwaccel_ctx;
336
334 /* video only */337 /* video only */
335 AVRational frame_rate;338 AVRational frame_rate;
336 int force_fps;339 int force_fps;
@@ -443,5 +446,7 @@ int avconv_parse_options(int argc, char **argv); · 106 unmodified lines
443int vdpau_init(AVCodecContext *s);446int vdpau_init(AVCodecContext *s);
444int dxva2_init(AVCodecContext *s);447int dxva2_init(AVCodecContext *s);
445int vda_init(AVCodecContext *s);448int vda_init(AVCodecContext *s);
449int qsv_init(AVCodecContext *s);
450int qsv_transcode_init(OutputStream *ost);
446 451
447#endif /* AVCONV_H */452#endif /* AVCONV_H */
avconv_opt.c+3−0
@@ -64,6 +64,9 @@ const HWAccel hwaccels[] = { · 63 unmodified lines
64#endif64#endif
65#if CONFIG_VDA65#if CONFIG_VDA
66 { "vda", vda_init, HWACCEL_VDA, AV_PIX_FMT_VDA },66 { "vda", vda_init, HWACCEL_VDA, AV_PIX_FMT_VDA },
67#endif
68#if CONFIG_LIBMFX
69 { "qsv", qsv_init, HWACCEL_QSV, AV_PIX_FMT_QSV },
67#endif70#endif
68 { 0 },71 { 0 },
69};72};
avconv_qsv.c+268−0
@@ -0,0 +1,268 @@
1/*
2 * This file is part of Libav.
3 *
4 * Libav is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * Libav is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with Libav; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19#include <mfx/mfxvideo.h>
20#include <stdlib.h>
21
22#include "libavutil/dict.h"
23#include "libavutil/mem.h"
24#include "libavutil/opt.h"
25#include "libavcodec/qsv.h"
26
27#include "avconv.h"
28
29typedef struct QSVContext {
30 OutputStream *ost;
31
32 mfxSession session;
33
34 mfxExtOpaqueSurfaceAlloc opaque_alloc;
35 AVBufferRef *opaque_surfaces_buf;
36
37 uint8_t *surface_used;
38 mfxFrameSurface1 **surface_ptrs;
39 int nb_surfaces;
40
41 mfxExtBuffer *ext_buffers[1];
42} QSVContext;
43
44static void buffer_release(void *opaque, uint8_t *data)
45{
46 *(uint8_t*)opaque = 0;
47}
48
49static int qsv_get_buffer(AVCodecContext *s, AVFrame *frame, int flags)
50{
51 InputStream *ist = s->opaque;
52 QSVContext *qsv = ist->hwaccel_ctx;
53 int i;
54
55 for (i = 0; i < qsv->nb_surfaces; i++) {
56 if (qsv->surface_used[i])
57 continue;
58
59 frame->buf[0] = av_buffer_create((uint8_t*)qsv->surface_ptrs[i], sizeof(*qsv->surface_ptrs[i]),
60 buffer_release, &qsv->surface_used[i], 0);
61 if (!frame->buf[0])
62 return AVERROR(ENOMEM);
63 frame->data[3] = (uint8_t*)qsv->surface_ptrs[i];
64 qsv->surface_used[i] = 1;
65 return 0;
66 }
67
68 return AVERROR(ENOMEM);
69}
70
71static int init_opaque_surf(QSVContext *qsv)
72{
73 AVQSVContext *hwctx_enc = qsv->ost->enc_ctx->hwaccel_context;
74 mfxFrameSurface1 *surfaces;
75 int i;
76
77 qsv->nb_surfaces = hwctx_enc->nb_opaque_surfaces;
78
79 qsv->opaque_surfaces_buf = av_buffer_ref(hwctx_enc->opaque_surfaces);
80 qsv->surface_ptrs = av_mallocz_array(qsv->nb_surfaces, sizeof(*qsv->surface_ptrs));
81 qsv->surface_used = av_mallocz_array(qsv->nb_surfaces, sizeof(*qsv->surface_used));
82 if (!qsv->opaque_surfaces_buf || !qsv->surface_ptrs || !qsv->surface_used)
83 return AVERROR(ENOMEM);
84
85 surfaces = (mfxFrameSurface1*)qsv->opaque_surfaces_buf->data;
86 for (i = 0; i < qsv->nb_surfaces; i++)
87 qsv->surface_ptrs[i] = surfaces + i;
88
89 qsv->opaque_alloc.Out.Surfaces = qsv->surface_ptrs;
90 qsv->opaque_alloc.Out.NumSurface = qsv->nb_surfaces;
91 qsv->opaque_alloc.Out.Type = hwctx_enc->opaque_alloc_type;
92
93 qsv->opaque_alloc.Header.BufferId = MFX_EXTBUFF_OPAQUE_SURFACE_ALLOCATION;
94 qsv->opaque_alloc.Header.BufferSz = sizeof(qsv->opaque_alloc);
95 qsv->ext_buffers[0] = (mfxExtBuffer*)&qsv->opaque_alloc;
96
97 return 0;
98}
99
100static void qsv_uninit(AVCodecContext *s)
101{
102 InputStream *ist = s->opaque;
103 QSVContext *qsv = ist->hwaccel_ctx;
104
105 av_freep(&qsv->ost->enc_ctx->hwaccel_context);
106 av_freep(&s->hwaccel_context);
107
108 av_buffer_unref(&qsv->opaque_surfaces_buf);
109 av_freep(&qsv->surface_used);
110 av_freep(&qsv->surface_ptrs);
111
112 av_freep(&qsv);
113}
114
115int qsv_init(AVCodecContext *s)
116{
117 InputStream *ist = s->opaque;
118 QSVContext *qsv = ist->hwaccel_ctx;
119 AVQSVContext *hwctx_dec;
120 int ret;
121
122 if (!qsv) {
123 av_log(NULL, AV_LOG_ERROR, "QSV transcoding is not initialized. "
124 "-hwaccel qsv should only be used for one-to-one QSV transcoding "
125 "with no filters.\n");
126 return AVERROR_BUG;
127 }
128
129 ret = init_opaque_surf(qsv);
130 if (ret < 0)
131 return ret;
132
133 hwctx_dec = av_qsv_alloc_context();
134 if (!hwctx_dec)
135 return AVERROR(ENOMEM);
136
137 hwctx_dec->session = qsv->session;
138 hwctx_dec->iopattern = MFX_IOPATTERN_OUT_OPAQUE_MEMORY;
139 hwctx_dec->ext_buffers = qsv->ext_buffers;
140 hwctx_dec->nb_ext_buffers = FF_ARRAY_ELEMS(qsv->ext_buffers);
141
142 av_freep(&s->hwaccel_context);
143 s->hwaccel_context = hwctx_dec;
144
145 ist->hwaccel_get_buffer = qsv_get_buffer;
146 ist->hwaccel_uninit = qsv_uninit;
147
148 return 0;
149}
150
151static mfxIMPL choose_implementation(const InputStream *ist)
152{
153 static const struct {
154 const char *name;
155 mfxIMPL impl;
156 } impl_map[] = {
157 { "auto", MFX_IMPL_AUTO },
158 { "sw", MFX_IMPL_SOFTWARE },
159 { "hw", MFX_IMPL_HARDWARE },
160 { "auto_any", MFX_IMPL_AUTO_ANY },
161 { "hw_any", MFX_IMPL_HARDWARE_ANY },
162 { "hw2", MFX_IMPL_HARDWARE2 },
163 { "hw3", MFX_IMPL_HARDWARE3 },
164 { "hw4", MFX_IMPL_HARDWARE4 },
165 };
166
167 mfxIMPL impl = MFX_IMPL_AUTO_ANY;
168 int i;
169
170 if (ist->hwaccel_device) {
171 for (i = 0; i < FF_ARRAY_ELEMS(impl_map); i++)
172 if (!strcmp(ist->hwaccel_device, impl_map[i].name)) {
173 impl = impl_map[i].impl;
174 break;
175 }
176 if (i == FF_ARRAY_ELEMS(impl_map))
177 impl = strtol(ist->hwaccel_device, NULL, 0);
178 }
179
180 return impl;
181}
182
183int qsv_transcode_init(OutputStream *ost)
184{
185 InputStream *ist;
186 const enum AVPixelFormat *pix_fmt;
187
188 AVDictionaryEntry *e;
189 const AVOption *opt;
190 int flags = 0;
191
192 int err, i;
193
194 QSVContext *qsv = NULL;
195 AVQSVContext *hwctx = NULL;
196 mfxIMPL impl;
197 mfxVersion ver = { { 3, 1 } };
198
199 /* check if the encoder supports QSV */
200 if (!ost->enc->pix_fmts)
201 return 0;
202 for (pix_fmt = ost->enc->pix_fmts; *pix_fmt != AV_PIX_FMT_NONE; pix_fmt++)
203 if (*pix_fmt == AV_PIX_FMT_QSV)
204 break;
205 if (*pix_fmt == AV_PIX_FMT_NONE)
206 return 0;
207
208 if (strcmp(ost->avfilter, "null") || ost->source_index < 0)
209 return 0;
210
211 /* check if the decoder supports QSV and the output only goes to this stream */
212 ist = input_streams[ost->source_index];
213 if (ist->nb_filters || ist->hwaccel_id != HWACCEL_QSV ||
214 !ist->dec || !ist->dec->pix_fmts)
215 return 0;
216 for (pix_fmt = ist->dec->pix_fmts; *pix_fmt != AV_PIX_FMT_NONE; pix_fmt++)
217 if (*pix_fmt == AV_PIX_FMT_QSV)
218 break;
219 if (*pix_fmt == AV_PIX_FMT_NONE)
220 return 0;
221
222 for (i = 0; i < nb_output_streams; i++)
223 if (output_streams[i] != ost &&
224 output_streams[i]->source_index == ost->source_index)
225 return 0;
226
227 av_log(NULL, AV_LOG_VERBOSE, "Setting up QSV transcoding\n");
228
229 qsv = av_mallocz(sizeof(*qsv));
230 hwctx = av_qsv_alloc_context();
231 if (!qsv || !hwctx)
232 goto fail;
233
234 impl = choose_implementation(ist);
235
236 err = MFXInit(impl, &ver, &qsv->session);
237 if (err != MFX_ERR_NONE) {
238 av_log(NULL, AV_LOG_ERROR, "Error initializing an MFX session: %d\n", err);
239 goto fail;
240 }
241
242 e = av_dict_get(ost->encoder_opts, "flags", NULL, 0);
243 opt = av_opt_find(ost->enc_ctx, "flags", NULL, 0, 0);
244 if (e && opt)
245 av_opt_eval_flags(ost->enc_ctx, opt, e->value, &flags);
246
247 qsv->ost = ost;
248
249 hwctx->session = qsv->session;
250 hwctx->iopattern = MFX_IOPATTERN_IN_OPAQUE_MEMORY;
251 hwctx->opaque_alloc = 1;
252 hwctx->nb_opaque_surfaces = 16;
253
254 ost->hwaccel_ctx = qsv;
255 ost->enc_ctx->hwaccel_context = hwctx;
256 ost->enc_ctx->pix_fmt = AV_PIX_FMT_QSV;
257
258 ist->hwaccel_ctx = qsv;
259 ist->dec_ctx->pix_fmt = AV_PIX_FMT_QSV;
260 ist->resample_pix_fmt = AV_PIX_FMT_QSV;
261
262 return 0;
263
264fail:
265 av_freep(&hwctx);
266 av_freep(&qsv);
267 return AVERROR_UNKNOWN;
268}
doc/avconv.texi+24−0
@@ -602,6 +602,16 @@ Use VDPAU (Video Decode and Presentation API for Unix) hardware acceleration. · 601 unmodified lines
602 602
603@item dxva2603@item dxva2
604Use DXVA2 (DirectX Video Acceleration) hardware acceleration.604Use DXVA2 (DirectX Video Acceleration) hardware acceleration.
605
606@item qsv
607Use the Intel QuickSync Video acceleration for video transcoding.
608
609Unlike most other values, this option does not enable accelerated decoding (that
610is used automatically whenever a qsv decoder is selected), but accelerated
611transcoding, without copying the frames into the system memory.
612
613For it to work, both the decoder and the encoder must support QSV acceleration
614and no filters must be used.
605@end table615@end table
606 616
607This option has no effect if the selected hwaccel is not available or not617This option has no effect if the selected hwaccel is not available or not
@@ -628,6 +638,20 @@ is not specified, the value of the @var{DISPLAY} environment variable is used · 20 unmodified lines
628@item dxva2638@item dxva2
629For DXVA2, this option should contain the number of the display adapter to use.639For DXVA2, this option should contain the number of the display adapter to use.
630If this option is not specified, the default adapter is used.640If this option is not specified, the default adapter is used.
641
642@item qsv
643For QSV, this option corresponds to the valus of MFX_IMPL_* . Allowed values
644are:
645@table @option
646@item auto
647@item sw
648@item hw
649@item auto_any
650@item hw_any
651@item hw2
652@item hw3
653@item hw4
654@end table
631@end table655@end table
632 656
633@item -hwaccels657@item -hwaccels

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t