OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
11 #include "webrtc/modules/video_coding/main/source/decoding_state.h" | 11 #include "webrtc/modules/video_coding/main/source/decoding_state.h" |
12 | 12 |
13 #include "webrtc/modules/include/module_common_types.h" | 13 #include "webrtc/modules/include/module_common_types.h" |
14 #include "webrtc/modules/video_coding/main/source/frame_buffer.h" | 14 #include "webrtc/modules/video_coding/main/source/frame_buffer.h" |
15 #include "webrtc/modules/video_coding/main/source/jitter_buffer_common.h" | 15 #include "webrtc/modules/video_coding/main/source/jitter_buffer_common.h" |
16 #include "webrtc/modules/video_coding/main/source/packet.h" | 16 #include "webrtc/modules/video_coding/main/source/packet.h" |
17 | 17 |
18 namespace webrtc { | 18 namespace webrtc { |
19 | 19 |
20 VCMDecodingState::VCMDecodingState() | 20 VCMDecodingState::VCMDecodingState() |
21 : sequence_num_(0), | 21 : sequence_num_(0), |
22 time_stamp_(0), | 22 time_stamp_(0), |
23 picture_id_(kNoPictureId), | 23 picture_id_(kNoPictureId), |
24 temporal_id_(kNoTemporalIdx), | 24 temporal_id_(kNoTemporalIdx), |
25 tl0_pic_id_(kNoTl0PicIdx), | 25 tl0_pic_id_(kNoTl0PicIdx), |
26 full_sync_(true), | 26 full_sync_(true), |
27 in_initial_state_(true) { | 27 in_initial_state_(true) {} |
28 memset(frame_decoded_, 0, sizeof(frame_decoded_)); | |
29 } | |
30 | 28 |
31 VCMDecodingState::~VCMDecodingState() {} | 29 VCMDecodingState::~VCMDecodingState() {} |
32 | 30 |
33 void VCMDecodingState::Reset() { | 31 void VCMDecodingState::Reset() { |
34 // TODO(mikhal): Verify - not always would want to reset the sync | 32 // TODO(mikhal): Verify - not always would want to reset the sync |
35 sequence_num_ = 0; | 33 sequence_num_ = 0; |
36 time_stamp_ = 0; | 34 time_stamp_ = 0; |
37 picture_id_ = kNoPictureId; | 35 picture_id_ = kNoPictureId; |
38 temporal_id_ = kNoTemporalIdx; | 36 temporal_id_ = kNoTemporalIdx; |
39 tl0_pic_id_ = kNoTl0PicIdx; | 37 tl0_pic_id_ = kNoTl0PicIdx; |
40 full_sync_ = true; | 38 full_sync_ = true; |
41 in_initial_state_ = true; | 39 in_initial_state_ = true; |
42 memset(frame_decoded_, 0, sizeof(frame_decoded_)); | |
43 } | 40 } |
44 | 41 |
45 uint32_t VCMDecodingState::time_stamp() const { | 42 uint32_t VCMDecodingState::time_stamp() const { |
46 return time_stamp_; | 43 return time_stamp_; |
47 } | 44 } |
48 | 45 |
49 uint16_t VCMDecodingState::sequence_num() const { | 46 uint16_t VCMDecodingState::sequence_num() const { |
50 return sequence_num_; | 47 return sequence_num_; |
51 } | 48 } |
52 | 49 |
53 bool VCMDecodingState::IsOldFrame(const VCMFrameBuffer* frame) const { | 50 bool VCMDecodingState::IsOldFrame(const VCMFrameBuffer* frame) const { |
54 assert(frame != NULL); | 51 assert(frame != NULL); |
55 if (in_initial_state_) | 52 if (in_initial_state_) |
56 return false; | 53 return false; |
57 return !IsNewerTimestamp(frame->TimeStamp(), time_stamp_); | 54 return !IsNewerTimestamp(frame->TimeStamp(), time_stamp_); |
58 } | 55 } |
59 | 56 |
60 bool VCMDecodingState::IsOldPacket(const VCMPacket* packet) const { | 57 bool VCMDecodingState::IsOldPacket(const VCMPacket* packet) const { |
61 assert(packet != NULL); | 58 assert(packet != NULL); |
62 if (in_initial_state_) | 59 if (in_initial_state_) |
63 return false; | 60 return false; |
64 return !IsNewerTimestamp(packet->timestamp, time_stamp_); | 61 return !IsNewerTimestamp(packet->timestamp, time_stamp_); |
65 } | 62 } |
66 | 63 |
67 void VCMDecodingState::SetState(const VCMFrameBuffer* frame) { | 64 void VCMDecodingState::SetState(const VCMFrameBuffer* frame) { |
68 assert(frame != NULL && frame->GetHighSeqNum() >= 0); | 65 assert(frame != NULL && frame->GetHighSeqNum() >= 0); |
69 if (!UsingFlexibleMode(frame)) | 66 UpdateSyncState(frame); |
70 UpdateSyncState(frame); | |
71 sequence_num_ = static_cast<uint16_t>(frame->GetHighSeqNum()); | 67 sequence_num_ = static_cast<uint16_t>(frame->GetHighSeqNum()); |
72 time_stamp_ = frame->TimeStamp(); | 68 time_stamp_ = frame->TimeStamp(); |
73 picture_id_ = frame->PictureId(); | 69 picture_id_ = frame->PictureId(); |
74 temporal_id_ = frame->TemporalId(); | 70 temporal_id_ = frame->TemporalId(); |
75 tl0_pic_id_ = frame->Tl0PicId(); | 71 tl0_pic_id_ = frame->Tl0PicId(); |
76 | |
77 if (UsingFlexibleMode(frame)) { | |
78 uint16_t frame_index = picture_id_ % kFrameDecodedLength; | |
79 if (in_initial_state_) { | |
80 frame_decoded_cleared_to_ = frame_index; | |
81 } else if (frame->FrameType() == kVideoFrameKey) { | |
82 memset(frame_decoded_, 0, sizeof(frame_decoded_)); | |
83 frame_decoded_cleared_to_ = frame_index; | |
84 } else { | |
85 if (AheadOfFramesDecodedClearedTo(frame_index)) { | |
86 while (frame_decoded_cleared_to_ != frame_index) { | |
87 frame_decoded_cleared_to_ = | |
88 (frame_decoded_cleared_to_ + 1) % kFrameDecodedLength; | |
89 frame_decoded_[frame_decoded_cleared_to_] = false; | |
90 } | |
91 } | |
92 } | |
93 frame_decoded_[frame_index] = true; | |
94 } | |
95 | |
96 in_initial_state_ = false; | 72 in_initial_state_ = false; |
97 } | 73 } |
98 | 74 |
99 void VCMDecodingState::CopyFrom(const VCMDecodingState& state) { | 75 void VCMDecodingState::CopyFrom(const VCMDecodingState& state) { |
100 sequence_num_ = state.sequence_num_; | 76 sequence_num_ = state.sequence_num_; |
101 time_stamp_ = state.time_stamp_; | 77 time_stamp_ = state.time_stamp_; |
102 picture_id_ = state.picture_id_; | 78 picture_id_ = state.picture_id_; |
103 temporal_id_ = state.temporal_id_; | 79 temporal_id_ = state.temporal_id_; |
104 tl0_pic_id_ = state.tl0_pic_id_; | 80 tl0_pic_id_ = state.tl0_pic_id_; |
105 full_sync_ = state.full_sync_; | 81 full_sync_ = state.full_sync_; |
106 in_initial_state_ = state.in_initial_state_; | 82 in_initial_state_ = state.in_initial_state_; |
107 frame_decoded_cleared_to_ = state.frame_decoded_cleared_to_; | |
108 memcpy(frame_decoded_, state.frame_decoded_, sizeof(frame_decoded_)); | |
109 } | 83 } |
110 | 84 |
111 bool VCMDecodingState::UpdateEmptyFrame(const VCMFrameBuffer* frame) { | 85 bool VCMDecodingState::UpdateEmptyFrame(const VCMFrameBuffer* frame) { |
112 bool empty_packet = frame->GetHighSeqNum() == frame->GetLowSeqNum(); | 86 bool empty_packet = frame->GetHighSeqNum() == frame->GetLowSeqNum(); |
113 if (in_initial_state_ && empty_packet) { | 87 if (in_initial_state_ && empty_packet) { |
114 // Drop empty packets as long as we are in the initial state. | 88 // Drop empty packets as long as we are in the initial state. |
115 return true; | 89 return true; |
116 } | 90 } |
117 if ((empty_packet && ContinuousSeqNum(frame->GetHighSeqNum())) || | 91 if ((empty_packet && ContinuousSeqNum(frame->GetHighSeqNum())) || |
118 ContinuousFrame(frame)) { | 92 ContinuousFrame(frame)) { |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
192 return true; | 166 return true; |
193 // tl0picId is either not used, or should remain unchanged. | 167 // tl0picId is either not used, or should remain unchanged. |
194 if (frame->Tl0PicId() != tl0_pic_id_) | 168 if (frame->Tl0PicId() != tl0_pic_id_) |
195 return false; | 169 return false; |
196 // Base layers are not continuous or temporal layers are inactive. | 170 // Base layers are not continuous or temporal layers are inactive. |
197 // In the presence of temporal layers, check for Picture ID/sequence number | 171 // In the presence of temporal layers, check for Picture ID/sequence number |
198 // continuity if sync can be restored by this frame. | 172 // continuity if sync can be restored by this frame. |
199 if (!full_sync_ && !frame->LayerSync()) | 173 if (!full_sync_ && !frame->LayerSync()) |
200 return false; | 174 return false; |
201 if (UsingPictureId(frame)) { | 175 if (UsingPictureId(frame)) { |
202 if (UsingFlexibleMode(frame)) { | 176 return ContinuousPictureId(frame->PictureId()); |
203 return ContinuousFrameRefs(frame); | |
204 } else { | |
205 return ContinuousPictureId(frame->PictureId()); | |
206 } | |
207 } else { | 177 } else { |
208 return ContinuousSeqNum(static_cast<uint16_t>(frame->GetLowSeqNum())); | 178 return ContinuousSeqNum(static_cast<uint16_t>(frame->GetLowSeqNum())); |
209 } | 179 } |
210 } | 180 } |
211 | 181 |
212 bool VCMDecodingState::ContinuousPictureId(int picture_id) const { | 182 bool VCMDecodingState::ContinuousPictureId(int picture_id) const { |
213 int next_picture_id = picture_id_ + 1; | 183 int next_picture_id = picture_id_ + 1; |
214 if (picture_id < picture_id_) { | 184 if (picture_id < picture_id_) { |
215 // Wrap | 185 // Wrap |
216 if (picture_id_ >= 0x80) { | 186 if (picture_id_ >= 0x80) { |
(...skipping 22 matching lines...) Expand all Loading... |
239 else if (tl0_pic_id_ == kNoTl0PicIdx && temporal_id_ == kNoTemporalIdx && | 209 else if (tl0_pic_id_ == kNoTl0PicIdx && temporal_id_ == kNoTemporalIdx && |
240 temporal_id == 0) | 210 temporal_id == 0) |
241 return true; | 211 return true; |
242 | 212 |
243 // Current implementation: Look for base layer continuity. | 213 // Current implementation: Look for base layer continuity. |
244 if (temporal_id != 0) | 214 if (temporal_id != 0) |
245 return false; | 215 return false; |
246 return (static_cast<uint8_t>(tl0_pic_id_ + 1) == tl0_pic_id); | 216 return (static_cast<uint8_t>(tl0_pic_id_ + 1) == tl0_pic_id); |
247 } | 217 } |
248 | 218 |
249 bool VCMDecodingState::ContinuousFrameRefs(const VCMFrameBuffer* frame) const { | |
250 uint8_t num_refs = frame->CodecSpecific()->codecSpecific.VP9.num_ref_pics; | |
251 for (uint8_t r = 0; r < num_refs; ++r) { | |
252 uint16_t frame_ref = frame->PictureId() - | |
253 frame->CodecSpecific()->codecSpecific.VP9.p_diff[r]; | |
254 uint16_t frame_index = frame_ref % kFrameDecodedLength; | |
255 if (AheadOfFramesDecodedClearedTo(frame_index) || | |
256 !frame_decoded_[frame_index]) { | |
257 return false; | |
258 } | |
259 } | |
260 return true; | |
261 } | |
262 | |
263 bool VCMDecodingState::UsingPictureId(const VCMFrameBuffer* frame) const { | 219 bool VCMDecodingState::UsingPictureId(const VCMFrameBuffer* frame) const { |
264 return (frame->PictureId() != kNoPictureId && picture_id_ != kNoPictureId); | 220 return (frame->PictureId() != kNoPictureId && picture_id_ != kNoPictureId); |
265 } | 221 } |
266 | 222 |
267 bool VCMDecodingState::UsingFlexibleMode(const VCMFrameBuffer* frame) const { | |
268 return frame->CodecSpecific()->codecType == kVideoCodecVP9 && | |
269 frame->CodecSpecific()->codecSpecific.VP9.flexible_mode; | |
270 } | |
271 | |
272 // TODO(philipel): change how check work, this check practially | |
273 // limits the max p_diff to 64. | |
274 bool VCMDecodingState::AheadOfFramesDecodedClearedTo(uint16_t index) const { | |
275 // No way of knowing for sure if we are actually ahead of | |
276 // frame_decoded_cleared_to_. We just make the assumption | |
277 // that we are not trying to reference back to a very old | |
278 // index, but instead are referencing a newer index. | |
279 uint16_t diff = | |
280 index > frame_decoded_cleared_to_ | |
281 ? kFrameDecodedLength - (index - frame_decoded_cleared_to_) | |
282 : frame_decoded_cleared_to_ - index; | |
283 return diff > kFrameDecodedLength / 2; | |
284 } | |
285 | |
286 } // namespace webrtc | 223 } // namespace webrtc |
OLD | NEW |