1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "media/base/decoder_buffer_queue.h"
6
7#include "base/logging.h"
8#include "media/base/buffers.h"
9#include "media/base/decoder_buffer.h"
10
11namespace media {
12
13DecoderBufferQueue::DecoderBufferQueue()
14    : earliest_valid_timestamp_(kNoTimestamp()) {
15}
16
17DecoderBufferQueue::~DecoderBufferQueue() {}
18
19void DecoderBufferQueue::Push(const scoped_refptr<DecoderBuffer>& buffer) {
20  CHECK(!buffer->end_of_stream());
21
22  queue_.push_back(buffer);
23
24  // TODO(scherkus): FFmpeg returns some packets with no timestamp after
25  // seeking. Fix and turn this into CHECK(). See http://crbug.com/162192
26  if (buffer->timestamp() == kNoTimestamp()) {
27    DVLOG(1) << "Buffer has no timestamp";
28    return;
29  }
30
31  if (earliest_valid_timestamp_ == kNoTimestamp()) {
32    earliest_valid_timestamp_ = buffer->timestamp();
33  }
34
35  if (buffer->timestamp() < earliest_valid_timestamp_) {
36    DVLOG(1)
37        << "Out of order timestamps: "
38        << buffer->timestamp().InMicroseconds()
39        << " vs. "
40        << earliest_valid_timestamp_.InMicroseconds();
41    return;
42  }
43
44  earliest_valid_timestamp_ = buffer->timestamp();
45  in_order_queue_.push_back(buffer);
46}
47
48scoped_refptr<DecoderBuffer> DecoderBufferQueue::Pop() {
49  scoped_refptr<DecoderBuffer> buffer = queue_.front();
50  queue_.pop_front();
51
52  if (!in_order_queue_.empty() &&
53      in_order_queue_.front().get() == buffer.get()) {
54    in_order_queue_.pop_front();
55  }
56
57  return buffer;
58}
59
60void DecoderBufferQueue::Clear() {
61  queue_.clear();
62  in_order_queue_.clear();
63  earliest_valid_timestamp_ = kNoTimestamp();
64}
65
66bool DecoderBufferQueue::IsEmpty() {
67  return queue_.empty();
68}
69
70base::TimeDelta DecoderBufferQueue::Duration() {
71  if (in_order_queue_.size() < 2)
72    return base::TimeDelta();
73
74  base::TimeDelta start = in_order_queue_.front()->timestamp();
75  base::TimeDelta end = in_order_queue_.back()->timestamp();
76  return end - start;
77}
78
79}  // namespace media
80