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/interface/module_common_types.h" | 13 #include "webrtc/modules/interface/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_)); | |
sprang_webrtc
2015/09/15 15:41:22
Don't think you need this?
philipel
2015/09/16 09:35:54
I think I do: http://stackoverflow.com/questions/7
sprang_webrtc
2015/09/25 09:53:15
You're right. I was drunk.
Maybe frame_decoded_{}
| |
29 } | |
28 | 30 |
29 VCMDecodingState::~VCMDecodingState() {} | 31 VCMDecodingState::~VCMDecodingState() {} |
30 | 32 |
31 void VCMDecodingState::Reset() { | 33 void VCMDecodingState::Reset() { |
32 // TODO(mikhal): Verify - not always would want to reset the sync | 34 // TODO(mikhal): Verify - not always would want to reset the sync |
33 sequence_num_ = 0; | 35 sequence_num_ = 0; |
34 time_stamp_ = 0; | 36 time_stamp_ = 0; |
35 picture_id_ = kNoPictureId; | 37 picture_id_ = kNoPictureId; |
36 temporal_id_ = kNoTemporalIdx; | 38 temporal_id_ = kNoTemporalIdx; |
37 tl0_pic_id_ = kNoTl0PicIdx; | 39 tl0_pic_id_ = kNoTl0PicIdx; |
38 full_sync_ = true; | 40 full_sync_ = true; |
39 in_initial_state_ = true; | 41 in_initial_state_ = true; |
42 memset(frame_decoded_, 0, sizeof(frame_decoded_)); | |
40 } | 43 } |
41 | 44 |
42 uint32_t VCMDecodingState::time_stamp() const { | 45 uint32_t VCMDecodingState::time_stamp() const { |
43 return time_stamp_; | 46 return time_stamp_; |
44 } | 47 } |
45 | 48 |
46 uint16_t VCMDecodingState::sequence_num() const { | 49 uint16_t VCMDecodingState::sequence_num() const { |
47 return sequence_num_; | 50 return sequence_num_; |
48 } | 51 } |
49 | 52 |
50 bool VCMDecodingState::IsOldFrame(const VCMFrameBuffer* frame) const { | 53 bool VCMDecodingState::IsOldFrame(const VCMFrameBuffer* frame) const { |
51 assert(frame != NULL); | 54 assert(frame != NULL); |
52 if (in_initial_state_) | 55 if (in_initial_state_) |
53 return false; | 56 return false; |
54 return !IsNewerTimestamp(frame->TimeStamp(), time_stamp_); | 57 return !IsNewerTimestamp(frame->TimeStamp(), time_stamp_); |
55 } | 58 } |
56 | 59 |
57 bool VCMDecodingState::IsOldPacket(const VCMPacket* packet) const { | 60 bool VCMDecodingState::IsOldPacket(const VCMPacket* packet) const { |
58 assert(packet != NULL); | 61 assert(packet != NULL); |
59 if (in_initial_state_) | 62 if (in_initial_state_) |
60 return false; | 63 return false; |
61 return !IsNewerTimestamp(packet->timestamp, time_stamp_); | 64 return !IsNewerTimestamp(packet->timestamp, time_stamp_); |
62 } | 65 } |
63 | 66 |
64 void VCMDecodingState::SetState(const VCMFrameBuffer* frame) { | 67 void VCMDecodingState::SetState(const VCMFrameBuffer* frame) { |
65 assert(frame != NULL && frame->GetHighSeqNum() >= 0); | 68 assert(frame != NULL && frame->GetHighSeqNum() >= 0); |
66 UpdateSyncState(frame); | 69 if (frame->CodecSpecific()->codecType != kVideoCodecVP9) |
70 UpdateSyncState(frame); | |
67 sequence_num_ = static_cast<uint16_t>(frame->GetHighSeqNum()); | 71 sequence_num_ = static_cast<uint16_t>(frame->GetHighSeqNum()); |
68 time_stamp_ = frame->TimeStamp(); | 72 time_stamp_ = frame->TimeStamp(); |
69 picture_id_ = frame->PictureId(); | 73 picture_id_ = frame->PictureId(); |
70 temporal_id_ = frame->TemporalId(); | 74 temporal_id_ = frame->TemporalId(); |
71 tl0_pic_id_ = frame->Tl0PicId(); | 75 tl0_pic_id_ = frame->Tl0PicId(); |
76 | |
77 if (UsingFlexibleMode(frame)) { | |
78 uint16_t frame_index = picture_id_ % kFrameDecodedLength; | |
79 if (in_initial_state_) { | |
80 fd_cleared_to_ = frame_index; | |
81 frame_decoded_[frame_index] = true; | |
82 } else if (frame->FrameType() == kVideoFrameKey) { | |
83 memset(frame_decoded_, 0, sizeof(frame_decoded_)); | |
84 fd_cleared_to_ = frame_index; | |
85 } else { | |
86 while (fd_cleared_to_ != frame_index) { | |
87 fd_cleared_to_ = (fd_cleared_to_ + 1) % kFrameDecodedLength; | |
88 frame_decoded_[fd_cleared_to_] = false; | |
89 } | |
90 frame_decoded_[frame_index] = true; | |
91 } | |
92 } | |
93 | |
72 in_initial_state_ = false; | 94 in_initial_state_ = false; |
73 } | 95 } |
74 | 96 |
75 void VCMDecodingState::CopyFrom(const VCMDecodingState& state) { | 97 void VCMDecodingState::CopyFrom(const VCMDecodingState& state) { |
76 sequence_num_ = state.sequence_num_; | 98 sequence_num_ = state.sequence_num_; |
77 time_stamp_ = state.time_stamp_; | 99 time_stamp_ = state.time_stamp_; |
78 picture_id_ = state.picture_id_; | 100 picture_id_ = state.picture_id_; |
79 temporal_id_ = state.temporal_id_; | 101 temporal_id_ = state.temporal_id_; |
80 tl0_pic_id_ = state.tl0_pic_id_; | 102 tl0_pic_id_ = state.tl0_pic_id_; |
81 full_sync_ = state.full_sync_; | 103 full_sync_ = state.full_sync_; |
82 in_initial_state_ = state.in_initial_state_; | 104 in_initial_state_ = state.in_initial_state_; |
105 fd_cleared_to_ = state.fd_cleared_to_; | |
106 memcpy(frame_decoded_, state.frame_decoded_, sizeof(frame_decoded_)); | |
83 } | 107 } |
84 | 108 |
85 bool VCMDecodingState::UpdateEmptyFrame(const VCMFrameBuffer* frame) { | 109 bool VCMDecodingState::UpdateEmptyFrame(const VCMFrameBuffer* frame) { |
86 bool empty_packet = frame->GetHighSeqNum() == frame->GetLowSeqNum(); | 110 bool empty_packet = frame->GetHighSeqNum() == frame->GetLowSeqNum(); |
87 if (in_initial_state_ && empty_packet) { | 111 if (in_initial_state_ && empty_packet) { |
88 // Drop empty packets as long as we are in the initial state. | 112 // Drop empty packets as long as we are in the initial state. |
89 return true; | 113 return true; |
90 } | 114 } |
91 if ((empty_packet && ContinuousSeqNum(frame->GetHighSeqNum())) || | 115 if ((empty_packet && ContinuousSeqNum(frame->GetHighSeqNum())) || |
92 ContinuousFrame(frame)) { | 116 ContinuousFrame(frame)) { |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
166 return true; | 190 return true; |
167 // tl0picId is either not used, or should remain unchanged. | 191 // tl0picId is either not used, or should remain unchanged. |
168 if (frame->Tl0PicId() != tl0_pic_id_) | 192 if (frame->Tl0PicId() != tl0_pic_id_) |
169 return false; | 193 return false; |
170 // Base layers are not continuous or temporal layers are inactive. | 194 // Base layers are not continuous or temporal layers are inactive. |
171 // In the presence of temporal layers, check for Picture ID/sequence number | 195 // In the presence of temporal layers, check for Picture ID/sequence number |
172 // continuity if sync can be restored by this frame. | 196 // continuity if sync can be restored by this frame. |
173 if (!full_sync_ && !frame->LayerSync()) | 197 if (!full_sync_ && !frame->LayerSync()) |
174 return false; | 198 return false; |
175 if (UsingPictureId(frame)) { | 199 if (UsingPictureId(frame)) { |
176 return ContinuousPictureId(frame->PictureId()); | 200 if (UsingFlexibleMode(frame)) { |
201 return ContinuousFrameRefs(frame); | |
202 } else { | |
203 return ContinuousPictureId(frame->PictureId()); | |
204 } | |
177 } else { | 205 } else { |
178 return ContinuousSeqNum(static_cast<uint16_t>(frame->GetLowSeqNum())); | 206 return ContinuousSeqNum(static_cast<uint16_t>(frame->GetLowSeqNum())); |
179 } | 207 } |
180 } | 208 } |
181 | 209 |
182 bool VCMDecodingState::ContinuousPictureId(int picture_id) const { | 210 bool VCMDecodingState::ContinuousPictureId(int picture_id) const { |
183 int next_picture_id = picture_id_ + 1; | 211 int next_picture_id = picture_id_ + 1; |
184 if (picture_id < picture_id_) { | 212 if (picture_id < picture_id_) { |
185 // Wrap | 213 // Wrap |
186 if (picture_id_ >= 0x80) { | 214 if (picture_id_ >= 0x80) { |
(...skipping 22 matching lines...) Expand all Loading... | |
209 else if (tl0_pic_id_ == kNoTl0PicIdx && temporal_id_ == kNoTemporalIdx && | 237 else if (tl0_pic_id_ == kNoTl0PicIdx && temporal_id_ == kNoTemporalIdx && |
210 temporal_id == 0) | 238 temporal_id == 0) |
211 return true; | 239 return true; |
212 | 240 |
213 // Current implementation: Look for base layer continuity. | 241 // Current implementation: Look for base layer continuity. |
214 if (temporal_id != 0) | 242 if (temporal_id != 0) |
215 return false; | 243 return false; |
216 return (static_cast<uint8_t>(tl0_pic_id_ + 1) == tl0_pic_id); | 244 return (static_cast<uint8_t>(tl0_pic_id_ + 1) == tl0_pic_id); |
217 } | 245 } |
218 | 246 |
247 bool VCMDecodingState::ContinuousFrameRefs(const VCMFrameBuffer* frame) const { | |
248 bool continuous = true; | |
249 uint8_t num_refs = frame->CodecSpecific()->codecSpecific.VP9.num_ref_pics; | |
250 for (uint8_t r = 0; r < num_refs; ++r) { | |
251 uint16_t frame_ref = frame->PictureId() - | |
252 frame->CodecSpecific()->codecSpecific.VP9.p_diff[r]; | |
253 continuous &= frame_decoded_[frame_ref % kFrameDecodedLength]; | |
sprang_webrtc
2015/09/15 15:41:22
Just return false early here, and true below.
philipel
2015/09/16 09:35:54
Done.
| |
254 } | |
255 return continuous; | |
256 } | |
257 | |
219 bool VCMDecodingState::UsingPictureId(const VCMFrameBuffer* frame) const { | 258 bool VCMDecodingState::UsingPictureId(const VCMFrameBuffer* frame) const { |
220 return (frame->PictureId() != kNoPictureId && picture_id_ != kNoPictureId); | 259 return (frame->PictureId() != kNoPictureId && picture_id_ != kNoPictureId); |
221 } | 260 } |
222 | 261 |
262 bool VCMDecodingState::UsingFlexibleMode(const VCMFrameBuffer* frame) const { | |
263 return frame->CodecSpecific()->codecType == kVideoCodecVP9 && | |
264 frame->CodecSpecific()->codecSpecific.VP9.flexible_mode; | |
265 } | |
266 | |
223 } // namespace webrtc | 267 } // namespace webrtc |
OLD | NEW |