| OLD | NEW | 
|    1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |    1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 
|    2 // Use of this source code is governed by a BSD-style license that can be |    2 // Use of this source code is governed by a BSD-style license that can be | 
|    3 // found in the LICENSE file. |    3 // found in the LICENSE file. | 
|    4  |    4  | 
|    5 #include "media/audio/audio_output_device.h" |    5 #include "media/audio/audio_output_device.h" | 
|    6  |    6  | 
|    7 #include <stddef.h> |    7 #include <stddef.h> | 
|    8 #include <stdint.h> |    8 #include <stdint.h> | 
|    9  |    9  | 
|   10 #include <cmath> |   10 #include <cmath> | 
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   84 } |   84 } | 
|   85  |   85  | 
|   86 void AudioOutputDevice::Initialize(const AudioParameters& params, |   86 void AudioOutputDevice::Initialize(const AudioParameters& params, | 
|   87                                    RenderCallback* callback) { |   87                                    RenderCallback* callback) { | 
|   88   DCHECK(!callback_) << "Calling Initialize() twice?"; |   88   DCHECK(!callback_) << "Calling Initialize() twice?"; | 
|   89   DCHECK(params.IsValid()); |   89   DCHECK(params.IsValid()); | 
|   90   audio_parameters_ = params; |   90   audio_parameters_ = params; | 
|   91   callback_ = callback; |   91   callback_ = callback; | 
|   92 } |   92 } | 
|   93  |   93  | 
|   94 AudioOutputDevice::~AudioOutputDevice() { |   94 AudioOutputDevice::~AudioOutputDevice() {} | 
|   95   // The current design requires that the user calls Stop() before deleting |  | 
|   96   // this class. |  | 
|   97   DCHECK(audio_thread_.IsStopped()); |  | 
|   98 } |  | 
|   99  |   95  | 
|  100 void AudioOutputDevice::RequestDeviceAuthorization() { |   96 void AudioOutputDevice::RequestDeviceAuthorization() { | 
|  101   task_runner()->PostTask( |   97   task_runner()->PostTask( | 
|  102       FROM_HERE, |   98       FROM_HERE, | 
|  103       base::Bind(&AudioOutputDevice::RequestDeviceAuthorizationOnIOThread, |   99       base::Bind(&AudioOutputDevice::RequestDeviceAuthorizationOnIOThread, | 
|  104                  this)); |  100                  this)); | 
|  105 } |  101 } | 
|  106  |  102  | 
|  107 void AudioOutputDevice::Start() { |  103 void AudioOutputDevice::Start() { | 
|  108   DCHECK(callback_) << "Initialize hasn't been called"; |  104   DCHECK(callback_) << "Initialize hasn't been called"; | 
|  109   task_runner()->PostTask(FROM_HERE, |  105   task_runner()->PostTask(FROM_HERE, | 
|  110       base::Bind(&AudioOutputDevice::CreateStreamOnIOThread, this, |  106       base::Bind(&AudioOutputDevice::CreateStreamOnIOThread, this, | 
|  111                  audio_parameters_)); |  107                  audio_parameters_)); | 
|  112 } |  108 } | 
|  113  |  109  | 
|  114 void AudioOutputDevice::Stop() { |  110 void AudioOutputDevice::Stop() { | 
|  115   { |  111   { | 
|  116     base::AutoLock auto_lock(audio_thread_lock_); |  112     base::AutoLock auto_lock(audio_thread_lock_); | 
|  117     audio_thread_.Stop(base::MessageLoop::current()); |  113     audio_thread_.reset(); | 
|  118     stopping_hack_ = true; |  114     stopping_hack_ = true; | 
|  119   } |  115   } | 
|  120  |  116  | 
|  121   task_runner()->PostTask(FROM_HERE, |  117   task_runner()->PostTask(FROM_HERE, | 
|  122       base::Bind(&AudioOutputDevice::ShutDownOnIOThread, this)); |  118       base::Bind(&AudioOutputDevice::ShutDownOnIOThread, this)); | 
|  123 } |  119 } | 
|  124  |  120  | 
|  125 void AudioOutputDevice::Play() { |  121 void AudioOutputDevice::Play() { | 
|  126   task_runner()->PostTask(FROM_HERE, |  122   task_runner()->PostTask(FROM_HERE, | 
|  127       base::Bind(&AudioOutputDevice::PlayOnIOThread, this)); |  123       base::Bind(&AudioOutputDevice::PlayOnIOThread, this)); | 
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  249   // We can run into an issue where ShutDownOnIOThread is called right after |  245   // We can run into an issue where ShutDownOnIOThread is called right after | 
|  250   // OnStreamCreated is called in cases where Start/Stop are called before we |  246   // OnStreamCreated is called in cases where Start/Stop are called before we | 
|  251   // get the OnStreamCreated callback.  To handle that corner case, we call |  247   // get the OnStreamCreated callback.  To handle that corner case, we call | 
|  252   // Stop(). In most cases, the thread will already be stopped. |  248   // Stop(). In most cases, the thread will already be stopped. | 
|  253   // |  249   // | 
|  254   // Another situation is when the IO thread goes away before Stop() is called |  250   // Another situation is when the IO thread goes away before Stop() is called | 
|  255   // in which case, we cannot use the message loop to close the thread handle |  251   // in which case, we cannot use the message loop to close the thread handle | 
|  256   // and can't rely on the main thread existing either. |  252   // and can't rely on the main thread existing either. | 
|  257   base::AutoLock auto_lock_(audio_thread_lock_); |  253   base::AutoLock auto_lock_(audio_thread_lock_); | 
|  258   base::ThreadRestrictions::ScopedAllowIO allow_io; |  254   base::ThreadRestrictions::ScopedAllowIO allow_io; | 
|  259   audio_thread_.Stop(NULL); |  255   audio_thread_.reset(); | 
|  260   audio_callback_.reset(); |  256   audio_callback_.reset(); | 
|  261   stopping_hack_ = false; |  257   stopping_hack_ = false; | 
|  262 } |  258 } | 
|  263  |  259  | 
|  264 void AudioOutputDevice::SetVolumeOnIOThread(double volume) { |  260 void AudioOutputDevice::SetVolumeOnIOThread(double volume) { | 
|  265   DCHECK(task_runner()->BelongsToCurrentThread()); |  261   DCHECK(task_runner()->BelongsToCurrentThread()); | 
|  266   if (state_ >= CREATING_STREAM) |  262   if (state_ >= CREATING_STREAM) | 
|  267     ipc_->SetVolume(volume); |  263     ipc_->SetVolume(volume); | 
|  268 } |  264 } | 
|  269  |  265  | 
| (...skipping 11 matching lines...) Expand all  Loading... | 
|  281     case AUDIO_OUTPUT_IPC_DELEGATE_STATE_PAUSED: |  277     case AUDIO_OUTPUT_IPC_DELEGATE_STATE_PAUSED: | 
|  282       break; |  278       break; | 
|  283     case AUDIO_OUTPUT_IPC_DELEGATE_STATE_ERROR: |  279     case AUDIO_OUTPUT_IPC_DELEGATE_STATE_ERROR: | 
|  284       DLOG(WARNING) << "AudioOutputDevice::OnStateChanged(ERROR)"; |  280       DLOG(WARNING) << "AudioOutputDevice::OnStateChanged(ERROR)"; | 
|  285       // Don't dereference the callback object if the audio thread |  281       // Don't dereference the callback object if the audio thread | 
|  286       // is stopped or stopping.  That could mean that the callback |  282       // is stopped or stopping.  That could mean that the callback | 
|  287       // object has been deleted. |  283       // object has been deleted. | 
|  288       // TODO(tommi): Add an explicit contract for clearing the callback |  284       // TODO(tommi): Add an explicit contract for clearing the callback | 
|  289       // object.  Possibly require calling Initialize again or provide |  285       // object.  Possibly require calling Initialize again or provide | 
|  290       // a callback object via Start() and clear it in Stop(). |  286       // a callback object via Start() and clear it in Stop(). | 
|  291       if (!audio_thread_.IsStopped()) |  287       { | 
|  292         callback_->OnRenderError(); |  288         base::AutoLock auto_lock_(audio_thread_lock_); | 
 |  289         if (audio_thread_) | 
 |  290           callback_->OnRenderError(); | 
 |  291       } | 
