Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / chromecast / media / cma / base / buffering_frame_provider.cc
1 // Copyright 2014 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 "chromecast/media/cma/base/buffering_frame_provider.h"
6
7 #include "base/bind.h"
8 #include "base/callback_helpers.h"
9 #include "chromecast/media/cma/base/buffering_state.h"
10 #include "chromecast/media/cma/base/decoder_buffer_base.h"
11 #include "media/base/bind_to_current_loop.h"
12 #include "media/base/buffers.h"
13
14 namespace chromecast {
15 namespace media {
16
17 BufferingFrameProvider::BufferWithConfig::BufferWithConfig(
18     const scoped_refptr<DecoderBufferBase>& buffer,
19     const ::media::AudioDecoderConfig& audio_config,
20     const ::media::VideoDecoderConfig& video_config)
21     : buffer_(buffer),
22       audio_config_(audio_config),
23       video_config_(video_config) {
24 }
25
26 BufferingFrameProvider::BufferWithConfig::~BufferWithConfig() {
27 }
28
29 BufferingFrameProvider::BufferingFrameProvider(
30     scoped_ptr<CodedFrameProvider> coded_frame_provider,
31     size_t max_buffer_size,
32     size_t max_frame_size,
33     const FrameBufferedCB& frame_buffered_cb)
34     : coded_frame_provider_(coded_frame_provider.Pass()),
35       is_pending_request_(false),
36       is_eos_(false),
37       total_buffer_size_(0),
38       max_buffer_size_(max_buffer_size),
39       max_frame_size_(max_frame_size),
40       frame_buffered_cb_(frame_buffered_cb),
41       weak_factory_(this),
42       weak_this_(weak_factory_.GetWeakPtr()) {
43   DCHECK_LE(max_frame_size, max_buffer_size);
44   thread_checker_.DetachFromThread();
45 }
46
47 BufferingFrameProvider::~BufferingFrameProvider() {
48   // Required since some weak pointers might be released in the destructor.
49   DCHECK(thread_checker_.CalledOnValidThread());
50 }
51
52 void BufferingFrameProvider::Read(const ReadCB& read_cb) {
53   DCHECK(thread_checker_.CalledOnValidThread());
54
55   DCHECK(!read_cb.is_null());
56   read_cb_ = read_cb;
57
58   CompleteReadIfNeeded();
59
60   RequestBufferIfNeeded();
61 }
62
63 void BufferingFrameProvider::Flush(const base::Closure& flush_cb) {
64   DCHECK(thread_checker_.CalledOnValidThread());
65
66   // Invalidate all the buffers that belong to this media timeline.
67   // This is needed since, even though |coded_frame_provider_| is flushed later
68   // in this function, there might be a pending task holding onto a buffer.
69   weak_factory_.InvalidateWeakPtrs();
70
71   // Create a new valid weak pointer that is used for the next media timeline.
72   weak_this_ = weak_factory_.GetWeakPtr();
73
74   is_pending_request_ = false;
75   is_eos_ = false;
76   buffer_list_.clear();
77   total_buffer_size_ = 0;
78   read_cb_.Reset();
79   coded_frame_provider_->Flush(flush_cb);
80 }
81
82 void BufferingFrameProvider::OnNewBuffer(
83     const scoped_refptr<DecoderBufferBase>& buffer,
84     const ::media::AudioDecoderConfig& audio_config,
85     const ::media::VideoDecoderConfig& video_config) {
86   is_pending_request_ = false;
87   buffer_list_.push_back(
88       BufferWithConfig(buffer, audio_config, video_config));
89
90   if (buffer->end_of_stream()) {
91     is_eos_ = true;
92   } else {
93     total_buffer_size_ += buffer->data_size();
94   }
95
96   if (!frame_buffered_cb_.is_null()) {
97     // If the next upcoming frame is possibly filling the whole buffer,
98     // then the buffer is considered as having reached its max capacity.
99     bool max_capacity_flag =
100         (total_buffer_size_ + max_frame_size_ >= max_buffer_size_);
101     frame_buffered_cb_.Run(buffer, max_capacity_flag);
102   }
103
104   RequestBufferIfNeeded();
105
106   CompleteReadIfNeeded();
107 }
108
109 void BufferingFrameProvider::RequestBufferIfNeeded() {
110   if (is_pending_request_)
111     return;
112
113   if (is_eos_ || total_buffer_size_ >= max_buffer_size_)
114     return;
115
116   is_pending_request_ = true;
117   coded_frame_provider_->Read(BindToCurrentLoop(
118       base::Bind(&BufferingFrameProvider::OnNewBuffer, weak_this_)));
119 }
120
121 void BufferingFrameProvider::CompleteReadIfNeeded() {
122   if (read_cb_.is_null())
123     return;
124
125   if (buffer_list_.empty())
126     return;
127
128   BufferWithConfig buffer_with_config(buffer_list_.front());
129   buffer_list_.pop_front();
130   if (!buffer_with_config.buffer()->end_of_stream())
131     total_buffer_size_ -= buffer_with_config.buffer()->data_size();
132
133   base::ResetAndReturn(&read_cb_).Run(
134       buffer_with_config.buffer(),
135       buffer_with_config.audio_config(),
136       buffer_with_config.video_config());
137 }
138
139 }  // namespace media
140 }  // namespace chromecast