15c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Copyright 2014 The Chromium Authors. All rights reserved.
25c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Use of this source code is governed by a BSD-style license that can be
35c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// found in the LICENSE file.
45c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
55c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "media/base/audio_discard_helper.h"
65c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
75c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include <algorithm>
85c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
95c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/logging.h"
105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "media/base/audio_buffer.h"
115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "media/base/buffers.h"
125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liunamespace media {
145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liustatic void WarnOnNonMonotonicTimestamps(base::TimeDelta last_timestamp,
165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                         base::TimeDelta current_timestamp) {
175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (last_timestamp == kNoTimestamp() || last_timestamp < current_timestamp)
185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return;
195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  const base::TimeDelta diff = current_timestamp - last_timestamp;
215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  DLOG(WARNING) << "Input timestamps are not monotonically increasing! "
225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                << " ts " << current_timestamp.InMicroseconds() << " us"
235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                << " diff " << diff.InMicroseconds() << " us";
245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
26010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)AudioDiscardHelper::AudioDiscardHelper(int sample_rate, size_t decoder_delay)
275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    : sample_rate_(sample_rate),
28010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      decoder_delay_(decoder_delay),
295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      timestamp_helper_(sample_rate_),
305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      discard_frames_(0),
31010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      last_input_timestamp_(kNoTimestamp()),
325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      delayed_discard_(false),
335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      delayed_end_discard_(0) {
345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  DCHECK_GT(sample_rate_, 0);
355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuAudioDiscardHelper::~AudioDiscardHelper() {
385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liusize_t AudioDiscardHelper::TimeDeltaToFrames(base::TimeDelta duration) const {
415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  DCHECK(duration >= base::TimeDelta());
425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  return duration.InSecondsF() * sample_rate_ + 0.5;
435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid AudioDiscardHelper::Reset(size_t initial_discard) {
465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  discard_frames_ = initial_discard;
475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  last_input_timestamp_ = kNoTimestamp();
485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  timestamp_helper_.SetBaseTimestamp(kNoTimestamp());
49010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  delayed_discard_ = false;
50010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  delayed_discard_padding_ = DecoderBuffer::DiscardPadding();
515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liubool AudioDiscardHelper::ProcessBuffers(
545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    const scoped_refptr<DecoderBuffer>& encoded_buffer,
555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    const scoped_refptr<AudioBuffer>& decoded_buffer) {
565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  DCHECK(!encoded_buffer->end_of_stream());
575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  DCHECK(encoded_buffer->timestamp() != kNoTimestamp());
585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Issue a debug warning when we see non-monotonic timestamps.  Only a warning
605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // to allow chained OGG playback.
615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  WarnOnNonMonotonicTimestamps(last_input_timestamp_,
625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                               encoded_buffer->timestamp());
635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  last_input_timestamp_ = encoded_buffer->timestamp();
645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // If this is the first buffer seen, setup the timestamp helper.
66010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  const bool first_buffer = !initialized();
67010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (first_buffer) {
685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    // Clamp the base timestamp to zero.
695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    timestamp_helper_.SetBaseTimestamp(
705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        std::max(base::TimeDelta(), encoded_buffer->timestamp()));
715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  DCHECK(initialized());
735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!decoded_buffer.get()) {
75010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // If there's a one buffer delay for decoding, we need to save it so it can
76010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // be processed with the next decoder buffer.
77010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (first_buffer) {
78010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      delayed_discard_ = true;
79010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      delayed_discard_padding_ = encoded_buffer->discard_padding();
80010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    }
815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return false;
82010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
83010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
84010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  const size_t original_frame_count = decoded_buffer->frame_count();
85010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
86010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // If there's a one buffer delay for decoding, pick up the last encoded
87010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // buffer's discard padding for processing with the current decoded buffer.
88010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DecoderBuffer::DiscardPadding current_discard_padding =
89010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      encoded_buffer->discard_padding();
90cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (delayed_discard_) {
91cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // For simplicity disallow cases where decoder delay is present with delayed
92cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // discard (no codecs at present).  Doing so allows us to avoid complexity
93cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // around endpoint tracking when handling complete buffer discards.
94cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    DCHECK_EQ(decoder_delay_, 0u);
95010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    std::swap(current_discard_padding, delayed_discard_padding_);
96cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
975c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
985c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (discard_frames_ > 0) {
995c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    const size_t decoded_frames = decoded_buffer->frame_count();
1005c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    const size_t frames_to_discard = std::min(discard_frames_, decoded_frames);
1015c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    discard_frames_ -= frames_to_discard;
1025c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    DVLOG(1) << "Initial discard of " << frames_to_discard << " out of "
1045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)             << decoded_frames << " frames.";
1055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1065c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    // If everything would be discarded, indicate a new buffer is required.
107010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (frames_to_discard == decoded_frames) {
108010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      // For simplicity disallow cases where a buffer with discard padding is
109010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      // present.  Doing so allows us to avoid complexity around tracking
110010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      // discards across buffers.
111010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      DCHECK(current_discard_padding.first == base::TimeDelta());
112010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      DCHECK(current_discard_padding.second == base::TimeDelta());
1135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      return false;
114010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    }
1155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    decoded_buffer->TrimStart(frames_to_discard);
1175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
1185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Process any delayed end discard from the previous buffer.
1205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (delayed_end_discard_ > 0) {
1215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    DCHECK_GT(decoder_delay_, 0u);
1225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const size_t discard_index = decoder_delay_ - delayed_end_discard_;
1245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    DCHECK_LT(discard_index, decoder_delay_);
1255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const size_t decoded_frames = decoded_buffer->frame_count();
1275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    DCHECK_LT(delayed_end_discard_, decoded_frames);
1285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    DVLOG(1) << "Delayed end discard of " << delayed_end_discard_ << " out of "
1305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)             << decoded_frames << " frames starting at " << discard_index;
1315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    decoded_buffer->TrimRange(discard_index,
1335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                              discard_index + delayed_end_discard_);
1345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    delayed_end_discard_ = 0;
1355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
1365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
137010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // Handle front discard padding.
138010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (current_discard_padding.first > base::TimeDelta()) {
139010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const size_t decoded_frames = decoded_buffer->frame_count();
140cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
141cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // If a complete buffer discard is requested and there's no decoder delay,
142cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // just discard all remaining frames from this buffer.  With decoder delay
143cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // we have to estimate the correct number of frames to discard based on the
144cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // duration of the encoded buffer.
145010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const size_t start_frames_to_discard =
146cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        current_discard_padding.first == kInfiniteDuration()
147cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            ? (decoder_delay_ > 0
148cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                   ? TimeDeltaToFrames(encoded_buffer->duration())
149cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                   : decoded_frames)
150cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            : TimeDeltaToFrames(current_discard_padding.first);
151010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
152010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // Regardless of the timestamp on the encoded buffer, the corresponding
153010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // decoded output will appear |decoder_delay_| frames later.
154010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    size_t discard_start = decoder_delay_;
155010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (decoder_delay_ > 0) {
156010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      // If we have a |decoder_delay_| and have already discarded frames from
157010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      // this buffer, the |discard_start| must be adjusted by the number of
158010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      // frames already discarded.
159010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      const size_t frames_discarded_so_far =
160010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          original_frame_count - decoded_buffer->frame_count();
161010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      CHECK_LE(frames_discarded_so_far, decoder_delay_);
162010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      discard_start -= frames_discarded_so_far;
163010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    }
164010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
165010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // For simplicity require the start of the discard to be within the current
166010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // buffer.  Doing so allows us avoid complexity around tracking discards
167010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // across buffers.
168010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    CHECK_LT(discard_start, decoded_frames);
169010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
170010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const size_t frames_to_discard =
171010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        std::min(start_frames_to_discard, decoded_frames - discard_start);
172010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
173010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // Carry over any frames which need to be discarded from the front of the
174010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // next buffer.
175010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    DCHECK(!discard_frames_);
176010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    discard_frames_ = start_frames_to_discard - frames_to_discard;
177010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
1785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    DVLOG(1) << "Front discard of " << frames_to_discard << " out of "
1795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)             << decoded_frames << " frames starting at " << discard_start;
1805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
181010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // If everything would be discarded, indicate a new buffer is required.
182010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (frames_to_discard == decoded_frames) {
183010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      // The buffer should not have been marked with end discard if the front
184010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      // discard removes everything.
185010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      DCHECK(current_discard_padding.second == base::TimeDelta());
186010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      return false;
187010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    }
188010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
189010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    decoded_buffer->TrimRange(discard_start, discard_start + frames_to_discard);
190010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  } else {
191010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    DCHECK(current_discard_padding.first == base::TimeDelta());
192010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
193010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
194010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // Handle end discard padding.
195010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (current_discard_padding.second > base::TimeDelta()) {
1965c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    const size_t decoded_frames = decoded_buffer->frame_count();
1975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    size_t end_frames_to_discard =
198010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        TimeDeltaToFrames(current_discard_padding.second);
199010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
2005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (decoder_delay_) {
2015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      // Delayed end discard only works if the decoder delay is less than a
2025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      // single buffer.
2035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      DCHECK_LT(decoder_delay_, original_frame_count);
2045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      // If the discard is >= the decoder delay, trim everything we can off the
2065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      // end of this buffer and the rest from the start of the next.
2075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      if (end_frames_to_discard >= decoder_delay_) {
2085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        DCHECK(!discard_frames_);
2095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        discard_frames_ = decoder_delay_;
2105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        end_frames_to_discard -= decoder_delay_;
2115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      } else {
2125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        DCHECK(!delayed_end_discard_);
2135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        std::swap(delayed_end_discard_, end_frames_to_discard);
2145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      }
2155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
2165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (end_frames_to_discard > decoded_frames) {
2185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      DLOG(ERROR) << "Encountered invalid discard padding value.";
2195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      return false;
2205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    }
2215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (end_frames_to_discard > 0) {
2235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      DVLOG(1) << "End discard of " << end_frames_to_discard << " out of "
2245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)               << decoded_frames;
2255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      // If everything would be discarded, indicate a new buffer is required.
2275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      if (end_frames_to_discard == decoded_frames)
2285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return false;
2295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      decoded_buffer->TrimEnd(end_frames_to_discard);
2315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
2325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  } else {
233010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    DCHECK(current_discard_padding.second == base::TimeDelta());
2345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
2355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
236010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // Assign timestamp to the buffer.
2375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  decoded_buffer->set_timestamp(timestamp_helper_.GetTimestamp());
2385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  timestamp_helper_.AddFrames(decoded_buffer->frame_count());
2395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  return true;
2405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
2415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}  // namespace media
243