Shaka Packager SDK
Loading...
Searching...
No Matches
bandwidth_estimator.cc
1// Copyright 2014 Google LLC. All rights reserved.
2//
3// Use of this source code is governed by a BSD-style
4// license that can be found in the LICENSE file or at
5// https://developers.google.com/open-source/licenses/bsd
6
7#include <packager/mpd/base/bandwidth_estimator.h>
8
9#include <algorithm>
10#include <cmath>
11#include <numeric>
12
13#include <absl/log/check.h>
14#include <absl/log/log.h>
15
16#include <packager/macros/logging.h>
17
18namespace shaka {
19
20BandwidthEstimator::BandwidthEstimator() = default;
21
22BandwidthEstimator::~BandwidthEstimator() = default;
23
24void BandwidthEstimator::AddBlock(uint64_t size_in_bytes, double duration) {
25 if (size_in_bytes == 0 || duration == 0) {
26 LOG(WARNING) << "Ignore block with size=" << size_in_bytes
27 << ", duration=" << duration;
28 return;
29 }
30
31 const int kBitsInByte = 8;
32 const uint64_t size_in_bits = size_in_bytes * kBitsInByte;
33 total_size_in_bits_ += size_in_bits;
34 total_duration_ += duration;
35
36 const size_t kTargetDurationThreshold = 10;
37 if (initial_blocks_.size() < kTargetDurationThreshold) {
38 initial_blocks_.push_back({size_in_bits, duration});
39 return;
40 }
41
42 if (target_block_duration_ == 0) {
43 // Use the average duration as the target block duration. It will be used
44 // to filter small blocks from bandwidth calculation.
45 target_block_duration_ = GetAverageBlockDuration();
46 for (const Block& block : initial_blocks_) {
47 max_bitrate_ =
48 std::max(max_bitrate_, GetBitrate(block, target_block_duration_));
49 }
50 return;
51 }
52 max_bitrate_ = std::max(max_bitrate_, GetBitrate({size_in_bits, duration},
53 target_block_duration_));
54}
55
57 if (total_duration_ == 0)
58 return 0;
59 return static_cast<uint64_t>(ceil(total_size_in_bits_ / total_duration_));
60}
61
62uint64_t BandwidthEstimator::Max() const {
63 if (max_bitrate_ != 0)
64 return max_bitrate_;
65
66 // We don't have the |target_block_duration_| yet. Calculate a target
67 // duration from the current available blocks.
68 DCHECK(target_block_duration_ == 0);
69 const double target_block_duration = GetAverageBlockDuration();
70
71 // Calculate maximum bitrate with the target duration calculated above.
72 uint64_t max_bitrate = 0;
73 for (const Block& block : initial_blocks_) {
74 max_bitrate =
75 std::max(max_bitrate, GetBitrate(block, target_block_duration));
76 }
77 return max_bitrate;
78}
79
80double BandwidthEstimator::GetAverageBlockDuration() const {
81 if (initial_blocks_.empty())
82 return 0.0;
83 const double sum =
84 std::accumulate(initial_blocks_.begin(), initial_blocks_.end(), 0.0,
85 [](double duration, const Block& block) {
86 return duration + block.duration;
87 });
88 return sum / initial_blocks_.size();
89}
90
91uint64_t BandwidthEstimator::GetBitrate(const Block& block,
92 double target_block_duration) const {
93 if (block.duration < 0.5 * target_block_duration) {
94 // https://tools.ietf.org/html/rfc8216#section-4.1
95 // The peak segment bit rate of a Media Playlist is the largest bit rate of
96 // any continuous set of segments whose total duration is between 0.5
97 // and 1.5 times the target duration.
98 // Only the short segments are excluded here as our media playlist generator
99 // sets the target duration in the playlist to the largest segment duration.
100 // So although the segment duration could be 1.5 times the user provided
101 // segment duration, it will never be larger than the actual target
102 // duration.
103 //
104 // We also apply the same exclusion to the bandwidth computation for DASH as
105 // the bitrate for the short segment is not a good signal for peak
106 // bandwidth.
107 // See https://github.com/shaka-project/shaka-packager/issues/498 for
108 // details.
109 VLOG(1) << "Exclude short segment (duration " << block.duration
110 << ", target_duration " << target_block_duration
111 << ") in peak bandwidth computation.";
112 return 0;
113 }
114 return static_cast<uint64_t>(ceil(block.size_in_bits / block.duration));
115}
116
117} // namespace shaka
void AddBlock(uint64_t size_in_bytes, double duration)
All the methods that are virtual are virtual for mocking.