OLD | NEW |
(Empty) | |
| 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. |
| 4 |
| 5 #include "chromecast/media/cma/ipc_streamer/av_streamer_proxy.h" |
| 6 |
| 7 #include "base/bind.h" |
| 8 #include "base/location.h" |
| 9 #include "base/message_loop/message_loop_proxy.h" |
| 10 #include "chromecast/media/cma/base/coded_frame_provider.h" |
| 11 #include "chromecast/media/cma/base/decoder_buffer_base.h" |
| 12 #include "chromecast/media/cma/ipc/media_memory_chunk.h" |
| 13 #include "chromecast/media/cma/ipc/media_message.h" |
| 14 #include "chromecast/media/cma/ipc/media_message_fifo.h" |
| 15 #include "chromecast/media/cma/ipc/media_message_type.h" |
| 16 #include "chromecast/media/cma/ipc_streamer/audio_decoder_config_marshaller.h" |
| 17 #include "chromecast/media/cma/ipc_streamer/decoder_buffer_base_marshaller.h" |
| 18 #include "chromecast/media/cma/ipc_streamer/video_decoder_config_marshaller.h" |
| 19 |
| 20 namespace chromecast { |
| 21 namespace media { |
| 22 |
| 23 AvStreamerProxy::AvStreamerProxy() |
| 24 : is_running_(false), |
| 25 pending_read_(false), |
| 26 pending_av_data_(false), |
| 27 weak_factory_(this), |
| 28 weak_this_(weak_factory_.GetWeakPtr()) { |
| 29 thread_checker_.DetachFromThread(); |
| 30 } |
| 31 |
| 32 AvStreamerProxy::~AvStreamerProxy() { |
| 33 DCHECK(thread_checker_.CalledOnValidThread()); |
| 34 } |
| 35 |
| 36 void AvStreamerProxy::SetCodedFrameProvider( |
| 37 scoped_ptr<CodedFrameProvider> frame_provider) { |
| 38 DCHECK(thread_checker_.CalledOnValidThread()); |
| 39 DCHECK(!frame_provider_); |
| 40 frame_provider_.reset(frame_provider.release()); |
| 41 } |
| 42 |
| 43 void AvStreamerProxy::SetMediaMessageFifo( |
| 44 scoped_ptr<MediaMessageFifo> fifo) { |
| 45 DCHECK(thread_checker_.CalledOnValidThread()); |
| 46 DCHECK(!fifo_); |
| 47 fifo_.reset(fifo.release()); |
| 48 } |
| 49 |
| 50 void AvStreamerProxy::Start() { |
| 51 DCHECK(!is_running_); |
| 52 |
| 53 is_running_ = true; |
| 54 RequestBufferIfNeeded(); |
| 55 } |
| 56 |
| 57 void AvStreamerProxy::StopAndFlush(const base::Closure& done_cb) { |
| 58 is_running_ = false; |
| 59 |
| 60 pending_av_data_ = false; |
| 61 pending_audio_config_ = ::media::AudioDecoderConfig(); |
| 62 pending_video_config_ = ::media::VideoDecoderConfig(); |
| 63 pending_buffer_ = scoped_refptr<DecoderBufferBase>(); |
| 64 |
| 65 pending_read_ = false; |
| 66 frame_provider_->Flush(done_cb); |
| 67 } |
| 68 |
| 69 void AvStreamerProxy::OnFifoReadEvent() { |
| 70 DCHECK(thread_checker_.CalledOnValidThread()); |
| 71 |
| 72 // Some enough space might have been released |
| 73 // to accommodate the pending data. |
| 74 if (pending_av_data_) |
| 75 ProcessPendingData(); |
| 76 } |
| 77 |
| 78 void AvStreamerProxy::RequestBufferIfNeeded() { |
| 79 DCHECK(thread_checker_.CalledOnValidThread()); |
| 80 |
| 81 if (!is_running_ || pending_read_ || pending_av_data_) |
| 82 return; |
| 83 |
| 84 // |frame_provider_| is assumed to run on the same message loop. |
| 85 // Add a BindToCurrentLoop if that's not the case in the future. |
| 86 pending_read_ = true; |
| 87 frame_provider_->Read(base::Bind(&AvStreamerProxy::OnNewBuffer, weak_this_)); |
| 88 } |
| 89 |
| 90 void AvStreamerProxy::OnNewBuffer( |
| 91 const scoped_refptr<DecoderBufferBase>& buffer, |
| 92 const ::media::AudioDecoderConfig& audio_config, |
| 93 const ::media::VideoDecoderConfig& video_config) { |
| 94 DCHECK(thread_checker_.CalledOnValidThread()); |
| 95 |
| 96 pending_read_ = false; |
| 97 |
| 98 if (buffer->end_of_stream()) |
| 99 is_running_ = false; |
| 100 |
| 101 DCHECK(!pending_av_data_); |
| 102 pending_av_data_ = true; |
| 103 |
| 104 pending_buffer_ = buffer; |
| 105 pending_audio_config_ = audio_config; |
| 106 pending_video_config_ = video_config; |
| 107 |
| 108 ProcessPendingData(); |
| 109 } |
| 110 |
| 111 void AvStreamerProxy::ProcessPendingData() { |
| 112 if (pending_audio_config_.IsValidConfig()) { |
| 113 if (!SendAudioDecoderConfig(pending_audio_config_)) |
| 114 return; |
| 115 pending_audio_config_ = ::media::AudioDecoderConfig(); |
| 116 } |
| 117 |
| 118 if (pending_video_config_.IsValidConfig()) { |
| 119 if (!SendVideoDecoderConfig(pending_video_config_)) |
| 120 return; |
| 121 pending_video_config_ = ::media::VideoDecoderConfig(); |
| 122 } |
| 123 |
| 124 if (pending_buffer_.get()) { |
| 125 if (!SendBuffer(pending_buffer_)) |
| 126 return; |
| 127 pending_buffer_ = scoped_refptr<DecoderBufferBase>(); |
| 128 } |
| 129 |
| 130 pending_av_data_ = false; |
| 131 base::MessageLoopProxy::current()->PostTask( |
| 132 FROM_HERE, |
| 133 base::Bind(&AvStreamerProxy::RequestBufferIfNeeded, weak_this_)); |
| 134 } |
| 135 |
| 136 bool AvStreamerProxy::SendAudioDecoderConfig( |
| 137 const ::media::AudioDecoderConfig& config) { |
| 138 // Create a dummy message to calculate first the message size. |
| 139 scoped_ptr<MediaMessage> dummy_msg( |
| 140 MediaMessage::CreateDummyMessage(AudioConfigMediaMsg)); |
| 141 AudioDecoderConfigMarshaller::Write(config, dummy_msg.get()); |
| 142 |
| 143 // Create the real message and write the actual content. |
| 144 scoped_ptr<MediaMessage> msg( |
| 145 MediaMessage::CreateMessage( |
| 146 AudioConfigMediaMsg, |
| 147 base::Bind(&MediaMessageFifo::ReserveMemory, |
| 148 base::Unretained(fifo_.get())), |
| 149 dummy_msg->content_size())); |
| 150 if (!msg) |
| 151 return false; |
| 152 |
| 153 AudioDecoderConfigMarshaller::Write(config, msg.get()); |
| 154 return true; |
| 155 } |
| 156 |
| 157 bool AvStreamerProxy::SendVideoDecoderConfig( |
| 158 const ::media::VideoDecoderConfig& config) { |
| 159 // Create a dummy message to calculate first the message size. |
| 160 scoped_ptr<MediaMessage> dummy_msg( |
| 161 MediaMessage::CreateDummyMessage(VideoConfigMediaMsg)); |
| 162 VideoDecoderConfigMarshaller::Write(config, dummy_msg.get()); |
| 163 |
| 164 // Create the real message and write the actual content. |
| 165 scoped_ptr<MediaMessage> msg( |
| 166 MediaMessage::CreateMessage( |
| 167 VideoConfigMediaMsg, |
| 168 base::Bind(&MediaMessageFifo::ReserveMemory, |
| 169 base::Unretained(fifo_.get())), |
| 170 dummy_msg->content_size())); |
| 171 if (!msg) |
| 172 return false; |
| 173 |
| 174 VideoDecoderConfigMarshaller::Write(config, msg.get()); |
| 175 return true; |
| 176 } |
| 177 |
| 178 bool AvStreamerProxy::SendBuffer( |
| 179 const scoped_refptr<DecoderBufferBase>& buffer) { |
| 180 // Create a dummy message to calculate first the message size. |
| 181 scoped_ptr<MediaMessage> dummy_msg( |
| 182 MediaMessage::CreateDummyMessage(FrameMediaMsg)); |
| 183 DecoderBufferBaseMarshaller::Write(buffer, dummy_msg.get()); |
| 184 |
| 185 // Create the real message and write the actual content. |
| 186 scoped_ptr<MediaMessage> msg( |
| 187 MediaMessage::CreateMessage( |
| 188 FrameMediaMsg, |
| 189 base::Bind(&MediaMessageFifo::ReserveMemory, |
| 190 base::Unretained(fifo_.get())), |
| 191 dummy_msg->content_size())); |
| 192 if (!msg) |
| 193 return false; |
| 194 |
| 195 DecoderBufferBaseMarshaller::Write(buffer, msg.get()); |
| 196 return true; |
| 197 } |
| 198 |
| 199 } // namespace media |
| 200 } // namespace chromecast |
OLD | NEW |