1b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/*
2b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
3b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *
4b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  Use of this source code is governed by a BSD-style license
5b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  that can be found in the LICENSE file in the root of the source
6b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  tree. An additional intellectual property rights grant can be found
7b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  in the file PATENTS.  All contributing project authors may
8b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
9b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org */
10b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
11a557f436b9d694d5a0a045e0295e1794f2df48eapbos@webrtc.org#include "webrtc/modules/video_coding/main/source/decoding_state.h"
12b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
13a557f436b9d694d5a0a045e0295e1794f2df48eapbos@webrtc.org#include "webrtc/modules/interface/module_common_types.h"
14a557f436b9d694d5a0a045e0295e1794f2df48eapbos@webrtc.org#include "webrtc/modules/video_coding/main/source/frame_buffer.h"
15a557f436b9d694d5a0a045e0295e1794f2df48eapbos@webrtc.org#include "webrtc/modules/video_coding/main/source/jitter_buffer_common.h"
16a557f436b9d694d5a0a045e0295e1794f2df48eapbos@webrtc.org#include "webrtc/modules/video_coding/main/source/packet.h"
17b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
18b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgnamespace webrtc {
19b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
20b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgVCMDecodingState::VCMDecodingState()
21b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    : sequence_num_(0),
22b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      time_stamp_(0),
23b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      picture_id_(kNoPictureId),
24b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      temporal_id_(kNoTemporalIdx),
25b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      tl0_pic_id_(kNoTl0PicIdx),
26b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      full_sync_(true),
27bb78b2c7ce8cc4445811d0e881890a29b14a4f2bstefan@webrtc.org      in_initial_state_(true) {}
28b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
29b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgVCMDecodingState::~VCMDecodingState() {}
30b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
31b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid VCMDecodingState::Reset() {
32b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // TODO(mikhal): Verify - not always would want to reset the sync
33b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  sequence_num_ = 0;
34b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  time_stamp_ = 0;
35b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  picture_id_ = kNoPictureId;
36b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  temporal_id_ = kNoTemporalIdx;
37b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  tl0_pic_id_ = kNoTl0PicIdx;
38b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  full_sync_ = true;
39bb78b2c7ce8cc4445811d0e881890a29b14a4f2bstefan@webrtc.org  in_initial_state_ = true;
40b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
41b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
42b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orguint32_t VCMDecodingState::time_stamp() const {
43b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return time_stamp_;
44b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
45b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
46b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orguint16_t VCMDecodingState::sequence_num() const {
47b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return sequence_num_;
48b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
49b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
50b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool VCMDecodingState::IsOldFrame(const VCMFrameBuffer* frame) const {
51b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  assert(frame != NULL);
52bb78b2c7ce8cc4445811d0e881890a29b14a4f2bstefan@webrtc.org  if (in_initial_state_)
53b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return false;
5442c7409229636a59e28814451bd49ada2c6803a1stefan@webrtc.org  return !IsNewerTimestamp(frame->TimeStamp(), time_stamp_);
55b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
56b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
57b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool VCMDecodingState::IsOldPacket(const VCMPacket* packet) const {
58b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  assert(packet != NULL);
59bb78b2c7ce8cc4445811d0e881890a29b14a4f2bstefan@webrtc.org  if (in_initial_state_)
60b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return false;
6142c7409229636a59e28814451bd49ada2c6803a1stefan@webrtc.org  return !IsNewerTimestamp(packet->timestamp, time_stamp_);
62b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
63b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
64b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid VCMDecodingState::SetState(const VCMFrameBuffer* frame) {
65b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  assert(frame != NULL && frame->GetHighSeqNum() >= 0);
66b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateSyncState(frame);
67b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  sequence_num_ = static_cast<uint16_t>(frame->GetHighSeqNum());
68b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  time_stamp_ = frame->TimeStamp();
69b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  picture_id_ = frame->PictureId();
70b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  temporal_id_ = frame->TemporalId();
71b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  tl0_pic_id_ = frame->Tl0PicId();
72bb78b2c7ce8cc4445811d0e881890a29b14a4f2bstefan@webrtc.org  in_initial_state_ = false;
73b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
74b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
7540bd7448cb81dea34512c6970864a710a75da666mikhal@webrtc.orgvoid VCMDecodingState::CopyFrom(const VCMDecodingState& state) {
7640bd7448cb81dea34512c6970864a710a75da666mikhal@webrtc.org  sequence_num_ = state.sequence_num_;
7740bd7448cb81dea34512c6970864a710a75da666mikhal@webrtc.org  time_stamp_ = state.time_stamp_;
7840bd7448cb81dea34512c6970864a710a75da666mikhal@webrtc.org  picture_id_ = state.picture_id_;
7940bd7448cb81dea34512c6970864a710a75da666mikhal@webrtc.org  temporal_id_ = state.temporal_id_;
8040bd7448cb81dea34512c6970864a710a75da666mikhal@webrtc.org  tl0_pic_id_ = state.tl0_pic_id_;
8140bd7448cb81dea34512c6970864a710a75da666mikhal@webrtc.org  full_sync_ = state.full_sync_;
8240bd7448cb81dea34512c6970864a710a75da666mikhal@webrtc.org  in_initial_state_ = state.in_initial_state_;
8340bd7448cb81dea34512c6970864a710a75da666mikhal@webrtc.org}
8440bd7448cb81dea34512c6970864a710a75da666mikhal@webrtc.org
85376ae3eaeb3751c41f2e2640b692a657e0e2d78dstefan@webrtc.orgbool VCMDecodingState::UpdateEmptyFrame(const VCMFrameBuffer* frame) {
86376ae3eaeb3751c41f2e2640b692a657e0e2d78dstefan@webrtc.org  bool empty_packet = frame->GetHighSeqNum() == frame->GetLowSeqNum();
87376ae3eaeb3751c41f2e2640b692a657e0e2d78dstefan@webrtc.org  if (in_initial_state_ && empty_packet) {
88376ae3eaeb3751c41f2e2640b692a657e0e2d78dstefan@webrtc.org    // Drop empty packets as long as we are in the initial state.
89376ae3eaeb3751c41f2e2640b692a657e0e2d78dstefan@webrtc.org    return true;
90376ae3eaeb3751c41f2e2640b692a657e0e2d78dstefan@webrtc.org  }
91376ae3eaeb3751c41f2e2640b692a657e0e2d78dstefan@webrtc.org  if ((empty_packet && ContinuousSeqNum(frame->GetHighSeqNum())) ||
92376ae3eaeb3751c41f2e2640b692a657e0e2d78dstefan@webrtc.org      ContinuousFrame(frame)) {
93376ae3eaeb3751c41f2e2640b692a657e0e2d78dstefan@webrtc.org    // Continuous empty packets or continuous frames can be dropped if we
94376ae3eaeb3751c41f2e2640b692a657e0e2d78dstefan@webrtc.org    // advance the sequence number.
958bf7456eb477062c2a0a0693c3fa99063d529ed9tnakamura@webrtc.org    sequence_num_ = frame->GetHighSeqNum();
96376ae3eaeb3751c41f2e2640b692a657e0e2d78dstefan@webrtc.org    time_stamp_ = frame->TimeStamp();
97376ae3eaeb3751c41f2e2640b692a657e0e2d78dstefan@webrtc.org    return true;
98c54118274ff0879c38b36494cf57ee9376ccee61stefan@webrtc.org  }
99376ae3eaeb3751c41f2e2640b692a657e0e2d78dstefan@webrtc.org  return false;
100c54118274ff0879c38b36494cf57ee9376ccee61stefan@webrtc.org}
101c54118274ff0879c38b36494cf57ee9376ccee61stefan@webrtc.org
102b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid VCMDecodingState::UpdateOldPacket(const VCMPacket* packet) {
103b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  assert(packet != NULL);
104b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (packet->timestamp == time_stamp_) {
105b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Late packet belonging to the last decoded frame - make sure we update the
106b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // last decoded sequence number.
10742c7409229636a59e28814451bd49ada2c6803a1stefan@webrtc.org    sequence_num_ = LatestSequenceNumber(packet->seqNum, sequence_num_);
108b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
109b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
110b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
111b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid VCMDecodingState::SetSeqNum(uint16_t new_seq_num) {
112b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  sequence_num_ = new_seq_num;
113b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
114b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
115bb78b2c7ce8cc4445811d0e881890a29b14a4f2bstefan@webrtc.orgbool VCMDecodingState::in_initial_state() const {
116bb78b2c7ce8cc4445811d0e881890a29b14a4f2bstefan@webrtc.org  return in_initial_state_;
117b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
118b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
119b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool VCMDecodingState::full_sync() const {
120b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return full_sync_;
121b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
122b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
123b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid VCMDecodingState::UpdateSyncState(const VCMFrameBuffer* frame) {
124bb78b2c7ce8cc4445811d0e881890a29b14a4f2bstefan@webrtc.org  if (in_initial_state_)
125b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return;
126b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (frame->TemporalId() == kNoTemporalIdx ||
127b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      frame->Tl0PicId() == kNoTl0PicIdx) {
128b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    full_sync_ = true;
129b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  } else if (frame->FrameType() == kVideoFrameKey || frame->LayerSync()) {
130b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    full_sync_ = true;
131b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  } else if (full_sync_) {
132b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Verify that we are still in sync.
133b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Sync will be broken if continuity is true for layers but not for the
134b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // other methods (PictureId and SeqNum).
135b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (UsingPictureId(frame)) {
136991d66abe94107b866c29ede42602d2169e16739mikhal@webrtc.org      // First check for a valid tl0PicId.
137991d66abe94107b866c29ede42602d2169e16739mikhal@webrtc.org      if (frame->Tl0PicId() - tl0_pic_id_ > 1) {
138991d66abe94107b866c29ede42602d2169e16739mikhal@webrtc.org        full_sync_ = false;
139991d66abe94107b866c29ede42602d2169e16739mikhal@webrtc.org      } else {
140991d66abe94107b866c29ede42602d2169e16739mikhal@webrtc.org        full_sync_ = ContinuousPictureId(frame->PictureId());
141991d66abe94107b866c29ede42602d2169e16739mikhal@webrtc.org      }
142b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    } else {
143b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      full_sync_ = ContinuousSeqNum(static_cast<uint16_t>(
144b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org          frame->GetLowSeqNum()));
145b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
146b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
147b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
148b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
149b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool VCMDecodingState::ContinuousFrame(const VCMFrameBuffer* frame) const {
150b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Check continuity based on the following hierarchy:
151b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // - Temporal layers (stop here if out of sync).
152b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // - Picture Id when available.
153b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // - Sequence numbers.
154b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Return true when in initial state.
155b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Note that when a method is not applicable it will return false.
156b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  assert(frame != NULL);
157376ae3eaeb3751c41f2e2640b692a657e0e2d78dstefan@webrtc.org  // A key frame is always considered continuous as it doesn't refer to any
158376ae3eaeb3751c41f2e2640b692a657e0e2d78dstefan@webrtc.org  // frames and therefore won't introduce any errors even if prior frames are
159376ae3eaeb3751c41f2e2640b692a657e0e2d78dstefan@webrtc.org  // missing.
160376ae3eaeb3751c41f2e2640b692a657e0e2d78dstefan@webrtc.org  if (frame->FrameType() == kVideoFrameKey)
161376ae3eaeb3751c41f2e2640b692a657e0e2d78dstefan@webrtc.org    return true;
162376ae3eaeb3751c41f2e2640b692a657e0e2d78dstefan@webrtc.org  // When in the initial state we always require a key frame to start decoding.
163376ae3eaeb3751c41f2e2640b692a657e0e2d78dstefan@webrtc.org  if (in_initial_state_)
164b47b7e077c86e3b02c4db99bdb4a2d2c0722b52bmikhal@webrtc.org    return false;
165991d66abe94107b866c29ede42602d2169e16739mikhal@webrtc.org  if (ContinuousLayer(frame->TemporalId(), frame->Tl0PicId()))
166991d66abe94107b866c29ede42602d2169e16739mikhal@webrtc.org    return true;
167991d66abe94107b866c29ede42602d2169e16739mikhal@webrtc.org  // tl0picId is either not used, or should remain unchanged.
168991d66abe94107b866c29ede42602d2169e16739mikhal@webrtc.org  if (frame->Tl0PicId() != tl0_pic_id_)
169991d66abe94107b866c29ede42602d2169e16739mikhal@webrtc.org    return false;
170991d66abe94107b866c29ede42602d2169e16739mikhal@webrtc.org  // Base layers are not continuous or temporal layers are inactive.
171991d66abe94107b866c29ede42602d2169e16739mikhal@webrtc.org  // In the presence of temporal layers, check for Picture ID/sequence number
172991d66abe94107b866c29ede42602d2169e16739mikhal@webrtc.org  // continuity if sync can be restored by this frame.
173991d66abe94107b866c29ede42602d2169e16739mikhal@webrtc.org  if (!full_sync_ && !frame->LayerSync())
174991d66abe94107b866c29ede42602d2169e16739mikhal@webrtc.org    return false;
175991d66abe94107b866c29ede42602d2169e16739mikhal@webrtc.org  if (UsingPictureId(frame)) {
176991d66abe94107b866c29ede42602d2169e16739mikhal@webrtc.org    return ContinuousPictureId(frame->PictureId());
177991d66abe94107b866c29ede42602d2169e16739mikhal@webrtc.org  } else {
178991d66abe94107b866c29ede42602d2169e16739mikhal@webrtc.org    return ContinuousSeqNum(static_cast<uint16_t>(frame->GetLowSeqNum()));
179b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
180b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
181b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
182b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool VCMDecodingState::ContinuousPictureId(int picture_id) const {
183b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int next_picture_id = picture_id_ + 1;
184b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (picture_id < picture_id_) {
185b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Wrap
186b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (picture_id_ >= 0x80) {
187b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      // 15 bits used for picture id
188b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      return ((next_picture_id & 0x7FFF) == picture_id);
189b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    } else {
190b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      // 7 bits used for picture id
191b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      return ((next_picture_id & 0x7F) == picture_id);
192b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
193b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
194b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // No wrap
195b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return (next_picture_id == picture_id);
196b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
197b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
198b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool VCMDecodingState::ContinuousSeqNum(uint16_t seq_num) const {
199b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return (seq_num == static_cast<uint16_t>(sequence_num_ + 1));
200b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
201b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
202b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool VCMDecodingState::ContinuousLayer(int temporal_id,
203b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                       int tl0_pic_id) const {
204b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // First, check if applicable.
205b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (temporal_id == kNoTemporalIdx || tl0_pic_id == kNoTl0PicIdx)
206b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return false;
207b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // If this is the first frame to use temporal layers, make sure we start
208b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // from base.
209b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  else if (tl0_pic_id_ == kNoTl0PicIdx && temporal_id_ == kNoTemporalIdx &&
210b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org           temporal_id == 0)
211b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return true;
212b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
213b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Current implementation: Look for base layer continuity.
214b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (temporal_id != 0)
215b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return false;
216b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return (static_cast<uint8_t>(tl0_pic_id_ + 1) == tl0_pic_id);
217b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
218b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
219b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool VCMDecodingState::UsingPictureId(const VCMFrameBuffer* frame) const {
220b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return (frame->PictureId() != kNoPictureId && picture_id_ != kNoPictureId);
221b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
222b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
223b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}  // namespace webrtc
224