Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(475)

Unified Diff: media/base/audio_discard_helper.cc

Issue 251893002: Support start trimming post-decoding. Use it with FFmpegDemuxer. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Comments. Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: media/base/audio_discard_helper.cc
diff --git a/media/base/audio_discard_helper.cc b/media/base/audio_discard_helper.cc
index d868382ef42c6a639e832484bc4830ac0b4f6254..f7279d72cfa8e3b2e7d9e455f485a7350d260289 100644
--- a/media/base/audio_discard_helper.cc
+++ b/media/base/audio_discard_helper.cc
@@ -9,7 +9,6 @@
#include "base/logging.h"
#include "media/base/audio_buffer.h"
#include "media/base/buffers.h"
-#include "media/base/decoder_buffer.h"
namespace media {
@@ -24,11 +23,13 @@ static void WarnOnNonMonotonicTimestamps(base::TimeDelta last_timestamp,
<< " diff " << diff.InMicroseconds() << " us";
}
-AudioDiscardHelper::AudioDiscardHelper(int sample_rate)
+AudioDiscardHelper::AudioDiscardHelper(int sample_rate, size_t decoder_delay)
: sample_rate_(sample_rate),
+ decoder_delay_(decoder_delay),
timestamp_helper_(sample_rate_),
discard_frames_(0),
- last_input_timestamp_(kNoTimestamp()) {
+ last_input_timestamp_(kNoTimestamp()),
+ delayed_discard_(false) {
DCHECK_GT(sample_rate_, 0);
}
@@ -44,6 +45,8 @@ void AudioDiscardHelper::Reset(size_t initial_discard) {
discard_frames_ = initial_discard;
last_input_timestamp_ = kNoTimestamp();
timestamp_helper_.SetBaseTimestamp(kNoTimestamp());
+ delayed_discard_ = false;
+ delayed_discard_padding_ = DecoderBuffer::DiscardPadding();
}
bool AudioDiscardHelper::ProcessBuffers(
@@ -59,15 +62,32 @@ bool AudioDiscardHelper::ProcessBuffers(
last_input_timestamp_ = encoded_buffer->timestamp();
// If this is the first buffer seen, setup the timestamp helper.
- if (!initialized()) {
+ const bool first_buffer = !initialized();
+ if (first_buffer) {
// Clamp the base timestamp to zero.
timestamp_helper_.SetBaseTimestamp(
std::max(base::TimeDelta(), encoded_buffer->timestamp()));
}
DCHECK(initialized());
- if (!decoded_buffer || !decoded_buffer->frame_count())
+ if (!decoded_buffer) {
+ // If there's a one buffer delay for decoding, we need to save it so it can
+ // be processed with the next decoder buffer.
+ if (first_buffer) {
+ delayed_discard_ = true;
+ delayed_discard_padding_ = encoded_buffer->discard_padding();
+ }
return false;
+ }
+
+ const size_t original_frame_count = decoded_buffer->frame_count();
+
+ // If there's a one buffer delay for decoding, pick up the last encoded
+ // buffer's discard padding for processing with the current decoded buffer.
+ DecoderBuffer::DiscardPadding current_discard_padding =
+ encoded_buffer->discard_padding();
+ if (delayed_discard_)
+ std::swap(current_discard_padding, delayed_discard_padding_);
if (discard_frames_ > 0) {
const size_t decoded_frames = decoded_buffer->frame_count();
@@ -75,20 +95,73 @@ bool AudioDiscardHelper::ProcessBuffers(
discard_frames_ -= frames_to_discard;
// If everything would be discarded, indicate a new buffer is required.
- if (frames_to_discard == decoded_frames)
+ if (frames_to_discard == decoded_frames) {
+ // For simplicity disallow cases where a buffer with discard padding is
wolenetz 2014/05/05 19:01:23 nit: how common is this? should we track it in rel
DaleCurtis 2014/05/05 20:16:03 It shouldn't be possible right now, so the DCHECK(
+ // present. Doing so allows us to avoid complexity around tracking
+ // discards across buffers.
+ DCHECK(current_discard_padding.first == base::TimeDelta());
+ DCHECK(current_discard_padding.second == base::TimeDelta());
return false;
+ }
decoded_buffer->TrimStart(frames_to_discard);
}
- // TODO(dalecurtis): Applying the current buffer's discard padding doesn't
- // make sense in the Vorbis case because there is a delay of one buffer before
- // decoded buffers are returned. Fix and add support for more than just end
- // trimming. See http://crbug.com/360961.
- if (encoded_buffer->discard_padding() > base::TimeDelta()) {
+ // Handle front discard padding.
+ if (current_discard_padding.first > base::TimeDelta()) {
+ const size_t decoded_frames = decoded_buffer->frame_count();
+ const size_t start_frames_to_discard =
+ TimeDeltaToFrames(current_discard_padding.first);
+
+ // Regardless of the timestamp on the encoded buffer, the corresponding
+ // decoded output will appear |decoder_delay_| frames later.
+ size_t discard_start = decoder_delay_;
+ if (decoder_delay_ > 0) {
+ // If we have a |decoder_delay_| and have already discarded frames from
+ // this buffer, the |discard_start| must be adjusted by the number of
+ // frames already discarded.
+ const size_t frames_discarded_so_far =
+ original_frame_count - decoded_buffer->frame_count();
+ CHECK_LE(frames_discarded_so_far, decoder_delay_);
+ discard_start -= frames_discarded_so_far;
+ }
+
+ // For simplicity require the start of the discard to be within the current
+ // buffer. Doing so allows us avoid complexity around tracking discards
+ // across buffers.
+ CHECK_LT(discard_start, decoded_frames);
+
+ const size_t frames_to_discard =
+ std::min(start_frames_to_discard, decoded_frames - discard_start);
+
+ // Carry over any frames which need to be discarded from the front of the
+ // next buffer.
+ DCHECK(!discard_frames_);
+ discard_frames_ = start_frames_to_discard - frames_to_discard;
+
+ // If everything would be discarded, indicate a new buffer is required.
+ if (frames_to_discard == decoded_frames) {
+ // The buffer should not have been marked with end discard if the front
+ // discard removes everything.
+ DCHECK(current_discard_padding.second == base::TimeDelta());
+ return false;
+ }
+
+ decoded_buffer->TrimRange(discard_start, discard_start + frames_to_discard);
+ } else {
+ DCHECK(current_discard_padding.first == base::TimeDelta());
+ }
+
+ // Handle end discard padding.
+ if (current_discard_padding.second > base::TimeDelta()) {
+ // Limit end discarding to when there is no |decoder_delay_|, otherwise it's
+ // non-trivial determining where to start discarding end frames.
+ CHECK(!decoder_delay_);
+
const size_t decoded_frames = decoded_buffer->frame_count();
const size_t end_frames_to_discard =
- TimeDeltaToFrames(encoded_buffer->discard_padding());
+ TimeDeltaToFrames(current_discard_padding.second);
+
if (end_frames_to_discard > decoded_frames) {
DLOG(ERROR) << "Encountered invalid discard padding value.";
return false;
@@ -100,7 +173,7 @@ bool AudioDiscardHelper::ProcessBuffers(
decoded_buffer->TrimEnd(end_frames_to_discard);
} else {
- DCHECK(encoded_buffer->discard_padding() == base::TimeDelta());
+ DCHECK(current_discard_padding.second == base::TimeDelta());
}
// Assign timestamp to the buffer.

Powered by Google App Engine
This is Rietveld 408576698