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/coded_frame_provider_host.h" 6 7#include "base/bind.h" 8#include "base/callback_helpers.h" 9#include "chromecast/media/cma/base/decoder_buffer_base.h" 10#include "chromecast/media/cma/ipc/media_message.h" 11#include "chromecast/media/cma/ipc/media_message_fifo.h" 12#include "chromecast/media/cma/ipc/media_message_type.h" 13#include "chromecast/media/cma/ipc_streamer/audio_decoder_config_marshaller.h" 14#include "chromecast/media/cma/ipc_streamer/decoder_buffer_base_marshaller.h" 15#include "chromecast/media/cma/ipc_streamer/video_decoder_config_marshaller.h" 16#include "media/base/buffers.h" 17#include "media/base/decrypt_config.h" 18 19namespace chromecast { 20namespace media { 21 22CodedFrameProviderHost::CodedFrameProviderHost( 23 scoped_ptr<MediaMessageFifo> media_message_fifo) 24 : fifo_(media_message_fifo.Pass()), 25 weak_factory_(this), 26 weak_this_(weak_factory_.GetWeakPtr()) { 27 thread_checker_.DetachFromThread(); 28} 29 30CodedFrameProviderHost::~CodedFrameProviderHost() { 31 DCHECK(thread_checker_.CalledOnValidThread()); 32} 33 34void CodedFrameProviderHost::Read(const ReadCB& read_cb) { 35 DCHECK(thread_checker_.CalledOnValidThread()); 36 37 // Cannot be called if there is already a pending read. 38 DCHECK(read_cb_.is_null()); 39 read_cb_ = read_cb; 40 41 ReadMessages(); 42} 43 44void CodedFrameProviderHost::Flush(const base::Closure& flush_cb) { 45 DCHECK(thread_checker_.CalledOnValidThread()); 46 audio_config_ = ::media::AudioDecoderConfig(); 47 video_config_ = ::media::VideoDecoderConfig(); 48 read_cb_.Reset(); 49 fifo_->Flush(); 50 flush_cb.Run(); 51} 52 53void CodedFrameProviderHost::OnFifoWriteEvent() { 54 DCHECK(thread_checker_.CalledOnValidThread()); 55 ReadMessages(); 56} 57 58base::Closure CodedFrameProviderHost::GetFifoWriteEventCb() { 59 return base::Bind(&CodedFrameProviderHost::OnFifoWriteEvent, weak_this_); 60} 61 62void CodedFrameProviderHost::ReadMessages() { 63 // Read messages until a frame is provided (i.e. not just the audio/video 64 // configurations). 65 while (!read_cb_.is_null()) { 66 scoped_ptr<MediaMessage> msg(fifo_->Pop()); 67 if (!msg) 68 break; 69 70 if (msg->type() == PaddingMediaMsg) { 71 // Ignore the message. 72 } else if (msg->type() == AudioConfigMediaMsg) { 73 audio_config_ = AudioDecoderConfigMarshaller::Read(msg.get()); 74 } else if (msg->type() == VideoConfigMediaMsg) { 75 video_config_ = VideoDecoderConfigMarshaller::Read(msg.get()); 76 } else if (msg->type() == FrameMediaMsg) { 77 scoped_refptr<DecoderBufferBase> buffer = 78 DecoderBufferBaseMarshaller::Read(msg.Pass()); 79 base::ResetAndReturn(&read_cb_).Run( 80 buffer, audio_config_, video_config_); 81 audio_config_ = ::media::AudioDecoderConfig(); 82 video_config_ = ::media::VideoDecoderConfig(); 83 } else { 84 // Receiving an unexpected message. 85 // Possible use case (except software bugs): the renderer process has 86 // been compromised and an invalid message value has been written to 87 // the fifo. Crash the browser process in this case to avoid further 88 // security implications (so do not use NOTREACHED which crashes only 89 // in debug builds). 90 LOG(FATAL) << "Unknown media message"; 91 } 92 } 93} 94 95} // namespace media 96} // namespace chromecast 97