1 /*****************************************************************************
2 * qsv.c: mpeg4-part10/mpeg2 video encoder using Intel Media SDK
3 *****************************************************************************
4 * Copyright (C) 2013 VideoLabs
7 * Authors: Julien 'Lta' BALLET <contact@lta.io>
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU Lesser General Public License as published by
11 * the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
14 * This program 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
17 * GNU Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this program; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
31 #include <vlc_common.h>
32 #include <vlc_plugin.h>
33 #include <vlc_picture.h>
34 #include <vlc_codec.h>
36 #include <mfx/mfxvideo.h>
38 #define SOUT_CFG_PREFIX "sout-qsv-"
40 /* Default wait on Intel Media SDK SyncOperation. Almost useless when async-depth >= 2 */
41 #define QSV_SYNCPOINT_WAIT (420)
42 /* Encoder input synchronization busy wait loop time */
43 #define QSV_BUSYWAIT_TIME (10000)
44 /* The SDK doesn't have a default bitrate, so here's one. */
45 #define QSV_BITRATE_DEFAULT (842)
47 /* Makes x a multiple of 'align'. 'align' must be a power of 2 */
48 #define QSV_ALIGN(align, x) (((x)+(align)-1)&~((align)-1))
50 /*****************************************************************************
52 *****************************************************************************/
53 static int Open(vlc_object_t
*);
54 static void Close(vlc_object_t
*);
56 #define SW_IMPL_TEXT N_("Enable software mode")
57 #define SW_IMPL_LONGTEXT N_("Allow the use of the Intel Media SDK software " \
58 "implementation of the codecs if no QuickSync Video hardware " \
59 "acceleration is present on the system.")
61 #define PROFILE_TEXT N_("Codec Profile")
62 #define PROFILE_LONGTEXT N_( \
63 "Specify the codec profile explicitly. If you don't, the codec will " \
64 "determine the correct profile from other sources, such as resolution " \
65 "and bitrate. E.g. 'high'")
67 #define LEVEL_TEXT N_("Codec Level")
68 #define LEVEL_LONGTEXT N_( \
69 "Specify the codec level explicitly. If you don't, the codec will " \
70 "determine the correct profile from other sources, such as resolution " \
71 "and bitrate. E.g. '4.2' for mpeg4-part10 or 'low' for mpeg2")
73 #define GOP_SIZE_TEXT N_("Group of Picture size")
74 #define GOP_SIZE_LONGTEXT N_( \
75 "Number of pictures within the current GOP (Group of Pictures); if " \
76 "GopPicSize=0, then the GOP size is unspecified. If GopPicSize=1, " \
77 "only I-frames are used.")
79 #define GOP_REF_DIST_TEXT N_("Group of Picture Reference Distance")
80 #define GOP_REF_DIST_LONGTEXT N_( \
81 "Distance between I- or P- key frames; if it is zero, the GOP " \
82 "structure is unspecified. Note: If GopRefDist = 1, there are no B- " \
85 #define TARGET_USAGE_TEXT N_("Target Usage")
86 #define TARGET_USAGE_LONGTEXT N_("The target usage allow to choose between " \
87 "different trade-offs between quality and speed. Allowed values are : " \
88 "'speed', 'balanced' and 'quality'.")
90 #define IDR_INTERVAL_TEXT N_("IDR interval")
91 #define IDR_INTERVAL_LONGTEXT N_( \
92 "For H.264, IdrInterval specifies IDR-frame interval in terms of I- " \
93 "frames; if IdrInterval=0, then every I-frame is an IDR-frame. If " \
94 "IdrInterval=1, then every other I-frame is an IDR-frame, etc. " \
95 "For MPEG2, IdrInterval defines sequence header interval in terms " \
96 "of I-frames. If IdrInterval=N, SDK inserts the sequence header " \
97 "before every Nth I-frame. If IdrInterval=0 (default), SDK inserts " \
98 "the sequence header once at the beginning of the stream. ")
100 #define RATE_CONTROL_TEXT N_("Rate Control Method")
101 #define RATE_CONTROL_LONGTEXT N_( \
102 "The rate control method to use when encoding. Can be one of " \
103 "'crb', 'vbr', 'qp', 'avbr'. 'qp' mode isn't supported for mpeg2")
105 #define QP_TEXT N_("Quantization parameter")
106 #define QP_LONGTEXT N_("Quantization parameter for all types of frames. " \
107 "This parameters sets qpi, qpp and qpp. It has less precedence than " \
108 "the forementionned parameters. Used only if rc_method is 'qp'.")
110 #define QPI_TEXT N_("Quantization parameter for I-frames")
111 #define QPI_LONGTEXT N_("Quantization parameter for I-frames. This parameter " \
112 "overrides any qp set globally. Used only if rc_method is 'qp'.")
114 #define QPP_TEXT N_("Quantization parameter for P-frames")
115 #define QPP_LONGTEXT N_("Quantization parameter for P-frames. This parameter " \
116 "overrides any qp set globally. Used only if rc_method is 'qp'.")
118 #define QPB_TEXT N_("Quantization parameter for B-frames")
119 #define QPB_LONGTEXT N_("Quantization parameter for B-frames. This parameter " \
120 "overrides any qp set globally. Used only if rc_method is 'qp'.")
122 #define MAX_BITRATE_TEXT N_("Maximum Bitrate")
123 #define MAX_BITRATE_LONGTEXT N_("Defines the maximum bitrate in Kpbs " \
124 "(1000 bits/s) for VBR rate control method. If not set, this parameter" \
125 " is computed from other sources such as bitrate, profile, level, etc.")
127 #define ACCURACY_TEXT N_("Accuracy of RateControl")
128 #define ACCURACY_LONGTEXT N_("Tolerance in percentage of the 'avbr' " \
129 " (Average Variable BitRate) method. (e.g. 10 with a bitrate of 800 " \
130 " kpbs means the encoder tries not to go above 880 kpbs and under " \
131 " 730 kpbs. The targeted accuracy is only reached after a certained " \
132 " convergence period. See the convergence parameter")
134 #define CONVERGENCE_TEXT N_("Convergence time of 'avbr' RateControl")
135 #define CONVERGENCE_LONGTEXT N_("Number of 100 frames before the " \
136 "'avbr' rate control method reaches the requested bitrate with " \
137 "the requested accuracy. See the accuracy parameter. ")
139 #define NUM_SLICE_TEXT N_("Number of slices per frame")
140 #define NUM_SLICE_LONGTEXT N_("Number of slices in each video frame; "\
141 "each slice contains one or more macro-block rows. If numslice is " \
142 "not set, the encoder may choose any slice partitioning allowed " \
143 "by the codec standard.")
145 #define NUM_REF_FRAME_TEXT N_("Number of reference frames")
146 #define NUM_REF_FRAME_LONGTEXT N_("Number of reference frames")
148 #define ASYNC_DEPTH_TEXT N_("Number of parallel operations")
149 #define ASYNC_DEPTH_LONGTEXT N_("Defines the number of parallel " \
150 "encoding operations before we synchronise the result. Higher " \
151 " may result on better throughput depending on hardware. " \
152 "MPEG2 needs at least 1 here.")
154 static const int const profile_h264_list
[] =
155 { 0, MFX_PROFILE_AVC_BASELINE
, MFX_PROFILE_AVC_MAIN
,
156 MFX_PROFILE_AVC_EXTENDED
, MFX_PROFILE_AVC_HIGH
};
157 static const char *const profile_h264_text
[] =
158 { "decide", "baseline", "main", "extended", "high" };
160 static const int const profile_mpeg2_list
[] =
161 { 0, MFX_PROFILE_MPEG2_SIMPLE
, MFX_PROFILE_MPEG2_MAIN
,
162 MFX_PROFILE_MPEG2_HIGH
};
163 static const char *const profile_mpeg2_text
[] =
164 { "decide", "simple", "main", "high" };
166 static const int const level_h264_list
[] =
167 { 0, 10, 9, 12, 13, 20, 21, 22, 30, 31, 32, 40, 41, 42, 50, 51, 52};
168 static const char *const level_h264_text
[] =
169 { "decide", "1", "1.1b", "1.2", "1.3", "2", "2.1", "2.2", "3", "3.1",
170 "3.2", "4", "4.1", "4.2", "5", "5.1", "5.2" };
172 static const int const level_mpeg2_list
[] =
173 { 0, MFX_LEVEL_MPEG2_LOW
, MFX_LEVEL_MPEG2_MAIN
,
174 MFX_LEVEL_MPEG2_HIGH
, MFX_LEVEL_MPEG2_HIGH1440
};
175 static const char *const level_mpeg2_text
[] =
176 { "decide", "low", "main", "high", "high1440" };
178 static const int const target_usage_list
[] =
179 { 0, MFX_TARGETUSAGE_BEST_QUALITY
, MFX_TARGETUSAGE_BALANCED
,
180 MFX_TARGETUSAGE_BEST_SPEED
};
181 static const char *const target_usage_text
[] =
182 { "decide", "quality", "balanced", "speed" };
184 static const int const rc_method_list
[] =
185 { MFX_RATECONTROL_CBR
, MFX_RATECONTROL_VBR
,
186 MFX_RATECONTROL_CQP
, MFX_RATECONTROL_AVBR
};
187 static const char *const rc_method_text
[] =
188 { "cbr", "vbr", "qp", "avbr" };
191 set_category(CAT_INPUT
)
192 set_subcategory(SUBCAT_INPUT_VCODEC
)
193 set_description(N_("Intel QuickSync Video encoder for MPEG4-Part10/MPEG2 (aka H.264/H.262)"))
195 set_capability("encoder", 0)
196 set_callbacks(Open
, Close
)
198 add_bool(SOUT_CFG_PREFIX
"software", false, SW_IMPL_TEXT
, SW_IMPL_LONGTEXT
, true)
200 add_string(SOUT_CFG_PREFIX
"h264-profile", "unspecified" , PROFILE_TEXT
, PROFILE_LONGTEXT
, false)
201 change_string_list(profile_h264_text
, profile_h264_text
)
203 add_string(SOUT_CFG_PREFIX
"h264-level", "unspecified", LEVEL_TEXT
, LEVEL_LONGTEXT
, false)
204 change_string_list(level_h264_text
, level_h264_text
)
206 add_string(SOUT_CFG_PREFIX
"mpeg2-profile", "unspecified", PROFILE_TEXT
, PROFILE_LONGTEXT
, false)
207 change_string_list(profile_mpeg2_text
, profile_mpeg2_text
)
209 add_string(SOUT_CFG_PREFIX
"mpeg2-level", "unspecified", LEVEL_TEXT
, LEVEL_LONGTEXT
, false)
210 change_string_list(level_mpeg2_text
, level_mpeg2_text
)
212 add_integer(SOUT_CFG_PREFIX
"gop-size", 32, GOP_SIZE_TEXT
, GOP_SIZE_LONGTEXT
, true)
213 add_integer(SOUT_CFG_PREFIX
"gop-refdist", 4, GOP_REF_DIST_TEXT
, GOP_REF_DIST_LONGTEXT
, true)
214 add_integer(SOUT_CFG_PREFIX
"idr-interval", 0, IDR_INTERVAL_TEXT
, IDR_INTERVAL_LONGTEXT
, true)
216 add_string(SOUT_CFG_PREFIX
"target-usage", "quality", TARGET_USAGE_TEXT
, TARGET_USAGE_LONGTEXT
, false)
217 change_string_list(target_usage_text
, target_usage_text
)
219 add_string(SOUT_CFG_PREFIX
"rc-method", "vbr", RATE_CONTROL_TEXT
, RATE_CONTROL_LONGTEXT
, true)
220 change_string_list(rc_method_text
, rc_method_text
)
222 add_integer(SOUT_CFG_PREFIX
"qp", 0, QP_TEXT
, QP_LONGTEXT
, true)
223 change_integer_range(0, 51)
224 add_integer(SOUT_CFG_PREFIX
"qpi", 0, QPI_TEXT
, QPI_LONGTEXT
, true)
225 change_integer_range(0, 51)
226 add_integer(SOUT_CFG_PREFIX
"qpp", 0, QPP_TEXT
, QPP_LONGTEXT
, true)
227 change_integer_range(0, 51)
228 add_integer(SOUT_CFG_PREFIX
"qpb", 0, QPB_TEXT
, QPB_LONGTEXT
, true)
229 change_integer_range(0, 51)
231 add_integer(SOUT_CFG_PREFIX
"bitrate-max", 0, MAX_BITRATE_TEXT
, MAX_BITRATE_LONGTEXT
, true)
233 add_integer(SOUT_CFG_PREFIX
"accuracy", 0, ACCURACY_TEXT
, ACCURACY_LONGTEXT
, true)
234 change_integer_range(0, 100)
236 add_integer(SOUT_CFG_PREFIX
"convergence", 0, CONVERGENCE_TEXT
, CONVERGENCE_LONGTEXT
, true)
238 add_integer(SOUT_CFG_PREFIX
"num-slice", 0, NUM_SLICE_TEXT
, NUM_SLICE_LONGTEXT
, true)
239 add_integer(SOUT_CFG_PREFIX
"num-ref-frame", 0, NUM_REF_FRAME_TEXT
, NUM_REF_FRAME_LONGTEXT
, true)
241 add_integer(SOUT_CFG_PREFIX
"async-depth", 4, ASYNC_DEPTH_TEXT
, ASYNC_DEPTH_LONGTEXT
, true)
242 change_integer_range(1, 32)
246 /*****************************************************************************
248 *****************************************************************************/
249 static const char *const sout_options
[] = {
250 "software", "h264-profile", "h264-level", "mpeg2-profile", "mpeg2-level",
251 "gop-size", "gop-refdist", "target-usage", "rc-method", "qp", "qpi", "qpp",
252 "qpb", "bitrate-max", "accuracy", "convergence", "num-slice",
253 "num-ref-frame", "async-depth",
257 // Frame pool for QuickSync video encoder with Intel Media SDK's format frames.
258 typedef struct qsv_frame_pool_t
260 mfxFrameInfo fmt
; // IntelMediaSDK format info.
261 mfxFrameSurface1
*frames
; // An allocated array of 'size' frames.
262 size_t size
; // The number of frame in the pool.
265 typedef struct async_task_t
267 mfxBitstream bs
; // Intel's bitstream structure.
268 mfxSyncPoint syncp
; // Async Task Sync Point.
269 block_t
*block
; // VLC's block structure to be returned by Encode.
274 mfxSession session
; // Intel Media SDK Session.
275 mfxVideoParam params
; // Encoding parameters.
276 mfxIMPL impl
; // Actual implementation (hw/sw).
277 qsv_frame_pool_t frames
; // IntelMediaSDK's frame pool.
278 uint64_t dts_warn_counter
; // DTS warning counter for rate-limiting of msg;
279 uint64_t busy_warn_counter
; // Device Bussy warning counter for rate-limiting of msg;
280 uint64_t async_depth
; // Number of parallel encoding operations.
281 uint64_t first_task
; // The next sync point to be synchronized.
282 async_task_t
*tasks
; // The async encoding tasks.
283 mtime_t offset_pts
; // The pts of the first frame, to avoid conversion overflow.
284 mtime_t last_dts
; // The dts of the last frame, to interpolate over buggy dts
287 static block_t
*Encode(encoder_t
*, picture_t
*);
290 static inline mtime_t
qsv_timestamp_to_mtime(int64_t mfx_ts
)
292 return mfx_ts
/ INT64_C(9) * INT64_C(100);
295 static inline uint64_t qsv_mtime_to_timestamp(mtime_t vlc_ts
)
297 return vlc_ts
/ UINT64_C(100) * UINT64_C(9);
301 * Create a new frame pool with 'size' frames in it. Pools cannot be resized.
303 static int qsv_frame_pool_Init(qsv_frame_pool_t
*pool
,
304 mfxFrameAllocRequest
*request
,
305 uint64_t async_depth
)
307 size_t size
= request
->NumFrameSuggested
+ async_depth
;
309 pool
->frames
= calloc(size
, sizeof(mfxFrameSurface1
));
310 if (unlikely(!pool
->frames
))
314 memcpy(&pool
->fmt
, &request
->Info
, sizeof(request
->Info
));
316 for (size_t i
= 0; i
< size
; i
++) {
317 memcpy(&pool
->frames
[i
].Info
, &request
->Info
, sizeof(request
->Info
));
318 pool
->frames
[i
].Data
.Pitch
= QSV_ALIGN(32, request
->Info
.Width
);
325 * Destroys a pool frame. Only call this function after a MFXClose
326 * call since we doesn't check for Locked frames.
328 static void qsv_frame_pool_Destroy(qsv_frame_pool_t
*pool
)
330 for (size_t i
= 0; i
< pool
->size
; i
++) {
331 picture_t
*pic
= (picture_t
*) pool
->frames
[i
].Data
.MemId
;
333 picture_Release(pic
);
340 * Finds an unlocked frame, releases the associated picture if
341 * necessary associates the new picture with it and return the frame.
342 * Returns 0 if there's an error.
344 static mfxFrameSurface1
*qsv_frame_pool_Get(qsv_frame_pool_t
*pool
,
347 for (size_t i
= 0; i
< pool
->size
; i
++) {
348 mfxFrameSurface1
*frame
= &pool
->frames
[i
];
349 if (frame
->Data
.Locked
)
351 if (frame
->Data
.MemId
)
352 picture_Release((picture_t
*)frame
->Data
.MemId
);
354 frame
->Data
.MemId
= pic
;
355 frame
->Data
.Y
= pic
->p
[0].p_pixels
;
356 frame
->Data
.U
= pic
->p
[1].p_pixels
;
357 frame
->Data
.V
= pic
->p
[1].p_pixels
+ 1;
358 frame
->Data
.TimeStamp
= qsv_mtime_to_timestamp(pic
->date
);
360 // Specify picture structure at runtime.
361 if (pic
->b_progressive
)
362 frame
->Info
.PicStruct
= MFX_PICSTRUCT_PROGRESSIVE
;
363 else if (pic
->b_top_field_first
)
364 frame
->Info
.PicStruct
= MFX_PICSTRUCT_FIELD_TFF
;
366 frame
->Info
.PicStruct
= MFX_PICSTRUCT_FIELD_BFF
;
376 static uint64_t qsv_params_get_value(const char *const *text
,
377 const int const *list
,
378 size_t size
, char *sel
)
385 size
/= sizeof(list
[0]);
386 for (size_t i
= 0; i
< size
; i
++)
387 if (!strcmp(sel
, text
[i
])) {
392 // sel comes from var_InheritString and must be freed.
394 // Returns the found item, or the default/first one if not found.
398 static int Open(vlc_object_t
*this)
400 encoder_t
*enc
= (encoder_t
*)this;
401 encoder_sys_t
*sys
= NULL
;
403 mfxStatus sts
= MFX_ERR_NONE
;
404 mfxFrameAllocRequest alloc_request
;
405 mfxExtCodingOptionSPSPPS headers
;
406 mfxExtBuffer
*extended_params
[1] = {(mfxExtBuffer
*)&headers
};
412 if (enc
->fmt_out
.i_codec
!= VLC_CODEC_H264
&&
413 enc
->fmt_out
.i_codec
!= VLC_CODEC_MPGV
&& !enc
->obj
.force
)
416 if (!enc
->fmt_in
.video
.i_visible_height
|| !enc
->fmt_in
.video
.i_visible_width
||
417 !enc
->fmt_in
.video
.i_frame_rate
|| !enc
->fmt_in
.video
.i_frame_rate_base
) {
418 msg_Err(enc
, "Framerate and picture dimensions must be non-zero");
422 /* Allocate the memory needed to store the decoder's structure */
423 sys
= calloc(1, sizeof(encoder_sys_t
));
427 /* Initialize dispatcher, it will loads the actual SW/HW Implementation */
428 sts
= MFXInit(MFX_IMPL_AUTO
, 0, &sys
->session
);
430 if (sts
!= MFX_ERR_NONE
) {
431 msg_Err(enc
, "Unable to find an Intel Media SDK implementation.");
436 config_ChainParse(enc
, SOUT_CFG_PREFIX
, sout_options
, enc
->p_cfg
);
438 /* Checking if we are on software and are allowing it */
439 MFXQueryIMPL(sys
->session
, &sys
->impl
);
440 if (!var_InheritBool(enc
, SOUT_CFG_PREFIX
"software") && (sys
->impl
& MFX_IMPL_SOFTWARE
)) {
441 msg_Err(enc
, "No hardware implementation found and software mode disabled");
446 msg_Dbg(enc
, "Using Intel QuickSync Video %s implementation",
447 sys
->impl
& MFX_IMPL_HARDWARE
? "hardware" : "software");
449 /* Vlc module configuration */
451 enc
->fmt_in
.i_codec
= VLC_CODEC_NV12
; // Intel Media SDK requirement
452 enc
->fmt_in
.video
.i_chroma
= VLC_CODEC_NV12
;
453 enc
->fmt_in
.video
.i_bits_per_pixel
= 12;
455 /* Input picture format description */
456 sys
->params
.mfx
.FrameInfo
.FrameRateExtN
= enc
->fmt_in
.video
.i_frame_rate
;
457 sys
->params
.mfx
.FrameInfo
.FrameRateExtD
= enc
->fmt_in
.video
.i_frame_rate_base
;
458 sys
->params
.mfx
.FrameInfo
.FourCC
= MFX_FOURCC_NV12
;
459 sys
->params
.mfx
.FrameInfo
.ChromaFormat
= MFX_CHROMAFORMAT_YUV420
;
460 sys
->params
.mfx
.FrameInfo
.Width
= QSV_ALIGN(16, enc
->fmt_in
.video
.i_width
);
461 sys
->params
.mfx
.FrameInfo
.Height
= QSV_ALIGN(32, enc
->fmt_in
.video
.i_height
);
462 sys
->params
.mfx
.FrameInfo
.CropW
= enc
->fmt_in
.video
.i_visible_width
;
463 sys
->params
.mfx
.FrameInfo
.CropH
= enc
->fmt_in
.video
.i_visible_height
;
464 sys
->params
.mfx
.FrameInfo
.PicStruct
= MFX_PICSTRUCT_UNKNOWN
;
466 /* Parsing options common to all RC methods and codecs */
467 sys
->params
.IOPattern
= MFX_IOPATTERN_IN_SYSTEM_MEMORY
;
468 sys
->params
.AsyncDepth
= var_InheritInteger(enc
, SOUT_CFG_PREFIX
"async-depth");
469 sys
->params
.mfx
.GopPicSize
= var_InheritInteger(enc
, SOUT_CFG_PREFIX
"gop-size");
470 sys
->params
.mfx
.GopRefDist
= var_InheritInteger(enc
, SOUT_CFG_PREFIX
"gop-refdist");
471 sys
->params
.mfx
.IdrInterval
= var_InheritInteger(enc
, SOUT_CFG_PREFIX
"idr-interval");
472 sys
->params
.mfx
.NumSlice
= var_InheritInteger(enc
, SOUT_CFG_PREFIX
"num-slice");
473 sys
->params
.mfx
.NumRefFrame
= var_InheritInteger(enc
, SOUT_CFG_PREFIX
"num-ref-frame");
474 sys
->params
.mfx
.TargetUsage
= qsv_params_get_value(target_usage_text
,
475 target_usage_list
, sizeof(target_usage_list
),
476 var_InheritString(enc
, SOUT_CFG_PREFIX
"target-usage"));
478 if (enc
->fmt_out
.i_codec
== VLC_CODEC_H264
) {
479 sys
->params
.mfx
.CodecId
= MFX_CODEC_AVC
;
480 sys
->params
.mfx
.CodecProfile
= qsv_params_get_value(profile_h264_text
,
481 profile_h264_list
, sizeof(profile_h264_list
),
482 var_InheritString(enc
, SOUT_CFG_PREFIX
"h264-profile"));
483 sys
->params
.mfx
.CodecLevel
= qsv_params_get_value(level_h264_text
,
484 level_h264_list
, sizeof(level_h264_list
),
485 var_InheritString(enc
, SOUT_CFG_PREFIX
"h264-level"));
486 msg_Dbg(enc
, "Encoder in H264 mode, with profile %d and level %d",
487 sys
->params
.mfx
.CodecProfile
, sys
->params
.mfx
.CodecLevel
);
490 sys
->params
.mfx
.CodecId
= MFX_CODEC_MPEG2
;
491 sys
->params
.mfx
.CodecProfile
= qsv_params_get_value(profile_mpeg2_text
,
492 profile_mpeg2_list
, sizeof(profile_mpeg2_list
),
493 var_InheritString(enc
, SOUT_CFG_PREFIX
"mpeg2-profile"));
494 sys
->params
.mfx
.CodecLevel
= qsv_params_get_value(level_mpeg2_text
,
495 level_mpeg2_list
, sizeof(level_mpeg2_list
),
496 var_InheritString(enc
, SOUT_CFG_PREFIX
"mpeg2-level"));
497 msg_Dbg(enc
, "Encoder in MPEG2 mode, with profile %d and level %d",
498 sys
->params
.mfx
.CodecProfile
, sys
->params
.mfx
.CodecLevel
);
501 char *psz_rc
= var_InheritString(enc
, SOUT_CFG_PREFIX
"rc-method");
502 msg_Dbg(enc
, "Encoder using '%s' Rate Control method", psz_rc
);
503 sys
->params
.mfx
.RateControlMethod
= qsv_params_get_value(rc_method_text
,
504 rc_method_list
, sizeof(rc_method_list
), psz_rc
);
506 if (sys
->params
.mfx
.RateControlMethod
== MFX_RATECONTROL_CQP
) {
507 sys
->params
.mfx
.QPI
= sys
->params
.mfx
.QPB
= sys
->params
.mfx
.QPP
=
508 var_InheritInteger(enc
, SOUT_CFG_PREFIX
"qp");
509 sys
->params
.mfx
.QPI
= var_InheritInteger(enc
, SOUT_CFG_PREFIX
"qpi");
510 sys
->params
.mfx
.QPB
= var_InheritInteger(enc
, SOUT_CFG_PREFIX
"qpb");
511 sys
->params
.mfx
.QPP
= var_InheritInteger(enc
, SOUT_CFG_PREFIX
"qpp");
513 if (!enc
->fmt_out
.i_bitrate
) {
514 msg_Warn(enc
, "No bitrate specified, using default %d",
515 QSV_BITRATE_DEFAULT
);
516 sys
->params
.mfx
.TargetKbps
= QSV_BITRATE_DEFAULT
;
518 sys
->params
.mfx
.TargetKbps
= enc
->fmt_out
.i_bitrate
/ 1000;
520 if (sys
->params
.mfx
.RateControlMethod
== MFX_RATECONTROL_AVBR
) {
521 sys
->params
.mfx
.Accuracy
= var_InheritInteger(enc
, SOUT_CFG_PREFIX
"accuracy");
522 sys
->params
.mfx
.Convergence
= var_InheritInteger(enc
, SOUT_CFG_PREFIX
"convergence");
523 } else if (sys
->params
.mfx
.RateControlMethod
== MFX_RATECONTROL_VBR
)
524 sys
->params
.mfx
.MaxKbps
= var_InheritInteger(enc
, SOUT_CFG_PREFIX
"bitrate-max");
527 /* Initializing MFX_Encoder */
528 sts
= MFXVideoENCODE_Init(sys
->session
, &sys
->params
);
529 if (sts
== MFX_ERR_NONE
)
530 msg_Dbg(enc
, "Successfuly initialized video encoder");
531 else if (sts
< MFX_ERR_NONE
) {
532 msg_Err(enc
, "Unable to initialize video encoder error (%d). " \
533 " Most likely because of provided encoding parameters", sts
);
536 msg_Warn(enc
, "Video encoder initialization : %d. The stream might be corrupted/invalid", sts
);
538 /* Querying PPS/SPS Headers, BufferSizeInKB, ... */
539 memset(&headers
, 0, sizeof(headers
));
540 memset(&nals
, 0, sizeof(nals
));
541 headers
.Header
.BufferId
= MFX_EXTBUFF_CODING_OPTION_SPSPPS
;
542 headers
.Header
.BufferSz
= sizeof(headers
);
543 headers
.SPSBufSize
= headers
.PPSBufSize
= 64;
544 headers
.SPSBuffer
= nals
;
545 headers
.PPSBuffer
= nals
+ 64;
546 sys
->params
.ExtParam
= (mfxExtBuffer
**)&extended_params
;
547 sys
->params
.NumExtParam
= 1;
549 MFXVideoENCODE_GetVideoParam(sys
->session
, &sys
->params
);
550 sys
->params
.NumExtParam
= 0;
551 sys
->params
.ExtParam
= NULL
;
553 i_extra
= headers
.SPSBufSize
+ headers
.PPSBufSize
;
554 p_extra
= malloc(i_extra
);
556 if (unlikely(!p_extra
))
559 memcpy(p_extra
, headers
.SPSBuffer
, headers
.SPSBufSize
);
560 memcpy(p_extra
+ headers
.SPSBufSize
, headers
.PPSBuffer
, headers
.PPSBufSize
);
561 enc
->fmt_out
.p_extra
= p_extra
;
562 enc
->fmt_out
.i_extra
= i_extra
;
564 sys
->async_depth
= sys
->params
.AsyncDepth
;
565 sys
->tasks
= calloc(sys
->async_depth
, sizeof(async_task_t
));
566 if (unlikely(!sys
->tasks
))
569 /* Request number of surface needed and creating frame pool */
570 if (MFXVideoENCODE_QueryIOSurf(sys
->session
, &sys
->params
, &alloc_request
)!= MFX_ERR_NONE
)
572 if (qsv_frame_pool_Init(&sys
->frames
, &alloc_request
, sys
->async_depth
) != VLC_SUCCESS
)
574 msg_Dbg(enc
, "Requested %d surfaces for work", alloc_request
.NumFrameSuggested
);
576 enc
->pf_encode_video
= Encode
;
588 static void Close(vlc_object_t
*this)
590 encoder_t
*enc
= (encoder_t
*)this;
591 encoder_sys_t
*sys
= enc
->p_sys
;
593 MFXVideoENCODE_Close(sys
->session
);
594 MFXClose(sys
->session
);
595 /* if (enc->fmt_out.p_extra) */
596 /* free(enc->fmt_out.p_extra); */
597 if (sys
->frames
.size
)
598 qsv_frame_pool_Destroy(&sys
->frames
);
605 * The behavior in the next function comes from x264.c
607 static void qsv_set_block_flags(block_t
*block
, uint16_t frame_type
)
609 if ((frame_type
& MFX_FRAMETYPE_IDR
) || (frame_type
& MFX_FRAMETYPE_REF
))
610 block
->i_flags
= BLOCK_FLAG_TYPE_I
;
611 else if ((frame_type
& MFX_FRAMETYPE_P
) || (frame_type
& MFX_FRAMETYPE_I
))
612 block
->i_flags
= BLOCK_FLAG_TYPE_P
;
613 else if (frame_type
& MFX_FRAMETYPE_B
)
614 block
->i_flags
= BLOCK_FLAG_TYPE_B
;
616 block
->i_flags
= BLOCK_FLAG_TYPE_PB
;
620 * Convert the Intel Media SDK's timestamps into VLC's format.
622 static void qsv_set_block_ts(encoder_t
*enc
, encoder_sys_t
*sys
, block_t
*block
, mfxBitstream
*bs
)
627 block
->i_pts
= qsv_timestamp_to_mtime(bs
->TimeStamp
) + sys
->offset_pts
;
628 block
->i_dts
= qsv_timestamp_to_mtime(bs
->DecodeTimeStamp
) + sys
->offset_pts
;
630 /* HW encoder (with old driver versions) and some parameters
631 combinations doesn't set the DecodeTimeStamp field so we warn
633 if (!bs
->DecodeTimeStamp
|| bs
->DecodeTimeStamp
> (int64_t)bs
->TimeStamp
)
634 if (sys
->dts_warn_counter
++ % 16 == 0) // Rate limiting this message.
635 msg_Warn(enc
, "Encode returning empty DTS or DTS > PTS. Your stream will be invalid. "
636 " Please double-check they weren't any warning at encoder initialization "
637 " and that you have the last version of Intel's drivers installed.");
642 * The Encode function has 3 encoding phases :
643 * - Feed : We feed the encoder until it stops to return MFX_MORE_DATA_NEEDED
644 * and the async_tasks are all in use (honouring the AsyncDepth)
645 * - Main encoding phase : synchronizing the oldest task each call.
646 * - Empty : pic = 0, we empty the decoder. Synchronizing the remaining tasks.
648 static block_t
*Encode(encoder_t
*this, picture_t
*pic
)
650 encoder_t
*enc
= (encoder_t
*)this;
651 encoder_sys_t
*sys
= enc
->p_sys
;
652 async_task_t
*task
= NULL
;
653 block_t
*block
= NULL
;
655 mfxFrameSurface1
*frame
= NULL
;
659 /* To avoid qsv -> vlc timestamp conversion overflow, we use timestamp relative
660 to the first picture received. That way, vlc will overflow before us.
661 (Thanks to funman for the idea) */
662 if (!sys
->offset_pts
) // First frame
663 sys
->offset_pts
= pic
->date
;
664 pic
->date
-= sys
->offset_pts
;
666 frame
= qsv_frame_pool_Get(&sys
->frames
, pic
);
668 msg_Warn(enc
, "Unable to find an unlocked surface in the pool");
672 /* Finds an available SyncPoint */
673 for (size_t i
= 0; i
< sys
->async_depth
; i
++)
674 if ((sys
->tasks
+ (i
+ sys
->first_task
) % sys
->async_depth
)->syncp
== 0) {
675 task
= sys
->tasks
+ (i
+ sys
->first_task
) % sys
->async_depth
;
679 /* If !pic, we are emptying encoder and tasks, so we force the SyncOperation */
680 msg_Dbg(enc
, "Emptying encoder");
682 /* There is no available task, we need to synchronize */
684 task
= sys
->tasks
+ sys
->first_task
;
686 /* Synchronize and fill block_t. If the SyncOperation fails we leak :-/ (or we can segfault, ur choice) */
687 if (MFXVideoCORE_SyncOperation(sys
->session
, task
->syncp
, QSV_SYNCPOINT_WAIT
) == MFX_ERR_NONE
) {
689 block
->i_buffer
= task
->bs
.DataLength
;
690 block
->p_buffer
+= task
->bs
.DataOffset
;
692 qsv_set_block_ts(enc
, sys
, block
, &task
->bs
);
693 qsv_set_block_flags(block
, task
->bs
.FrameType
);
695 /* msg_Dbg(enc, "block->i_pts = %lld, block->i_dts = %lld", block->i_pts, block->i_dts); */
696 /* msg_Dbg(enc, "FrameType = %#.4x, TimeStamp (pts) = %lld, DecodeTimeStamp = %lld", */
697 /* task->bs.FrameType, task->bs.TimeStamp, task->bs.DecodeTimeStamp); */
699 /* Copied from x264.c: This isn't really valid for streams with B-frames */
700 block
->i_length
= CLOCK_FREQ
*
701 enc
->fmt_in
.video
.i_frame_rate_base
/
702 enc
->fmt_in
.video
.i_frame_rate
;
704 // Buggy DTS (value comes from experiments)
705 if (task
->bs
.DecodeTimeStamp
< -10000)
706 block
->i_dts
= sys
->last_dts
+ block
->i_length
;
707 sys
->last_dts
= block
->i_dts
;
708 } else // Only happens on buggy drivers
709 msg_Err(enc
, "SyncOperation failed, outputting garbage data. "
710 "Updating your drivers and/or changing the encoding settings might resolve this");
712 /* Reset the task now it has been synchronized and advances first_task pointer */
714 sys
->first_task
= (sys
->first_task
+ 1) % sys
->async_depth
;
717 /* Allocate block_t and prepare mfxBitstream for encoder */
718 if (!(task
->block
= block_Alloc(sys
->params
.mfx
.BufferSizeInKB
* 1000))) {
719 msg_Err(enc
, "Unable to allocate block for encoder output");
722 memset(&task
->bs
, 0, sizeof(task
->bs
));
723 task
->bs
.MaxLength
= sys
->params
.mfx
.BufferSizeInKB
* 1000;
724 task
->bs
.Data
= task
->block
->p_buffer
;
727 sts
= MFXVideoENCODE_EncodeFrameAsync(sys
->session
, 0, frame
, &task
->bs
, &task
->syncp
);
728 if (sts
!= MFX_WRN_DEVICE_BUSY
)
730 if (sys
->busy_warn_counter
++ % 16 == 0)
731 msg_Dbg(enc
, "Device is busy, let's wait and retry");
732 msleep(QSV_BUSYWAIT_TIME
);
735 // msg_Dbg(enc, "Encode async status: %d, Syncpoint = %tx", sts, (ptrdiff_t)task->syncp);
737 if (sts
== MFX_ERR_MORE_DATA
)
739 msg_Dbg(enc
, "Encoder feeding phase, more data is needed.");
741 msg_Dbg(enc
, "Encoder is empty");
742 else if (sts
< MFX_ERR_NONE
) {
743 msg_Err(enc
, "Encoder not ready or error (%d), trying a reset...", sts
);
744 MFXVideoENCODE_Reset(sys
->session
, &sys
->params
);