History

vaapi_encode: Clean up rate control configuration

Query which modes are supported and select between VBR and CBR based on that - this removes all of the codec-specific rate control mode selection code.

Mark Thompson committed 8 years ago

Commit af532c91 parent 2562dd99 files · +145 −114Browse files

Showing the changes to libavcodec/vaapi_encode.c (1 of 9 files). Show all

Unified · Split

libavcodec/vaapi_encode.c+130−51
@@ -1213,7 +1213,6 @@ static av_cold int vaapi_encode_config_attributes(AVCodecContext *avctx) · 1212 unmodified lines
1213 int i;1213 int i;
1214 1214
1215 VAConfigAttrib attr[] = {1215 VAConfigAttrib attr[] = {
1216 { VAConfigAttribRateControl },
1217 { VAConfigAttribEncMaxRefFrames },1216 { VAConfigAttribEncMaxRefFrames },
1218 { VAConfigAttribEncPackedHeaders },1217 { VAConfigAttribEncPackedHeaders },
1219 };1218 };
@@ -1237,32 +1236,6 @@ static av_cold int vaapi_encode_config_attributes(AVCodecContext *avctx) · 17 unmodified lines
1237 continue;1236 continue;
1238 }1237 }
1239 switch (attr[i].type) {1238 switch (attr[i].type) {
1240 case VAConfigAttribRateControl:
1241 // Hack for backward compatibility: CBR was the only
1242 // usable RC mode for a long time, so old drivers will
1243 // only have it. Normal default options may now choose
1244 // VBR and then fail, however, so override it here with
1245 // CBR if that is the only supported mode.
1246 if (ctx->va_rc_mode == VA_RC_VBR &&
1247 !(attr[i].value & VA_RC_VBR) &&
1248 (attr[i].value & VA_RC_CBR)) {
1249 av_log(avctx, AV_LOG_WARNING, "VBR rate control is "
1250 "not supported with this driver version; "
1251 "using CBR instead.\n");
1252 ctx->va_rc_mode = VA_RC_CBR;
1253 }
1254 if (!(ctx->va_rc_mode & attr[i].value)) {
1255 av_log(avctx, AV_LOG_ERROR, "Rate control mode %#x "
1256 "is not supported (mask: %#x).\n",
1257 ctx->va_rc_mode, attr[i].value);
1258 return AVERROR(EINVAL);
1259 }
1260 ctx->config_attributes[ctx->nb_config_attributes++] =
1261 (VAConfigAttrib) {
1262 .type = VAConfigAttribRateControl,
1263 .value = ctx->va_rc_mode,
1264 };
1265 break;
1266 case VAConfigAttribEncMaxRefFrames:1239 case VAConfigAttribEncMaxRefFrames:
1267 {1240 {
1268 unsigned int ref_l0 = attr[i].value & 0xffff;1241 unsigned int ref_l0 = attr[i].value & 0xffff;
@@ -1309,44 +1282,152 @@ static av_cold int vaapi_encode_config_attributes(AVCodecContext *avctx) · 40 unmodified lines
1309static av_cold int vaapi_encode_init_rate_control(AVCodecContext *avctx)1282static av_cold int vaapi_encode_init_rate_control(AVCodecContext *avctx)
1310{1283{
1311 VAAPIEncodeContext *ctx = avctx->priv_data;1284 VAAPIEncodeContext *ctx = avctx->priv_data;
1312 int rc_bits_per_second;1285 int64_t rc_bits_per_second;
1313 int rc_target_percentage;1286 int rc_target_percentage;
1314 int rc_window_size;1287 int rc_window_size;
1315 int hrd_buffer_size;1288 int64_t hrd_buffer_size;
1316 int hrd_initial_buffer_fullness;1289 int64_t hrd_initial_buffer_fullness;
1317 int fr_num, fr_den;1290 int fr_num, fr_den;
1291 VAConfigAttrib rc_attr = { VAConfigAttribRateControl };
1292 VAStatus vas;
1293
1294 vas = vaGetConfigAttributes(ctx->hwctx->display,
1295 ctx->va_profile, ctx->va_entrypoint,
1296 &rc_attr, 1);
1297 if (vas != VA_STATUS_SUCCESS) {
1298 av_log(avctx, AV_LOG_ERROR, "Failed to query rate control "
1299 "config attribute: %d (%s).\n", vas, vaErrorStr(vas));
1300 return AVERROR_EXTERNAL;
1301 }
1302
1303 if (rc_attr.value == VA_ATTRIB_NOT_SUPPORTED) {
1304 av_log(avctx, AV_LOG_VERBOSE, "Driver does not report any "
1305 "supported rate control modes: assuming constant-quality.\n");
1306 ctx->va_rc_mode = VA_RC_CQP;
1307 return 0;
1308 }
1309 if (avctx->flags & AV_CODEC_FLAG_QSCALE ||
1310 avctx->bit_rate <= 0) {
1311 if (rc_attr.value & VA_RC_CQP) {
1312 av_log(avctx, AV_LOG_VERBOSE, "Using constant-quality mode.\n");
1313 ctx->va_rc_mode = VA_RC_CQP;
1314 if (avctx->bit_rate > 0 || avctx->rc_max_rate > 0) {
1315 av_log(avctx, AV_LOG_WARNING, "Bitrate target parameters "
1316 "ignored in constant-quality mode.\n");
1317 }
1318 return 0;
1319 } else {
1320 av_log(avctx, AV_LOG_ERROR, "Driver does not support "
1321 "constant-quality mode (%#x).\n", rc_attr.value);
1322 return AVERROR(EINVAL);
1323 }
1324 }
1318 1325
1319 if (avctx->bit_rate > INT32_MAX) {1326 if (!(rc_attr.value & (VA_RC_CBR | VA_RC_VBR))) {
1320 av_log(avctx, AV_LOG_ERROR, "Target bitrate of 2^31 bps or "1327 av_log(avctx, AV_LOG_ERROR, "Driver does not support any "
1321 "higher is not supported.\n");1328 "bitrate-targetted rate control modes.\n");
1322 return AVERROR(EINVAL);1329 return AVERROR(EINVAL);
1323 }1330 }
1324 1331
1325 if (avctx->rc_buffer_size)1332 if (avctx->rc_buffer_size)
1326 hrd_buffer_size = avctx->rc_buffer_size;1333 hrd_buffer_size = avctx->rc_buffer_size;
1334 else if (avctx->rc_max_rate > 0)
1335 hrd_buffer_size = avctx->rc_max_rate;
1327 else1336 else
1328 hrd_buffer_size = avctx->bit_rate;1337 hrd_buffer_size = avctx->bit_rate;
1329 if (avctx->rc_initial_buffer_occupancy)1338 if (avctx->rc_initial_buffer_occupancy) {
1339 if (avctx->rc_initial_buffer_occupancy > hrd_buffer_size) {
1340 av_log(avctx, AV_LOG_ERROR, "Invalid RC buffer settings: "
1341 "must have initial buffer size (%d) < "
1342 "buffer size (%"PRId64").\n",
1343 avctx->rc_initial_buffer_occupancy, hrd_buffer_size);
1344 return AVERROR(EINVAL);
1345 }
1330 hrd_initial_buffer_fullness = avctx->rc_initial_buffer_occupancy;1346 hrd_initial_buffer_fullness = avctx->rc_initial_buffer_occupancy;
1331 else1347 } else {
1332 hrd_initial_buffer_fullness = hrd_buffer_size * 3 / 4;1348 hrd_initial_buffer_fullness = hrd_buffer_size * 3 / 4;
1349 }
1350
1351 if (avctx->rc_max_rate && avctx->rc_max_rate < avctx->bit_rate) {
1352 av_log(avctx, AV_LOG_ERROR, "Invalid bitrate settings: must have "
1353 "bitrate (%"PRId64") <= maxrate (%"PRId64").\n",
1354 avctx->bit_rate, avctx->rc_max_rate);
1355 return AVERROR(EINVAL);
1356 }
1357
1358 if (avctx->rc_max_rate > avctx->bit_rate) {
1359 if (!(rc_attr.value & VA_RC_VBR)) {
1360 av_log(avctx, AV_LOG_WARNING, "Driver does not support "
1361 "VBR mode (%#x), using CBR mode instead.\n",
1362 rc_attr.value);
1363 ctx->va_rc_mode = VA_RC_CBR;
1364
1365 rc_bits_per_second = avctx->bit_rate;
1366 rc_target_percentage = 100;
1367 } else {
1368 ctx->va_rc_mode = VA_RC_VBR;
1369
1370 rc_bits_per_second = avctx->rc_max_rate;
1371 rc_target_percentage = (avctx->bit_rate * 100) /
1372 avctx->rc_max_rate;
1373 }
1374
1375 } else if (avctx->rc_max_rate == avctx->bit_rate) {
1376 if (!(rc_attr.value & VA_RC_CBR)) {
1377 av_log(avctx, AV_LOG_WARNING, "Driver does not support "
1378 "CBR mode (%#x), using VBR mode instead.\n",
1379 rc_attr.value);
1380 ctx->va_rc_mode = VA_RC_VBR;
1381 } else {
1382 ctx->va_rc_mode = VA_RC_CBR;
1383 }
1333 1384
1334 if (ctx->va_rc_mode == VA_RC_CBR) {
1335 rc_bits_per_second = avctx->bit_rate;1385 rc_bits_per_second = avctx->bit_rate;
1336 rc_target_percentage = 100;1386 rc_target_percentage = 100;
1337 rc_window_size = 1000;1387
1338 } else {1388 } else {
1339 if (avctx->rc_max_rate < avctx->bit_rate) {1389 if (rc_attr.value & VA_RC_VBR) {
1340 // Max rate is unset or invalid, just use the normal bitrate.1390 ctx->va_rc_mode = VA_RC_VBR;
1391
1392 // We only have a target bitrate, but VAAPI requires that a
1393 // maximum rate be supplied as well. Since the user has
1394 // offered no particular constraint, arbitrarily pick a
1395 // maximum rate of double the target rate.
1396 rc_bits_per_second = 2 * avctx->bit_rate;
1397 rc_target_percentage = 50;
1398 } else {
1399 ctx->va_rc_mode = VA_RC_CBR;
1400
1341 rc_bits_per_second = avctx->bit_rate;1401 rc_bits_per_second = avctx->bit_rate;
1342 rc_target_percentage = 100;1402 rc_target_percentage = 100;
1343 } else {
1344 rc_bits_per_second = avctx->rc_max_rate;
1345 rc_target_percentage = (avctx->bit_rate * 100) / rc_bits_per_second;
1346 }1403 }
1347 rc_window_size = (hrd_buffer_size * 1000) / avctx->bit_rate;
1348 }1404 }
1349 1405
1406 rc_window_size = (hrd_buffer_size * 1000) / rc_bits_per_second;
1407
1408 av_log(avctx, AV_LOG_VERBOSE, "RC mode: %s, %d%% of %"PRId64" bps "
1409 "over %d ms.\n", ctx->va_rc_mode == VA_RC_VBR ? "VBR" : "CBR",
1410 rc_target_percentage, rc_bits_per_second, rc_window_size);
1411 av_log(avctx, AV_LOG_VERBOSE, "RC buffer: %"PRId64" bits, "
1412 "initial fullness %"PRId64" bits.\n",
1413 hrd_buffer_size, hrd_initial_buffer_fullness);
1414
1415 if (rc_bits_per_second > UINT32_MAX ||
1416 hrd_buffer_size > UINT32_MAX ||
1417 hrd_initial_buffer_fullness > UINT32_MAX) {
1418 av_log(avctx, AV_LOG_ERROR, "RC parameters of 2^32 or "
1419 "greater are not supported by VAAPI.\n");
1420 return AVERROR(EINVAL);
1421 }
1422
1423 ctx->va_bit_rate = rc_bits_per_second;
1424
1425 ctx->config_attributes[ctx->nb_config_attributes++] =
1426 (VAConfigAttrib) {
1427 .type = VAConfigAttribRateControl,
1428 .value = ctx->va_rc_mode,
1429 };
1430
1350 ctx->rc_params.misc.type = VAEncMiscParameterTypeRateControl;1431 ctx->rc_params.misc.type = VAEncMiscParameterTypeRateControl;
1351 ctx->rc_params.rc = (VAEncMiscParameterRateControl) {1432 ctx->rc_params.rc = (VAEncMiscParameterRateControl) {
1352 .bits_per_second = rc_bits_per_second,1433 .bits_per_second = rc_bits_per_second,
@@ -1607,6 +1688,10 @@ av_cold int ff_vaapi_encode_init(AVCodecContext *avctx) · 254 unmodified lines
1607 if (err < 0)1688 if (err < 0)
1608 goto fail;1689 goto fail;
1609 1690
1691 err = vaapi_encode_init_rate_control(avctx);
1692 if (err < 0)
1693 goto fail;
1694
1610 err = vaapi_encode_config_attributes(avctx);1695 err = vaapi_encode_config_attributes(avctx);
1611 if (err < 0)1696 if (err < 0)
1612 goto fail;1697 goto fail;
@@ -1654,12 +1739,6 @@ av_cold int ff_vaapi_encode_init(AVCodecContext *avctx) · 41 unmodified lines
1654 goto fail;1739 goto fail;
1655 }1740 }
1656 1741
1657 if (ctx->va_rc_mode & ~VA_RC_CQP) {
1658 err = vaapi_encode_init_rate_control(avctx);
1659 if (err < 0)
1660 goto fail;
1661 }
1662
1663 if (ctx->codec->configure) {1742 if (ctx->codec->configure) {
1664 err = ctx->codec->configure(avctx);1743 err = ctx->codec->configure(avctx);
1665 if (err < 0)1744 if (err < 0)

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