buffering_frame_provider.cc revision 1320f92c476a1ad9d19dba2a48c72b75566198e9
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "chromecast/media/cma/base/buffering_frame_provider.h"
6d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/callback_helpers.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chromecast/media/cma/base/buffering_state.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chromecast/media/cma/base/decoder_buffer_base.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/bind_to_current_loop.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/buffers.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace chromecast {
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace media {
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BufferingFrameProvider::BufferWithConfig::BufferWithConfig(
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const scoped_refptr<DecoderBufferBase>& buffer,
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ::media::AudioDecoderConfig& audio_config,
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ::media::VideoDecoderConfig& video_config)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : buffer_(buffer),
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      audio_config_(audio_config),
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      video_config_(video_config) {
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BufferingFrameProvider::BufferWithConfig::~BufferWithConfig() {
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BufferingFrameProvider::BufferingFrameProvider(
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<CodedFrameProvider> coded_frame_provider,
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t max_buffer_size,
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t max_frame_size,
33a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const FrameBufferedCB& frame_buffered_cb)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : coded_frame_provider_(coded_frame_provider.Pass()),
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      is_pending_request_(false),
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      is_eos_(false),
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      total_buffer_size_(0),
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      max_buffer_size_(max_buffer_size),
39a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      max_frame_size_(max_frame_size),
40a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      frame_buffered_cb_(frame_buffered_cb),
4146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      weak_factory_(this),
4246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      weak_this_(weak_factory_.GetWeakPtr()) {
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_LE(max_frame_size, max_buffer_size);
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  thread_checker_.DetachFromThread();
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BufferingFrameProvider::~BufferingFrameProvider() {
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Required since some weak pointers might be released in the destructor.
49cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
50cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
51cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
52cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void BufferingFrameProvider::Read(const ReadCB& read_cb) {
531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(!read_cb.is_null());
565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  read_cb_ = read_cb;
575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CompleteReadIfNeeded();
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RequestBufferIfNeeded();
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
63a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void BufferingFrameProvider::Flush(const base::Closure& flush_cb) {
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Invalidate all the buffers that belong to this media timeline.
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // This is needed since, even though |coded_frame_provider_| is flushed later
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // in this function, there might be a pending task holding onto a buffer.
69eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  weak_factory_.InvalidateWeakPtrs();
70eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
71eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Create a new valid weak pointer that is used for the next media timeline.
72eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  weak_this_ = weak_factory_.GetWeakPtr();
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  is_pending_request_ = false;
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  is_eos_ = false;
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  buffer_list_.clear();
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  total_buffer_size_ = 0;
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  read_cb_.Reset();
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  coded_frame_provider_->Flush(flush_cb);
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BufferingFrameProvider::OnNewBuffer(
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const scoped_refptr<DecoderBufferBase>& buffer,
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ::media::AudioDecoderConfig& audio_config,
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ::media::VideoDecoderConfig& video_config) {
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  is_pending_request_ = false;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  buffer_list_.push_back(
88010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      BufferWithConfig(buffer, audio_config, video_config));
89010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
90010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (buffer->end_of_stream()) {
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    is_eos_ = true;
927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  } else {
93a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    total_buffer_size_ += buffer->data_size();
94c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!frame_buffered_cb_.is_null()) {
970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    // If the next upcoming frame is possibly filling the whole buffer,
980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    // then the buffer is considered as having reached its max capacity.
990529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    bool max_capacity_flag =
1005c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        (total_buffer_size_ + max_frame_size_ >= max_buffer_size_);
1015c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    frame_buffered_cb_.Run(buffer, max_capacity_flag);
1025c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
10346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
10446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  RequestBufferIfNeeded();
1055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  CompleteReadIfNeeded();
1070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
1080529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BufferingFrameProvider::RequestBufferIfNeeded() {
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (is_pending_request_)
111cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
112cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
113cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (is_eos_ || total_buffer_size_ >= max_buffer_size_)
114cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
115cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
116cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  is_pending_request_ = true;
117cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  coded_frame_provider_->Read(BindToCurrentLoop(
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&BufferingFrameProvider::OnNewBuffer, weak_this_)));
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BufferingFrameProvider::CompleteReadIfNeeded() {
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (read_cb_.is_null())
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (buffer_list_.empty())
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BufferWithConfig buffer_with_config(buffer_list_.front());
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  buffer_list_.pop_front();
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!buffer_with_config.buffer()->end_of_stream())
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    total_buffer_size_ -= buffer_with_config.buffer()->data_size();
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::ResetAndReturn(&read_cb_).Run(
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      buffer_with_config.buffer(),
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      buffer_with_config.audio_config(),
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      buffer_with_config.video_config());
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
139116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}  // namespace media
140116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}  // namespace chromecast
141116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch