Index: content/common/gpu/media/vaapi_h264_decoder.cc |
diff --git a/content/common/gpu/media/vaapi_h264_decoder.cc b/content/common/gpu/media/vaapi_h264_decoder.cc |
index 768a02371fceac67a214585070b9e42950d9d5ea..fc66729f6dd39918667a65443c2d94dc7a222f4a 100644 |
--- a/content/common/gpu/media/vaapi_h264_decoder.cc |
+++ b/content/common/gpu/media/vaapi_h264_decoder.cc |
@@ -7,6 +7,7 @@ |
#include "base/bind.h" |
#include "base/bind_helpers.h" |
+#include "base/numerics/safe_conversions.h" |
#include "base/stl_util.h" |
#include "content/common/gpu/media/vaapi_h264_decoder.h" |
@@ -62,6 +63,7 @@ VaapiH264Decoder::VaapiH264Decoder( |
max_frame_num_(0), |
max_pic_num_(0), |
max_long_term_frame_idx_(0), |
+ max_num_reorder_frames_(0), |
curr_sps_id_(-1), |
curr_pps_id_(-1), |
vaapi_wrapper_(vaapi_wrapper), |
@@ -1329,20 +1331,18 @@ bool VaapiH264Decoder::FinishPicture() { |
dpb_.GetNotOutputtedPicsAppending(not_outputted); |
// Include the one we've just decoded. |
not_outputted.push_back(pic.get()); |
+ |
// Sort in output order. |
std::sort(not_outputted.begin(), not_outputted.end(), POCAscCompare()); |
- // Try to output as many pictures as we can. A picture can be output |
- // if its POC is next after the previously outputted one (which means |
- // last_output_poc_ + 2, because POCs are incremented by 2 to accommodate |
- // fields when decoding interleaved streams). POC can also be equal to |
- // last outputted picture's POC when it wraps around back to 0. |
+ // Try to output as many pictures as we can. A picture can be output, |
+ // if the number of decoded and not yet outputted pictures that would remain |
+ // in DPB afterwards would at least be equal to max_num_reorder_frames. |
// If the outputted picture is not a reference picture, it doesn't have |
// to remain in the DPB and can be removed. |
H264Picture::PtrVector::iterator output_candidate = not_outputted.begin(); |
- for (; output_candidate != not_outputted.end() && |
- (*output_candidate)->pic_order_cnt <= last_output_poc_ + 2; |
- ++output_candidate) { |
+ size_t num_remaining = not_outputted.size(); |
+ while (num_remaining > max_num_reorder_frames_) { |
int poc = (*output_candidate)->pic_order_cnt; |
DCHECK_GE(poc, last_output_poc_); |
if (!OutputPic(*output_candidate)) |
@@ -1356,6 +1356,9 @@ bool VaapiH264Decoder::FinishPicture() { |
// Mark as unused. |
UnassignSurfaceFromPoC(poc); |
} |
+ |
+ ++output_candidate; |
+ --num_remaining; |
} |
// If we haven't managed to output the picture that we just decoded, or if |
@@ -1399,6 +1402,43 @@ static int LevelToMaxDpbMbs(int level) { |
} |
} |
+bool VaapiH264Decoder::UpdateMaxNumReorderFrames(const media::H264SPS* sps) { |
+ if (sps->vui_parameters_present_flag && sps->bitstream_restriction_flag) { |
+ max_num_reorder_frames_ = |
+ base::checked_cast<size_t>(sps->max_num_reorder_frames); |
+ if (max_num_reorder_frames_ > dpb_.max_num_pics()) { |
+ DVLOG(1) |
+ << "max_num_reorder_frames present, but larger than MaxDpbFrames (" |
+ << max_num_reorder_frames_ << " > " << dpb_.max_num_pics() << ")"; |
+ max_num_reorder_frames_ = 0; |
+ return false; |
+ } |
+ return true; |
+ } |
+ |
+ // max_num_reorder_frames not present, infer from profile/constraints |
+ // (see VUI semantics in spec). |
+ if (sps->constraint_setx_flag[3]) { |
+ switch (sps->profile_idc) { |
+ case 44: |
+ case 86: |
+ case 100: |
+ case 110: |
+ case 122: |
+ case 244: |
+ max_num_reorder_frames_ = 0; |
+ break; |
+ default: |
+ max_num_reorder_frames_ = dpb_.max_num_pics(); |
+ break; |
+ } |
+ } else { |
+ max_num_reorder_frames_ = dpb_.max_num_pics(); |
+ } |
+ |
+ return true; |
+} |
+ |
bool VaapiH264Decoder::ProcessSPS(int sps_id, bool* need_new_buffers) { |
const media::H264SPS* sps = parser_.GetSPS(sps_id); |
DCHECK(sps); |
@@ -1459,6 +1499,10 @@ bool VaapiH264Decoder::ProcessSPS(int sps_id, bool* need_new_buffers) { |
dpb_.set_max_num_pics(max_dpb_size); |
+ if (!UpdateMaxNumReorderFrames(sps)) |
+ return false; |
+ DVLOG(1) << "max_num_reorder_frames: " << max_num_reorder_frames_; |
+ |
*need_new_buffers = true; |
return true; |
} |