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.
5 #include "media/cast/test/utility/in_process_receiver.h"
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"
17 using media::cast::transport::CastTransportStatus;
18 using media::cast::transport::UdpTransport;
23 InProcessReceiver::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) {}
36 InProcessReceiver::~InProcessReceiver() {
40 void InProcessReceiver::Start() {
41 cast_environment_->PostTask(CastEnvironment::MAIN,
43 base::Bind(&InProcessReceiver::StartOnMainThread,
44 base::Unretained(this)));
47 void InProcessReceiver::Stop() {
48 base::WaitableEvent event(false, false);
49 if (cast_environment_->CurrentlyOn(CastEnvironment::MAIN)) {
50 StopOnMainThread(&event);
52 cast_environment_->PostTask(CastEnvironment::MAIN,
54 base::Bind(&InProcessReceiver::StopOnMainThread,
55 base::Unretained(this),
61 void 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();
69 void InProcessReceiver::UpdateCastTransportStatus(CastTransportStatus status) {
70 LOG_IF(ERROR, status == media::cast::transport::TRANSPORT_SOCKET_ERROR)
71 << "Transport socket error occurred. InProcessReceiver is likely dead.";
72 VLOG(1) << "CastTransportStatus is now " << status;
75 void InProcessReceiver::StartOnMainThread() {
76 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
78 DCHECK(!transport_ && !cast_receiver_);
80 new UdpTransport(NULL,
81 cast_environment_->GetTaskRunner(CastEnvironment::MAIN),
84 base::Bind(&InProcessReceiver::UpdateCastTransportStatus,
85 base::Unretained(this))));
86 cast_receiver_ = CastReceiver::Create(
87 cast_environment_, audio_config_, video_config_, transport_.get());
89 // TODO(hubbe): Make the cast receiver do this automatically.
90 transport_->StartReceiving(cast_receiver_->packet_receiver());
96 void InProcessReceiver::GotAudioFrame(scoped_ptr<AudioBus> audio_frame,
97 const base::TimeTicks& playout_time,
99 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
100 if (audio_frame.get())
101 OnAudioFrame(audio_frame.Pass(), playout_time, is_continuous);
102 PullNextAudioFrame();
105 void 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));
111 OnVideoFrame(video_frame, playout_time, is_continuous);
112 PullNextVideoFrame();
115 void InProcessReceiver::PullNextAudioFrame() {
116 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
117 cast_receiver_->frame_receiver()->GetRawAudioFrame(
118 base::Bind(&InProcessReceiver::GotAudioFrame,
119 weak_factory_.GetWeakPtr()));
122 void InProcessReceiver::PullNextVideoFrame() {
123 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
124 cast_receiver_->frame_receiver()->GetRawVideoFrame(base::Bind(
125 &InProcessReceiver::GotVideoFrame, weak_factory_.GetWeakPtr()));