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 | 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 | |||
| 1309 | static av_cold int vaapi_encode_init_rate_control(AVCodecContext *avctx) | 1282 | static 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 | else | 1336 | 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 | else | 1347 | } 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) |