1 /*****************************************************************************
2 * qsv.c: mpeg4-part10/mpeg2 video encoder using Intel Media SDK
3 *****************************************************************************
4 * Copyright (C) 2013 VideoLabs
6 * Authors: Julien 'Lta' BALLET <contact@lta.io>
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU Lesser General Public License as published by
10 * the Free Software Foundation; either version 2.1 of the License, or
11 * (at your option) any later version.
13 * This program 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
16 * GNU Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21 *****************************************************************************/
23 /*****************************************************************************
25 *****************************************************************************/
30 #include <vlc_common.h>
31 #include <vlc_plugin.h>
32 #include <vlc_picture.h>
33 #include <vlc_codec.h>
34 #include <vlc_picture_pool.h>
38 #include <mfx/mfxvideo.h>
39 #include "../demux/mpeg/timestamps.h"
41 #define SOUT_CFG_PREFIX "sout-qsv-"
43 #define QSV_HAVE_CO2 (MFX_VERSION_MAJOR > 1 || (MFX_VERSION_MAJOR == 1 && MFX_VERSION_MINOR >= 6))
45 /* Default wait on libavcodec */
46 #define QSV_SYNCPOINT_WAIT (1000)
47 /* Encoder input synchronization busy wait loop time */
48 #define QSV_BUSYWAIT_TIME VLC_HARD_MIN_SLEEP
49 /* The SDK doesn't have a default bitrate, so here's one. */
50 #define QSV_BITRATE_DEFAULT (842)
52 /*****************************************************************************
54 *****************************************************************************/
55 static int Open(vlc_object_t
*);
56 static void Close(vlc_object_t
*);
58 #define SW_IMPL_TEXT N_("Enable software mode")
59 #define SW_IMPL_LONGTEXT N_("Allow the use of the Intel Media SDK software " \
60 "implementation of the codecs if no QuickSync Video hardware " \
61 "acceleration is present on the system.")
63 #define PROFILE_TEXT N_("Codec Profile")
64 #define PROFILE_LONGTEXT N_( \
65 "Specify the codec profile explicitly. If you don't, the codec will " \
66 "determine the correct profile from other sources, such as resolution " \
67 "and bitrate. E.g. 'high'")
69 #define LEVEL_TEXT N_("Codec Level")
70 #define LEVEL_LONGTEXT N_( \
71 "Specify the codec level explicitly. If you don't, the codec will " \
72 "determine the correct profile from other sources, such as resolution " \
73 "and bitrate. E.g. '4.2' for mpeg4-part10 or 'low' for mpeg2")
75 #define GOP_SIZE_TEXT N_("Group of Picture size")
76 #define GOP_SIZE_LONGTEXT N_( \
77 "Number of pictures within the current GOP (Group of Pictures); if " \
78 "GopPicSize=0, then the GOP size is unspecified. If GopPicSize=1, " \
79 "only I-frames are used.")
81 #define GOP_REF_DIST_TEXT N_("Group of Picture Reference Distance")
82 #define GOP_REF_DIST_LONGTEXT N_( \
83 "Distance between I- or P- key frames; if it is zero, the GOP " \
84 "structure is unspecified. Note: If GopRefDist = 1, there are no B-" \
87 #define TARGET_USAGE_TEXT N_("Target Usage")
88 #define TARGET_USAGE_LONGTEXT N_("The target usage allow to choose between " \
89 "different trade-offs between quality and speed. Allowed values are: " \
90 "'speed', 'balanced' and 'quality'.")
92 #define IDR_INTERVAL_TEXT N_("IDR interval")
93 #define IDR_INTERVAL_LONGTEXT N_( \
94 "For H.264, IdrInterval specifies IDR-frame interval in terms of I-" \
95 "frames; if IdrInterval=0, then every I-frame is an IDR-frame. If " \
96 "IdrInterval=1, then every other I-frame is an IDR-frame, etc. " \
97 "For MPEG2, IdrInterval defines sequence header interval in terms " \
98 "of I-frames. If IdrInterval=N, SDK inserts the sequence header " \
99 "before every Nth I-frame. If IdrInterval=0 (default), SDK inserts " \
100 "the sequence header once at the beginning of the stream.")
102 #define RATE_CONTROL_TEXT N_("Rate Control Method")
103 #define RATE_CONTROL_LONGTEXT N_( \
104 "The rate control method to use when encoding. Can be one of " \
105 "'cbr', 'vbr', 'qp', 'avbr'. 'qp' mode isn't supported for mpeg2.")
107 #define QP_TEXT N_("Quantization parameter")
108 #define QP_LONGTEXT N_("Quantization parameter for all types of frames. " \
109 "This parameters sets qpi, qpp and qpb. It has less precedence than " \
110 "the forementionned parameters. Used only if rc_method is 'qp'.")
112 #define QPI_TEXT N_("Quantization parameter for I-frames")
113 #define QPI_LONGTEXT N_("Quantization parameter for I-frames. This parameter " \
114 "overrides any qp set globally. Used only if rc_method is 'qp'.")
116 #define QPP_TEXT N_("Quantization parameter for P-frames")
117 #define QPP_LONGTEXT N_("Quantization parameter for P-frames. This parameter " \
118 "overrides any qp set globally. Used only if rc_method is 'qp'.")
120 #define QPB_TEXT N_("Quantization parameter for B-frames")
121 #define QPB_LONGTEXT N_("Quantization parameter for B-frames. This parameter " \
122 "overrides any qp set globally. Used only if rc_method is 'qp'.")
124 #define MAX_BITRATE_TEXT N_("Maximum Bitrate")
125 #define MAX_BITRATE_LONGTEXT N_("Defines the maximum bitrate in kbps " \
126 "(1000 bits/s) for VBR rate control method. If not set, this parameter" \
127 " is computed from other sources such as bitrate, profile, level, etc.")
129 #define ACCURACY_TEXT N_("Accuracy of RateControl")
130 #define ACCURACY_LONGTEXT N_("Tolerance in percentage of the 'avbr' " \
131 " (Average Variable BitRate) method. (e.g. 10 with a bitrate of 800 " \
132 " kbps means the encoder tries not to go above 880 kbps and under " \
133 " 730 kbps. The targeted accuracy is only reached after a certained " \
134 " convergence period. See the convergence parameter")
136 #define CONVERGENCE_TEXT N_("Convergence time of 'avbr' RateControl")
137 #define CONVERGENCE_LONGTEXT N_("Number of 100 frames before the " \
138 "'avbr' rate control method reaches the requested bitrate with " \
139 "the requested accuracy. See the accuracy parameter.")
141 #define NUM_SLICE_TEXT N_("Number of slices per frame")
142 #define NUM_SLICE_LONGTEXT N_("Number of slices in each video frame; "\
143 "each slice contains one or more macro-block rows. If numslice is " \
144 "not set, the encoder may choose any slice partitioning allowed " \
145 "by the codec standard.")
147 #define NUM_REF_FRAME_TEXT N_("Number of reference frames")
148 #define NUM_REF_FRAME_LONGTEXT N_("Number of reference frames")
150 #define ASYNC_DEPTH_TEXT N_("Number of parallel operations")
151 #define ASYNC_DEPTH_LONGTEXT N_("Defines the number of parallel " \
152 "encoding operations before we synchronise the result. Higher " \
153 "numbers may result on better throughput depending on hardware. " \
154 "MPEG2 needs at least 1 here.")
156 static const int profile_h264_list
[] =
157 { MFX_PROFILE_UNKNOWN
, MFX_PROFILE_AVC_CONSTRAINED_BASELINE
, MFX_PROFILE_AVC_MAIN
,
158 MFX_PROFILE_AVC_EXTENDED
, MFX_PROFILE_AVC_HIGH
};
159 static const char *const profile_h264_text
[] =
160 { "decide", "baseline", "main", "extended", "high" };
162 static const int profile_mpeg2_list
[] =
163 { MFX_PROFILE_UNKNOWN
, MFX_PROFILE_MPEG2_SIMPLE
, MFX_PROFILE_MPEG2_MAIN
,
164 MFX_PROFILE_MPEG2_HIGH
};
165 static const char *const profile_mpeg2_text
[] =
166 { "decide", "simple", "main", "high" };
168 static const int level_h264_list
[] =
169 { MFX_LEVEL_UNKNOWN
, MFX_LEVEL_AVC_1
, MFX_LEVEL_AVC_1b
, MFX_LEVEL_AVC_12
,
170 MFX_LEVEL_AVC_13
, MFX_LEVEL_AVC_2
, MFX_LEVEL_AVC_21
, MFX_LEVEL_AVC_22
,
171 MFX_LEVEL_AVC_3
, MFX_LEVEL_AVC_31
, MFX_LEVEL_AVC_32
, MFX_LEVEL_AVC_4
,
172 MFX_LEVEL_AVC_41
, MFX_LEVEL_AVC_42
, MFX_LEVEL_AVC_5
, MFX_LEVEL_AVC_51
,
174 static const char *const level_h264_text
[] =
175 { "decide", "1", "1.1b", "1.2", "1.3", "2", "2.1", "2.2", "3", "3.1",
176 "3.2", "4", "4.1", "4.2", "5", "5.1", "5.2" };
178 static const int level_mpeg2_list
[] =
179 { MFX_LEVEL_UNKNOWN
, MFX_LEVEL_MPEG2_LOW
, MFX_LEVEL_MPEG2_MAIN
,
180 MFX_LEVEL_MPEG2_HIGH
, MFX_LEVEL_MPEG2_HIGH1440
};
181 static const char *const level_mpeg2_text
[] =
182 { "decide", "low", "main", "high", "high1440" };
184 static const int target_usage_list
[] =
185 { MFX_TARGETUSAGE_UNKNOWN
, MFX_TARGETUSAGE_BEST_QUALITY
, MFX_TARGETUSAGE_BALANCED
,
186 MFX_TARGETUSAGE_BEST_SPEED
};
187 static const char *const target_usage_text
[] =
188 { "decide", "quality", "balanced", "speed" };
190 static const int rc_method_list
[] =
191 { MFX_RATECONTROL_CBR
, MFX_RATECONTROL_VBR
,
192 MFX_RATECONTROL_CQP
, MFX_RATECONTROL_AVBR
};
193 static const char *const rc_method_text
[] =
194 { "cbr", "vbr", "qp", "avbr" };
197 set_category(CAT_INPUT
)
198 set_subcategory(SUBCAT_INPUT_VCODEC
)
199 set_description(N_("Intel QuickSync Video encoder for MPEG4-Part10/MPEG2 (aka H.264/H.262)"))
201 set_capability("encoder", 0)
202 set_callbacks(Open
, Close
)
204 add_bool(SOUT_CFG_PREFIX
"software", false, SW_IMPL_TEXT
, SW_IMPL_LONGTEXT
, true)
206 add_string(SOUT_CFG_PREFIX
"h264-profile", "unspecified" , PROFILE_TEXT
, PROFILE_LONGTEXT
, false)
207 change_string_list(profile_h264_text
, profile_h264_text
)
209 add_string(SOUT_CFG_PREFIX
"h264-level", "unspecified", LEVEL_TEXT
, LEVEL_LONGTEXT
, false)
210 change_string_list(level_h264_text
, level_h264_text
)
212 add_string(SOUT_CFG_PREFIX
"mpeg2-profile", "unspecified", PROFILE_TEXT
, PROFILE_LONGTEXT
, false)
213 change_string_list(profile_mpeg2_text
, profile_mpeg2_text
)
215 add_string(SOUT_CFG_PREFIX
"mpeg2-level", "unspecified", LEVEL_TEXT
, LEVEL_LONGTEXT
, false)
216 change_string_list(level_mpeg2_text
, level_mpeg2_text
)
218 add_integer(SOUT_CFG_PREFIX
"gop-size", 32, GOP_SIZE_TEXT
, GOP_SIZE_LONGTEXT
, true)
219 add_integer(SOUT_CFG_PREFIX
"gop-refdist", 4, GOP_REF_DIST_TEXT
, GOP_REF_DIST_LONGTEXT
, true)
220 add_integer(SOUT_CFG_PREFIX
"idr-interval", 0, IDR_INTERVAL_TEXT
, IDR_INTERVAL_LONGTEXT
, true)
222 add_string(SOUT_CFG_PREFIX
"target-usage", "quality", TARGET_USAGE_TEXT
, TARGET_USAGE_LONGTEXT
, false)
223 change_string_list(target_usage_text
, target_usage_text
)
225 add_string(SOUT_CFG_PREFIX
"rc-method", "vbr", RATE_CONTROL_TEXT
, RATE_CONTROL_LONGTEXT
, true)
226 change_string_list(rc_method_text
, rc_method_text
)
228 add_integer(SOUT_CFG_PREFIX
"qp", 0, QP_TEXT
, QP_LONGTEXT
, true)
229 change_integer_range(0, 51)
230 add_integer(SOUT_CFG_PREFIX
"qpi", 0, QPI_TEXT
, QPI_LONGTEXT
, true)
231 change_integer_range(0, 51)
232 add_integer(SOUT_CFG_PREFIX
"qpp", 0, QPP_TEXT
, QPP_LONGTEXT
, true)
233 change_integer_range(0, 51)
234 add_integer(SOUT_CFG_PREFIX
"qpb", 0, QPB_TEXT
, QPB_LONGTEXT
, true)
235 change_integer_range(0, 51)
237 add_integer(SOUT_CFG_PREFIX
"bitrate-max", 0, MAX_BITRATE_TEXT
, MAX_BITRATE_LONGTEXT
, true)
239 add_integer(SOUT_CFG_PREFIX
"accuracy", 0, ACCURACY_TEXT
, ACCURACY_LONGTEXT
, true)
240 change_integer_range(0, 100)
242 add_integer(SOUT_CFG_PREFIX
"convergence", 0, CONVERGENCE_TEXT
, CONVERGENCE_LONGTEXT
, true)
244 add_integer(SOUT_CFG_PREFIX
"num-slice", 0, NUM_SLICE_TEXT
, NUM_SLICE_LONGTEXT
, true)
245 add_integer(SOUT_CFG_PREFIX
"num-ref-frame", 0, NUM_REF_FRAME_TEXT
, NUM_REF_FRAME_LONGTEXT
, true)
247 add_integer(SOUT_CFG_PREFIX
"async-depth", 4, ASYNC_DEPTH_TEXT
, ASYNC_DEPTH_LONGTEXT
, true)
248 change_integer_range(1, 32)
252 /*****************************************************************************
254 *****************************************************************************/
255 static const char *const sout_options
[] = {
256 "software", "h264-profile", "h264-level", "mpeg2-profile", "mpeg2-level",
257 "gop-size", "gop-refdist", "target-usage", "rc-method", "qp", "qpi", "qpp",
258 "qpb", "bitrate-max", "accuracy", "convergence", "num-slice",
259 "num-ref-frame", "async-depth",
263 // Frame pool for QuickSync video encoder with Intel Media SDK's format frames.
264 typedef struct _QSVFrame
266 struct _QSVFrame
*next
;
268 mfxFrameSurface1 surface
;
269 mfxEncodeCtrl enc_ctrl
;
273 typedef struct async_task_t
275 struct vlc_list fifo
;
276 mfxBitstream bs
; // Intel's bitstream structure.
277 mfxSyncPoint
*syncp
; // Async Task Sync Point.
278 block_t
*block
; // VLC's block structure to be returned by Encode.
283 mfxSession session
; // Intel Media SDK Session.
284 mfxVideoParam params
; // Encoding parameters.
285 QSVFrame
*work_frames
; // IntelMediaSDK's frame pool.
286 uint64_t dts_warn_counter
; // DTS warning counter for rate-limiting of msg;
287 uint64_t busy_warn_counter
; // Device Busy warning counter for rate-limiting of msg;
288 uint64_t async_depth
; // Number of parallel encoding operations.
289 struct vlc_list packets
; // FIFO of queued packets
290 vlc_tick_t offset_pts
; // The pts of the first frame, to avoid conversion overflow.
291 vlc_tick_t last_dts
; // The dts of the last frame, to interpolate over buggy dts
293 picture_pool_t
*input_pool
; // pool of pictures to feed the decoder
294 // as it doesn't like constantly changing buffers
297 static block_t
*Encode(encoder_t
*, picture_t
*);
300 static void clear_unused_frames(encoder_sys_t
*sys
)
302 QSVFrame
*cur
= sys
->work_frames
;
304 if (cur
->used
&& !cur
->surface
.Data
.Locked
) {
305 picture_Release(cur
->pic
);
313 * Finds an unlocked frame, releases the associated picture if
314 * necessary associates the new picture with it and return the frame.
315 * Returns 0 if there's an error.
317 static int get_free_frame(encoder_sys_t
*sys
, QSVFrame
**out
)
319 QSVFrame
*frame
, **last
;
321 clear_unused_frames(sys
);
323 frame
= sys
->work_frames
;
324 last
= &sys
->work_frames
;
336 frame
= calloc(1,sizeof(QSVFrame
));
337 if (unlikely(frame
==NULL
))
347 static uint64_t qsv_params_get_value(const char *const *text
,
349 size_t size
, char *sel
)
356 size
/= sizeof(list
[0]);
357 for (size_t i
= 0; i
< size
; i
++)
358 if (!strcmp(sel
, text
[i
])) {
363 // sel comes from var_InheritString and must be freed.
365 // Returns the found item, or the default/first one if not found.
369 static int Open(vlc_object_t
*this)
371 encoder_t
*enc
= (encoder_t
*)this;
372 encoder_sys_t
*sys
= NULL
;
374 mfxStatus sts
= MFX_ERR_NONE
;
375 mfxFrameAllocRequest alloc_request
= { 0 };
376 uint8_t sps_buf
[128];
377 uint8_t pps_buf
[128];
378 mfxExtCodingOptionSPSPPS headers
;
379 mfxExtCodingOption co
= {
380 .Header
.BufferId
= MFX_EXTBUFF_CODING_OPTION
,
381 .Header
.BufferSz
= sizeof(co
),
382 .PicTimingSEI
= MFX_CODINGOPTION_ON
,
385 mfxExtCodingOption2 co2
= {
386 .Header
.BufferId
= MFX_EXTBUFF_CODING_OPTION2
,
387 .Header
.BufferSz
= sizeof(co2
),
390 mfxExtBuffer
*init_params
[] =
397 mfxExtBuffer
*extended_params
[] = {
398 (mfxExtBuffer
*)&headers
,
404 mfxVersion ver
= { { 1, 1 } };
406 mfxVideoParam param_out
= { 0 };
411 if (enc
->fmt_out
.i_codec
!= VLC_CODEC_H264
&&
412 enc
->fmt_out
.i_codec
!= VLC_CODEC_MPGV
&& !enc
->obj
.force
)
415 if (!enc
->fmt_in
.video
.i_visible_height
|| !enc
->fmt_in
.video
.i_visible_width
||
416 !enc
->fmt_in
.video
.i_frame_rate
|| !enc
->fmt_in
.video
.i_frame_rate_base
) {
417 msg_Err(enc
, "Framerate and picture dimensions must be non-zero");
421 /* Allocate the memory needed to store the decoder's structure */
422 sys
= calloc(1, sizeof(encoder_sys_t
));
426 /* Initialize dispatcher, it will loads the actual SW/HW Implementation */
427 sts
= MFXInit(MFX_IMPL_AUTO_ANY
, &ver
, &sys
->session
);
429 if (sts
!= MFX_ERR_NONE
) {
430 if (sts
== MFX_ERR_UNSUPPORTED
)
431 msg_Err(enc
, "Intel Media SDK implementation not supported, is your card plugged?");
433 msg_Err(enc
, "Unable to find an Intel Media SDK implementation (%d).", sts
);
440 vlc_list_init(&sys
->packets
);
442 config_ChainParse(enc
, SOUT_CFG_PREFIX
, sout_options
, enc
->p_cfg
);
444 /* Checking if we are on software and are allowing it */
445 MFXQueryIMPL(sys
->session
, &impl
);
446 if (!var_InheritBool(enc
, SOUT_CFG_PREFIX
"software") && (impl
& MFX_IMPL_SOFTWARE
)) {
447 msg_Err(enc
, "No hardware implementation found and software mode disabled");
451 msg_Dbg(enc
, "Using Intel QuickSync Video %s implementation",
452 impl
& MFX_IMPL_HARDWARE
? "hardware" : "software");
454 /* Input picture format description */
455 sys
->params
.mfx
.FrameInfo
.FrameRateExtN
= enc
->fmt_in
.video
.i_frame_rate
;
456 sys
->params
.mfx
.FrameInfo
.FrameRateExtD
= enc
->fmt_in
.video
.i_frame_rate_base
;
457 sys
->params
.mfx
.FrameInfo
.FourCC
= MFX_FOURCC_NV12
;
458 sys
->params
.mfx
.FrameInfo
.ChromaFormat
= MFX_CHROMAFORMAT_YUV420
;
459 sys
->params
.mfx
.FrameInfo
.Width
= vlc_align(enc
->fmt_in
.video
.i_width
, 16);
460 sys
->params
.mfx
.FrameInfo
.Height
= vlc_align(enc
->fmt_in
.video
.i_height
, 32);
461 sys
->params
.mfx
.FrameInfo
.CropW
= enc
->fmt_in
.video
.i_visible_width
;
462 sys
->params
.mfx
.FrameInfo
.CropH
= enc
->fmt_in
.video
.i_visible_height
;
463 sys
->params
.mfx
.FrameInfo
.PicStruct
= MFX_PICSTRUCT_PROGRESSIVE
;
464 sys
->params
.mfx
.FrameInfo
.AspectRatioH
= enc
->fmt_in
.video
.i_sar_num
;
465 sys
->params
.mfx
.FrameInfo
.AspectRatioW
= enc
->fmt_in
.video
.i_sar_den
;
466 sys
->params
.mfx
.FrameInfo
.BitDepthChroma
= 8; /* for VLC_CODEC_NV12 */
467 sys
->params
.mfx
.FrameInfo
.BitDepthLuma
= 8; /* for VLC_CODEC_NV12 */
469 /* Parsing options common to all RC methods and codecs */
470 sys
->params
.IOPattern
= MFX_IOPATTERN_OUT_SYSTEM_MEMORY
;
471 sys
->params
.IOPattern
|= MFX_IOPATTERN_IN_SYSTEM_MEMORY
;
472 sys
->params
.AsyncDepth
= var_InheritInteger(enc
, SOUT_CFG_PREFIX
"async-depth");
473 sys
->params
.mfx
.GopOptFlag
= 1; /* TODO */
474 sys
->params
.mfx
.GopPicSize
= var_InheritInteger(enc
, SOUT_CFG_PREFIX
"gop-size");
475 sys
->params
.mfx
.GopRefDist
= var_InheritInteger(enc
, SOUT_CFG_PREFIX
"gop-refdist");
476 sys
->params
.mfx
.IdrInterval
= var_InheritInteger(enc
, SOUT_CFG_PREFIX
"idr-interval");
477 sys
->params
.mfx
.NumSlice
= var_InheritInteger(enc
, SOUT_CFG_PREFIX
"num-slice");
478 sys
->params
.mfx
.NumRefFrame
= var_InheritInteger(enc
, SOUT_CFG_PREFIX
"num-ref-frame");
479 sys
->params
.mfx
.TargetUsage
= qsv_params_get_value(target_usage_text
,
480 target_usage_list
, sizeof(target_usage_list
),
481 var_InheritString(enc
, SOUT_CFG_PREFIX
"target-usage"));
483 if (enc
->fmt_out
.i_codec
== VLC_CODEC_H264
) {
484 sys
->params
.mfx
.CodecId
= MFX_CODEC_AVC
;
485 sys
->params
.mfx
.CodecProfile
= qsv_params_get_value(profile_h264_text
,
486 profile_h264_list
, sizeof(profile_h264_list
),
487 var_InheritString(enc
, SOUT_CFG_PREFIX
"h264-profile"));
488 sys
->params
.mfx
.CodecLevel
= qsv_params_get_value(level_h264_text
,
489 level_h264_list
, sizeof(level_h264_list
),
490 var_InheritString(enc
, SOUT_CFG_PREFIX
"h264-level"));
491 msg_Dbg(enc
, "Encoder in H264 mode, with profile %d and level %d",
492 sys
->params
.mfx
.CodecProfile
, sys
->params
.mfx
.CodecLevel
);
495 sys
->params
.mfx
.CodecId
= MFX_CODEC_MPEG2
;
496 sys
->params
.mfx
.CodecProfile
= qsv_params_get_value(profile_mpeg2_text
,
497 profile_mpeg2_list
, sizeof(profile_mpeg2_list
),
498 var_InheritString(enc
, SOUT_CFG_PREFIX
"mpeg2-profile"));
499 sys
->params
.mfx
.CodecLevel
= qsv_params_get_value(level_mpeg2_text
,
500 level_mpeg2_list
, sizeof(level_mpeg2_list
),
501 var_InheritString(enc
, SOUT_CFG_PREFIX
"mpeg2-level"));
502 msg_Dbg(enc
, "Encoder in MPEG2 mode, with profile %d and level %d",
503 sys
->params
.mfx
.CodecProfile
, sys
->params
.mfx
.CodecLevel
);
505 param_out
.mfx
.CodecId
= sys
->params
.mfx
.CodecId
;
507 char *psz_rc
= var_InheritString(enc
, SOUT_CFG_PREFIX
"rc-method");
508 msg_Dbg(enc
, "Encoder using '%s' Rate Control method", psz_rc
);
509 sys
->params
.mfx
.RateControlMethod
= qsv_params_get_value(rc_method_text
,
510 rc_method_list
, sizeof(rc_method_list
), psz_rc
);
512 if (sys
->params
.mfx
.RateControlMethod
== MFX_RATECONTROL_CQP
) {
513 sys
->params
.mfx
.QPI
= sys
->params
.mfx
.QPB
= sys
->params
.mfx
.QPP
=
514 var_InheritInteger(enc
, SOUT_CFG_PREFIX
"qp");
515 sys
->params
.mfx
.QPI
= var_InheritInteger(enc
, SOUT_CFG_PREFIX
"qpi");
516 sys
->params
.mfx
.QPB
= var_InheritInteger(enc
, SOUT_CFG_PREFIX
"qpb");
517 sys
->params
.mfx
.QPP
= var_InheritInteger(enc
, SOUT_CFG_PREFIX
"qpp");
519 if (!enc
->fmt_out
.i_bitrate
) {
520 msg_Warn(enc
, "No bitrate specified, using default %d",
521 QSV_BITRATE_DEFAULT
);
522 sys
->params
.mfx
.TargetKbps
= QSV_BITRATE_DEFAULT
;
524 sys
->params
.mfx
.TargetKbps
= enc
->fmt_out
.i_bitrate
/ 1000;
526 if (sys
->params
.mfx
.RateControlMethod
== MFX_RATECONTROL_AVBR
) {
527 sys
->params
.mfx
.Accuracy
= var_InheritInteger(enc
, SOUT_CFG_PREFIX
"accuracy");
528 sys
->params
.mfx
.Convergence
= var_InheritInteger(enc
, SOUT_CFG_PREFIX
"convergence");
529 } else if (sys
->params
.mfx
.RateControlMethod
== MFX_RATECONTROL_VBR
)
530 sys
->params
.mfx
.MaxKbps
= var_InheritInteger(enc
, SOUT_CFG_PREFIX
"bitrate-max");
533 sts
= MFXVideoENCODE_Query(sys
->session
, &sys
->params
, ¶m_out
);
534 if ( sts
< MFX_ERR_NONE
)
536 msg_Err(enc
, "Unsupported encoding parameters (%d)", sts
);
540 if ( sys
->params
.mfx
.RateControlMethod
!= param_out
.mfx
.RateControlMethod
)
542 msg_Err(enc
, "Unsupported control method %d got %d", sys
->params
.mfx
.RateControlMethod
, param_out
.mfx
.RateControlMethod
);
546 if (MFXVideoENCODE_Query(sys
->session
, &sys
->params
, &sys
->params
) < 0)
548 msg_Err(enc
, "Error querying encoder params");
552 /* Request number of surface needed and creating frame pool */
553 if (MFXVideoENCODE_QueryIOSurf(sys
->session
, &sys
->params
, &alloc_request
)!= MFX_ERR_NONE
)
555 msg_Err(enc
, "Failed to query for allocation");
559 sys
->params
.ExtParam
= (mfxExtBuffer
**)&init_params
;
560 sys
->params
.NumExtParam
=
567 /* Initializing MFX_Encoder */
568 sts
= MFXVideoENCODE_Init(sys
->session
, &sys
->params
);
569 if (sts
== MFX_ERR_NONE
)
570 msg_Dbg(enc
, "Successfuly initialized video encoder");
571 else if (sts
< MFX_ERR_NONE
) {
572 msg_Err(enc
, "Unable to initialize video encoder error (%d). " \
573 " Most likely because of provided encoding parameters", sts
);
576 msg_Warn(enc
, "Video encoder initialization : %d. The stream might be corrupted/invalid", sts
);
578 /* Querying PPS/SPS Headers, BufferSizeInKB, ... */
579 memset(&headers
, 0, sizeof(headers
));
580 headers
.Header
.BufferId
= MFX_EXTBUFF_CODING_OPTION_SPSPPS
;
581 headers
.Header
.BufferSz
= sizeof(headers
);
582 headers
.PPSBufSize
= sizeof(pps_buf
);
583 headers
.SPSBufSize
= sizeof(sps_buf
);
584 headers
.SPSBuffer
= sps_buf
;
585 headers
.PPSBuffer
= pps_buf
;
586 sys
->params
.ExtParam
= (mfxExtBuffer
**)&extended_params
;
587 sys
->params
.NumExtParam
=
594 MFXVideoENCODE_GetVideoParam(sys
->session
, &sys
->params
);
596 i_extra
= headers
.SPSBufSize
+ headers
.PPSBufSize
;
597 p_extra
= malloc(i_extra
);
599 if (unlikely(!p_extra
))
602 memcpy(p_extra
, headers
.SPSBuffer
, headers
.SPSBufSize
);
603 memcpy(p_extra
+ headers
.SPSBufSize
, headers
.PPSBuffer
, headers
.PPSBufSize
);
604 enc
->fmt_out
.p_extra
= p_extra
;
605 enc
->fmt_out
.i_extra
= i_extra
;
607 sys
->async_depth
= sys
->params
.AsyncDepth
;
609 /* Vlc module configuration */
610 enc
->fmt_in
.i_codec
= VLC_CODEC_NV12
; // Intel Media SDK requirement
611 enc
->fmt_in
.video
.i_chroma
= VLC_CODEC_NV12
;
612 enc
->fmt_in
.video
.i_bits_per_pixel
= 12;
613 // require aligned pictures on input, a filter may be added before the encoder
614 enc
->fmt_in
.video
.i_width
= sys
->params
.mfx
.FrameInfo
.Width
;
615 enc
->fmt_in
.video
.i_height
= sys
->params
.mfx
.FrameInfo
.Height
;
617 sys
->input_pool
= picture_pool_NewFromFormat( &enc
->fmt_in
.video
, 18 );
618 if (sys
->input_pool
== NULL
)
620 msg_Err(enc
, "Failed to create the internal pool");
624 enc
->pf_encode_video
= Encode
;
638 static void Close(vlc_object_t
*this)
640 encoder_t
*enc
= (encoder_t
*)this;
641 encoder_sys_t
*sys
= enc
->p_sys
;
643 MFXVideoENCODE_Close(sys
->session
);
644 MFXClose(sys
->session
);
645 /* if (enc->fmt_out.p_extra) */
646 /* free(enc->fmt_out.p_extra); */
647 assert(vlc_list_is_empty(&sys
->packets
));
649 picture_pool_Release(sys
->input_pool
);
654 * The behavior in the next function comes from x264.c
656 static void qsv_set_block_flags(block_t
*block
, uint16_t frame_type
)
658 if (frame_type
& MFX_FRAMETYPE_IDR
)
659 block
->i_flags
= BLOCK_FLAG_TYPE_I
;
660 else if ((frame_type
& MFX_FRAMETYPE_P
) || (frame_type
& MFX_FRAMETYPE_I
))
661 block
->i_flags
= BLOCK_FLAG_TYPE_P
;
662 else if (frame_type
& MFX_FRAMETYPE_B
)
663 block
->i_flags
= BLOCK_FLAG_TYPE_B
;
665 block
->i_flags
= BLOCK_FLAG_TYPE_PB
;
669 * Convert the Intel Media SDK's timestamps into VLC's format.
671 static void qsv_set_block_ts(encoder_t
*enc
, encoder_sys_t
*sys
, block_t
*block
, mfxBitstream
*bs
)
673 block
->i_pts
= FROM_SCALE_NZ(bs
->TimeStamp
) + sys
->offset_pts
;
674 block
->i_dts
= FROM_SCALE_NZ(bs
->DecodeTimeStamp
) + sys
->offset_pts
;
676 /* HW encoder (with old driver versions) and some parameters
677 combinations doesn't set the DecodeTimeStamp field so we warn
679 if (!bs
->DecodeTimeStamp
|| bs
->DecodeTimeStamp
> (int64_t)bs
->TimeStamp
)
680 if (sys
->dts_warn_counter
++ % 16 == 0) // Rate limiting this message.
681 msg_Warn(enc
, "Encode returning empty DTS or DTS > PTS. Your stream will be invalid. "
682 " Please double-check they weren't any warning at encoder initialization "
683 " and that you have the last version of Intel's drivers installed.");
686 static block_t
*qsv_synchronize_block(encoder_t
*enc
, async_task_t
*task
)
688 encoder_sys_t
*sys
= enc
->p_sys
;
691 /* Synchronize and fill block_t. If the SyncOperation fails we leak :-/ (or we can segfault, ur choice) */
693 sts
= MFXVideoCORE_SyncOperation(sys
->session
, *task
->syncp
, QSV_SYNCPOINT_WAIT
);
694 } while (sts
== MFX_WRN_IN_EXECUTION
);
695 if (sts
!= MFX_ERR_NONE
) {
696 msg_Err(enc
, "SyncOperation failed (%d), outputting garbage data. "
697 "Updating your drivers and/or changing the encoding settings might resolve this", sts
);
700 if (task
->bs
.DataLength
== 0)
702 msg_Dbg(enc
, "Empty encoded block");
705 block_t
*block
= task
->block
;
706 block
->i_buffer
= task
->bs
.DataLength
;
707 block
->p_buffer
+= task
->bs
.DataOffset
;
709 qsv_set_block_ts(enc
, sys
, block
, &task
->bs
);
710 qsv_set_block_flags(block
, task
->bs
.FrameType
);
712 /* msg_Dbg(enc, "block->i_pts = %lld, block->i_dts = %lld", block->i_pts, block->i_dts); */
713 /* msg_Dbg(enc, "FrameType = %#.4x, TimeStamp = %lld (pts %lld), DecodeTimeStamp = %lld syncp=0x%x",*/
714 /* task->bs.FrameType, task->bs.TimeStamp, block->i_pts, task->bs.DecodeTimeStamp, *task->syncp); */
716 /* Copied from x264.c: This isn't really valid for streams with B-frames */
717 block
->i_length
= vlc_tick_from_samples( enc
->fmt_in
.video
.i_frame_rate_base
,
718 enc
->fmt_in
.video
.i_frame_rate
);
720 // Buggy DTS (value comes from experiments)
721 if (task
->bs
.DecodeTimeStamp
< -10000)
722 block
->i_dts
= sys
->last_dts
+ block
->i_length
;
723 sys
->last_dts
= block
->i_dts
;
725 task
->bs
.DataLength
= task
->bs
.DataOffset
= 0;
729 static int submit_frame(encoder_t
*enc
, picture_t
*pic
, QSVFrame
**new_frame
)
731 encoder_sys_t
*sys
= enc
->p_sys
;
733 int ret
= get_free_frame(sys
, &qf
);
734 if (ret
!= VLC_SUCCESS
) {
735 msg_Warn(enc
, "Unable to find an unlocked surface in the pool");
739 qf
->pic
= picture_pool_Get( sys
->input_pool
);
740 if (unlikely(!qf
->pic
))
742 msg_Warn(enc
, "Unable to find an unlocked surface in the pool");
746 picture_Copy( qf
->pic
, pic
);
748 assert(qf
->pic
->p
[0].p_pixels
+ (qf
->pic
->p
[0].i_pitch
* qf
->pic
->p
[0].i_lines
) == qf
->pic
->p
[1].p_pixels
);
750 qf
->surface
.Info
= sys
->params
.mfx
.FrameInfo
;
752 // Specify picture structure at runtime.
753 if (pic
->b_progressive
)
754 qf
->surface
.Info
.PicStruct
= MFX_PICSTRUCT_PROGRESSIVE
;
755 else if (pic
->b_top_field_first
)
756 qf
->surface
.Info
.PicStruct
= MFX_PICSTRUCT_FIELD_TFF
;
758 qf
->surface
.Info
.PicStruct
= MFX_PICSTRUCT_FIELD_BFF
;
760 //qf->surface.Data.Pitch = vlc_align(qf->surface.Info.Width, 16);
762 qf
->surface
.Data
.PitchLow
= qf
->pic
->p
[0].i_pitch
;
763 qf
->surface
.Data
.Y
= qf
->pic
->p
[0].p_pixels
;
764 qf
->surface
.Data
.UV
= qf
->pic
->p
[1].p_pixels
;
766 qf
->surface
.Data
.TimeStamp
= TO_SCALE_NZ(pic
->date
- sys
->offset_pts
);
773 static async_task_t
*encode_frame(encoder_t
*enc
, picture_t
*pic
)
775 encoder_sys_t
*sys
= enc
->p_sys
;
776 mfxStatus sts
= MFX_ERR_MEMORY_ALLOC
;
777 QSVFrame
*qsv_frame
= NULL
;
778 mfxFrameSurface1
*surf
= NULL
;
779 async_task_t
*task
= calloc(1, sizeof(*task
));
780 if (unlikely(task
== NULL
))
784 /* To avoid qsv -> vlc timestamp conversion overflow, we use timestamp relative
785 to the first picture received. That way, vlc will overflow before us.
786 (Thanks to funman for the idea) */
787 if (!sys
->offset_pts
) // First frame
788 sys
->offset_pts
= pic
->date
;
790 if (submit_frame(enc
, pic
, &qsv_frame
) != VLC_SUCCESS
)
792 msg_Warn(enc
, "Unable to find an unlocked surface in the pool");
797 if (!(task
->syncp
= calloc(1, sizeof(*task
->syncp
)))) {
798 msg_Err(enc
, "Unable to allocate syncpoint for encoder output");
802 /* Allocate block_t and prepare mfxBitstream for encoder */
803 if (!(task
->block
= block_Alloc(sys
->params
.mfx
.BufferSizeInKB
* 1000))) {
804 msg_Err(enc
, "Unable to allocate block for encoder output");
807 memset(&task
->bs
, 0, sizeof(task
->bs
));
808 task
->bs
.MaxLength
= task
->block
->i_buffer
;
809 task
->bs
.Data
= task
->block
->p_buffer
;
812 surf
= &qsv_frame
->surface
;
816 sts
= MFXVideoENCODE_EncodeFrameAsync(sys
->session
, 0, surf
, &task
->bs
, task
->syncp
);
817 if (sts
!= MFX_WRN_DEVICE_BUSY
&& sts
!= MFX_WRN_IN_EXECUTION
)
819 if (sys
->busy_warn_counter
++ % 16 == 0)
820 msg_Dbg(enc
, "Device is busy, let's wait and retry %d", sts
);
821 if (sts
== MFX_WRN_DEVICE_BUSY
)
822 vlc_tick_sleep(QSV_BUSYWAIT_TIME
);
825 // msg_Dbg(enc, "Encode async status: %d, Syncpoint = %tx", sts, (ptrdiff_t)task->syncp);
827 if (sts
== MFX_ERR_MORE_DATA
)
829 msg_Dbg(enc
, "Encoder feeding phase, more data is needed.");
831 msg_Dbg(enc
, "Encoder is empty");
832 else if (sts
< MFX_ERR_NONE
) {
833 msg_Err(enc
, "Encoder not ready or error (%d), trying a reset...", sts
);
834 MFXVideoENCODE_Reset(sys
->session
, &sys
->params
);
838 if (sts
< MFX_ERR_NONE
|| (task
!= NULL
&& !task
->syncp
)) {
839 if (task
->block
!= NULL
)
840 block_Release(task
->block
);
848 * The Encode function has 3 encoding phases :
849 * - Feed : We feed the encoder until it stops to return MFX_MORE_DATA_NEEDED
850 * and the async_tasks are all in use (honouring the AsyncDepth)
851 * - Main encoding phase : synchronizing the oldest task each call.
852 * - Empty : pic = 0, we empty the decoder. Synchronizing the remaining tasks.
854 static block_t
*Encode(encoder_t
*this, picture_t
*pic
)
856 encoder_t
*enc
= (encoder_t
*)this;
857 encoder_sys_t
*sys
= enc
->p_sys
;
859 block_t
*block
= NULL
;
861 if (likely(pic
!= NULL
))
863 task
= encode_frame( enc
, pic
);
864 if (likely(task
!= NULL
))
865 vlc_list_append(&sys
->packets
, &task
->fifo
);
868 size_t fifo_count
= 0;
869 vlc_list_foreach( task
, &sys
->packets
, fifo
)
872 if ( fifo_count
== (sys
->async_depth
+ 1) ||
873 (!pic
&& fifo_count
))
875 task
= vlc_list_first_entry_or_null(&sys
->packets
, async_task_t
, fifo
);
876 assert(task
->syncp
!= 0);
877 vlc_list_remove(&task
->fifo
);
878 block
= qsv_synchronize_block( enc
, task
);