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/net/cast_transport_config.h" 15#include "media/cast/net/udp_transport.h" 16 17using media::cast::CastTransportStatus; 18using media::cast::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 FrameReceiverConfig& audio_config, 28 const FrameReceiverConfig& 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::UpdateCastTransportStatus(CastTransportStatus status) { 70 LOG_IF(ERROR, status == media::cast::TRANSPORT_SOCKET_ERROR) 71 << "Transport socket error occurred. InProcessReceiver is likely dead."; 72 VLOG(1) << "CastTransportStatus is now " << status; 73} 74 75void InProcessReceiver::StartOnMainThread() { 76 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); 77 78 DCHECK(!transport_ && !cast_receiver_); 79 transport_.reset( 80 new UdpTransport(NULL, 81 cast_environment_->GetTaskRunner(CastEnvironment::MAIN), 82 local_end_point_, 83 remote_end_point_, 84 base::Bind(&InProcessReceiver::UpdateCastTransportStatus, 85 base::Unretained(this)))); 86 cast_receiver_ = CastReceiver::Create( 87 cast_environment_, audio_config_, video_config_, transport_.get()); 88 89 // TODO(hubbe): Make the cast receiver do this automatically. 90 transport_->StartReceiving(cast_receiver_->packet_receiver()); 91 92 PullNextAudioFrame(); 93 PullNextVideoFrame(); 94} 95 96void InProcessReceiver::GotAudioFrame(scoped_ptr<AudioBus> audio_frame, 97 const base::TimeTicks& playout_time, 98 bool is_continuous) { 99 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); 100 if (audio_frame.get()) 101 OnAudioFrame(audio_frame.Pass(), playout_time, is_continuous); 102 PullNextAudioFrame(); 103} 104 105void InProcessReceiver::GotVideoFrame( 106 const scoped_refptr<VideoFrame>& video_frame, 107 const base::TimeTicks& playout_time, 108 bool is_continuous) { 109 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); 110 if (video_frame.get()) 111 OnVideoFrame(video_frame, playout_time, is_continuous); 112 PullNextVideoFrame(); 113} 114 115void InProcessReceiver::PullNextAudioFrame() { 116 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); 117 cast_receiver_->RequestDecodedAudioFrame( 118 base::Bind(&InProcessReceiver::GotAudioFrame, 119 weak_factory_.GetWeakPtr())); 120} 121 122void InProcessReceiver::PullNextVideoFrame() { 123 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); 124 cast_receiver_->RequestDecodedVideoFrame(base::Bind( 125 &InProcessReceiver::GotVideoFrame, weak_factory_.GetWeakPtr())); 126} 127 128} // namespace cast 129} // namespace media 130