1 /* 2 * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #include "webrtc/modules/video_coding/main/source/decoding_state.h" 12 13 #include "webrtc/modules/interface/module_common_types.h" 14 #include "webrtc/modules/video_coding/main/source/frame_buffer.h" 15 #include "webrtc/modules/video_coding/main/source/jitter_buffer_common.h" 16 #include "webrtc/modules/video_coding/main/source/packet.h" 17 18 namespace webrtc { 19 20 VCMDecodingState::VCMDecodingState() 21 : sequence_num_(0), 22 time_stamp_(0), 23 picture_id_(kNoPictureId), 24 temporal_id_(kNoTemporalIdx), 25 tl0_pic_id_(kNoTl0PicIdx), 26 full_sync_(true), 27 in_initial_state_(true) {} 28 29 VCMDecodingState::~VCMDecodingState() {} 30 31 void VCMDecodingState::Reset() { 32 // TODO(mikhal): Verify - not always would want to reset the sync 33 sequence_num_ = 0; 34 time_stamp_ = 0; 35 picture_id_ = kNoPictureId; 36 temporal_id_ = kNoTemporalIdx; 37 tl0_pic_id_ = kNoTl0PicIdx; 38 full_sync_ = true; 39 in_initial_state_ = true; 40 } 41 42 uint32_t VCMDecodingState::time_stamp() const { 43 return time_stamp_; 44 } 45 46 uint16_t VCMDecodingState::sequence_num() const { 47 return sequence_num_; 48 } 49 50 bool VCMDecodingState::IsOldFrame(const VCMFrameBuffer* frame) const { 51 assert(frame != NULL); 52 if (in_initial_state_) 53 return false; 54 return !IsNewerTimestamp(frame->TimeStamp(), time_stamp_); 55 } 56 57 bool VCMDecodingState::IsOldPacket(const VCMPacket* packet) const { 58 assert(packet != NULL); 59 if (in_initial_state_) 60 return false; 61 return !IsNewerTimestamp(packet->timestamp, time_stamp_); 62 } 63 64 void VCMDecodingState::SetState(const VCMFrameBuffer* frame) { 65 assert(frame != NULL && frame->GetHighSeqNum() >= 0); 66 UpdateSyncState(frame); 67 sequence_num_ = static_cast<uint16_t>(frame->GetHighSeqNum()); 68 time_stamp_ = frame->TimeStamp(); 69 picture_id_ = frame->PictureId(); 70 temporal_id_ = frame->TemporalId(); 71 tl0_pic_id_ = frame->Tl0PicId(); 72 in_initial_state_ = false; 73 } 74 75 void VCMDecodingState::CopyFrom(const VCMDecodingState& state) { 76 sequence_num_ = state.sequence_num_; 77 time_stamp_ = state.time_stamp_; 78 picture_id_ = state.picture_id_; 79 temporal_id_ = state.temporal_id_; 80 tl0_pic_id_ = state.tl0_pic_id_; 81 full_sync_ = state.full_sync_; 82 in_initial_state_ = state.in_initial_state_; 83 } 84 85 bool VCMDecodingState::UpdateEmptyFrame(const VCMFrameBuffer* frame) { 86 bool empty_packet = frame->GetHighSeqNum() == frame->GetLowSeqNum(); 87 if (in_initial_state_ && empty_packet) { 88 // Drop empty packets as long as we are in the initial state. 89 return true; 90 } 91 if ((empty_packet && ContinuousSeqNum(frame->GetHighSeqNum())) || 92 ContinuousFrame(frame)) { 93 // Continuous empty packets or continuous frames can be dropped if we 94 // advance the sequence number. 95 sequence_num_ = frame->GetHighSeqNum(); 96 time_stamp_ = frame->TimeStamp(); 97 return true; 98 } 99 return false; 100 } 101 102 void VCMDecodingState::UpdateOldPacket(const VCMPacket* packet) { 103 assert(packet != NULL); 104 if (packet->timestamp == time_stamp_) { 105 // Late packet belonging to the last decoded frame - make sure we update the 106 // last decoded sequence number. 107 sequence_num_ = LatestSequenceNumber(packet->seqNum, sequence_num_); 108 } 109 } 110 111 void VCMDecodingState::SetSeqNum(uint16_t new_seq_num) { 112 sequence_num_ = new_seq_num; 113 } 114 115 bool VCMDecodingState::in_initial_state() const { 116 return in_initial_state_; 117 } 118 119 bool VCMDecodingState::full_sync() const { 120 return full_sync_; 121 } 122 123 void VCMDecodingState::UpdateSyncState(const VCMFrameBuffer* frame) { 124 if (in_initial_state_) 125 return; 126 if (frame->TemporalId() == kNoTemporalIdx || 127 frame->Tl0PicId() == kNoTl0PicIdx) { 128 full_sync_ = true; 129 } else if (frame->FrameType() == kVideoFrameKey || frame->LayerSync()) { 130 full_sync_ = true; 131 } else if (full_sync_) { 132 // Verify that we are still in sync. 133 // Sync will be broken if continuity is true for layers but not for the 134 // other methods (PictureId and SeqNum). 135 if (UsingPictureId(frame)) { 136 // First check for a valid tl0PicId. 137 if (frame->Tl0PicId() - tl0_pic_id_ > 1) { 138 full_sync_ = false; 139 } else { 140 full_sync_ = ContinuousPictureId(frame->PictureId()); 141 } 142 } else { 143 full_sync_ = ContinuousSeqNum(static_cast<uint16_t>( 144 frame->GetLowSeqNum())); 145 } 146 } 147 } 148 149 bool VCMDecodingState::ContinuousFrame(const VCMFrameBuffer* frame) const { 150 // Check continuity based on the following hierarchy: 151 // - Temporal layers (stop here if out of sync). 152 // - Picture Id when available. 153 // - Sequence numbers. 154 // Return true when in initial state. 155 // Note that when a method is not applicable it will return false. 156 assert(frame != NULL); 157 // A key frame is always considered continuous as it doesn't refer to any 158 // frames and therefore won't introduce any errors even if prior frames are 159 // missing. 160 if (frame->FrameType() == kVideoFrameKey) 161 return true; 162 // When in the initial state we always require a key frame to start decoding. 163 if (in_initial_state_) 164 return false; 165 if (ContinuousLayer(frame->TemporalId(), frame->Tl0PicId())) 166 return true; 167 // tl0picId is either not used, or should remain unchanged. 168 if (frame->Tl0PicId() != tl0_pic_id_) 169 return false; 170 // Base layers are not continuous or temporal layers are inactive. 171 // In the presence of temporal layers, check for Picture ID/sequence number 172 // continuity if sync can be restored by this frame. 173 if (!full_sync_ && !frame->LayerSync()) 174 return false; 175 if (UsingPictureId(frame)) { 176 return ContinuousPictureId(frame->PictureId()); 177 } else { 178 return ContinuousSeqNum(static_cast<uint16_t>(frame->GetLowSeqNum())); 179 } 180 } 181 182 bool VCMDecodingState::ContinuousPictureId(int picture_id) const { 183 int next_picture_id = picture_id_ + 1; 184 if (picture_id < picture_id_) { 185 // Wrap 186 if (picture_id_ >= 0x80) { 187 // 15 bits used for picture id 188 return ((next_picture_id & 0x7FFF) == picture_id); 189 } else { 190 // 7 bits used for picture id 191 return ((next_picture_id & 0x7F) == picture_id); 192 } 193 } 194 // No wrap 195 return (next_picture_id == picture_id); 196 } 197 198 bool VCMDecodingState::ContinuousSeqNum(uint16_t seq_num) const { 199 return (seq_num == static_cast<uint16_t>(sequence_num_ + 1)); 200 } 201 202 bool VCMDecodingState::ContinuousLayer(int temporal_id, 203 int tl0_pic_id) const { 204 // First, check if applicable. 205 if (temporal_id == kNoTemporalIdx || tl0_pic_id == kNoTl0PicIdx) 206 return false; 207 // If this is the first frame to use temporal layers, make sure we start 208 // from base. 209 else if (tl0_pic_id_ == kNoTl0PicIdx && temporal_id_ == kNoTemporalIdx && 210 temporal_id == 0) 211 return true; 212 213 // Current implementation: Look for base layer continuity. 214 if (temporal_id != 0) 215 return false; 216 return (static_cast<uint8_t>(tl0_pic_id_ + 1) == tl0_pic_id); 217 } 218 219 bool VCMDecodingState::UsingPictureId(const VCMFrameBuffer* frame) const { 220 return (frame->PictureId() != kNoPictureId && picture_id_ != kNoPictureId); 221 } 222 223 } // namespace webrtc 224