av_streamer_proxy.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)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chromecast/media/cma/ipc_streamer/av_streamer_proxy.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/location.h"
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/message_loop/message_loop_proxy.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chromecast/media/cma/base/coded_frame_provider.h"
11b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "chromecast/media/cma/base/decoder_buffer_base.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chromecast/media/cma/ipc/media_memory_chunk.h"
13a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "chromecast/media/cma/ipc/media_message.h"
14010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "chromecast/media/cma/ipc/media_message_fifo.h"
1503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "chromecast/media/cma/ipc/media_message_type.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chromecast/media/cma/ipc_streamer/audio_decoder_config_marshaller.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chromecast/media/cma/ipc_streamer/decoder_buffer_base_marshaller.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chromecast/media/cma/ipc_streamer/video_decoder_config_marshaller.h"
1990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace chromecast {
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace media {
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AvStreamerProxy::AvStreamerProxy()
24f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    : is_running_(false),
2590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      pending_read_(false),
2690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      pending_av_data_(false),
2790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      weak_factory_(this),
28f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      weak_this_(weak_factory_.GetWeakPtr()) {
29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  thread_checker_.DetachFromThread();
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)AvStreamerProxy::~AvStreamerProxy() {
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AvStreamerProxy::SetCodedFrameProvider(
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<CodedFrameProvider> frame_provider) {
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(!frame_provider_);
405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  frame_provider_.reset(frame_provider.release());
415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AvStreamerProxy::SetMediaMessageFifo(
445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    scoped_ptr<MediaMessageFifo> fifo) {
455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!fifo_);
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  fifo_.reset(fifo.release());
485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AvStreamerProxy::Start() {
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!is_running_);
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  is_running_ = true;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RequestBufferIfNeeded();
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5758e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdochvoid AvStreamerProxy::StopAndFlush(const base::Closure& done_cb) {
5858e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch  is_running_ = false;
5958e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch
60ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  pending_av_data_ = false;
61ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  pending_audio_config_ = ::media::AudioDecoderConfig();
62f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  pending_video_config_ = ::media::VideoDecoderConfig();
63f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  pending_buffer_ = scoped_refptr<DecoderBufferBase>();
64ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
65ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  pending_read_ = false;
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  frame_provider_->Flush(done_cb);
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AvStreamerProxy::OnFifoReadEvent() {
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
7190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Some enough space might have been released
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // to accommodate the pending data.
745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (pending_av_data_)
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ProcessPendingData();
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AvStreamerProxy::RequestBufferIfNeeded() {
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!is_running_ || pending_read_ || pending_av_data_)
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // |frame_provider_| is assumed to run on the same message loop.
855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Add a BindToCurrentLoop if that's not the case in the future.
86f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  pending_read_ = true;
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  frame_provider_->Read(base::Bind(&AvStreamerProxy::OnNewBuffer, weak_this_));
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AvStreamerProxy::OnNewBuffer(
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const scoped_refptr<DecoderBufferBase>& buffer,
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ::media::AudioDecoderConfig& audio_config,
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ::media::VideoDecoderConfig& video_config) {
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  pending_read_ = false;
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (buffer->end_of_stream())
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    is_running_ = false;
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!pending_av_data_);
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_av_data_ = true;
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_buffer_ = buffer;
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_audio_config_ = audio_config;
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_video_config_ = video_config;
10790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
10890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ProcessPendingData();
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
111868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void AvStreamerProxy::ProcessPendingData() {
112868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (pending_audio_config_.IsValidConfig()) {
113868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!SendAudioDecoderConfig(pending_audio_config_))
114868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
115868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    pending_audio_config_ = ::media::AudioDecoderConfig();
116868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
117868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
118868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (pending_video_config_.IsValidConfig()) {
119868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!SendVideoDecoderConfig(pending_video_config_))
120868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
121868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    pending_video_config_ = ::media::VideoDecoderConfig();
122868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (pending_buffer_.get()) {
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!SendBuffer(pending_buffer_))
126b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      return;
127a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    pending_buffer_ = scoped_refptr<DecoderBufferBase>();
128a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
129a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
130a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  pending_av_data_ = false;
131a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  base::MessageLoopProxy::current()->PostTask(
132b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      FROM_HERE,
133b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      base::Bind(&AvStreamerProxy::RequestBufferIfNeeded, weak_this_));
134b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
135b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
136b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)bool AvStreamerProxy::SendAudioDecoderConfig(
137a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    const ::media::AudioDecoderConfig& config) {
138a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Create a dummy message to calculate first the message size.
139a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  scoped_ptr<MediaMessage> dummy_msg(
140a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      MediaMessage::CreateDummyMessage(AudioConfigMediaMsg));
141a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  AudioDecoderConfigMarshaller::Write(config, dummy_msg.get());
142a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
143a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Create the real message and write the actual content.
144a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  scoped_ptr<MediaMessage> msg(
145a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      MediaMessage::CreateMessage(
146a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)          AudioConfigMediaMsg,
147a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)          base::Bind(&MediaMessageFifo::ReserveMemory,
148a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                     base::Unretained(fifo_.get())),
149a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)          dummy_msg->content_size()));
150a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (!msg)
151b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return false;
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
153a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  AudioDecoderConfigMarshaller::Write(config, msg.get());
154a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return true;
155a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool AvStreamerProxy::SendVideoDecoderConfig(
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ::media::VideoDecoderConfig& config) {
159a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Create a dummy message to calculate first the message size.
160a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  scoped_ptr<MediaMessage> dummy_msg(
1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      MediaMessage::CreateDummyMessage(VideoConfigMediaMsg));
162a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  VideoDecoderConfigMarshaller::Write(config, dummy_msg.get());
163a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
164a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Create the real message and write the actual content.
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<MediaMessage> msg(
1661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      MediaMessage::CreateMessage(
1671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          VideoConfigMediaMsg,
168f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          base::Bind(&MediaMessageFifo::ReserveMemory,
169f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                     base::Unretained(fifo_.get())),
170f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          dummy_msg->content_size()));
171f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!msg)
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
173c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
17490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  VideoDecoderConfigMarshaller::Write(config, msg.get());
17590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return true;
17690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
17790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool AvStreamerProxy::SendBuffer(
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const scoped_refptr<DecoderBufferBase>& buffer) {
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Create a dummy message to calculate first the message size.
181cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<MediaMessage> dummy_msg(
18258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      MediaMessage::CreateDummyMessage(FrameMediaMsg));
18358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DecoderBufferBaseMarshaller::Write(buffer, dummy_msg.get());
18458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
185cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Create the real message and write the actual content.
18658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  scoped_ptr<MediaMessage> msg(
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      MediaMessage::CreateMessage(
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          FrameMediaMsg,
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          base::Bind(&MediaMessageFifo::ReserveMemory,
1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                     base::Unretained(fifo_.get())),
191f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          dummy_msg->content_size()));
1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!msg)
1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
195f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DecoderBufferBaseMarshaller::Write(buffer, msg.get());
196f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return true;
197f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
19890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
19990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}  // namespace media
200f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}  // namespace chromecast
201868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)