Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2017 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 "content/renderer/media/mojo_audio_output_ipc.h" | |
| 6 | |
| 7 #include <utility> | |
| 8 | |
| 9 #include "content/renderer/media/audio_ipc_factory.h" | |
| 10 #include "media/audio/audio_device_description.h" | |
| 11 #include "mojo/public/cpp/system/platform_handle.h" | |
| 12 | |
| 13 namespace content { | |
| 14 | |
| 15 namespace { | |
| 16 | |
| 17 void TrivialAuthorizedCallback(media::OutputDeviceStatus, | |
| 18 const media::AudioParameters&, | |
| 19 const std::string&) {} | |
| 20 | |
| 21 } // namespace | |
| 22 | |
| 23 MojoAudioOutputIPC::MojoAudioOutputIPC(int frame_id) | |
| 24 : frame_id_(frame_id), weak_factory_(this) { | |
| 25 thread_checker_.DetachFromThread(); | |
| 26 } | |
| 27 | |
| 28 MojoAudioOutputIPC::~MojoAudioOutputIPC() { | |
| 29 // No thread check. | |
| 30 // Destructing |weak_factory_| on any thread is safe since it's not used after | |
| 31 // the final call to CloseStream. | |
|
o1ka
2017/04/20 10:36:00
Could you please clarify the comment?
o1ka
2017/04/20 10:36:00
* if CloseStream() has been called. DCHECKs for th
Max Morin
2017/05/05 13:10:58
Done.
Max Morin
2017/05/05 13:10:59
Done.
| |
| 32 } | |
| 33 | |
| 34 media::mojom::AudioOutputStreamProviderRequest | |
| 35 MojoAudioOutputIPC::MakeProviderRequest( | |
| 36 media::AudioOutputIPCDelegate* delegate) { | |
| 37 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 38 DCHECK(!stream_provider_.is_bound()); | |
| 39 media::mojom::AudioOutputStreamProviderRequest request = | |
| 40 mojo::MakeRequest(&stream_provider_); | |
| 41 | |
| 42 // Unretained is safe because |delegate| owns |this|. | |
| 43 stream_provider_.set_connection_error_handler(base::Bind( | |
| 44 &media::AudioOutputIPCDelegate::OnError, base::Unretained(delegate))); | |
| 45 return request; | |
| 46 } | |
| 47 | |
| 48 void MojoAudioOutputIPC::RequestDeviceAuthorization( | |
| 49 media::AudioOutputIPCDelegate* delegate, | |
| 50 int session_id, | |
| 51 const std::string& device_id, | |
| 52 const url::Origin& security_origin) { | |
| 53 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 54 DCHECK(delegate); | |
| 55 DCHECK(!stream_provider_.is_bound()); | |
| 56 DCHECK(!stream_.is_bound()); | |
| 57 auto* factory = AudioIPCFactory::get()->GetRemoteFactory(frame_id_); | |
| 58 if (!factory) { | |
| 59 LOG(ERROR) << "No factory is registered for " << frame_id_; | |
| 60 delegate->OnIPCClosed(); // deletes |this|. | |
| 61 return; | |
| 62 } | |
| 63 | |
| 64 // Unretained is safe because |delegate| owns |this|. | |
| 65 factory->RequestDeviceAuthorization( | |
| 66 MakeProviderRequest(delegate), session_id, device_id, | |
| 67 base::Bind(&MojoAudioOutputIPC::RecievedDeviceAuthorization, | |
| 68 weak_factory_.GetWeakPtr(), delegate)); | |
| 69 } | |
| 70 | |
| 71 void MojoAudioOutputIPC::RecievedDeviceAuthorization( | |
| 72 media::AudioOutputIPCDelegate* delegate, | |
| 73 media::OutputDeviceStatus status, | |
| 74 const media::AudioParameters& params, | |
| 75 const std::string& device_id) const { | |
| 76 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 77 delegate->OnDeviceAuthorized(status, params, device_id); | |
| 78 } | |
| 79 | |
| 80 void MojoAudioOutputIPC::CreateStream(media::AudioOutputIPCDelegate* delegate, | |
| 81 const media::AudioParameters& params) { | |
| 82 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 83 DCHECK(delegate); | |
| 84 DCHECK(!stream_.is_bound()); | |
| 85 if (!stream_provider_.is_bound()) { | |
|
o1ka
2017/04/20 10:35:59
M.b. would be more readable to have AuthorizationR
Max Morin
2017/05/05 13:10:59
Done.
| |
| 86 // No authorization requested yet. Request one for the default device. | |
| 87 // This also means we shouldn't callback to the delegate for the reply. | |
| 88 auto* factory = AudioIPCFactory::get()->GetRemoteFactory(frame_id_); | |
| 89 if (!factory) { | |
| 90 LOG(ERROR) << "No factory is registered for " << frame_id_; | |
| 91 delegate->OnIPCClosed(); // deletes |this|. | |
| 92 return; | |
| 93 } | |
| 94 | |
| 95 factory->RequestDeviceAuthorization( | |
|
o1ka
2017/04/20 10:35:59
WDYT about making a helper function and using it h
Max Morin
2017/05/05 13:10:59
Looks more complex (since it returns early if ther
| |
| 96 MakeProviderRequest(delegate), 0, | |
| 97 media::AudioDeviceDescription::kDefaultDeviceId, | |
| 98 base::Bind(&TrivialAuthorizedCallback)); | |
| 99 } | |
| 100 | |
| 101 // Since the callback won't fire if the binding is gone, unretained is safe. | |
|
o1ka
2017/04/20 10:35:59
Which callback and which binding? It's hard for an
Max Morin
2017/05/05 13:10:58
Done.
| |
| 102 stream_provider_->Acquire(mojo::MakeRequest(&stream_), params, | |
| 103 base::Bind(&MojoAudioOutputIPC::StreamCreated, | |
| 104 base::Unretained(this), delegate)); | |
| 105 | |
| 106 // Unretained is safe because |delegate| owns |this|. | |
| 107 stream_.set_connection_error_handler(base::Bind( | |
| 108 &media::AudioOutputIPCDelegate::OnError, base::Unretained(delegate))); | |
| 109 } | |
| 110 | |
| 111 void MojoAudioOutputIPC::StreamCreated( | |
| 112 media::AudioOutputIPCDelegate* delegate, | |
| 113 mojo::ScopedSharedBufferHandle shared_memory, | |
| 114 mojo::ScopedHandle socket) { | |
| 115 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 116 DCHECK(socket.is_valid()); | |
| 117 DCHECK(shared_memory.is_valid()); | |
| 118 | |
| 119 base::PlatformFile socket_handle; | |
| 120 mojo::UnwrapPlatformFile(std::move(socket), &socket_handle); | |
| 121 | |
| 122 base::SharedMemoryHandle memory_handle; | |
| 123 bool read_only = false; | |
| 124 size_t memory_length = 0; | |
| 125 auto result = mojo::UnwrapSharedMemoryHandle( | |
| 126 std::move(shared_memory), &memory_handle, &memory_length, &read_only); | |
| 127 DCHECK_EQ(result, MOJO_RESULT_OK); | |
| 128 DCHECK(!read_only); | |
| 129 | |
| 130 delegate->OnStreamCreated(memory_handle, socket_handle, memory_length); | |
| 131 } | |
| 132 | |
| 133 void MojoAudioOutputIPC::PlayStream() { | |
| 134 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 135 if (stream_.is_bound()) | |
| 136 stream_->Play(); | |
| 137 } | |
| 138 | |
| 139 void MojoAudioOutputIPC::PauseStream() { | |
| 140 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 141 if (stream_.is_bound()) | |
| 142 stream_->Pause(); | |
| 143 } | |
| 144 | |
| 145 void MojoAudioOutputIPC::CloseStream() { | |
| 146 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 147 stream_provider_.reset(); | |
| 148 stream_.reset(); | |
| 149 | |
| 150 // Make sure we don't send an authorization callback for this stream to the | |
|
o1ka
2017/04/20 10:36:00
We need a comment explaining why we are never stuc
Max Morin
2017/05/05 13:10:59
In this case, the AudioOutputDevice must take care
| |
| 151 // delegate. | |
| 152 weak_factory_.InvalidateWeakPtrs(); | |
| 153 } | |
| 154 | |
| 155 void MojoAudioOutputIPC::SetVolume(double volume) { | |
| 156 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 157 if (stream_.is_bound()) | |
| 158 stream_->SetVolume(volume); | |
| 159 } | |
| 160 | |
| 161 } // namespace content | |
| OLD | NEW |