| 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_)); |
| 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 frame_decoded_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 frame_decoded_cleared_to_ = frame_index; |
| 85 } else { |
| 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 frame_decoded_[frame_index] = true; |
| 92 } |
| 93 } |
| 94 |
| 72 in_initial_state_ = false; | 95 in_initial_state_ = false; |
| 73 } | 96 } |
| 74 | 97 |
| 75 void VCMDecodingState::CopyFrom(const VCMDecodingState& state) { | 98 void VCMDecodingState::CopyFrom(const VCMDecodingState& state) { |
| 76 sequence_num_ = state.sequence_num_; | 99 sequence_num_ = state.sequence_num_; |
| 77 time_stamp_ = state.time_stamp_; | 100 time_stamp_ = state.time_stamp_; |
| 78 picture_id_ = state.picture_id_; | 101 picture_id_ = state.picture_id_; |
| 79 temporal_id_ = state.temporal_id_; | 102 temporal_id_ = state.temporal_id_; |
| 80 tl0_pic_id_ = state.tl0_pic_id_; | 103 tl0_pic_id_ = state.tl0_pic_id_; |
| 81 full_sync_ = state.full_sync_; | 104 full_sync_ = state.full_sync_; |
| 82 in_initial_state_ = state.in_initial_state_; | 105 in_initial_state_ = state.in_initial_state_; |
| 106 frame_decoded_cleared_to_ = state.frame_decoded_cleared_to_; |
| 107 memcpy(frame_decoded_, state.frame_decoded_, sizeof(frame_decoded_)); |
| 83 } | 108 } |
| 84 | 109 |
| 85 bool VCMDecodingState::UpdateEmptyFrame(const VCMFrameBuffer* frame) { | 110 bool VCMDecodingState::UpdateEmptyFrame(const VCMFrameBuffer* frame) { |
| 86 bool empty_packet = frame->GetHighSeqNum() == frame->GetLowSeqNum(); | 111 bool empty_packet = frame->GetHighSeqNum() == frame->GetLowSeqNum(); |
| 87 if (in_initial_state_ && empty_packet) { | 112 if (in_initial_state_ && empty_packet) { |
| 88 // Drop empty packets as long as we are in the initial state. | 113 // Drop empty packets as long as we are in the initial state. |
| 89 return true; | 114 return true; |
| 90 } | 115 } |
| 91 if ((empty_packet && ContinuousSeqNum(frame->GetHighSeqNum())) || | 116 if ((empty_packet && ContinuousSeqNum(frame->GetHighSeqNum())) || |
| 92 ContinuousFrame(frame)) { | 117 ContinuousFrame(frame)) { |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 166 return true; | 191 return true; |
| 167 // tl0picId is either not used, or should remain unchanged. | 192 // tl0picId is either not used, or should remain unchanged. |
| 168 if (frame->Tl0PicId() != tl0_pic_id_) | 193 if (frame->Tl0PicId() != tl0_pic_id_) |
| 169 return false; | 194 return false; |
| 170 // Base layers are not continuous or temporal layers are inactive. | 195 // Base layers are not continuous or temporal layers are inactive. |
| 171 // In the presence of temporal layers, check for Picture ID/sequence number | 196 // In the presence of temporal layers, check for Picture ID/sequence number |
| 172 // continuity if sync can be restored by this frame. | 197 // continuity if sync can be restored by this frame. |
| 173 if (!full_sync_ && !frame->LayerSync()) | 198 if (!full_sync_ && !frame->LayerSync()) |
| 174 return false; | 199 return false; |
| 175 if (UsingPictureId(frame)) { | 200 if (UsingPictureId(frame)) { |
| 176 return ContinuousPictureId(frame->PictureId()); | 201 if (UsingFlexibleMode(frame)) { |
| 202 return ContinuousFrameRefs(frame); |
| 203 } else { |
| 204 return ContinuousPictureId(frame->PictureId()); |
| 205 } |
| 177 } else { | 206 } else { |
| 178 return ContinuousSeqNum(static_cast<uint16_t>(frame->GetLowSeqNum())); | 207 return ContinuousSeqNum(static_cast<uint16_t>(frame->GetLowSeqNum())); |
| 179 } | 208 } |
| 180 } | 209 } |
| 181 | 210 |
| 182 bool VCMDecodingState::ContinuousPictureId(int picture_id) const { | 211 bool VCMDecodingState::ContinuousPictureId(int picture_id) const { |
| 183 int next_picture_id = picture_id_ + 1; | 212 int next_picture_id = picture_id_ + 1; |
| 184 if (picture_id < picture_id_) { | 213 if (picture_id < picture_id_) { |
| 185 // Wrap | 214 // Wrap |
| 186 if (picture_id_ >= 0x80) { | 215 if (picture_id_ >= 0x80) { |
| (...skipping 22 matching lines...) Expand all Loading... |
| 209 else if (tl0_pic_id_ == kNoTl0PicIdx && temporal_id_ == kNoTemporalIdx && | 238 else if (tl0_pic_id_ == kNoTl0PicIdx && temporal_id_ == kNoTemporalIdx && |
| 210 temporal_id == 0) | 239 temporal_id == 0) |
| 211 return true; | 240 return true; |
| 212 | 241 |
| 213 // Current implementation: Look for base layer continuity. | 242 // Current implementation: Look for base layer continuity. |
| 214 if (temporal_id != 0) | 243 if (temporal_id != 0) |
| 215 return false; | 244 return false; |
| 216 return (static_cast<uint8_t>(tl0_pic_id_ + 1) == tl0_pic_id); | 245 return (static_cast<uint8_t>(tl0_pic_id_ + 1) == tl0_pic_id); |
| 217 } | 246 } |
| 218 | 247 |
| 248 bool VCMDecodingState::ContinuousFrameRefs(const VCMFrameBuffer* frame) const { |
| 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 if (!frame_decoded_[frame_ref % kFrameDecodedLength]) { |
| 254 return false; |
| 255 } |
| 256 } |
| 257 return true; |
| 258 } |
| 259 |
| 219 bool VCMDecodingState::UsingPictureId(const VCMFrameBuffer* frame) const { | 260 bool VCMDecodingState::UsingPictureId(const VCMFrameBuffer* frame) const { |
| 220 return (frame->PictureId() != kNoPictureId && picture_id_ != kNoPictureId); | 261 return (frame->PictureId() != kNoPictureId && picture_id_ != kNoPictureId); |
| 221 } | 262 } |
| 222 | 263 |
| 264 bool VCMDecodingState::UsingFlexibleMode(const VCMFrameBuffer* frame) const { |
| 265 return frame->CodecSpecific()->codecType == kVideoCodecVP9 && |
| 266 frame->CodecSpecific()->codecSpecific.VP9.flexible_mode; |
| 267 } |
| 268 |
| 223 } // namespace webrtc | 269 } // namespace webrtc |
| OLD | NEW |