- Query GPU caps for B-frame support and warn if unsupported. - Make `-max_b_frames` optional - Drop explicit `-pa_lookahead_buffer_depth` requirement in adaptive mode.
Unified · Split
| @@ -468,26 +468,61 @@ static av_cold int amf_encode_init_h264(AVCodecContext *avctx) · 467 unmodified lines | ||
| 468 | 468 | } |
| 469 | 469 | |
| 470 | 470 | // B-Frames |
| 471 | − if (ctx->max_consecutive_b_frames != -1) { | |
| 472 | − AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_MAX_CONSECUTIVE_BPICTURES, ctx->max_consecutive_b_frames); | |
| 473 | − if (ctx->max_b_frames != -1) { | |
| 474 | − AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_B_PIC_PATTERN, ctx->max_b_frames); | |
| 475 | − if (res != AMF_OK) { | |
| 476 | − res = ctx->encoder->pVtbl->GetProperty(ctx->encoder, AMF_VIDEO_ENCODER_B_PIC_PATTERN, &var); | |
| 477 | − av_log(ctx, AV_LOG_WARNING, "B-frames=%d is not supported by this GPU, switched to %d\n", | |
| 478 | − ctx->max_b_frames, (int)var.int64Value); | |
| 479 | − ctx->max_b_frames = (int)var.int64Value; | |
| 471 | + AMFVariantStruct is_adaptive_b_frames = { 0 }; | |
| 472 | + res = ctx->encoder->pVtbl->GetProperty(ctx->encoder, AMF_VIDEO_ENCODER_ADAPTIVE_MINIGOP, &is_adaptive_b_frames); | |
| 473 | + if (ctx->max_consecutive_b_frames != -1 || ctx->max_b_frames != -1 || is_adaptive_b_frames.boolValue == true) { | |
| 474 | + | |
| 475 | + //Get the capability of encoder | |
| 476 | + AMFCaps *encoder_caps = NULL; | |
| 477 | + ctx->encoder->pVtbl->GetCaps(ctx->encoder, &encoder_caps); | |
| 478 | + if (encoder_caps != NULL) | |
| 479 | + { | |
| 480 | + res = encoder_caps->pVtbl->GetProperty(encoder_caps, AMF_VIDEO_ENCODER_CAP_BFRAMES, &var); | |
| 481 | + if (res == AMF_OK) { | |
| 482 | + | |
| 483 | + //encoder supports H.264 B-frame | |
| 484 | + if(var.boolValue == true){ | |
| 485 | + //adaptive b-frames is higher priority than max_b_frames | |
| 486 | + if (is_adaptive_b_frames.boolValue == true) | |
| 487 | + { | |
| 488 | + //force AMF_VIDEO_ENCODER_MAX_CONSECUTIVE_BPICTURES to 3 | |
| 489 | + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_MAX_CONSECUTIVE_BPICTURES, 3); | |
| 490 | + | |
| 491 | + if(ctx->pa_lookahead_buffer_depth < 1) | |
| 492 | + { | |
| 493 | + //force AMF_PA_LOOKAHEAD_BUFFER_DEPTH to 1 if not set or smaller than 1 | |
| 494 | + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_PA_LOOKAHEAD_BUFFER_DEPTH, 1); | |
| 495 | + } | |
| 496 | + } | |
| 497 | + else { | |
| 498 | + if (ctx->max_b_frames != -1) { | |
| 499 | + //in case user sets B-frames | |
| 500 | + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_B_PIC_PATTERN, ctx->max_b_frames); | |
| 501 | + if (res != AMF_OK) { | |
| 502 | + res = ctx->encoder->pVtbl->GetProperty(ctx->encoder, AMF_VIDEO_ENCODER_B_PIC_PATTERN, &var); | |
| 503 | + av_log(ctx, AV_LOG_WARNING, "B-frames=%d is not supported by this GPU, switched to %d\n", ctx->max_b_frames, (int)var.int64Value); | |
| 504 | + ctx->max_b_frames = (int)var.int64Value; | |
| 505 | + } | |
| 506 | + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_MAX_CONSECUTIVE_BPICTURES, ctx->max_b_frames); | |
| 507 | + } | |
| 508 | + } | |
| 509 | + | |
| 510 | + } | |
| 511 | + //encoder doesn't support H.264 B-frame | |
| 512 | + else { | |
| 513 | + av_log(ctx, AV_LOG_WARNING, "The current GPU in use does not support H.264 B-frame encoding, there will be no B-frame in bitstream.\n"); | |
| 514 | + } | |
| 515 | + } else { | |
| 516 | + //Can't get the capability of encoder | |
| 517 | + av_log(ctx, AV_LOG_WARNING, "Unable to get H.264 B-frame capability.\n"); | |
| 518 | + av_log(ctx, AV_LOG_WARNING, "There will be no B-frame in bitstream.\n"); | |
| 480 | 519 | } |
| 481 | − if (ctx->max_consecutive_b_frames < ctx->max_b_frames) { | |
| 482 | − av_log(ctx, AVERROR_BUG, "Maxium B frames needs to be greater than the specified B frame count.\n"); | |
| 483 | − } | |
| 484 | − } | |
| 485 | − } | |
| 486 | − else { | |
| 487 | − if (ctx->max_b_frames != -1) { | |
| 488 | − av_log(ctx, AVERROR_BUG, "Maxium number of B frames needs to be specified.\n"); | |
| 520 | + | |
| 521 | + encoder_caps->pVtbl->Release(encoder_caps); | |
| 522 | + encoder_caps = NULL; | |
| 489 | 523 | } |
| 490 | 524 | } |
| 525 | + | |
| 491 | 526 | res = ctx->encoder->pVtbl->GetProperty(ctx->encoder, AMF_VIDEO_ENCODER_B_PIC_PATTERN, &var); |
| 492 | 527 | if ((int)var.int64Value) { |
| 493 | 528 | AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_B_PIC_DELTA_QP, ctx->b_frame_delta_qp); |