| OLD | NEW |
| 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 675 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 686 | 686 |
| 687 // Find AudioBufferSourceNodes to see if we can stop playing them. | 687 // Find AudioBufferSourceNodes to see if we can stop playing them. |
| 688 for (AudioNode* node : m_activeSourceNodes) { | 688 for (AudioNode* node : m_activeSourceNodes) { |
| 689 if (node->handler().nodeType() == AudioHandler::NodeTypeAudioBufferSourc
e) { | 689 if (node->handler().nodeType() == AudioHandler::NodeTypeAudioBufferSourc
e) { |
| 690 AudioBufferSourceNode* sourceNode = static_cast<AudioBufferSourceNod
e*>(node); | 690 AudioBufferSourceNode* sourceNode = static_cast<AudioBufferSourceNod
e*>(node); |
| 691 sourceNode->audioBufferSourceHandler().handleStoppableSourceNode(); | 691 sourceNode->audioBufferSourceHandler().handleStoppableSourceNode(); |
| 692 } | 692 } |
| 693 } | 693 } |
| 694 } | 694 } |
| 695 | 695 |
| 696 void AbstractAudioContext::performPostRenderTasks() |
| 697 { |
| 698 // Take care of AudioNode tasks where the tryLock() failed previously. |
| 699 deferredTaskHandler().breakConnections(); |
| 700 |
| 701 // Dynamically clean up nodes which are no longer needed. |
| 702 releaseFinishedSourceNodes(); |
| 703 |
| 704 deferredTaskHandler().handleDeferredTasks(); |
| 705 deferredTaskHandler().requestToDeleteHandlersOnMainThread(); |
| 706 } |
| 707 |
| 696 void AbstractAudioContext::handlePreRenderTasks() | 708 void AbstractAudioContext::handlePreRenderTasks() |
| 697 { | 709 { |
| 698 ASSERT(isAudioThread()); | 710 ASSERT(isAudioThread()); |
| 699 | 711 |
| 712 // For the precise offline audio rendering, we need these tasks to be |
| 713 // performed every render quantum. Thus, we wait for the graph lock (rather |
| 714 // than tryLock()) so we can run the pre-render tasks without deferring |
| 715 // them. |
| 716 // |
| 717 // Also note that we do not need to run resolvePromiseForResume() here |
| 718 // because the offline audio context keeps its own suspend/resume promise |
| 719 // resolvers separately. |
| 720 if (!hasRealtimeConstraint()) { |
| 721 deferredTaskHandler().offlineContextLock(); |
| 722 deferredTaskHandler().handleDeferredTasks(); |
| 723 handleStoppableSourceNodes(); |
| 724 unlock(); |
| 725 return; |
| 726 } |
| 727 |
| 700 // At the beginning of every render quantum, try to update the internal rend
ering graph state (from main thread changes). | 728 // At the beginning of every render quantum, try to update the internal rend
ering graph state (from main thread changes). |
| 701 // It's OK if the tryLock() fails, we'll just take slightly longer to pick u
p the changes. | 729 // It's OK if the tryLock() fails, we'll just take slightly longer to pick u
p the changes. |
| 702 if (tryLock()) { | 730 if (tryLock()) { |
| 703 deferredTaskHandler().handleDeferredTasks(); | 731 deferredTaskHandler().handleDeferredTasks(); |
| 704 | 732 |
| 705 resolvePromisesForResume(); | 733 resolvePromisesForResume(); |
| 706 | 734 |
| 707 // Check to see if source nodes can be stopped because the end time has
passed. | 735 // Check to see if source nodes can be stopped because the end time has
passed. |
| 708 handleStoppableSourceNodes(); | 736 handleStoppableSourceNodes(); |
| 709 | 737 |
| 710 unlock(); | 738 unlock(); |
| 711 } | 739 } |
| 712 } | 740 } |
| 713 | 741 |
| 714 void AbstractAudioContext::handlePostRenderTasks() | 742 void AbstractAudioContext::handlePostRenderTasks() |
| 715 { | 743 { |
| 716 ASSERT(isAudioThread()); | 744 ASSERT(isAudioThread()); |
| 717 | 745 |
| 746 // Same as |handlePreRenderTasks()|. We force to perform the post-render |
| 747 // tasks for the offline rendering. |
| 748 if (!hasRealtimeConstraint()) { |
| 749 deferredTaskHandler().offlineContextLock(); |
| 750 performPostRenderTasks(); |
| 751 unlock(); |
| 752 return; |
| 753 } |
| 754 |
| 718 // Must use a tryLock() here too. Don't worry, the lock will very rarely be
contended and this method is called frequently. | 755 // Must use a tryLock() here too. Don't worry, the lock will very rarely be
contended and this method is called frequently. |
| 719 // 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 | 756 // 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 |
| 720 // from the render graph (in which case they'll render silence). | 757 // from the render graph (in which case they'll render silence). |
| 721 if (tryLock()) { | 758 if (tryLock()) { |
| 722 // Take care of AudioNode tasks where the tryLock() failed previously. | 759 performPostRenderTasks(); |
| 723 deferredTaskHandler().breakConnections(); | |
| 724 | |
| 725 // Dynamically clean up nodes which are no longer needed. | |
| 726 releaseFinishedSourceNodes(); | |
| 727 | |
| 728 deferredTaskHandler().handleDeferredTasks(); | |
| 729 deferredTaskHandler().requestToDeleteHandlersOnMainThread(); | |
| 730 | |
| 731 unlock(); | 760 unlock(); |
| 732 } | 761 } |
| 733 } | 762 } |
| 734 | 763 |
| 735 void AbstractAudioContext::resolvePromisesForResumeOnMainThread() | 764 void AbstractAudioContext::resolvePromisesForResumeOnMainThread() |
| 736 { | 765 { |
| 737 ASSERT(isMainThread()); | 766 ASSERT(isMainThread()); |
| 738 AutoLocker locker(this); | 767 AutoLocker locker(this); |
| 739 | 768 |
| 740 for (auto& resolver : m_resumeResolvers) { | 769 for (auto& resolver : m_resumeResolvers) { |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 793 // This is called for both online and offline contexts. | 822 // This is called for both online and offline contexts. |
| 794 ASSERT(isMainThread()); | 823 ASSERT(isMainThread()); |
| 795 ASSERT(m_destinationNode); | 824 ASSERT(m_destinationNode); |
| 796 | 825 |
| 797 if (m_contextState == Suspended) { | 826 if (m_contextState == Suspended) { |
| 798 destination()->audioDestinationHandler().startRendering(); | 827 destination()->audioDestinationHandler().startRendering(); |
| 799 setContextState(Running); | 828 setContextState(Running); |
| 800 } | 829 } |
| 801 } | 830 } |
| 802 | 831 |
| 803 void AbstractAudioContext::fireCompletionEvent() | |
| 804 { | |
| 805 ASSERT(isMainThread()); | |
| 806 if (!isMainThread()) | |
| 807 return; | |
| 808 | |
| 809 AudioBuffer* renderedBuffer = m_renderTarget.get(); | |
| 810 | |
| 811 // For an offline context, we set the state to closed here so that the oncom
plete handler sees | |
| 812 // that the context has been closed. | |
| 813 setContextState(Closed); | |
| 814 | |
| 815 ASSERT(renderedBuffer); | |
| 816 if (!renderedBuffer) | |
| 817 return; | |
| 818 | |
| 819 // Avoid firing the event if the document has already gone away. | |
| 820 if (executionContext()) { | |
| 821 // Call the offline rendering completion event listener and resolve the
promise too. | |
| 822 dispatchEvent(OfflineAudioCompletionEvent::create(renderedBuffer)); | |
| 823 m_offlineResolver->resolve(renderedBuffer); | |
| 824 } | |
| 825 } | |
| 826 | |
| 827 DEFINE_TRACE(AbstractAudioContext) | 832 DEFINE_TRACE(AbstractAudioContext) |
| 828 { | 833 { |
| 829 visitor->trace(m_offlineResolver); | |
| 830 visitor->trace(m_renderTarget); | 834 visitor->trace(m_renderTarget); |
| 831 visitor->trace(m_destinationNode); | 835 visitor->trace(m_destinationNode); |
| 832 visitor->trace(m_listener); | 836 visitor->trace(m_listener); |
| 833 // trace() can be called in AbstractAudioContext constructor, and | 837 // trace() can be called in AbstractAudioContext constructor, and |
| 834 // m_contextGraphMutex might be unavailable. | 838 // m_contextGraphMutex might be unavailable. |
| 835 if (m_didInitializeContextGraphMutex) { | 839 if (m_didInitializeContextGraphMutex) { |
| 836 AutoLocker lock(this); | 840 AutoLocker lock(this); |
| 837 visitor->trace(m_activeSourceNodes); | 841 visitor->trace(m_activeSourceNodes); |
| 838 } else { | 842 } else { |
| 839 visitor->trace(m_activeSourceNodes); | 843 visitor->trace(m_activeSourceNodes); |
| 840 } | 844 } |
| 841 visitor->trace(m_resumeResolvers); | 845 visitor->trace(m_resumeResolvers); |
| 842 RefCountedGarbageCollectedEventTargetWithInlineData<AbstractAudioContext>::t
race(visitor); | 846 RefCountedGarbageCollectedEventTargetWithInlineData<AbstractAudioContext>::t
race(visitor); |
| 843 ActiveDOMObject::trace(visitor); | 847 ActiveDOMObject::trace(visitor); |
| 844 } | 848 } |
| 845 | 849 |
| 846 SecurityOrigin* AbstractAudioContext::securityOrigin() const | 850 SecurityOrigin* AbstractAudioContext::securityOrigin() const |
| 847 { | 851 { |
| 848 if (executionContext()) | 852 if (executionContext()) |
| 849 return executionContext()->securityOrigin(); | 853 return executionContext()->securityOrigin(); |
| 850 | 854 |
| 851 return nullptr; | 855 return nullptr; |
| 852 } | 856 } |
| 853 | 857 |
| 854 } // namespace blink | 858 } // namespace blink |
| 855 | 859 |
| 856 #endif // ENABLE(WEB_AUDIO) | 860 #endif // ENABLE(WEB_AUDIO) |
| OLD | NEW |