11320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Copyright 2014 The Chromium Authors. All rights reserved. 21320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Use of this source code is governed by a BSD-style license that can be 31320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// found in the LICENSE file. 41320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 51320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "chromecast/media/cma/ipc_streamer/av_streamer_proxy.h" 61320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 71320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/bind.h" 81320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/location.h" 91320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/message_loop/message_loop_proxy.h" 101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "chromecast/media/cma/base/coded_frame_provider.h" 111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "chromecast/media/cma/base/decoder_buffer_base.h" 121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "chromecast/media/cma/ipc/media_memory_chunk.h" 131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "chromecast/media/cma/ipc/media_message.h" 141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "chromecast/media/cma/ipc/media_message_fifo.h" 151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "chromecast/media/cma/ipc/media_message_type.h" 161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "chromecast/media/cma/ipc_streamer/audio_decoder_config_marshaller.h" 171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "chromecast/media/cma/ipc_streamer/decoder_buffer_base_marshaller.h" 181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "chromecast/media/cma/ipc_streamer/video_decoder_config_marshaller.h" 191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccinamespace chromecast { 211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccinamespace media { 221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciAvStreamerProxy::AvStreamerProxy() 241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci : is_running_(false), 251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci pending_read_(false), 261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci pending_av_data_(false), 271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci weak_factory_(this), 281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci weak_this_(weak_factory_.GetWeakPtr()) { 291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci thread_checker_.DetachFromThread(); 301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciAvStreamerProxy::~AvStreamerProxy() { 331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK(thread_checker_.CalledOnValidThread()); 341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid AvStreamerProxy::SetCodedFrameProvider( 371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_ptr<CodedFrameProvider> frame_provider) { 381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK(thread_checker_.CalledOnValidThread()); 391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK(!frame_provider_); 401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci frame_provider_.reset(frame_provider.release()); 411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid AvStreamerProxy::SetMediaMessageFifo( 441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_ptr<MediaMessageFifo> fifo) { 451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK(thread_checker_.CalledOnValidThread()); 461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK(!fifo_); 471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci fifo_.reset(fifo.release()); 481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid AvStreamerProxy::Start() { 511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK(!is_running_); 521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci is_running_ = true; 541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci RequestBufferIfNeeded(); 551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid AvStreamerProxy::StopAndFlush(const base::Closure& done_cb) { 581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci is_running_ = false; 591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci pending_av_data_ = false; 611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci pending_audio_config_ = ::media::AudioDecoderConfig(); 621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci pending_video_config_ = ::media::VideoDecoderConfig(); 631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci pending_buffer_ = scoped_refptr<DecoderBufferBase>(); 641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci pending_read_ = false; 661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci frame_provider_->Flush(done_cb); 671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid AvStreamerProxy::OnFifoReadEvent() { 701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK(thread_checker_.CalledOnValidThread()); 711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Some enough space might have been released 731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // to accommodate the pending data. 741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (pending_av_data_) 751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ProcessPendingData(); 761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid AvStreamerProxy::RequestBufferIfNeeded() { 791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK(thread_checker_.CalledOnValidThread()); 801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!is_running_ || pending_read_ || pending_av_data_) 821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // |frame_provider_| is assumed to run on the same message loop. 851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Add a BindToCurrentLoop if that's not the case in the future. 861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci pending_read_ = true; 871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci frame_provider_->Read(base::Bind(&AvStreamerProxy::OnNewBuffer, weak_this_)); 881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid AvStreamerProxy::OnNewBuffer( 911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const scoped_refptr<DecoderBufferBase>& buffer, 921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const ::media::AudioDecoderConfig& audio_config, 931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const ::media::VideoDecoderConfig& video_config) { 941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK(thread_checker_.CalledOnValidThread()); 951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci pending_read_ = false; 971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (buffer->end_of_stream()) 991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci is_running_ = false; 1001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK(!pending_av_data_); 1021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci pending_av_data_ = true; 1031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci pending_buffer_ = buffer; 1051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci pending_audio_config_ = audio_config; 1061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci pending_video_config_ = video_config; 1071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ProcessPendingData(); 1091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid AvStreamerProxy::ProcessPendingData() { 1121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (pending_audio_config_.IsValidConfig()) { 1131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!SendAudioDecoderConfig(pending_audio_config_)) 1141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 1151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci pending_audio_config_ = ::media::AudioDecoderConfig(); 1161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (pending_video_config_.IsValidConfig()) { 1191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!SendVideoDecoderConfig(pending_video_config_)) 1201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 1211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci pending_video_config_ = ::media::VideoDecoderConfig(); 1221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (pending_buffer_.get()) { 1251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!SendBuffer(pending_buffer_)) 1261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 1271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci pending_buffer_ = scoped_refptr<DecoderBufferBase>(); 1281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci pending_av_data_ = false; 1311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::MessageLoopProxy::current()->PostTask( 1321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci FROM_HERE, 1331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Bind(&AvStreamerProxy::RequestBufferIfNeeded, weak_this_)); 1341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool AvStreamerProxy::SendAudioDecoderConfig( 1371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const ::media::AudioDecoderConfig& config) { 1381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Create a dummy message to calculate first the message size. 1391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_ptr<MediaMessage> dummy_msg( 1401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci MediaMessage::CreateDummyMessage(AudioConfigMediaMsg)); 1411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci AudioDecoderConfigMarshaller::Write(config, dummy_msg.get()); 1421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Create the real message and write the actual content. 1441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_ptr<MediaMessage> msg( 1451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci MediaMessage::CreateMessage( 1461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci AudioConfigMediaMsg, 1471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Bind(&MediaMessageFifo::ReserveMemory, 1481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Unretained(fifo_.get())), 1491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci dummy_msg->content_size())); 1501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!msg) 1511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return false; 1521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci AudioDecoderConfigMarshaller::Write(config, msg.get()); 1541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return true; 1551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool AvStreamerProxy::SendVideoDecoderConfig( 1581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const ::media::VideoDecoderConfig& config) { 1591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Create a dummy message to calculate first the message size. 1601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_ptr<MediaMessage> dummy_msg( 1611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci MediaMessage::CreateDummyMessage(VideoConfigMediaMsg)); 1621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci VideoDecoderConfigMarshaller::Write(config, dummy_msg.get()); 1631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Create the real message and write the actual content. 1651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_ptr<MediaMessage> msg( 1661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci MediaMessage::CreateMessage( 1671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci VideoConfigMediaMsg, 1681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Bind(&MediaMessageFifo::ReserveMemory, 1691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Unretained(fifo_.get())), 1701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci dummy_msg->content_size())); 1711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!msg) 1721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return false; 1731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci VideoDecoderConfigMarshaller::Write(config, msg.get()); 1751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return true; 1761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool AvStreamerProxy::SendBuffer( 1791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const scoped_refptr<DecoderBufferBase>& buffer) { 1801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Create a dummy message to calculate first the message size. 1811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_ptr<MediaMessage> dummy_msg( 1821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci MediaMessage::CreateDummyMessage(FrameMediaMsg)); 1831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DecoderBufferBaseMarshaller::Write(buffer, dummy_msg.get()); 1841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Create the real message and write the actual content. 1861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_ptr<MediaMessage> msg( 1871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci MediaMessage::CreateMessage( 1881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci FrameMediaMsg, 1891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Bind(&MediaMessageFifo::ReserveMemory, 1901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Unretained(fifo_.get())), 1911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci dummy_msg->content_size())); 1921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!msg) 1931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return false; 1941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DecoderBufferBaseMarshaller::Write(buffer, msg.get()); 1961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return true; 1971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} // namespace media 2001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} // namespace chromecast 201