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
VCMDecodingState()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
~VCMDecodingState()29 VCMDecodingState::~VCMDecodingState() {}
30
Reset()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
time_stamp() const42 uint32_t VCMDecodingState::time_stamp() const {
43 return time_stamp_;
44 }
45
sequence_num() const46 uint16_t VCMDecodingState::sequence_num() const {
47 return sequence_num_;
48 }
49
IsOldFrame(const VCMFrameBuffer * frame) const50 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
IsOldPacket(const VCMPacket * packet) const57 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
SetState(const VCMFrameBuffer * frame)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
CopyFrom(const VCMDecodingState & state)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
UpdateEmptyFrame(const VCMFrameBuffer * frame)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
UpdateOldPacket(const VCMPacket * packet)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
SetSeqNum(uint16_t new_seq_num)111 void VCMDecodingState::SetSeqNum(uint16_t new_seq_num) {
112 sequence_num_ = new_seq_num;
113 }
114
in_initial_state() const115 bool VCMDecodingState::in_initial_state() const {
116 return in_initial_state_;
117 }
118
full_sync() const119 bool VCMDecodingState::full_sync() const {
120 return full_sync_;
121 }
122
UpdateSyncState(const VCMFrameBuffer * frame)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
ContinuousFrame(const VCMFrameBuffer * frame) const149 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
ContinuousPictureId(int picture_id) const182 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
ContinuousSeqNum(uint16_t seq_num) const198 bool VCMDecodingState::ContinuousSeqNum(uint16_t seq_num) const {
199 return (seq_num == static_cast<uint16_t>(sequence_num_ + 1));
200 }
201
ContinuousLayer(int temporal_id,int tl0_pic_id) const202 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
UsingPictureId(const VCMFrameBuffer * frame) const219 bool VCMDecodingState::UsingPictureId(const VCMFrameBuffer* frame) const {
220 return (frame->PictureId() != kNoPictureId && picture_id_ != kNoPictureId);
221 }
222
223 } // namespace webrtc
224