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