vp8_vaapi_video_encoder_delegate.cc 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632
  1. // Copyright 2018 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "media/gpu/vaapi/vp8_vaapi_video_encoder_delegate.h"
  5. #include <va/va.h>
  6. #include <va/va_enc_vp8.h>
  7. #include "base/bits.h"
  8. #include "base/containers/contains.h"
  9. #include "base/memory/ref_counted_memory.h"
  10. #include "base/strings/string_number_conversions.h"
  11. #include "build/build_config.h"
  12. #include "media/base/media_switches.h"
  13. #include "media/gpu/gpu_video_encode_accelerator_helpers.h"
  14. #include "media/gpu/macros.h"
  15. #include "media/gpu/vaapi/vaapi_common.h"
  16. #include "media/gpu/vaapi/vaapi_wrapper.h"
  17. #include "third_party/libvpx/source/libvpx/vp8/vp8_ratectrl_rtc.h"
  18. namespace media {
  19. namespace {
  20. // Keyframe period.
  21. constexpr size_t kKFPeriod = 3000;
  22. // Quantization parameter. They are vp8 ac/dc indices and their ranges are
  23. // 0-127. Based on WebRTC's defaults.
  24. constexpr uint8_t kMinQP = 4;
  25. // b/110059922, crbug.com/1001900: Tuned 112->117 for bitrate issue in a lower
  26. // resolution (180p).
  27. constexpr uint8_t kMaxQP = 117;
  28. // The upper limitation of the quantization parameter for the software rate
  29. // controller. This is larger than |kMaxQP| because a driver might ignore the
  30. // specified maximum quantization parameter when the driver determines the
  31. // value, but it doesn't ignore the quantization parameter by the software rate
  32. // controller.
  33. constexpr uint8_t kMaxQPForSoftwareRateCtrl = 127;
  34. // Convert Qindex, whose range is 0-127, to the quantizer parameter used in
  35. // libvpx vp8 rate control, whose range is 0-63.
  36. // Cited from //third_party/libvpx/source/libvpx/vp8/vp8_ratectrl_rtc.cc
  37. uint8_t QindexToQuantizer(uint8_t q_index) {
  38. constexpr uint8_t kQuantizerToQindex[] = {
  39. 0, 1, 2, 3, 4, 5, 7, 8, 9, 10, 12, 13, 15, 17, 18, 19,
  40. 20, 21, 23, 24, 25, 26, 27, 28, 29, 30, 31, 33, 35, 37, 39, 41,
  41. 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 64, 67, 70, 73, 76, 79,
  42. 82, 85, 88, 91, 94, 97, 100, 103, 106, 109, 112, 115, 118, 121, 124, 127,
  43. };
  44. for (size_t q = 0; q < std::size(kQuantizerToQindex); ++q) {
  45. if (kQuantizerToQindex[q] >= q_index)
  46. return q;
  47. }
  48. return std::size(kQuantizerToQindex) - 1;
  49. }
  50. // The return value is expressed as a percentage of the average. For example,
  51. // to allocate no more than 4.5 frames worth of bitrate to a keyframe, the
  52. // return value is 450.
  53. uint32_t MaxSizeOfKeyframeAsPercentage(uint32_t optimal_buffer_size,
  54. uint32_t max_framerate) {
  55. // Set max to the optimal buffer level (normalized by target BR),
  56. // and scaled by a scale_par.
  57. // Max target size = scale_par * optimal_buffer_size * targetBR[Kbps].
  58. // This value is presented in percentage of perFrameBw:
  59. // perFrameBw = targetBR[Kbps] * 1000 / framerate.
  60. // The target in % is as follows:
  61. const double target_size_byte_per_frame = optimal_buffer_size * 0.5;
  62. const uint32_t target_size_kbyte =
  63. target_size_byte_per_frame * max_framerate / 1000;
  64. const uint32_t target_size_kbyte_as_percent = target_size_kbyte * 100;
  65. // Don't go below 3 times the per frame bandwidth.
  66. constexpr uint32_t kMinIntraSizePercentage = 300u;
  67. return std::max(kMinIntraSizePercentage, target_size_kbyte_as_percent);
  68. }
  69. libvpx::VP8RateControlRtcConfig CreateRateControlConfig(
  70. const gfx::Size encode_size,
  71. const VP8VaapiVideoEncoderDelegate::EncodeParams& encode_params,
  72. const VideoBitrateAllocation& bitrate_allocation,
  73. size_t num_temporal_layers) {
  74. libvpx::VP8RateControlRtcConfig rc_cfg{};
  75. rc_cfg.width = encode_size.width();
  76. rc_cfg.height = encode_size.height();
  77. rc_cfg.rc_mode = VPX_CBR;
  78. rc_cfg.max_quantizer = QindexToQuantizer(encode_params.max_qp);
  79. rc_cfg.min_quantizer = QindexToQuantizer(encode_params.min_qp);
  80. // libvpx::VP8RateControlRtcConfig is kbps.
  81. rc_cfg.target_bandwidth = encode_params.bitrate_allocation.GetSumBps() / 1000;
  82. // These default values come from
  83. // //third_party/webrtc/modules/video_coding/codecs/vp8/libvpx_vp8_encoder.cc
  84. rc_cfg.buf_initial_sz = 500;
  85. rc_cfg.buf_optimal_sz = 600;
  86. rc_cfg.buf_sz = 1000;
  87. rc_cfg.undershoot_pct = 100;
  88. rc_cfg.overshoot_pct = 15;
  89. rc_cfg.max_intra_bitrate_pct = MaxSizeOfKeyframeAsPercentage(
  90. rc_cfg.buf_optimal_sz, encode_params.framerate);
  91. rc_cfg.framerate = encode_params.framerate;
  92. // Fill temporal layers variables.
  93. rc_cfg.ts_number_layers = num_temporal_layers;
  94. int bitrate_sum = 0;
  95. for (size_t tid = 0; tid < num_temporal_layers; ++tid) {
  96. bitrate_sum += bitrate_allocation.GetBitrateBps(0u, tid) / 1000;
  97. rc_cfg.layer_target_bitrate[tid] = bitrate_sum;
  98. rc_cfg.ts_rate_decimator[tid] = 1u << (num_temporal_layers - tid - 1);
  99. }
  100. return rc_cfg;
  101. }
  102. scoped_refptr<VP8Picture> GetVP8Picture(
  103. const VaapiVideoEncoderDelegate::EncodeJob& job) {
  104. return base::WrapRefCounted(
  105. reinterpret_cast<VP8Picture*>(job.picture().get()));
  106. }
  107. Vp8FrameHeader GetDefaultVp8FrameHeader(bool keyframe,
  108. const gfx::Size& visible_size) {
  109. Vp8FrameHeader hdr;
  110. DCHECK(!visible_size.IsEmpty());
  111. hdr.width = visible_size.width();
  112. hdr.height = visible_size.height();
  113. hdr.show_frame = true;
  114. hdr.frame_type =
  115. keyframe ? Vp8FrameHeader::KEYFRAME : Vp8FrameHeader::INTERFRAME;
  116. // TODO(sprang): Make this dynamic. Value based on reference implementation
  117. // in libyami (https://github.com/intel/libyami).
  118. // Sets the highest loop filter level.
  119. // TODO(b/188853141): Set a loop filter level computed by a rate controller
  120. // every frame once the rate controller supports it.
  121. hdr.loopfilter_hdr.level = 63;
  122. // A VA-API driver recommends to set forced_lf_adjustment on keyframe.
  123. // Set loop_filter_adj_enable to 1 here because forced_lf_adjustment is read
  124. // only when a macroblock level loop filter adjustment.
  125. hdr.loopfilter_hdr.loop_filter_adj_enable = true;
  126. // Set mb_no_skip_coeff to 1 that some decoders (e.g. kepler) could not decode
  127. // correctly a stream encoded with mb_no_skip_coeff=0. It also enables an
  128. // encoder to produce a more optimized stream than when mb_no_skip_coeff=0.
  129. hdr.mb_no_skip_coeff = true;
  130. return hdr;
  131. }
  132. constexpr uint8_t kMinSupportedVP8TemporalLayers = 2;
  133. constexpr uint8_t kMaxSupportedVP8TemporalLayers = 3;
  134. bool UpdateFrameHeaderForTemporalLayerEncoding(
  135. const size_t num_layers,
  136. const size_t frame_num,
  137. Vp8FrameHeader& frame_hdr,
  138. Vp8Metadata& metadata,
  139. std::array<bool, kNumVp8ReferenceBuffers>& ref_frames_used) {
  140. DCHECK_GE(num_layers, kMinSupportedVP8TemporalLayers);
  141. DCHECK_LE(num_layers, kMaxSupportedVP8TemporalLayers);
  142. enum BufferFlags : uint8_t {
  143. kNone = 0,
  144. kReference = 1,
  145. kUpdate = 2,
  146. kReferenceAndUpdate = kReference | kUpdate,
  147. };
  148. std::array<BufferFlags, kNumVp8ReferenceBuffers> buffer_flags;
  149. const bool keyframe = frame_num == 0;
  150. if (keyframe) {
  151. metadata.non_reference = false;
  152. metadata.temporal_idx = 0;
  153. metadata.layer_sync = false;
  154. buffer_flags.fill(kUpdate);
  155. } else {
  156. constexpr size_t kTemporalLayerCycle = 4;
  157. constexpr std::pair<Vp8Metadata,
  158. std::array<BufferFlags, kNumVp8ReferenceBuffers>>
  159. kFrameConfigs[][kTemporalLayerCycle] = {
  160. {
  161. // For two temporal layers.
  162. {{.non_reference = false,
  163. .temporal_idx = 0,
  164. .layer_sync = false},
  165. {kReferenceAndUpdate, kNone, kNone}},
  166. {{.non_reference = true, .temporal_idx = 1, .layer_sync = true},
  167. {kReference, kNone, kNone}},
  168. {{.non_reference = false,
  169. .temporal_idx = 0,
  170. .layer_sync = false},
  171. {kReferenceAndUpdate, kNone, kNone}},
  172. {{.non_reference = true, .temporal_idx = 1, .layer_sync = true},
  173. {kReference, kNone, kNone}},
  174. },
  175. {
  176. // For three temporal layers.
  177. {{.non_reference = false,
  178. .temporal_idx = 0,
  179. .layer_sync = false},
  180. {kReferenceAndUpdate, kNone, kNone}},
  181. {{.non_reference = true, .temporal_idx = 2, .layer_sync = true},
  182. {kReference, kNone, kNone}},
  183. {{.non_reference = false,
  184. .temporal_idx = 1,
  185. .layer_sync = true},
  186. {kReference, kUpdate, kNone}},
  187. {{.non_reference = true,
  188. .temporal_idx = 2,
  189. .layer_sync = false},
  190. {kNone, kReference, kNone}},
  191. },
  192. };
  193. std::tie(metadata, buffer_flags) =
  194. kFrameConfigs[num_layers - kMinSupportedVP8TemporalLayers]
  195. [frame_num % kTemporalLayerCycle];
  196. }
  197. frame_hdr.frame_type =
  198. keyframe ? Vp8FrameHeader::KEYFRAME : Vp8FrameHeader::INTERFRAME;
  199. frame_hdr.refresh_last = buffer_flags[0] & kUpdate;
  200. frame_hdr.refresh_golden_frame = buffer_flags[1] & kUpdate;
  201. frame_hdr.refresh_alternate_frame = buffer_flags[2] & kUpdate;
  202. frame_hdr.copy_buffer_to_golden = Vp8FrameHeader::NO_GOLDEN_REFRESH;
  203. frame_hdr.copy_buffer_to_alternate = Vp8FrameHeader::NO_ALT_REFRESH;
  204. for (size_t i = 0; i < kNumVp8ReferenceBuffers; ++i)
  205. ref_frames_used[i] = buffer_flags[i] & kReference;
  206. return true;
  207. }
  208. } // namespace
  209. VP8VaapiVideoEncoderDelegate::EncodeParams::EncodeParams()
  210. : kf_period_frames(kKFPeriod),
  211. framerate(0),
  212. min_qp(kMinQP),
  213. max_qp(kMaxQP) {}
  214. void VP8VaapiVideoEncoderDelegate::Reset() {
  215. current_params_ = EncodeParams();
  216. reference_frames_.Clear();
  217. frame_num_ = 0;
  218. }
  219. VP8VaapiVideoEncoderDelegate::VP8VaapiVideoEncoderDelegate(
  220. scoped_refptr<VaapiWrapper> vaapi_wrapper,
  221. base::RepeatingClosure error_cb)
  222. : VaapiVideoEncoderDelegate(std::move(vaapi_wrapper), error_cb) {}
  223. VP8VaapiVideoEncoderDelegate::~VP8VaapiVideoEncoderDelegate() {
  224. // VP8VaapiVideoEncoderDelegate can be destroyed on any thread.
  225. }
  226. bool VP8VaapiVideoEncoderDelegate::Initialize(
  227. const VideoEncodeAccelerator::Config& config,
  228. const VaapiVideoEncoderDelegate::Config& ave_config) {
  229. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  230. if (VideoCodecProfileToVideoCodec(config.output_profile) !=
  231. VideoCodec::kVP8) {
  232. DVLOGF(1) << "Invalid profile: " << GetProfileName(config.output_profile);
  233. return false;
  234. }
  235. if (config.input_visible_size.IsEmpty()) {
  236. DVLOGF(1) << "Input visible size could not be empty";
  237. return false;
  238. }
  239. if (config.bitrate.mode() == Bitrate::Mode::kVariable) {
  240. DVLOGF(1) << "Invalid configuraiton. VBR is not supported for VP8.";
  241. return false;
  242. }
  243. if (config.HasSpatialLayer()) {
  244. DVLOGF(1) << "Invalid configuration. Spatial layers not supported in VP8";
  245. return false;
  246. }
  247. if (config.HasTemporalLayer()) {
  248. CHECK_EQ(config.spatial_layers.size(), 1u);
  249. // TODO(b/202926617): Remove once VP8 TL encoding is enabled by default.
  250. const bool enable_vp8_tl_encoding =
  251. #if defined(ARCH_CPU_X86_FAMILY) && BUILDFLAG(IS_CHROMEOS)
  252. base::FeatureList::IsEnabled(kVaapiVp8TemporalLayerHWEncoding);
  253. #else
  254. false;
  255. #endif
  256. if (enable_vp8_tl_encoding) {
  257. num_temporal_layers_ = config.spatial_layers[0].num_of_temporal_layers;
  258. if (num_temporal_layers_ > kMaxSupportedVP8TemporalLayers ||
  259. num_temporal_layers_ < kMinSupportedVP8TemporalLayers) {
  260. VLOGF(1) << "Unsupported number of temporal layers: "
  261. << base::strict_cast<size_t>(num_temporal_layers_);
  262. return false;
  263. }
  264. } else {
  265. DVLOGF(2) << "Ignoring temporal layer encoding request";
  266. num_temporal_layers_ = 1;
  267. }
  268. }
  269. visible_size_ = config.input_visible_size;
  270. coded_size_ = gfx::Size(base::bits::AlignUp(visible_size_.width(), 16),
  271. base::bits::AlignUp(visible_size_.height(), 16));
  272. Reset();
  273. VideoBitrateAllocation initial_bitrate_allocation;
  274. if (num_temporal_layers_ > 1)
  275. initial_bitrate_allocation = AllocateBitrateForDefaultEncoding(config);
  276. else
  277. initial_bitrate_allocation.SetBitrate(0, 0, config.bitrate.target_bps());
  278. current_params_.max_qp = kMaxQPForSoftwareRateCtrl;
  279. // |rate_ctrl_| might be injected for tests.
  280. if (!rate_ctrl_) {
  281. rate_ctrl_ = VP8RateControl::Create(CreateRateControlConfig(
  282. visible_size_, current_params_, initial_bitrate_allocation,
  283. num_temporal_layers_));
  284. if (!rate_ctrl_)
  285. return false;
  286. }
  287. return UpdateRates(initial_bitrate_allocation,
  288. config.initial_framerate.value_or(
  289. VideoEncodeAccelerator::kDefaultFramerate));
  290. }
  291. gfx::Size VP8VaapiVideoEncoderDelegate::GetCodedSize() const {
  292. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  293. DCHECK(!coded_size_.IsEmpty());
  294. return coded_size_;
  295. }
  296. size_t VP8VaapiVideoEncoderDelegate::GetMaxNumOfRefFrames() const {
  297. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  298. return kNumVp8ReferenceBuffers;
  299. }
  300. std::vector<gfx::Size> VP8VaapiVideoEncoderDelegate::GetSVCLayerResolutions() {
  301. return {visible_size_};
  302. }
  303. bool VP8VaapiVideoEncoderDelegate::PrepareEncodeJob(EncodeJob& encode_job) {
  304. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  305. if (encode_job.IsKeyframeRequested())
  306. frame_num_ = 0;
  307. if (frame_num_ == 0)
  308. encode_job.ProduceKeyframe();
  309. DCHECK_EQ(encode_job.IsKeyframeRequested(), frame_num_ == 0);
  310. scoped_refptr<VP8Picture> picture = GetVP8Picture(encode_job);
  311. DCHECK(picture);
  312. // We only use |last_frame| for a reference frame. This follows the behavior
  313. // of libvpx encoder in chromium webrtc use case.
  314. std::array<bool, kNumVp8ReferenceBuffers> ref_frames_used;
  315. SetFrameHeader(frame_num_, *picture, ref_frames_used);
  316. DCHECK(!picture->frame_hdr->IsKeyframe() ||
  317. !base::Contains(ref_frames_used, true));
  318. if (!SubmitFrameParameters(encode_job, current_params_, picture,
  319. reference_frames_, ref_frames_used)) {
  320. LOG(ERROR) << "Failed submitting frame parameters";
  321. return false;
  322. }
  323. UpdateReferenceFrames(picture);
  324. frame_num_ = (frame_num_ + 1) % current_params_.kf_period_frames;
  325. return true;
  326. }
  327. BitstreamBufferMetadata VP8VaapiVideoEncoderDelegate::GetMetadata(
  328. const EncodeJob& encode_job,
  329. size_t payload_size) {
  330. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  331. auto metadata =
  332. VaapiVideoEncoderDelegate::GetMetadata(encode_job, payload_size);
  333. auto picture = GetVP8Picture(encode_job);
  334. DCHECK(picture);
  335. metadata.vp8 = picture->metadata_for_encoding;
  336. metadata.qp =
  337. base::strict_cast<int32_t>(picture->frame_hdr->quantization_hdr.y_ac_qi);
  338. return metadata;
  339. }
  340. void VP8VaapiVideoEncoderDelegate::BitrateControlUpdate(
  341. uint64_t encoded_chunk_size_bytes) {
  342. if (!rate_ctrl_) {
  343. DLOG(ERROR) << __func__ << "() is called when no bitrate controller exists";
  344. return;
  345. }
  346. DVLOGF(4) << "|encoded_chunk_size_bytes|=" << encoded_chunk_size_bytes;
  347. rate_ctrl_->PostEncodeUpdate(encoded_chunk_size_bytes);
  348. }
  349. bool VP8VaapiVideoEncoderDelegate::UpdateRates(
  350. const VideoBitrateAllocation& bitrate_allocation,
  351. uint32_t framerate) {
  352. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  353. if (bitrate_allocation.GetMode() != Bitrate::Mode::kConstant) {
  354. DLOG(ERROR) << "VBR is not supported for VP8 but was requested.";
  355. return false;
  356. }
  357. uint32_t bitrate = bitrate_allocation.GetSumBps();
  358. if (bitrate == 0 || framerate == 0)
  359. return false;
  360. if (current_params_.bitrate_allocation == bitrate_allocation &&
  361. current_params_.framerate == framerate) {
  362. return true;
  363. }
  364. VLOGF(2) << "New bitrate: " << bitrate_allocation.ToString()
  365. << ", new framerate: " << framerate;
  366. current_params_.bitrate_allocation = bitrate_allocation;
  367. current_params_.framerate = framerate;
  368. rate_ctrl_->UpdateRateControl(
  369. CreateRateControlConfig(visible_size_, current_params_,
  370. bitrate_allocation, num_temporal_layers_));
  371. return true;
  372. }
  373. void VP8VaapiVideoEncoderDelegate::SetFrameHeader(
  374. size_t frame_num,
  375. VP8Picture& picture,
  376. std::array<bool, kNumVp8ReferenceBuffers>& ref_frames_used) {
  377. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  378. const bool keyframe = frame_num == 0;
  379. *picture.frame_hdr = GetDefaultVp8FrameHeader(keyframe, visible_size_);
  380. if (num_temporal_layers_ > 1) {
  381. UpdateFrameHeaderForTemporalLayerEncoding(
  382. num_temporal_layers_, frame_num, *picture.frame_hdr,
  383. picture.metadata_for_encoding.emplace(), ref_frames_used);
  384. } else {
  385. picture.frame_hdr->refresh_last = true;
  386. if (keyframe) {
  387. picture.frame_hdr->refresh_golden_frame = true;
  388. picture.frame_hdr->refresh_alternate_frame = true;
  389. picture.frame_hdr->copy_buffer_to_golden =
  390. Vp8FrameHeader::NO_GOLDEN_REFRESH;
  391. picture.frame_hdr->copy_buffer_to_alternate =
  392. Vp8FrameHeader::NO_ALT_REFRESH;
  393. ref_frames_used = {false, false, false};
  394. } else {
  395. picture.frame_hdr->refresh_golden_frame = false;
  396. picture.frame_hdr->refresh_alternate_frame = false;
  397. picture.frame_hdr->copy_buffer_to_golden =
  398. Vp8FrameHeader::COPY_LAST_TO_GOLDEN;
  399. picture.frame_hdr->copy_buffer_to_alternate =
  400. Vp8FrameHeader::COPY_GOLDEN_TO_ALT;
  401. ref_frames_used = {true, false, false};
  402. }
  403. }
  404. libvpx::VP8FrameParamsQpRTC frame_params{};
  405. frame_params.frame_type =
  406. keyframe ? FRAME_TYPE::KEY_FRAME : FRAME_TYPE::INTER_FRAME;
  407. frame_params.temporal_layer_id =
  408. picture.metadata_for_encoding.has_value()
  409. ? picture.metadata_for_encoding->temporal_idx
  410. : 0;
  411. rate_ctrl_->ComputeQP(frame_params);
  412. picture.frame_hdr->quantization_hdr.y_ac_qi = rate_ctrl_->GetQP();
  413. DVLOGF(4) << "qp="
  414. << static_cast<int>(picture.frame_hdr->quantization_hdr.y_ac_qi)
  415. << (keyframe ? " (keyframe)" : "")
  416. << (picture.metadata_for_encoding
  417. ? " temporal id=" +
  418. base::NumberToString(frame_params.temporal_layer_id)
  419. : "");
  420. }
  421. void VP8VaapiVideoEncoderDelegate::UpdateReferenceFrames(
  422. scoped_refptr<VP8Picture> picture) {
  423. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  424. reference_frames_.Refresh(picture);
  425. }
  426. bool VP8VaapiVideoEncoderDelegate::SubmitFrameParameters(
  427. EncodeJob& job,
  428. const EncodeParams& encode_params,
  429. scoped_refptr<VP8Picture> pic,
  430. const Vp8ReferenceFrameVector& ref_frames,
  431. const std::array<bool, kNumVp8ReferenceBuffers>& ref_frames_used) {
  432. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  433. VAEncSequenceParameterBufferVP8 seq_param = {};
  434. const auto& frame_header = pic->frame_hdr;
  435. seq_param.frame_width = frame_header->width;
  436. seq_param.frame_height = frame_header->height;
  437. seq_param.frame_width_scale = frame_header->horizontal_scale;
  438. seq_param.frame_height_scale = frame_header->vertical_scale;
  439. seq_param.error_resilient = 1;
  440. seq_param.bits_per_second = encode_params.bitrate_allocation.GetSumBps();
  441. seq_param.intra_period = encode_params.kf_period_frames;
  442. VAEncPictureParameterBufferVP8 pic_param = {};
  443. pic_param.reconstructed_frame = pic->AsVaapiVP8Picture()->GetVASurfaceID();
  444. DCHECK_NE(pic_param.reconstructed_frame, VA_INVALID_ID);
  445. auto last_frame = ref_frames.GetFrame(Vp8RefType::VP8_FRAME_LAST);
  446. pic_param.ref_last_frame =
  447. last_frame ? last_frame->AsVaapiVP8Picture()->GetVASurfaceID()
  448. : VA_INVALID_ID;
  449. auto golden_frame = ref_frames.GetFrame(Vp8RefType::VP8_FRAME_GOLDEN);
  450. pic_param.ref_gf_frame =
  451. golden_frame ? golden_frame->AsVaapiVP8Picture()->GetVASurfaceID()
  452. : VA_INVALID_ID;
  453. auto alt_frame = ref_frames.GetFrame(Vp8RefType::VP8_FRAME_ALTREF);
  454. pic_param.ref_arf_frame =
  455. alt_frame ? alt_frame->AsVaapiVP8Picture()->GetVASurfaceID()
  456. : VA_INVALID_ID;
  457. pic_param.coded_buf = job.coded_buffer_id();
  458. DCHECK_NE(pic_param.coded_buf, VA_INVALID_ID);
  459. pic_param.ref_flags.bits.no_ref_last =
  460. !ref_frames_used[Vp8RefType::VP8_FRAME_LAST];
  461. pic_param.ref_flags.bits.no_ref_gf =
  462. !ref_frames_used[Vp8RefType::VP8_FRAME_GOLDEN];
  463. pic_param.ref_flags.bits.no_ref_arf =
  464. !ref_frames_used[Vp8RefType::VP8_FRAME_ALTREF];
  465. if (frame_header->IsKeyframe()) {
  466. pic_param.ref_flags.bits.force_kf = true;
  467. }
  468. pic_param.pic_flags.bits.frame_type = frame_header->frame_type;
  469. pic_param.pic_flags.bits.version = frame_header->version;
  470. pic_param.pic_flags.bits.show_frame = frame_header->show_frame;
  471. pic_param.pic_flags.bits.loop_filter_type = frame_header->loopfilter_hdr.type;
  472. pic_param.pic_flags.bits.num_token_partitions =
  473. frame_header->num_of_dct_partitions;
  474. pic_param.pic_flags.bits.segmentation_enabled =
  475. frame_header->segmentation_hdr.segmentation_enabled;
  476. pic_param.pic_flags.bits.update_mb_segmentation_map =
  477. frame_header->segmentation_hdr.update_mb_segmentation_map;
  478. pic_param.pic_flags.bits.update_segment_feature_data =
  479. frame_header->segmentation_hdr.update_segment_feature_data;
  480. pic_param.pic_flags.bits.loop_filter_adj_enable =
  481. frame_header->loopfilter_hdr.loop_filter_adj_enable;
  482. pic_param.pic_flags.bits.refresh_entropy_probs =
  483. frame_header->refresh_entropy_probs;
  484. pic_param.pic_flags.bits.refresh_golden_frame =
  485. frame_header->refresh_golden_frame;
  486. pic_param.pic_flags.bits.refresh_alternate_frame =
  487. frame_header->refresh_alternate_frame;
  488. pic_param.pic_flags.bits.refresh_last = frame_header->refresh_last;
  489. pic_param.pic_flags.bits.copy_buffer_to_golden =
  490. frame_header->copy_buffer_to_golden;
  491. pic_param.pic_flags.bits.copy_buffer_to_alternate =
  492. frame_header->copy_buffer_to_alternate;
  493. pic_param.pic_flags.bits.sign_bias_golden = frame_header->sign_bias_golden;
  494. pic_param.pic_flags.bits.sign_bias_alternate =
  495. frame_header->sign_bias_alternate;
  496. pic_param.pic_flags.bits.mb_no_coeff_skip = frame_header->mb_no_skip_coeff;
  497. if (frame_header->IsKeyframe())
  498. pic_param.pic_flags.bits.forced_lf_adjustment = true;
  499. static_assert(std::extent<decltype(pic_param.loop_filter_level)>() ==
  500. std::extent<decltype(pic_param.ref_lf_delta)>() &&
  501. std::extent<decltype(pic_param.ref_lf_delta)>() ==
  502. std::extent<decltype(pic_param.mode_lf_delta)>() &&
  503. std::extent<decltype(pic_param.ref_lf_delta)>() ==
  504. std::extent<decltype(
  505. frame_header->loopfilter_hdr.ref_frame_delta)>() &&
  506. std::extent<decltype(pic_param.mode_lf_delta)>() ==
  507. std::extent<decltype(
  508. frame_header->loopfilter_hdr.mb_mode_delta)>(),
  509. "Invalid loop filter array sizes");
  510. for (size_t i = 0; i < std::size(pic_param.loop_filter_level); ++i) {
  511. pic_param.loop_filter_level[i] = frame_header->loopfilter_hdr.level;
  512. pic_param.ref_lf_delta[i] = frame_header->loopfilter_hdr.ref_frame_delta[i];
  513. pic_param.mode_lf_delta[i] = frame_header->loopfilter_hdr.mb_mode_delta[i];
  514. }
  515. pic_param.sharpness_level = frame_header->loopfilter_hdr.sharpness_level;
  516. pic_param.clamp_qindex_high = encode_params.max_qp;
  517. pic_param.clamp_qindex_low = encode_params.min_qp;
  518. VAQMatrixBufferVP8 qmatrix_buf = {};
  519. for (auto& index : qmatrix_buf.quantization_index)
  520. index = frame_header->quantization_hdr.y_ac_qi;
  521. qmatrix_buf.quantization_index_delta[0] =
  522. frame_header->quantization_hdr.y_dc_delta;
  523. qmatrix_buf.quantization_index_delta[1] =
  524. frame_header->quantization_hdr.y2_dc_delta;
  525. qmatrix_buf.quantization_index_delta[2] =
  526. frame_header->quantization_hdr.y2_ac_delta;
  527. qmatrix_buf.quantization_index_delta[3] =
  528. frame_header->quantization_hdr.uv_dc_delta;
  529. qmatrix_buf.quantization_index_delta[4] =
  530. frame_header->quantization_hdr.uv_ac_delta;
  531. return vaapi_wrapper_->SubmitBuffers(
  532. {{VAEncSequenceParameterBufferType, sizeof(seq_param), &seq_param},
  533. {VAEncPictureParameterBufferType, sizeof(pic_param), &pic_param},
  534. {VAQMatrixBufferType, sizeof(qmatrix_buf), &qmatrix_buf}});
  535. }
  536. } // namespace media