Home | History | Annotate | Download | only in video_coding
      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/decoding_state.h"
     12 
     13 #include "webrtc/modules/include/module_common_types.h"
     14 #include "webrtc/modules/video_coding/frame_buffer.h"
     15 #include "webrtc/modules/video_coding/jitter_buffer_common.h"
     16 #include "webrtc/modules/video_coding/packet.h"
     17 
     18 namespace webrtc {
     19 
     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   memset(frame_decoded_, 0, sizeof(frame_decoded_));
     29 }
     30 
     31 VCMDecodingState::~VCMDecodingState() {}
     32 
     33 void VCMDecodingState::Reset() {
     34   // TODO(mikhal): Verify - not always would want to reset the sync
     35   sequence_num_ = 0;
     36   time_stamp_ = 0;
     37   picture_id_ = kNoPictureId;
     38   temporal_id_ = kNoTemporalIdx;
     39   tl0_pic_id_ = kNoTl0PicIdx;
     40   full_sync_ = true;
     41   in_initial_state_ = true;
     42   memset(frame_decoded_, 0, sizeof(frame_decoded_));
     43 }
     44 
     45 uint32_t VCMDecodingState::time_stamp() const {
     46   return time_stamp_;
     47 }
     48 
     49 uint16_t VCMDecodingState::sequence_num() const {
     50   return sequence_num_;
     51 }
     52 
     53 bool VCMDecodingState::IsOldFrame(const VCMFrameBuffer* frame) const {
     54   assert(frame != NULL);
     55   if (in_initial_state_)
     56     return false;
     57   return !IsNewerTimestamp(frame->TimeStamp(), time_stamp_);
     58 }
     59 
     60 bool VCMDecodingState::IsOldPacket(const VCMPacket* packet) const {
     61   assert(packet != NULL);
     62   if (in_initial_state_)
     63     return false;
     64   return !IsNewerTimestamp(packet->timestamp, time_stamp_);
     65 }
     66 
     67 void VCMDecodingState::SetState(const VCMFrameBuffer* frame) {
     68   assert(frame != NULL && frame->GetHighSeqNum() >= 0);
     69   if (!UsingFlexibleMode(frame))
     70     UpdateSyncState(frame);
     71   sequence_num_ = static_cast<uint16_t>(frame->GetHighSeqNum());
     72   time_stamp_ = frame->TimeStamp();
     73   picture_id_ = frame->PictureId();
     74   temporal_id_ = frame->TemporalId();
     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     } 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;
     97 }
     98 
     99 void VCMDecodingState::CopyFrom(const VCMDecodingState& state) {
    100   sequence_num_ = state.sequence_num_;
    101   time_stamp_ = state.time_stamp_;
    102   picture_id_ = state.picture_id_;
    103   temporal_id_ = state.temporal_id_;
    104   tl0_pic_id_ = state.tl0_pic_id_;
    105   full_sync_ = state.full_sync_;
    106   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 }
    110 
    111 bool VCMDecodingState::UpdateEmptyFrame(const VCMFrameBuffer* frame) {
    112   bool empty_packet = frame->GetHighSeqNum() == frame->GetLowSeqNum();
    113   if (in_initial_state_ && empty_packet) {
    114     // Drop empty packets as long as we are in the initial state.
    115     return true;
    116   }
    117   if ((empty_packet && ContinuousSeqNum(frame->GetHighSeqNum())) ||
    118       ContinuousFrame(frame)) {
    119     // Continuous empty packets or continuous frames can be dropped if we
    120     // advance the sequence number.
    121     sequence_num_ = frame->GetHighSeqNum();
    122     time_stamp_ = frame->TimeStamp();
    123     return true;
    124   }
    125   return false;
    126 }
    127 
    128 void VCMDecodingState::UpdateOldPacket(const VCMPacket* packet) {
    129   assert(packet != NULL);
    130   if (packet->timestamp == time_stamp_) {
    131     // Late packet belonging to the last decoded frame - make sure we update the
    132     // last decoded sequence number.
    133     sequence_num_ = LatestSequenceNumber(packet->seqNum, sequence_num_);
    134   }
    135 }
    136 
    137 void VCMDecodingState::SetSeqNum(uint16_t new_seq_num) {
    138   sequence_num_ = new_seq_num;
    139 }
    140 
    141 bool VCMDecodingState::in_initial_state() const {
    142   return in_initial_state_;
    143 }
    144 
    145 bool VCMDecodingState::full_sync() const {
    146   return full_sync_;
    147 }
    148 
    149 void VCMDecodingState::UpdateSyncState(const VCMFrameBuffer* frame) {
    150   if (in_initial_state_)
    151     return;
    152   if (frame->TemporalId() == kNoTemporalIdx ||
    153       frame->Tl0PicId() == kNoTl0PicIdx) {
    154     full_sync_ = true;
    155   } else if (frame->FrameType() == kVideoFrameKey || frame->LayerSync()) {
    156     full_sync_ = true;
    157   } else if (full_sync_) {
    158     // Verify that we are still in sync.
    159     // Sync will be broken if continuity is true for layers but not for the
    160     // other methods (PictureId and SeqNum).
    161     if (UsingPictureId(frame)) {
    162       // First check for a valid tl0PicId.
    163       if (frame->Tl0PicId() - tl0_pic_id_ > 1) {
    164         full_sync_ = false;
    165       } else {
    166         full_sync_ = ContinuousPictureId(frame->PictureId());
    167       }
    168     } else {
    169       full_sync_ =
    170           ContinuousSeqNum(static_cast<uint16_t>(frame->GetLowSeqNum()));
    171     }
    172   }
    173 }
    174 
    175 bool VCMDecodingState::ContinuousFrame(const VCMFrameBuffer* frame) const {
    176   // Check continuity based on the following hierarchy:
    177   // - Temporal layers (stop here if out of sync).
    178   // - Picture Id when available.
    179   // - Sequence numbers.
    180   // Return true when in initial state.
    181   // Note that when a method is not applicable it will return false.
    182   assert(frame != NULL);
    183   // A key frame is always considered continuous as it doesn't refer to any
    184   // frames and therefore won't introduce any errors even if prior frames are
    185   // missing.
    186   if (frame->FrameType() == kVideoFrameKey)
    187     return true;
    188   // When in the initial state we always require a key frame to start decoding.
    189   if (in_initial_state_)
    190     return false;
    191   if (ContinuousLayer(frame->TemporalId(), frame->Tl0PicId()))
    192     return true;
    193   // tl0picId is either not used, or should remain unchanged.
    194   if (frame->Tl0PicId() != tl0_pic_id_)
    195     return false;
    196   // Base layers are not continuous or temporal layers are inactive.
    197   // In the presence of temporal layers, check for Picture ID/sequence number
    198   // continuity if sync can be restored by this frame.
    199   if (!full_sync_ && !frame->LayerSync())
    200     return false;
    201   if (UsingPictureId(frame)) {
    202     if (UsingFlexibleMode(frame)) {
    203       return ContinuousFrameRefs(frame);
    204     } else {
    205       return ContinuousPictureId(frame->PictureId());
    206     }
    207   } else {
    208     return ContinuousSeqNum(static_cast<uint16_t>(frame->GetLowSeqNum()));
    209   }
    210 }
    211 
    212 bool VCMDecodingState::ContinuousPictureId(int picture_id) const {
    213   int next_picture_id = picture_id_ + 1;
    214   if (picture_id < picture_id_) {
    215     // Wrap
    216     if (picture_id_ >= 0x80) {
    217       // 15 bits used for picture id
    218       return ((next_picture_id & 0x7FFF) == picture_id);
    219     } else {
    220       // 7 bits used for picture id
    221       return ((next_picture_id & 0x7F) == picture_id);
    222     }
    223   }
    224   // No wrap
    225   return (next_picture_id == picture_id);
    226 }
    227 
    228 bool VCMDecodingState::ContinuousSeqNum(uint16_t seq_num) const {
    229   return seq_num == static_cast<uint16_t>(sequence_num_ + 1);
    230 }
    231 
    232 bool VCMDecodingState::ContinuousLayer(int temporal_id, int tl0_pic_id) const {
    233   // First, check if applicable.
    234   if (temporal_id == kNoTemporalIdx || tl0_pic_id == kNoTl0PicIdx)
    235     return false;
    236   // If this is the first frame to use temporal layers, make sure we start
    237   // from base.
    238   else if (tl0_pic_id_ == kNoTl0PicIdx && temporal_id_ == kNoTemporalIdx &&
    239            temporal_id == 0)
    240     return true;
    241 
    242   // Current implementation: Look for base layer continuity.
    243   if (temporal_id != 0)
    244     return false;
    245   return (static_cast<uint8_t>(tl0_pic_id_ + 1) == tl0_pic_id);
    246 }
    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     uint16_t frame_index = frame_ref % kFrameDecodedLength;
    254     if (AheadOfFramesDecodedClearedTo(frame_index) ||
    255         !frame_decoded_[frame_index]) {
    256       return false;
    257     }
    258   }
    259   return true;
    260 }
    261 
    262 bool VCMDecodingState::UsingPictureId(const VCMFrameBuffer* frame) const {
    263   return (frame->PictureId() != kNoPictureId && picture_id_ != kNoPictureId);
    264 }
    265 
    266 bool VCMDecodingState::UsingFlexibleMode(const VCMFrameBuffer* frame) const {
    267   return frame->CodecSpecific()->codecType == kVideoCodecVP9 &&
    268          frame->CodecSpecific()->codecSpecific.VP9.flexible_mode;
    269 }
    270 
    271 // TODO(philipel): change how check work, this check practially
    272 // limits the max p_diff to 64.
    273 bool VCMDecodingState::AheadOfFramesDecodedClearedTo(uint16_t index) const {
    274   // No way of knowing for sure if we are actually ahead of
    275   // frame_decoded_cleared_to_. We just make the assumption
    276   // that we are not trying to reference back to a very old
    277   // index, but instead are referencing a newer index.
    278   uint16_t diff =
    279       index > frame_decoded_cleared_to_
    280           ? kFrameDecodedLength - (index - frame_decoded_cleared_to_)
    281           : frame_decoded_cleared_to_ - index;
    282   return diff > kFrameDecodedLength / 2;
    283 }
    284 
    285 }  // namespace webrtc
    286