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.
Showing the changes to libavcodec/vaapi_encode.c (1 of 9 files). Show all
Unified · Split
| @@ -1213,7 +1213,6 @@ static av_cold int vaapi_encode_config_attributes(AVCodecContext *avctx) · 1212 unmodified lines | ||
| 1213 | 1213 | int i; |
| 1214 | 1214 | |
| 1215 | 1215 | VAConfigAttrib attr[] = { |
| 1216 | − { VAConfigAttribRateControl }, | |
| 1217 | 1216 | { VAConfigAttribEncMaxRefFrames }, |
| 1218 | 1217 | { VAConfigAttribEncPackedHeaders }, |
| 1219 | 1218 | }; |
| @@ -1237,32 +1236,6 @@ static av_cold int vaapi_encode_config_attributes(AVCodecContext *avctx) · 17 unmodified lines | ||
| 1237 | 1236 | continue; |
| 1238 | 1237 | } |
| 1239 | 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 | 1239 | case VAConfigAttribEncMaxRefFrames: |
| 1267 | 1240 | { |
| 1268 | 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 | ||
| 1309 | 1282 | static av_cold int vaapi_encode_init_rate_control(AVCodecContext *avctx) |
| 1310 | 1283 | { |
| 1311 | 1284 | VAAPIEncodeContext *ctx = avctx->priv_data; |
| 1312 | − int rc_bits_per_second; | |
| 1313 | − int rc_target_percentage; | |
| 1314 | − int rc_window_size; | |
| 1315 | − int hrd_buffer_size; | |
| 1316 | − int hrd_initial_buffer_fullness; | |
| 1285 | + int64_t rc_bits_per_second; | |
| 1286 | + int rc_target_percentage; | |
| 1287 | + int rc_window_size; | |
| 1288 | + int64_t hrd_buffer_size; | |
| 1289 | + int64_t hrd_initial_buffer_fullness; | |
| 1317 | 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) { | |
| 1320 | − av_log(avctx, AV_LOG_ERROR, "Target bitrate of 2^31 bps or " | |
| 1321 | − "higher is not supported.\n"); | |
| 1326 | + if (!(rc_attr.value & (VA_RC_CBR | VA_RC_VBR))) { | |
| 1327 | + av_log(avctx, AV_LOG_ERROR, "Driver does not support any " | |
| 1328 | + "bitrate-targetted rate control modes.\n"); | |
| 1322 | 1329 | return AVERROR(EINVAL); |
| 1323 | 1330 | } |
| 1324 | 1331 | |
| 1325 | 1332 | if (avctx->rc_buffer_size) |
| 1326 | 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 | 1336 | else |
| 1328 | 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 | 1346 | hrd_initial_buffer_fullness = avctx->rc_initial_buffer_occupancy; |
| 1331 | − else | |
| 1347 | + } else { | |
| 1332 | 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 | 1385 | rc_bits_per_second = avctx->bit_rate; |
| 1336 | 1386 | rc_target_percentage = 100; |
| 1337 | − rc_window_size = 1000; | |
| 1387 | + | |
| 1338 | 1388 | } else { |
| 1339 | − if (avctx->rc_max_rate < avctx->bit_rate) { | |
| 1340 | − // Max rate is unset or invalid, just use the normal bitrate. | |
| 1389 | + if (rc_attr.value & VA_RC_VBR) { | |
| 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 | 1401 | rc_bits_per_second = avctx->bit_rate; |
| 1342 | 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 | 1431 | ctx->rc_params.misc.type = VAEncMiscParameterTypeRateControl; |
| 1351 | 1432 | ctx->rc_params.rc = (VAEncMiscParameterRateControl) { |
| 1352 | 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 | 1688 | if (err < 0) |
| 1608 | 1689 | goto fail; |
| 1609 | 1690 | |
| 1691 | + err = vaapi_encode_init_rate_control(avctx); | |
| 1692 | + if (err < 0) | |
| 1693 | + goto fail; | |
| 1694 | + | |
| 1610 | 1695 | err = vaapi_encode_config_attributes(avctx); |
| 1611 | 1696 | if (err < 0) |
| 1612 | 1697 | goto fail; |
| @@ -1654,12 +1739,6 @@ av_cold int ff_vaapi_encode_init(AVCodecContext *avctx) · 41 unmodified lines | ||
| 1654 | 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 | 1742 | if (ctx->codec->configure) { |
| 1664 | 1743 | err = ctx->codec->configure(avctx); |
| 1665 | 1744 | if (err < 0) |