|  293       break; |  292       break; | 
|  294     default: |  293     default: | 
|  295       NOTREACHED(); |  294       NOTREACHED(); | 
|  296       break; |  295       break; | 
|  297   } |  296   } | 
|  298 } |  297 } | 
|  299  |  298  | 
|  300 void AudioOutputDevice::OnDeviceAuthorized( |  299 void AudioOutputDevice::OnDeviceAuthorized( | 
|  301     OutputDeviceStatus device_status, |  300     OutputDeviceStatus device_status, | 
|  302     const media::AudioParameters& output_params, |  301     const media::AudioParameters& output_params, | 
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  382   // freed memory is a mess. AudioRendererSink should be non-refcounted so that |  381   // freed memory is a mess. AudioRendererSink should be non-refcounted so that | 
|  383   // owners (WebRtcAudioDeviceImpl, AudioRendererImpl, etc...) can Stop() and |  382   // owners (WebRtcAudioDeviceImpl, AudioRendererImpl, etc...) can Stop() and | 
|  384   // delete as they see fit. AudioOutputDevice should internally use WeakPtr |  383   // delete as they see fit. AudioOutputDevice should internally use WeakPtr | 
|  385   // to handle teardown and thread hopping. See http://crbug.com/151051 for |  384   // to handle teardown and thread hopping. See http://crbug.com/151051 for | 
|  386   // details. |  385   // details. | 
|  387   { |  386   { | 
|  388     base::AutoLock auto_lock(audio_thread_lock_); |  387     base::AutoLock auto_lock(audio_thread_lock_); | 
|  389     if (stopping_hack_) |  388     if (stopping_hack_) | 
|  390       return; |  389       return; | 
|  391  |  390  | 
|  392     DCHECK(audio_thread_.IsStopped()); |  391     DCHECK(!audio_thread_); | 
 |  392     DCHECK(!audio_callback_); | 
 |  393  | 
|  393     audio_callback_.reset(new AudioOutputDevice::AudioThreadCallback( |  394     audio_callback_.reset(new AudioOutputDevice::AudioThreadCallback( | 
|  394         audio_parameters_, handle, length, callback_)); |  395         audio_parameters_, handle, length, callback_)); | 
|  395     audio_thread_.Start(audio_callback_.get(), socket_handle, |  396     audio_thread_.reset(new AudioDeviceThread( | 
|  396                         "AudioOutputDevice", true); |  397         audio_callback_.get(), socket_handle, "AudioOutputDevice")); | 
|  397     state_ = PAUSED; |  398     state_ = PAUSED; | 
|  398  |  399  | 
|  399     // We handle the case where Play() and/or Pause() may have been called |  400     // We handle the case where Play() and/or Pause() may have been called | 
|  400     // multiple times before OnStreamCreated() gets called. |  401     // multiple times before OnStreamCreated() gets called. | 
|  401     if (play_on_start_) |  402     if (play_on_start_) | 
|  402       PlayOnIOThread(); |  403       PlayOnIOThread(); | 
|  403   } |  404   } | 
|  404 } |  405 } | 
|  405  |  406  | 
|  406 void AudioOutputDevice::OnIPCClosed() { |  407 void AudioOutputDevice::OnIPCClosed() { | 
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  471  |  472  | 
|  472   // Update the audio-delay measurement, inform about the number of skipped |  473   // Update the audio-delay measurement, inform about the number of skipped | 
|  473   // frames, and ask client to render audio.  Since |output_bus_| is wrapping |  474   // frames, and ask client to render audio.  Since |output_bus_| is wrapping | 
|  474   // the shared memory the Render() call is writing directly into the shared |  475   // the shared memory the Render() call is writing directly into the shared | 
|  475   // memory. |  476   // memory. | 
|  476   render_callback_->Render(output_bus_.get(), std::round(frames_delayed), |  477   render_callback_->Render(output_bus_.get(), std::round(frames_delayed), | 
|  477                            frames_skipped); |  478                            frames_skipped); | 
|  478 } |  479 } | 
|  479  |  480  | 
|  480 }  // namespace media |  481 }  // namespace media | 
| OLD | NEW |