| 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 |