123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585 |
- // Copyright 2019 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "media/gpu/vaapi/vp9_vaapi_video_encoder_delegate.h"
- #include <algorithm>
- #include <numeric>
- #include <va/va.h>
- #include "base/bits.h"
- #include "base/memory/ref_counted_memory.h"
- #include "base/numerics/safe_conversions.h"
- #include "base/strings/stringprintf.h"
- #include "media/gpu/gpu_video_encode_accelerator_helpers.h"
- #include "media/gpu/macros.h"
- #include "media/gpu/vaapi/vaapi_common.h"
- #include "media/gpu/vaapi/vaapi_wrapper.h"
- #include "media/gpu/video_rate_control.h"
- #include "media/gpu/vp9_svc_layers.h"
- #include "third_party/libvpx/source/libvpx/vp9/ratectrl_rtc.h"
- namespace media {
- namespace {
- // Keyframe period.
- constexpr size_t kKFPeriod = 3000;
- // Quantization parameter. They are vp9 ac/dc indices and their ranges are
- // 0-255. Based on WebRTC's defaults.
- constexpr uint8_t kMinQP = 4;
- constexpr uint8_t kMaxQP = 112;
- // The upper limitation of the quantization parameter for the software rate
- // controller. This is larger than |kMaxQP| because a driver might ignore the
- // specified maximum quantization parameter when the driver determines the
- // value, but it doesn't ignore the quantization parameter by the software rate
- // controller.
- constexpr uint8_t kMaxQPForSoftwareRateCtrl = 224;
- // This stands for 31 as a real ac value (see rfc 8.6.1 table
- // ac_qlookup[3][256]). Note: This needs to be revisited once we have 10&12 bit
- // encoder support.
- constexpr uint8_t kDefaultQP = 24;
- // filter level may affect on quality at lower bitrates; for now,
- // we set a constant value (== 10) which is what other VA-API
- // implementations like libyami and gstreamer-vaapi are using.
- constexpr uint8_t kDefaultLfLevel = 10;
- // Convert Qindex, whose range is 0-255, to the quantizer parameter used in
- // libvpx vp9 rate control, whose range is 0-63.
- // Cited from //third_party/libvpx/source/libvpx/vp9/encoder/vp9_quantize.cc.
- uint8_t QindexToQuantizer(uint8_t q_index) {
- constexpr uint8_t kQuantizerToQindex[] = {
- 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48,
- 52, 56, 60, 64, 68, 72, 76, 80, 84, 88, 92, 96, 100,
- 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 148, 152,
- 156, 160, 164, 168, 172, 176, 180, 184, 188, 192, 196, 200, 204,
- 208, 212, 216, 220, 224, 228, 232, 236, 240, 244, 249, 255,
- };
- for (size_t q = 0; q < std::size(kQuantizerToQindex); ++q) {
- if (kQuantizerToQindex[q] >= q_index)
- return q;
- }
- return std::size(kQuantizerToQindex) - 1;
- }
- // TODO(crbug.com/752720): remove this in favor of std::gcd if c++17 is enabled
- // to use.
- int GCD(int a, int b) {
- return a == 0 ? b : GCD(b % a, a);
- }
- // The return value is expressed as a percentage of the average. For example,
- // to allocate no more than 4.5 frames worth of bitrate to a keyframe, the
- // return value is 450.
- uint32_t MaxSizeOfKeyframeAsPercentage(uint32_t optimal_buffer_size,
- uint32_t max_framerate) {
- // Set max to the optimal buffer level (normalized by target BR),
- // and scaled by a scale_par.
- // Max target size = scale_par * optimal_buffer_size * targetBR[Kbps].
- // This value is presented in percentage of perFrameBw:
- // perFrameBw = targetBR[Kbps] * 1000 / framerate.
- // The target in % is as follows:
- const double target_size_byte_per_frame = optimal_buffer_size * 0.5;
- const uint32_t target_size_kbyte =
- target_size_byte_per_frame * max_framerate / 1000;
- const uint32_t target_size_kbyte_as_percent = target_size_kbyte * 100;
- // Don't go below 3 times the per frame bandwidth.
- constexpr uint32_t kMinIntraSizePercentage = 300u;
- return std::max(kMinIntraSizePercentage, target_size_kbyte_as_percent);
- }
- libvpx::VP9RateControlRtcConfig CreateRateControlConfig(
- const VP9VaapiVideoEncoderDelegate::EncodeParams& encode_params,
- const VideoBitrateAllocation& bitrate_allocation,
- const size_t num_temporal_layers,
- const std::vector<gfx::Size>& spatial_layer_resolutions) {
- DCHECK(!spatial_layer_resolutions.empty());
- const gfx::Size& encode_size = spatial_layer_resolutions.back();
- const size_t num_spatial_layers = spatial_layer_resolutions.size();
- libvpx::VP9RateControlRtcConfig rc_cfg{};
- rc_cfg.rc_mode = VPX_CBR;
- rc_cfg.width = encode_size.width();
- rc_cfg.height = encode_size.height();
- rc_cfg.max_quantizer = QindexToQuantizer(encode_params.max_qp);
- rc_cfg.min_quantizer = QindexToQuantizer(encode_params.min_qp);
- // libvpx::VP9RateControlRtcConfig is kbps.
- rc_cfg.target_bandwidth = encode_params.bitrate_allocation.GetSumBps() / 1000;
- // These default values come from
- // //third_party/webrtc/modules/video_coding/codecs/vp9/vp9_impl.cc.
- rc_cfg.buf_initial_sz = 500;
- rc_cfg.buf_optimal_sz = 600;
- rc_cfg.buf_sz = 1000;
- rc_cfg.undershoot_pct = 50;
- rc_cfg.overshoot_pct = 50;
- rc_cfg.max_intra_bitrate_pct = MaxSizeOfKeyframeAsPercentage(
- rc_cfg.buf_optimal_sz, encode_params.framerate);
- rc_cfg.framerate = encode_params.framerate;
- // Fill spatial/temporal layers variables.
- rc_cfg.ss_number_layers = num_spatial_layers;
- rc_cfg.ts_number_layers = num_temporal_layers;
- for (size_t sid = 0; sid < num_spatial_layers; ++sid) {
- int gcd =
- GCD(encode_size.height(), spatial_layer_resolutions[sid].height());
- rc_cfg.scaling_factor_num[sid] =
- spatial_layer_resolutions[sid].height() / gcd;
- rc_cfg.scaling_factor_den[sid] = encode_size.height() / gcd;
- int bitrate_sum = 0;
- for (size_t tid = 0; tid < num_temporal_layers; ++tid) {
- size_t idx = sid * num_temporal_layers + tid;
- rc_cfg.max_quantizers[idx] = rc_cfg.max_quantizer;
- rc_cfg.min_quantizers[idx] = rc_cfg.min_quantizer;
- bitrate_sum += bitrate_allocation.GetBitrateBps(sid, tid);
- rc_cfg.layer_target_bitrate[idx] = bitrate_sum / 1000;
- rc_cfg.ts_rate_decimator[tid] = 1u << (num_temporal_layers - tid - 1);
- }
- }
- return rc_cfg;
- }
- scoped_refptr<VP9Picture> GetVP9Picture(
- const VaapiVideoEncoderDelegate::EncodeJob& job) {
- return base::WrapRefCounted(
- reinterpret_cast<VP9Picture*>(job.picture().get()));
- }
- } // namespace
- VP9VaapiVideoEncoderDelegate::EncodeParams::EncodeParams()
- : kf_period_frames(kKFPeriod),
- framerate(0),
- min_qp(kMinQP),
- max_qp(kMaxQP) {}
- void VP9VaapiVideoEncoderDelegate::set_rate_ctrl_for_testing(
- std::unique_ptr<VP9RateControl> rate_ctrl) {
- rate_ctrl_ = std::move(rate_ctrl);
- }
- VP9VaapiVideoEncoderDelegate::VP9VaapiVideoEncoderDelegate(
- scoped_refptr<VaapiWrapper> vaapi_wrapper,
- base::RepeatingClosure error_cb)
- : VaapiVideoEncoderDelegate(std::move(vaapi_wrapper), error_cb) {}
- VP9VaapiVideoEncoderDelegate::~VP9VaapiVideoEncoderDelegate() {
- // VP9VaapiVideoEncoderDelegate can be destroyed on any thread.
- }
- bool VP9VaapiVideoEncoderDelegate::Initialize(
- const VideoEncodeAccelerator::Config& config,
- const VaapiVideoEncoderDelegate::Config& ave_config) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- if (VideoCodecProfileToVideoCodec(config.output_profile) !=
- VideoCodec::kVP9) {
- DVLOGF(1) << "Invalid profile: " << GetProfileName(config.output_profile);
- return false;
- }
- if (config.input_visible_size.IsEmpty()) {
- DVLOGF(1) << "Input visible size could not be empty";
- return false;
- }
- if (config.bitrate.mode() == Bitrate::Mode::kVariable) {
- DVLOGF(1) << "Invalid configuraiton. VBR is not supported for VP9.";
- return false;
- }
- visible_size_ = config.input_visible_size;
- coded_size_ = gfx::Size(base::bits::AlignUp(visible_size_.width(), 16),
- base::bits::AlignUp(visible_size_.height(), 16));
- current_params_ = EncodeParams();
- reference_frames_.Clear();
- frame_num_ = 0;
- size_t num_temporal_layers = 1;
- size_t num_spatial_layers = 1;
- std::vector<gfx::Size> spatial_layer_resolutions;
- if (config.HasTemporalLayer() || config.HasSpatialLayer()) {
- num_spatial_layers = config.spatial_layers.size();
- num_temporal_layers = config.spatial_layers[0].num_of_temporal_layers;
- DCHECK(num_spatial_layers != 1 || num_temporal_layers != 1);
- for (size_t sid = 1; sid < num_spatial_layers; ++sid) {
- if (num_temporal_layers !=
- config.spatial_layers[sid].num_of_temporal_layers) {
- VLOGF(1) << "The temporal layer sizes among spatial layers must be "
- "identical";
- return false;
- }
- }
- if (num_spatial_layers > VP9SVCLayers::kMaxSpatialLayers ||
- num_temporal_layers > VP9SVCLayers::kMaxSupportedTemporalLayers) {
- VLOGF(1) << "Unsupported amount of spatial/temporal layers: "
- << ", Spatial layer number: " << num_spatial_layers
- << ", Temporal layer number: " << num_temporal_layers;
- return false;
- }
- if (num_spatial_layers > 1 &&
- config.inter_layer_pred !=
- VideoEncodeAccelerator::Config::InterLayerPredMode::kOnKeyPic) {
- std::string inter_layer_pred;
- if (config.inter_layer_pred ==
- VideoEncodeAccelerator::Config::InterLayerPredMode::kOn)
- inter_layer_pred = base::StringPrintf("InterLayerPredMode::kOn");
- else
- inter_layer_pred = base::StringPrintf("InterLayerPredMode::kOff");
- VLOGF(1) << "Support only k-SVC encoding. inter_layer_pred="
- << inter_layer_pred;
- return false;
- }
- for (const auto& spatial_layer : config.spatial_layers) {
- spatial_layer_resolutions.emplace_back(
- gfx::Size(spatial_layer.width, spatial_layer.height));
- }
- svc_layers_ = std::make_unique<VP9SVCLayers>(config.spatial_layers);
- }
- current_params_.max_qp = kMaxQPForSoftwareRateCtrl;
- // Store layer size for vp9 simple stream.
- if (spatial_layer_resolutions.empty())
- spatial_layer_resolutions.push_back(visible_size_);
- auto initial_bitrate_allocation = AllocateBitrateForDefaultEncoding(config);
- // |rate_ctrl_| might be injected for tests.
- if (!rate_ctrl_) {
- rate_ctrl_ = VP9RateControl::Create(CreateRateControlConfig(
- current_params_, initial_bitrate_allocation, num_temporal_layers,
- spatial_layer_resolutions));
- }
- if (!rate_ctrl_)
- return false;
- DCHECK(!pending_update_rates_);
- pending_update_rates_ =
- std::make_pair(initial_bitrate_allocation,
- config.initial_framerate.value_or(
- VideoEncodeAccelerator::kDefaultFramerate));
- return ApplyPendingUpdateRates();
- }
- gfx::Size VP9VaapiVideoEncoderDelegate::GetCodedSize() const {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- DCHECK(!coded_size_.IsEmpty());
- return coded_size_;
- }
- size_t VP9VaapiVideoEncoderDelegate::GetMaxNumOfRefFrames() const {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- return kVp9NumRefFrames;
- }
- bool VP9VaapiVideoEncoderDelegate::PrepareEncodeJob(EncodeJob& encode_job) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- if (svc_layers_) {
- if (svc_layers_->UpdateEncodeJob(encode_job.IsKeyframeRequested(),
- current_params_.kf_period_frames)) {
- encode_job.ProduceKeyframe();
- }
- } else {
- if (encode_job.IsKeyframeRequested())
- frame_num_ = 0;
- if (frame_num_ == 0)
- encode_job.ProduceKeyframe();
- frame_num_++;
- frame_num_ %= current_params_.kf_period_frames;
- }
- scoped_refptr<VP9Picture> picture = GetVP9Picture(encode_job);
- DCHECK(picture);
- std::array<bool, kVp9NumRefsPerFrame> ref_frames_used = {false, false, false};
- SetFrameHeader(encode_job.IsKeyframeRequested(), picture.get(),
- &ref_frames_used);
- if (!SubmitFrameParameters(encode_job, current_params_, picture,
- reference_frames_, ref_frames_used)) {
- LOG(ERROR) << "Failed submitting frame parameters";
- return false;
- }
- UpdateReferenceFrames(picture);
- return true;
- }
- BitstreamBufferMetadata VP9VaapiVideoEncoderDelegate::GetMetadata(
- const EncodeJob& encode_job,
- size_t payload_size) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- auto metadata =
- VaapiVideoEncoderDelegate::GetMetadata(encode_job, payload_size);
- auto picture = GetVP9Picture(encode_job);
- DCHECK(picture);
- metadata.vp9 = picture->metadata_for_encoding;
- metadata.qp =
- base::strict_cast<int32_t>(picture->frame_hdr->quant_params.base_q_idx);
- return metadata;
- }
- std::vector<gfx::Size> VP9VaapiVideoEncoderDelegate::GetSVCLayerResolutions() {
- if (!ApplyPendingUpdateRates()) {
- DLOG(ERROR) << __func__ << " ApplyPendingUpdateRates failed";
- return {};
- }
- if (svc_layers_) {
- return svc_layers_->active_spatial_layer_resolutions();
- } else {
- return {visible_size_};
- }
- }
- void VP9VaapiVideoEncoderDelegate::BitrateControlUpdate(
- uint64_t encoded_chunk_size_bytes) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- CHECK(rate_ctrl_);
- DVLOGF(4) << "|encoded_chunk_size_bytes|=" << encoded_chunk_size_bytes;
- rate_ctrl_->PostEncodeUpdate(encoded_chunk_size_bytes);
- }
- bool VP9VaapiVideoEncoderDelegate::ApplyPendingUpdateRates() {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- if (!pending_update_rates_)
- return true;
- VLOGF(2) << "New bitrate: " << pending_update_rates_->first.ToString()
- << ", New framerate: " << pending_update_rates_->second;
- current_params_.bitrate_allocation = pending_update_rates_->first;
- current_params_.framerate = pending_update_rates_->second;
- pending_update_rates_.reset();
- // Update active layer status in |svc_layers_|, and key frame is produced when
- // active layer changed.
- if (svc_layers_) {
- if (!svc_layers_->MaybeUpdateActiveLayer(
- ¤t_params_.bitrate_allocation)) {
- return false;
- }
- } else {
- // Simple stream encoding.
- if (current_params_.bitrate_allocation.GetSumBps() !=
- current_params_.bitrate_allocation.GetBitrateBps(0, 0)) {
- return false;
- }
- }
- CHECK(rate_ctrl_);
- const size_t num_temporal_layers =
- svc_layers_ ? svc_layers_->num_temporal_layers() : 1u;
- std::vector<gfx::Size> spatial_layer_resolutions = {visible_size_};
- if (svc_layers_)
- spatial_layer_resolutions = svc_layers_->active_spatial_layer_resolutions();
- rate_ctrl_->UpdateRateControl(CreateRateControlConfig(
- current_params_, current_params_.bitrate_allocation, num_temporal_layers,
- spatial_layer_resolutions));
- return true;
- }
- bool VP9VaapiVideoEncoderDelegate::UpdateRates(
- const VideoBitrateAllocation& bitrate_allocation,
- uint32_t framerate) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- if (bitrate_allocation.GetMode() != Bitrate::Mode::kConstant) {
- DLOG(ERROR) << "VBR is not supported for VP9 but was requested.";
- return false;
- }
- if (bitrate_allocation.GetSumBps() == 0u || framerate == 0)
- return false;
- pending_update_rates_ = std::make_pair(bitrate_allocation, framerate);
- if (current_params_.bitrate_allocation == pending_update_rates_->first &&
- current_params_.framerate == pending_update_rates_->second) {
- pending_update_rates_.reset();
- }
- return true;
- }
- Vp9FrameHeader VP9VaapiVideoEncoderDelegate::GetDefaultFrameHeader(
- const bool keyframe) const {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- Vp9FrameHeader hdr{};
- DCHECK(!visible_size_.IsEmpty());
- hdr.frame_width = visible_size_.width();
- hdr.frame_height = visible_size_.height();
- hdr.render_width = visible_size_.width();
- hdr.render_height = visible_size_.height();
- hdr.quant_params.base_q_idx = kDefaultQP;
- hdr.loop_filter.level = kDefaultLfLevel;
- hdr.show_frame = true;
- hdr.frame_type =
- keyframe ? Vp9FrameHeader::KEYFRAME : Vp9FrameHeader::INTERFRAME;
- return hdr;
- }
- void VP9VaapiVideoEncoderDelegate::SetFrameHeader(
- bool keyframe,
- VP9Picture* picture,
- std::array<bool, kVp9NumRefsPerFrame>* ref_frames_used) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- DCHECK(picture);
- DCHECK(ref_frames_used);
- *picture->frame_hdr = GetDefaultFrameHeader(keyframe);
- if (svc_layers_) {
- // Reference frame settings for k-SVC stream.
- svc_layers_->FillUsedRefFramesAndMetadata(picture, ref_frames_used);
- // Enable error resilient mode so that the syntax of a frame can be decoded
- // independently of previous frames.
- picture->frame_hdr->error_resilient_mode = true;
- } else {
- // Reference frame settings for simple stream.
- if (keyframe) {
- picture->frame_hdr->refresh_frame_flags = 0xff;
- ref_frame_index_ = 0;
- } else {
- picture->frame_hdr->ref_frame_idx[0] = ref_frame_index_;
- picture->frame_hdr->ref_frame_idx[1] =
- (ref_frame_index_ - 1) & (kVp9NumRefFrames - 1);
- picture->frame_hdr->ref_frame_idx[2] =
- (ref_frame_index_ - 2) & (kVp9NumRefFrames - 1);
- ref_frame_index_ = (ref_frame_index_ + 1) % kVp9NumRefFrames;
- picture->frame_hdr->refresh_frame_flags = 1 << ref_frame_index_;
- // Use last, golden, alt frames.
- ref_frames_used->fill(true);
- }
- }
- CHECK(rate_ctrl_);
- libvpx::VP9FrameParamsQpRTC frame_params{};
- frame_params.frame_type =
- keyframe ? FRAME_TYPE::KEY_FRAME : FRAME_TYPE::INTER_FRAME;
- if (picture->metadata_for_encoding) {
- frame_params.temporal_layer_id =
- picture->metadata_for_encoding->temporal_idx;
- frame_params.spatial_layer_id = picture->metadata_for_encoding->spatial_idx;
- }
- rate_ctrl_->ComputeQP(frame_params);
- picture->frame_hdr->quant_params.base_q_idx = rate_ctrl_->GetQP();
- picture->frame_hdr->loop_filter.level = rate_ctrl_->GetLoopfilterLevel();
- DVLOGF(4) << "qp="
- << static_cast<int>(picture->frame_hdr->quant_params.base_q_idx)
- << ", filter_level="
- << static_cast<int>(picture->frame_hdr->loop_filter.level)
- << ", frame_params.temporal_layer_id:"
- << frame_params.temporal_layer_id
- << ", frame_params.spatial_layer_id:"
- << frame_params.spatial_layer_id;
- }
- void VP9VaapiVideoEncoderDelegate::UpdateReferenceFrames(
- scoped_refptr<VP9Picture> picture) {
- reference_frames_.Refresh(picture);
- }
- bool VP9VaapiVideoEncoderDelegate::SubmitFrameParameters(
- EncodeJob& job,
- const EncodeParams& encode_params,
- scoped_refptr<VP9Picture> pic,
- const Vp9ReferenceFrameVector& ref_frames,
- const std::array<bool, kVp9NumRefsPerFrame>& ref_frames_used) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- VAEncSequenceParameterBufferVP9 seq_param = {};
- const auto& frame_header = pic->frame_hdr;
- // TODO(crbug.com/811912): Double check whether the
- // max_frame_width or max_frame_height affects any of the memory
- // allocation and tighten these values based on that.
- constexpr gfx::Size kMaxFrameSize(4096, 4096);
- seq_param.max_frame_width = kMaxFrameSize.height();
- seq_param.max_frame_height = kMaxFrameSize.width();
- seq_param.bits_per_second = encode_params.bitrate_allocation.GetSumBps();
- seq_param.intra_period = encode_params.kf_period_frames;
- VAEncPictureParameterBufferVP9 pic_param = {};
- pic_param.frame_width_src = frame_header->frame_width;
- pic_param.frame_height_src = frame_header->frame_height;
- pic_param.frame_width_dst = frame_header->render_width;
- pic_param.frame_height_dst = frame_header->render_height;
- pic_param.reconstructed_frame = pic->AsVaapiVP9Picture()->GetVASurfaceID();
- DCHECK_NE(pic_param.reconstructed_frame, VA_INVALID_ID);
- for (size_t i = 0; i < kVp9NumRefFrames; i++) {
- auto ref_pic = ref_frames.GetFrame(i);
- pic_param.reference_frames[i] =
- ref_pic ? ref_pic->AsVaapiVP9Picture()->GetVASurfaceID()
- : VA_INVALID_ID;
- }
- pic_param.coded_buf = job.coded_buffer_id();
- DCHECK_NE(pic_param.coded_buf, VA_INVALID_ID);
- if (frame_header->IsKeyframe()) {
- pic_param.ref_flags.bits.force_kf = true;
- } else {
- // Non-key frame mode, the frame has at least 1 reference frames.
- size_t first_used_ref_frame = 3;
- for (size_t i = 0; i < kVp9NumRefsPerFrame; i++) {
- if (ref_frames_used[i]) {
- first_used_ref_frame = std::min(first_used_ref_frame, i);
- pic_param.ref_flags.bits.ref_frame_ctrl_l0 |= (1 << i);
- }
- }
- CHECK_LT(first_used_ref_frame, 3u);
- pic_param.ref_flags.bits.ref_last_idx =
- ref_frames_used[0] ? frame_header->ref_frame_idx[0]
- : frame_header->ref_frame_idx[first_used_ref_frame];
- pic_param.ref_flags.bits.ref_gf_idx =
- ref_frames_used[1] ? frame_header->ref_frame_idx[1]
- : frame_header->ref_frame_idx[first_used_ref_frame];
- pic_param.ref_flags.bits.ref_arf_idx =
- ref_frames_used[2] ? frame_header->ref_frame_idx[2]
- : frame_header->ref_frame_idx[first_used_ref_frame];
- }
- pic_param.pic_flags.bits.frame_type = frame_header->frame_type;
- pic_param.pic_flags.bits.show_frame = frame_header->show_frame;
- pic_param.pic_flags.bits.error_resilient_mode =
- frame_header->error_resilient_mode;
- pic_param.pic_flags.bits.intra_only = frame_header->intra_only;
- pic_param.pic_flags.bits.allow_high_precision_mv =
- frame_header->allow_high_precision_mv;
- pic_param.pic_flags.bits.mcomp_filter_type =
- frame_header->interpolation_filter;
- pic_param.pic_flags.bits.frame_parallel_decoding_mode =
- frame_header->frame_parallel_decoding_mode;
- pic_param.pic_flags.bits.reset_frame_context =
- frame_header->reset_frame_context;
- pic_param.pic_flags.bits.refresh_frame_context =
- frame_header->refresh_frame_context;
- pic_param.pic_flags.bits.frame_context_idx = frame_header->frame_context_idx;
- pic_param.refresh_frame_flags = frame_header->refresh_frame_flags;
- pic_param.luma_ac_qindex = frame_header->quant_params.base_q_idx;
- pic_param.luma_dc_qindex_delta = frame_header->quant_params.delta_q_y_dc;
- pic_param.chroma_ac_qindex_delta = frame_header->quant_params.delta_q_uv_ac;
- pic_param.chroma_dc_qindex_delta = frame_header->quant_params.delta_q_uv_dc;
- pic_param.filter_level = frame_header->loop_filter.level;
- pic_param.log2_tile_rows = frame_header->tile_rows_log2;
- pic_param.log2_tile_columns = frame_header->tile_cols_log2;
- return vaapi_wrapper_->SubmitBuffers(
- {{VAEncSequenceParameterBufferType, sizeof(seq_param), &seq_param},
- {VAEncPictureParameterBufferType, sizeof(pic_param), &pic_param}});
- }
- } // namespace media
|