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.
5 #include "chromecast/media/cma/base/buffering_frame_provider.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"
14 namespace chromecast
{
17 BufferingFrameProvider::BufferWithConfig::BufferWithConfig(
18 const scoped_refptr
<DecoderBufferBase
>& buffer
,
19 const ::media::AudioDecoderConfig
& audio_config
,
20 const ::media::VideoDecoderConfig
& video_config
)
22 audio_config_(audio_config
),
23 video_config_(video_config
) {
26 BufferingFrameProvider::BufferWithConfig::~BufferWithConfig() {
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),
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
),
42 DCHECK_LE(max_frame_size
, max_buffer_size
);
43 weak_this_
= weak_factory_
.GetWeakPtr();
44 thread_checker_
.DetachFromThread();
47 BufferingFrameProvider::~BufferingFrameProvider() {
48 // Required since some weak pointers might be released in the destructor.
49 DCHECK(thread_checker_
.CalledOnValidThread());
52 void BufferingFrameProvider::Read(const ReadCB
& read_cb
) {
53 DCHECK(thread_checker_
.CalledOnValidThread());
55 DCHECK(!read_cb
.is_null());
58 CompleteReadIfNeeded();
60 RequestBufferIfNeeded();
63 void BufferingFrameProvider::Flush(const base::Closure
& flush_cb
) {
64 DCHECK(thread_checker_
.CalledOnValidThread());
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();
71 // Create a new valid weak pointer that is used for the next media timeline.
72 weak_this_
= weak_factory_
.GetWeakPtr();
74 is_pending_request_
= false;
77 total_buffer_size_
= 0;
79 coded_frame_provider_
->Flush(flush_cb
);
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
));
90 if (buffer
->end_of_stream()) {
93 total_buffer_size_
+= buffer
->data_size();
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
);
104 RequestBufferIfNeeded();
106 CompleteReadIfNeeded();
109 void BufferingFrameProvider::RequestBufferIfNeeded() {
110 if (is_pending_request_
)
113 if (is_eos_
|| total_buffer_size_
>= max_buffer_size_
)
116 is_pending_request_
= true;
117 coded_frame_provider_
->Read(::media::BindToCurrentLoop(
118 base::Bind(&BufferingFrameProvider::OnNewBuffer
, weak_this_
)));
121 void BufferingFrameProvider::CompleteReadIfNeeded() {
122 if (read_cb_
.is_null())
125 if (buffer_list_
.empty())
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();
133 base::ResetAndReturn(&read_cb_
).Run(
134 buffer_with_config
.buffer(),
135 buffer_with_config
.audio_config(),
136 buffer_with_config
.video_config());
140 } // namespace chromecast