• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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