Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(832)

Side by Side Diff: Source/modules/webaudio/AudioContext.cpp

Issue 625363004: Implement suspend/resume for AudioContext (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2010, Google Inc. All rights reserved. 2 * Copyright (C) 2010, Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions 5 * modification, are permitted provided that the following conditions
6 * are met: 6 * are met:
7 * 1. Redistributions of source code must retain the above copyright 7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer. 8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright 9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the 10 * notice, this list of conditions and the following disclaimer in the
(...skipping 12 matching lines...) Expand all
23 */ 23 */
24 24
25 #include "config.h" 25 #include "config.h"
26 26
27 #if ENABLE(WEB_AUDIO) 27 #if ENABLE(WEB_AUDIO)
28 28
29 #include "modules/webaudio/AudioContext.h" 29 #include "modules/webaudio/AudioContext.h"
30 30
31 #include "bindings/core/v8/ExceptionMessages.h" 31 #include "bindings/core/v8/ExceptionMessages.h"
32 #include "bindings/core/v8/ExceptionState.h" 32 #include "bindings/core/v8/ExceptionState.h"
33 #include "bindings/core/v8/ScriptState.h"
33 #include "core/dom/Document.h" 34 #include "core/dom/Document.h"
34 #include "core/dom/ExceptionCode.h" 35 #include "core/dom/ExceptionCode.h"
35 #include "core/html/HTMLMediaElement.h" 36 #include "core/html/HTMLMediaElement.h"
36 #include "core/inspector/ScriptCallStack.h" 37 #include "core/inspector/ScriptCallStack.h"
37 #include "platform/audio/FFTFrame.h" 38 #include "platform/audio/FFTFrame.h"
38 #include "platform/audio/HRTFPanner.h" 39 #include "platform/audio/HRTFPanner.h"
39 #include "modules/mediastream/MediaStream.h" 40 #include "modules/mediastream/MediaStream.h"
40 #include "modules/webaudio/AnalyserNode.h" 41 #include "modules/webaudio/AnalyserNode.h"
41 #include "modules/webaudio/AudioBuffer.h" 42 #include "modules/webaudio/AudioBuffer.h"
42 #include "modules/webaudio/AudioBufferCallback.h" 43 #include "modules/webaudio/AudioBufferCallback.h"
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
94 return audioContext; 95 return audioContext;
95 } 96 }
96 97
97 // Constructor for rendering to the audio hardware. 98 // Constructor for rendering to the audio hardware.
98 AudioContext::AudioContext(Document* document) 99 AudioContext::AudioContext(Document* document)
99 : ActiveDOMObject(document) 100 : ActiveDOMObject(document)
100 , m_isStopScheduled(false) 101 , m_isStopScheduled(false)
101 , m_isCleared(false) 102 , m_isCleared(false)
102 , m_isInitialized(false) 103 , m_isInitialized(false)
103 , m_destinationNode(nullptr) 104 , m_destinationNode(nullptr)
105 , m_isResolvingResumePromises(false)
104 , m_automaticPullNodesNeedUpdating(false) 106 , m_automaticPullNodesNeedUpdating(false)
105 , m_connectionCount(0) 107 , m_connectionCount(0)
106 , m_audioThread(0) 108 , m_audioThread(0)
107 , m_isOfflineContext(false) 109 , m_isOfflineContext(false)
108 { 110 {
109 m_destinationNode = DefaultAudioDestinationNode::create(this); 111 m_destinationNode = DefaultAudioDestinationNode::create(this);
110 112
111 initialize(); 113 initialize();
112 #if DEBUG_AUDIONODE_REFERENCES 114 #if DEBUG_AUDIONODE_REFERENCES
113 fprintf(stderr, "%p: AudioContext::AudioContext() #%u\n", this, AudioContext ::s_hardwareContextCount); 115 fprintf(stderr, "%p: AudioContext::AudioContext() #%u\n", this, AudioContext ::s_hardwareContextCount);
114 #endif 116 #endif
115 } 117 }
116 118
117 // Constructor for offline (non-realtime) rendering. 119 // Constructor for offline (non-realtime) rendering.
118 AudioContext::AudioContext(Document* document, unsigned numberOfChannels, size_t numberOfFrames, float sampleRate) 120 AudioContext::AudioContext(Document* document, unsigned numberOfChannels, size_t numberOfFrames, float sampleRate)
119 : ActiveDOMObject(document) 121 : ActiveDOMObject(document)
120 , m_isStopScheduled(false) 122 , m_isStopScheduled(false)
121 , m_isCleared(false) 123 , m_isCleared(false)
122 , m_isInitialized(false) 124 , m_isInitialized(false)
123 , m_destinationNode(nullptr) 125 , m_destinationNode(nullptr)
126 , m_isResolvingResumePromises(false)
124 , m_automaticPullNodesNeedUpdating(false) 127 , m_automaticPullNodesNeedUpdating(false)
125 , m_connectionCount(0) 128 , m_connectionCount(0)
126 , m_audioThread(0) 129 , m_audioThread(0)
127 , m_isOfflineContext(true) 130 , m_isOfflineContext(true)
128 { 131 {
129 // Create a new destination for offline rendering. 132 // Create a new destination for offline rendering.
130 m_renderTarget = AudioBuffer::create(numberOfChannels, numberOfFrames, sampl eRate); 133 m_renderTarget = AudioBuffer::create(numberOfChannels, numberOfFrames, sampl eRate);
131 if (m_renderTarget.get()) 134 if (m_renderTarget.get())
132 m_destinationNode = OfflineAudioDestinationNode::create(this, m_renderTa rget.get()); 135 m_destinationNode = OfflineAudioDestinationNode::create(this, m_renderTa rget.get());
133 136
(...skipping 390 matching lines...) Expand 10 before | Expand all | Expand 10 after
524 exceptionState.throwDOMException( 527 exceptionState.throwDOMException(
525 IndexSizeError, 528 IndexSizeError,
526 "length of imaginary array (" + String::number(imag->length()) 529 "length of imaginary array (" + String::number(imag->length())
527 + ") exceeds allowed maximum of 4096"); 530 + ") exceeds allowed maximum of 4096");
528 return 0; 531 return 0;
529 } 532 }
530 533
531 return PeriodicWave::create(sampleRate(), real, imag); 534 return PeriodicWave::create(sampleRate(), real, imag);
532 } 535 }
533 536
537 void AudioContext::suspendContext()
538 {
539 ASSERT(isMainThread());
540 AutoLocker locker(this);
541
542 if (m_destinationNode && !isOfflineContext())
543 m_destinationNode->stop();
544 }
545
546 ScriptPromise AudioContext::resumeContext(ScriptState* scriptState)
547 {
548 ASSERT(isMainThread());
549 AutoLocker locker(this);
550
551 RefPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::create(scrip tState);
552
553 ScriptPromise promise = resolver->promise();
554
555 if (isOfflineContext()) {
556 // For offline context, just resolve the promise now.
557 resolver->resolve();
558 } else {
559 // Restart the destination node to pull on the audio graph.
560 if (m_destinationNode)
561 m_destinationNode->startRendering();
562
563 // Save the promise which will get resolved when the destination node st arts pulling on the
564 // graph again.
565 m_resumePromises.append(resolver);
566 }
567
568 return promise;
569 }
570
534 void AudioContext::notifyNodeFinishedProcessing(AudioNode* node) 571 void AudioContext::notifyNodeFinishedProcessing(AudioNode* node)
535 { 572 {
536 ASSERT(isAudioThread()); 573 ASSERT(isAudioThread());
537 m_finishedNodes.append(node); 574 m_finishedNodes.append(node);
538 } 575 }
539 576
540 void AudioContext::derefFinishedSourceNodes() 577 void AudioContext::derefFinishedSourceNodes()
541 { 578 {
542 ASSERT(isGraphOwner()); 579 ASSERT(isGraphOwner());
543 ASSERT(isAudioThread()); 580 ASSERT(isAudioThread());
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
630 // It's OK if the tryLock() fails, we'll just take slightly longer to pick u p the changes. 667 // It's OK if the tryLock() fails, we'll just take slightly longer to pick u p the changes.
631 if (tryLock()) { 668 if (tryLock()) {
632 // Update the channel count mode. 669 // Update the channel count mode.
633 updateChangedChannelCountMode(); 670 updateChangedChannelCountMode();
634 671
635 // Fixup the state of any dirty AudioSummingJunctions and AudioNodeOutpu ts. 672 // Fixup the state of any dirty AudioSummingJunctions and AudioNodeOutpu ts.
636 handleDirtyAudioSummingJunctions(); 673 handleDirtyAudioSummingJunctions();
637 handleDirtyAudioNodeOutputs(); 674 handleDirtyAudioNodeOutputs();
638 675
639 updateAutomaticPullNodes(); 676 updateAutomaticPullNodes();
677 resolvePromisesForResume();
678
640 unlock(); 679 unlock();
641 } 680 }
642 } 681 }
643 682
644 void AudioContext::handlePostRenderTasks() 683 void AudioContext::handlePostRenderTasks()
645 { 684 {
646 ASSERT(isAudioThread()); 685 ASSERT(isAudioThread());
647 686
648 // Must use a tryLock() here too. Don't worry, the lock will very rarely be contended and this method is called frequently. 687 // Must use a tryLock() here too. Don't worry, the lock will very rarely be contended and this method is called frequently.
649 // The worst that can happen is that there will be some nodes which will tak e slightly longer than usual to be deleted or removed 688 // The worst that can happen is that there will be some nodes which will tak e slightly longer than usual to be deleted or removed
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
795 } 834 }
796 835
797 void AudioContext::processAutomaticPullNodes(size_t framesToProcess) 836 void AudioContext::processAutomaticPullNodes(size_t framesToProcess)
798 { 837 {
799 ASSERT(isAudioThread()); 838 ASSERT(isAudioThread());
800 839
801 for (unsigned i = 0; i < m_renderingAutomaticPullNodes.size(); ++i) 840 for (unsigned i = 0; i < m_renderingAutomaticPullNodes.size(); ++i)
802 m_renderingAutomaticPullNodes[i]->processIfNecessary(framesToProcess); 841 m_renderingAutomaticPullNodes[i]->processIfNecessary(framesToProcess);
803 } 842 }
804 843
844 void AudioContext::resolvePromisesForResumeOnMainThread()
845 {
846 ASSERT(isMainThread);
yhirano 2014/10/08 01:12:14 Please acquire the lock.
yhirano 2014/10/08 01:15:54 Oh, I found AudioContext::lock is not callable fro
Raymond Toy 2014/10/14 17:16:59 Done.
847
848 for (unsigned k = 0; k < m_resumePromises.size(); ++k)
849 m_resumePromises[k]->resolve();
850
851 m_resumePromises.clear();
852 m_isResolvingResumePromises = false;
853 }
854
855 void AudioContext::resolvePromisesForResume()
856 {
857 ASSERT(isAudioThread());
858
yhirano 2014/10/08 01:12:14 Please add a comment that the lock is already acqu
Raymond Toy 2014/10/14 17:16:59 Done.
859 // Resolve any pending promises created by resume(). Only do this we if have n't already started
860 // resolving these promises. This gets called very often and it takes some t ime use to resolve
861 // the promises in the main thread.
862 if (!m_isResolvingResumePromises && m_resumePromises.size() > 0) {
863 m_isResolvingResumePromises = true;
864 callOnMainThread(bind(&AudioContext::resolvePromisesForResumeOnMainThrea d, this));
865 }
866 }
867
805 const AtomicString& AudioContext::interfaceName() const 868 const AtomicString& AudioContext::interfaceName() const
806 { 869 {
807 return EventTargetNames::AudioContext; 870 return EventTargetNames::AudioContext;
808 } 871 }
809 872
810 ExecutionContext* AudioContext::executionContext() const 873 ExecutionContext* AudioContext::executionContext() const
811 { 874 {
812 return m_isStopScheduled ? 0 : ActiveDOMObject::executionContext(); 875 return m_isStopScheduled ? 0 : ActiveDOMObject::executionContext();
813 } 876 }
814 877
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
867 930
868 for (HashSet<AudioNode*>::iterator k = m_deferredCountModeChange.begin(); k != m_deferredCountModeChange.end(); ++k) 931 for (HashSet<AudioNode*>::iterator k = m_deferredCountModeChange.begin(); k != m_deferredCountModeChange.end(); ++k)
869 (*k)->updateChannelCountMode(); 932 (*k)->updateChannelCountMode();
870 933
871 m_deferredCountModeChange.clear(); 934 m_deferredCountModeChange.clear();
872 } 935 }
873 936
874 } // namespace blink 937 } // namespace blink
875 938
876 #endif // ENABLE(WEB_AUDIO) 939 #endif // ENABLE(WEB_AUDIO)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698