/*
* Intel MediaSDK QSV based HEVC encoder
*
- * This file is part of Libav.
+ * This file is part of FFmpeg.
*
- * Libav is free software; you can redistribute it and/or
+ * FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
- * Libav is distributed in the hope that it will be useful,
+ * FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with Libav; if not, write to the Free Software
+ * License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
PutByteContext pbc;
GetBitContext gb;
+ H2645RBSP sps_rbsp = { NULL };
H2645NAL sps_nal = { NULL };
HEVCSPS sps = { 0 };
HEVCVPS vps = { 0 };
return AVERROR_UNKNOWN;
}
+ av_fast_padded_malloc(&sps_rbsp.rbsp_buffer, &sps_rbsp.rbsp_buffer_alloc_size, avctx->extradata_size);
+ if (!sps_rbsp.rbsp_buffer)
+ return AVERROR(ENOMEM);
+
/* parse the SPS */
- ret = ff_h2645_extract_rbsp(avctx->extradata + 4, avctx->extradata_size - 4, &sps_nal);
+ ret = ff_h2645_extract_rbsp(avctx->extradata + 4, avctx->extradata_size - 4, &sps_rbsp, &sps_nal, 1);
if (ret < 0) {
av_log(avctx, AV_LOG_ERROR, "Error unescaping the SPS buffer\n");
return ret;
ret = init_get_bits8(&gb, sps_nal.data, sps_nal.size);
if (ret < 0) {
- av_freep(&sps_nal.rbsp_buffer);
+ av_freep(&sps_rbsp.rbsp_buffer);
return ret;
}
if (type != HEVC_NAL_SPS) {
av_log(avctx, AV_LOG_ERROR, "Unexpected NAL type in the extradata: %d\n",
type);
- av_freep(&sps_nal.rbsp_buffer);
+ av_freep(&sps_rbsp.rbsp_buffer);
return AVERROR_INVALIDDATA;
}
get_bits(&gb, 9);
ret = ff_hevc_parse_sps(&sps, &gb, &sps_id, 0, NULL, avctx);
- av_freep(&sps_nal.rbsp_buffer);
+ av_freep(&sps_rbsp.rbsp_buffer);
if (ret < 0) {
av_log(avctx, AV_LOG_ERROR, "Error parsing the SPS\n");
return ret;
/* generate the VPS */
vps.vps_max_layers = 1;
vps.vps_max_sub_layers = sps.max_sub_layers;
+ vps.vps_temporal_id_nesting_flag = sps.temporal_id_nesting_flag;
memcpy(&vps.ptl, &sps.ptl, sizeof(vps.ptl));
vps.vps_sub_layer_ordering_info_present_flag = 1;
for (i = 0; i < HEVC_MAX_SUB_LAYERS; i++) {
vps.vps_time_scale = sps.vui.vui_time_scale;
vps.vps_poc_proportional_to_timing_flag = sps.vui.vui_poc_proportional_to_timing_flag;
vps.vps_num_ticks_poc_diff_one = sps.vui.vui_num_ticks_poc_diff_one_minus1 + 1;
+ vps.vps_num_hrd_parameters = 0;
/* generate the encoded RBSP form of the VPS */
ret = ff_hevc_encode_nal_vps(&vps, sps.vps_id, vps_rbsp_buf, sizeof(vps_rbsp_buf));
bytestream2_put_byte(&pbc, 1); // header
while (bytestream2_get_bytes_left(&gbc)) {
- uint32_t b = bytestream2_peek_be24(&gbc);
- if (b <= 3) {
+ if (bytestream2_get_bytes_left(&gbc) >= 3 && bytestream2_peek_be24(&gbc) <= 3) {
bytestream2_put_be24(&pbc, 3);
bytestream2_skip(&gbc, 2);
} else
if (ret < 0)
return ret;
- ret = generate_fake_vps(&q->qsv, avctx);
- if (ret < 0) {
- ff_qsv_enc_close(avctx, &q->qsv);
- return ret;
+ if (!q->qsv.hevc_vps) {
+ ret = generate_fake_vps(&q->qsv, avctx);
+ if (ret < 0) {
+ ff_qsv_enc_close(avctx, &q->qsv);
+ return ret;
+ }
}
return 0;
return ff_qsv_enc_close(avctx, &q->qsv);
}
-#if defined(_WIN32)
-#define LOAD_PLUGIN_DEFAULT LOAD_PLUGIN_HEVC_SW
-#else
-#define LOAD_PLUGIN_DEFAULT LOAD_PLUGIN_HEVC_HW
-#endif
-
#define OFFSET(x) offsetof(QSVHEVCEncContext, x)
#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
static const AVOption options[] = {
{ "idr_interval", "Distance (in I-frames) between IDR frames", OFFSET(qsv.idr_interval), AV_OPT_TYPE_INT, { .i64 = 0 }, -1, INT_MAX, VE, "idr_interval" },
{ "begin_only", "Output an IDR-frame only at the beginning of the stream", 0, AV_OPT_TYPE_CONST, { .i64 = -1 }, 0, 0, VE, "idr_interval" },
- { "load_plugin", "A user plugin to load in an internal session", OFFSET(load_plugin), AV_OPT_TYPE_INT, { .i64 = LOAD_PLUGIN_DEFAULT }, LOAD_PLUGIN_NONE, LOAD_PLUGIN_HEVC_HW, VE, "load_plugin" },
+ { "load_plugin", "A user plugin to load in an internal session", OFFSET(load_plugin), AV_OPT_TYPE_INT, { .i64 = LOAD_PLUGIN_HEVC_HW }, LOAD_PLUGIN_NONE, LOAD_PLUGIN_HEVC_HW, VE, "load_plugin" },
{ "none", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = LOAD_PLUGIN_NONE }, 0, 0, VE, "load_plugin" },
{ "hevc_sw", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = LOAD_PLUGIN_HEVC_SW }, 0, 0, VE, "load_plugin" },
{ "hevc_hw", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = LOAD_PLUGIN_HEVC_HW }, 0, 0, VE, "load_plugin" },
{ "main", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_PROFILE_HEVC_MAIN }, INT_MIN, INT_MAX, VE, "profile" },
{ "main10", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_PROFILE_HEVC_MAIN10 }, INT_MIN, INT_MAX, VE, "profile" },
{ "mainsp", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_PROFILE_HEVC_MAINSP }, INT_MIN, INT_MAX, VE, "profile" },
-#if QSV_HAVE_VDENC
- { "low_power", "enable low power mode (experimental, many limitations by mfx version, HW platform, BRC modes, etc.", OFFSET(qsv.low_power), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE },
-#endif
+ { "rext", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_PROFILE_HEVC_REXT }, INT_MIN, INT_MAX, VE, "profile" },
+
+ { "gpb", "1: GPB (generalized P/B frame); 0: regular P frame", OFFSET(qsv.gpb), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, VE},
+
+ { "tile_cols", "Number of columns for tiled encoding", OFFSET(qsv.tile_cols), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, UINT16_MAX, VE },
+ { "tile_rows", "Number of rows for tiled encoding", OFFSET(qsv.tile_rows), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, UINT16_MAX, VE },
{ NULL },
};
// same as the x264 default
{ "g", "248" },
{ "bf", "8" },
-
+ { "qmin", "-1" },
+ { "qmax", "-1" },
+ { "trellis", "-1" },
{ "flags", "+cgop" },
-#if FF_API_PRIVATE_OPT
- { "b_strategy", "-1" },
-#endif
{ NULL },
};
-AVCodec ff_hevc_qsv_encoder = {
+const AVCodec ff_hevc_qsv_encoder = {
.name = "hevc_qsv",
.long_name = NULL_IF_CONFIG_SMALL("HEVC (Intel Quick Sync Video acceleration)"),
.priv_data_size = sizeof(QSVHEVCEncContext),
.defaults = qsv_enc_defaults,
.caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
.wrapper_name = "qsv",
+ .hw_configs = ff_qsv_enc_hw_configs,
};