Chromium Code Reviews| Index: webrtc/modules/video_coding/decoding_state.cc |
| diff --git a/webrtc/modules/video_coding/decoding_state.cc b/webrtc/modules/video_coding/decoding_state.cc |
| index 89be9b66c1fe6e416069f248126733d742a5b7bc..a5a8542ff1c06aa3de1adc0e1737a8efebc1e75f 100644 |
| --- a/webrtc/modules/video_coding/decoding_state.cc |
| +++ b/webrtc/modules/video_coding/decoding_state.cc |
| @@ -10,6 +10,8 @@ |
| #include "webrtc/modules/video_coding/decoding_state.h" |
| +#include "webrtc/base/logging.h" |
| +#include "webrtc/common_video/h264/h264_common.h" |
| #include "webrtc/modules/include/module_common_types.h" |
| #include "webrtc/modules/video_coding/frame_buffer.h" |
| #include "webrtc/modules/video_coding/jitter_buffer_common.h" |
| @@ -40,6 +42,8 @@ void VCMDecodingState::Reset() { |
| full_sync_ = true; |
| in_initial_state_ = true; |
| memset(frame_decoded_, 0, sizeof(frame_decoded_)); |
| + received_sps_.clear(); |
| + received_pps_.clear(); |
| } |
| uint32_t VCMDecodingState::time_stamp() const { |
| @@ -74,6 +78,25 @@ void VCMDecodingState::SetState(const VCMFrameBuffer* frame) { |
| temporal_id_ = frame->TemporalId(); |
| tl0_pic_id_ = frame->Tl0PicId(); |
| + std::vector<NaluInfo> nalus = frame->GetNaluInfos(); |
| + for (const NaluInfo& nalu : nalus) { |
|
philipel
2016/09/15 12:52:46
Maybe clean up old sps/pps? How many sps/pps can w
philipel
2016/09/15 12:52:46
"const NaluInfo& nalu : frame->GetNaluInfos()" to
stefan-webrtc
2016/09/30 09:36:02
It must be able to track all of them according to
stefan-webrtc
2016/09/30 09:36:02
Done.
philipel
2016/09/30 10:52:52
Acknowledged.
|
| + if (nalu.type == H264::NaluType::kPps) { |
| + if (nalu.pps_id < 0) { |
| + LOG(LS_WARNING) << "Received pps without pps id."; |
| + } else if (nalu.sps_id < 0) { |
| + LOG(LS_WARNING) << "Received pps without sps id."; |
| + } else { |
| + received_pps_[nalu.pps_id] = nalu.sps_id; |
| + } |
| + } else if (nalu.type == H264::NaluType::kSps) { |
| + if (nalu.sps_id < 0) { |
| + LOG(LS_WARNING) << "Received sps without sps id."; |
| + } else { |
| + received_sps_.insert(nalu.sps_id); |
| + } |
| + } |
| + } |
| + |
| if (UsingFlexibleMode(frame)) { |
| uint16_t frame_index = picture_id_ % kFrameDecodedLength; |
| if (in_initial_state_) { |
| @@ -106,6 +129,8 @@ void VCMDecodingState::CopyFrom(const VCMDecodingState& state) { |
| in_initial_state_ = state.in_initial_state_; |
| frame_decoded_cleared_to_ = state.frame_decoded_cleared_to_; |
| memcpy(frame_decoded_, state.frame_decoded_, sizeof(frame_decoded_)); |
| + received_sps_ = state.received_sps_; |
| + received_pps_ = state.received_pps_; |
| } |
| bool VCMDecodingState::UpdateEmptyFrame(const VCMFrameBuffer* frame) { |
| @@ -183,8 +208,10 @@ bool VCMDecodingState::ContinuousFrame(const VCMFrameBuffer* frame) const { |
| // A key frame is always considered continuous as it doesn't refer to any |
| // frames and therefore won't introduce any errors even if prior frames are |
| // missing. |
| - if (frame->FrameType() == kVideoFrameKey) |
| + if (frame->FrameType() == kVideoFrameKey && |
| + HaveSpsAndPps(frame->GetNaluInfos())) { |
| return true; |
| + } |
| // When in the initial state we always require a key frame to start decoding. |
| if (in_initial_state_) |
| return false; |
| @@ -205,7 +232,8 @@ bool VCMDecodingState::ContinuousFrame(const VCMFrameBuffer* frame) const { |
| return ContinuousPictureId(frame->PictureId()); |
| } |
| } else { |
| - return ContinuousSeqNum(static_cast<uint16_t>(frame->GetLowSeqNum())); |
| + return ContinuousSeqNum(static_cast<uint16_t>(frame->GetLowSeqNum())) && |
| + HaveSpsAndPps(frame->GetNaluInfos()); |
| } |
| } |
| @@ -282,4 +310,48 @@ bool VCMDecodingState::AheadOfFramesDecodedClearedTo(uint16_t index) const { |
| return diff > kFrameDecodedLength / 2; |
| } |
| +bool VCMDecodingState::HaveSpsAndPps(const std::vector<NaluInfo>& nalus) const { |
| + std::set<int> new_sps; |
|
philipel
2016/09/15 12:52:46
Remove |new_sps| and insert new sps into |received
stefan-webrtc
2016/09/30 09:36:02
We can't insert them now since the frame hasn't be
philipel
2016/09/30 10:52:52
Acknowledged.
|
| + std::map<int, int> new_pps; |
|
philipel
2016/09/15 12:52:46
Remove |new_pps| and insert new pps into |received
|
| + for (const NaluInfo& nalu : nalus) { |
| + switch (nalu.type) { |
| + case H264::NaluType::kPps: |
| + if (nalu.pps_id < 0) { |
| + LOG(LS_WARNING) << "Received pps without pps id."; |
| + } else if (nalu.sps_id < 0) { |
| + LOG(LS_WARNING) << "Received pps without sps id."; |
| + } else { |
| + new_pps[nalu.pps_id] = nalu.sps_id; |
| + } |
| + break; |
| + case H264::NaluType::kSps: |
| + if (nalu.sps_id < 0) { |
| + LOG(LS_WARNING) << "Received sps without sps id."; |
| + } else { |
| + new_sps.insert(nalu.sps_id); |
| + } |
| + break; |
| + default: { |
| + int sps_needed = -1; |
| + auto pps_it = new_pps.find(nalu.pps_id); |
| + if (pps_it != new_pps.end()) { |
| + sps_needed = pps_it->second; |
| + } else { |
| + auto pps_it2 = received_pps_.find(nalu.pps_id); |
| + if (pps_it2 == received_pps_.end()) { |
| + return false; |
| + } |
| + sps_needed = pps_it2->second; |
| + } |
| + if (new_sps.find(sps_needed) == new_sps.end() && |
| + received_sps_.find(sps_needed) == received_sps_.end()) { |
| + return false; |
| + } |
| + break; |
| + } |
| + } |
| + } |
| + return true; |
| +} |
| + |
| } // namespace webrtc |