FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
ffmpeg_qsv.c
Go to the documentation of this file.
1 /*
2  * This file is part of FFmpeg.
3  *
4  * FFmpeg 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  * FFmpeg 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 FFmpeg; 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 "ffmpeg.h"
28 
29 typedef struct QSVContext {
31 
32  mfxSession session;
33 
34  mfxExtOpaqueSurfaceAlloc opaque_alloc;
36 
38  mfxFrameSurface1 **surface_ptrs;
40 
41  mfxExtBuffer *ext_buffers[1];
42 } QSVContext;
43 
44 static void buffer_release(void *opaque, uint8_t *data)
45 {
46  *(uint8_t*)opaque = 0;
47 }
48 
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 
71 static 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 
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 
101 {
102  InputStream *ist = s->opaque;
103  QSVContext *qsv = ist->hwaccel_ctx;
104 
107 
109  av_freep(&qsv->surface_used);
110  av_freep(&qsv->surface_ptrs);
111 
112  av_freep(&qsv);
113 }
114 
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 
143  s->hwaccel_context = hwctx_dec;
144 
146  ist->hwaccel_uninit = qsv_uninit;
147 
148  return 0;
149 }
150 
151 static 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 
184 {
185  InputStream *ist;
186  const enum AVPixelFormat *pix_fmt;
187 
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;
257 
258  ist->hwaccel_ctx = qsv;
261 
262  return 0;
263 
264 fail:
265  av_freep(&hwctx);
266  av_freep(&qsv);
267  return AVERROR_UNKNOWN;
268 }
#define NULL
Definition: coverity.c:32
const char * s
Definition: avisynth_c.h:631
static enum AVPixelFormat pix_fmt
void av_buffer_unref(AVBufferRef **buf)
Free a given reference and automatically free the buffer if there are no more references to it...
Definition: buffer.c:124
This structure describes decoded (raw) audio or video data.
Definition: frame.h:181
AVOption.
Definition: opt.h:245
ptrdiff_t const GLvoid * data
Definition: opengl_enc.c:101
static void qsv_uninit(AVCodecContext *s)
Definition: ffmpeg_qsv.c:100
static int init_opaque_surf(QSVContext *qsv)
Definition: ffmpeg_qsv.c:71
memory handling functions
AVBufferRef * buf[AV_NUM_DATA_POINTERS]
AVBuffer references backing the data for this frame.
Definition: frame.h:357
void * hwaccel_ctx
Definition: ffmpeg.h:422
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition: avcodec.h:1752
int(* hwaccel_get_buffer)(AVCodecContext *s, AVFrame *frame, int flags)
Definition: ffmpeg.h:333
int nb_opaque_surfaces
Encoding only, and only if opaque_alloc is set to non-zero.
Definition: qsv.h:76
Public dictionary API.
uint8_t
void * hwaccel_context
Hardware accelerator context.
Definition: avcodec.h:2855
mfxExtBuffer * ext_buffers[1]
Definition: ffmpeg_qsv.c:41
AVOptions.
int nb_surfaces
Definition: ffmpeg_qsv.c:39
int qsv_transcode_init(OutputStream *ost)
Definition: ffmpeg_qsv.c:183
int opaque_alloc
Encoding only.
Definition: qsv.h:65
static AVFrame * frame
AVDictionaryEntry * av_dict_get(const AVDictionary *m, const char *key, const AVDictionaryEntry *prev, int flags)
Get a dictionary entry with matching key.
Definition: dict.c:39
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:192
mfxFrameSurface1 ** surface_ptrs
Definition: ffmpeg_qsv.c:38
AVCodec * dec
Definition: ffmpeg.h:264
int nb_output_streams
Definition: ffmpeg.c:143
int resample_pix_fmt
Definition: ffmpeg.h:295
#define av_log(a,...)
int opaque_alloc_type
Encoding only, and only if opaque_alloc is set to non-zero.
Definition: qsv.h:97
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
void(* hwaccel_uninit)(AVCodecContext *s)
Definition: ffmpeg.h:332
static mfxIMPL choose_implementation(const InputStream *ist)
Definition: ffmpeg_qsv.c:151
#define AVERROR(e)
Definition: error.h:43
int av_opt_eval_flags(void *obj, const AVOption *o, const char *val, int *flags_out)
AVBufferRef * av_buffer_create(uint8_t *data, int size, void(*free)(void *opaque, uint8_t *data), void *opaque, int flags)
Create an AVBuffer from an existing array.
Definition: buffer.c:28
int iopattern
The IO pattern to use.
Definition: qsv.h:46
#define fail()
Definition: checkasm.h:80
int nb_ext_buffers
Definition: qsv.h:52
const AVOption * av_opt_find(void *obj, const char *name, const char *unit, int opt_flags, int search_flags)
Look for an option in an object.
Definition: opt.c:1497
enum AVPixelFormat * pix_fmts
array of supported pixel formats, or NULL if unknown, array is terminated by -1
Definition: avcodec.h:3413
int qsv_init(AVCodecContext *s)
Definition: ffmpeg_qsv.c:115
uint8_t * surface_used
Definition: ffmpeg_qsv.c:37
#define FF_ARRAY_ELEMS(a)
static int qsv_get_buffer(AVCodecContext *s, AVFrame *frame, int flags)
Definition: ffmpeg_qsv.c:49
mfxExtBuffer ** ext_buffers
Extra buffers to pass to encoder or decoder initialization.
Definition: qsv.h:51
main external API structure.
Definition: avcodec.h:1532
uint8_t * data
The data buffer.
Definition: buffer.h:89
AVCodecContext * enc_ctx
Definition: ffmpeg.h:414
#define AVERROR_BUG
Internal bug, also see AVERROR_BUG2.
Definition: error.h:50
AVCodecContext * dec_ctx
Definition: ffmpeg.h:263
AVBufferRef * opaque_surfaces
Encoding only, and only if opaque_alloc is set to non-zero.
Definition: qsv.h:90
OutputStream ** output_streams
Definition: ffmpeg.c:142
AVQSVContext * av_qsv_alloc_context(void)
Allocate a new context.
Definition: qsv_api.c:38
HW acceleration through QSV, data[3] contains a pointer to the mfxFrameSurface1 structure.
Definition: pixfmt.h:236
This struct is used for communicating QSV parameters between libavcodec and the caller.
Definition: qsv.h:36
int source_index
Definition: ffmpeg.h:400
int nb_filters
Definition: ffmpeg.h:321
static int flags
Definition: cpu.c:47
static void buffer_release(void *opaque, uint8_t *data)
Definition: ffmpeg_qsv.c:44
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:192
OutputStream * ost
Definition: ffmpeg_qsv.c:30
A reference to a data buffer.
Definition: buffer.h:81
AVBufferRef * opaque_surfaces_buf
Definition: ffmpeg_qsv.c:35
AVBufferRef * av_buffer_ref(AVBufferRef *buf)
Create a new reference to an AVBuffer.
Definition: buffer.c:92
#define AVERROR_UNKNOWN
Unknown error, typically from an external library.
Definition: error.h:71
AVCodec * enc
Definition: ffmpeg.h:415
char * avfilter
Definition: ffmpeg.h:449
char * value
Definition: dict.h:88
void * hwaccel_ctx
Definition: ffmpeg.h:331
mfxSession session
Definition: ffmpeg_qsv.c:32
char * hwaccel_device
Definition: ffmpeg.h:327
AVDictionary * encoder_opts
Definition: ffmpeg.h:453
static void * av_mallocz_array(size_t nmemb, size_t size)
Definition: mem.h:229
#define av_freep(p)
enum HWAccelID hwaccel_id
Definition: ffmpeg.h:326
mfxExtOpaqueSurfaceAlloc opaque_alloc
Definition: ffmpeg_qsv.c:34
AVPixelFormat
Pixel format.
Definition: pixfmt.h:61
mfxSession session
If non-NULL, the session to use for encoding or decoding.
Definition: qsv.h:41
void * av_mallocz(size_t size)
Allocate a block of size bytes with alignment suitable for all memory accesses (including vectors if ...
Definition: mem.c:252
void * opaque
Private data of the user, can be used to carry app specific stuff.
Definition: avcodec.h:1589
for(j=16;j >0;--j)
InputStream ** input_streams
Definition: ffmpeg.c:137
const char * name
Definition: opengl_enc.c:103