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