in_process_receiver.cc revision e5d81f57cb97b3b6b7fccc9c5610d21eb81db09d
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 "media/cast/test/utility/in_process_receiver.h" 6 7#include "base/bind_helpers.h" 8#include "base/synchronization/waitable_event.h" 9#include "base/time/time.h" 10#include "media/base/video_frame.h" 11#include "media/cast/cast_config.h" 12#include "media/cast/cast_environment.h" 13#include "media/cast/cast_receiver.h" 14#include "media/cast/transport/cast_transport_config.h" 15#include "media/cast/transport/transport/udp_transport.h" 16 17using media::cast::transport::CastTransportStatus; 18using media::cast::transport::UdpTransport; 19 20namespace media { 21namespace cast { 22 23InProcessReceiver::InProcessReceiver( 24 const scoped_refptr<CastEnvironment>& cast_environment, 25 const net::IPEndPoint& local_end_point, 26 const net::IPEndPoint& remote_end_point, 27 const AudioReceiverConfig& audio_config, 28 const VideoReceiverConfig& video_config) 29 : cast_environment_(cast_environment), 30 local_end_point_(local_end_point), 31 remote_end_point_(remote_end_point), 32 audio_config_(audio_config), 33 video_config_(video_config), 34 weak_factory_(this) {} 35 36InProcessReceiver::~InProcessReceiver() { 37 Stop(); 38} 39 40void InProcessReceiver::Start() { 41 cast_environment_->PostTask(CastEnvironment::MAIN, 42 FROM_HERE, 43 base::Bind(&InProcessReceiver::StartOnMainThread, 44 base::Unretained(this))); 45} 46 47void InProcessReceiver::Stop() { 48 base::WaitableEvent event(false, false); 49 if (cast_environment_->CurrentlyOn(CastEnvironment::MAIN)) { 50 StopOnMainThread(&event); 51 } else { 52 cast_environment_->PostTask(CastEnvironment::MAIN, 53 FROM_HERE, 54 base::Bind(&InProcessReceiver::StopOnMainThread, 55 base::Unretained(this), 56 &event)); 57 event.Wait(); 58 } 59} 60 61void InProcessReceiver::StopOnMainThread(base::WaitableEvent* event) { 62 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); 63 cast_receiver_.reset(NULL); 64 transport_.reset(NULL); 65 weak_factory_.InvalidateWeakPtrs(); 66 event->Signal(); 67} 68 69void InProcessReceiver::DestroySoon() { 70 cast_environment_->PostTask( 71 CastEnvironment::MAIN, 72 FROM_HERE, 73 base::Bind(&InProcessReceiver::WillDestroyReceiver, base::Owned(this))); 74} 75 76void InProcessReceiver::UpdateCastTransportStatus(CastTransportStatus status) { 77 LOG_IF(ERROR, status == media::cast::transport::TRANSPORT_SOCKET_ERROR) 78 << "Transport socket error occurred. InProcessReceiver is likely dead."; 79 VLOG(1) << "CastTransportStatus is now " << status; 80} 81 82void InProcessReceiver::StartOnMainThread() { 83 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); 84 85 DCHECK(!transport_ && !cast_receiver_); 86 transport_.reset( 87 new UdpTransport(NULL, 88 cast_environment_->GetTaskRunner(CastEnvironment::MAIN), 89 local_end_point_, 90 remote_end_point_, 91 base::Bind(&InProcessReceiver::UpdateCastTransportStatus, 92 base::Unretained(this)))); 93 cast_receiver_ = CastReceiver::Create( 94 cast_environment_, audio_config_, video_config_, transport_.get()); 95 96 // TODO(hubbe): Make the cast receiver do this automatically. 97 transport_->StartReceiving(cast_receiver_->packet_receiver()); 98 99 PullNextAudioFrame(); 100 PullNextVideoFrame(); 101} 102 103void InProcessReceiver::GotAudioFrame(scoped_ptr<AudioBus> audio_frame, 104 const base::TimeTicks& playout_time, 105 bool is_continuous) { 106 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); 107 if (audio_frame.get()) { 108 // TODO(miu): Remove use of deprecated PcmAudioFrame and also pass 109 // |is_continuous| flag. 110 scoped_ptr<PcmAudioFrame> pcm_frame(new PcmAudioFrame()); 111 pcm_frame->channels = audio_frame->channels(); 112 pcm_frame->frequency = audio_config_.frequency; 113 pcm_frame->samples.resize(audio_frame->channels() * audio_frame->frames()); 114 audio_frame->ToInterleaved( 115 audio_frame->frames(), sizeof(int16), &pcm_frame->samples.front()); 116 OnAudioFrame(pcm_frame.Pass(), playout_time); 117 } 118 PullNextAudioFrame(); 119} 120 121void InProcessReceiver::GotVideoFrame( 122 const scoped_refptr<VideoFrame>& video_frame, 123 const base::TimeTicks& render_time) { 124 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); 125 OnVideoFrame(video_frame, render_time); 126 PullNextVideoFrame(); 127} 128 129void InProcessReceiver::PullNextAudioFrame() { 130 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); 131 cast_receiver_->frame_receiver()->GetRawAudioFrame( 132 base::Bind(&InProcessReceiver::GotAudioFrame, 133 weak_factory_.GetWeakPtr())); 134} 135 136void InProcessReceiver::PullNextVideoFrame() { 137 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); 138 cast_receiver_->frame_receiver()->GetRawVideoFrame(base::Bind( 139 &InProcessReceiver::GotVideoFrame, weak_factory_.GetWeakPtr())); 140} 141 142// static 143void InProcessReceiver::WillDestroyReceiver(InProcessReceiver* receiver) { 144 DCHECK(receiver->cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); 145} 146 147} // namespace cast 148} // namespace media 149