| // Copyright 2016 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef CHROMECAST_MEDIA_BASE_MEDIA_RESOURCE_TRACKER_H_ |
| #define CHROMECAST_MEDIA_BASE_MEDIA_RESOURCE_TRACKER_H_ |
| |
| #include "base/callback.h" |
| #include "base/memory/ref_counted.h" |
| #include "base/sequenced_task_runner_helpers.h" |
| |
| namespace base { |
| class SingleThreadTaskRunner; |
| } |
| |
| namespace chromecast { |
| namespace media { |
| |
| // Keeps track of internal usage of resources that need access to underlying |
| // media playback hardware. Some example users are the CMA pipeline, and the |
| // CDMs. When it's time to release media resources, this class can be used |
| // to be wait and receive notification when all such users have stopped. |
| // |
| // Application should have one MediaResourceTracker instance and perform all |
| // CastMediaShlib::Initialize/Finalize through this interface. |
| // Threading model and lifetime: |
| // * This class interacts on both UI and media threads (task runners required |
| // by ctor to perform thread hopping and checks). See function-level comments |
| // on which thread to use for which operations. |
| // * All interaction with delegate is performed on UI thread. |
| // * The application should instantiate a single MediaResourceTracker instance. |
| // Destruction should be performed by calling FinalizeAndDestroy from the UI |
| // thread. |
| class MediaResourceTracker { |
| public: |
| class Delegate { |
| public: |
| // Called on UI thread when media usage starts (i.e. count steps 0->1). |
| // Does not mean Initialize has happened. |
| virtual void OnStartUsingMedia() = 0; |
| |
| // Called on UI thread when media usage stops (i.e. count steps 1->0). |
| // Does not mean Finalize has happened. |
| virtual void OnStopUsingMedia() = 0; |
| |
| protected: |
| virtual ~Delegate() {} |
| }; |
| |
| MediaResourceTracker( |
| const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner, |
| const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner); |
| |
| // Sets the delegate to receive start/stop media usage notifications. Must |
| // call on UI thread. Set to nullptr to clear existing delegate. |
| void SetDelegate(Delegate* delegate); |
| |
| // Media resource acquire implementation. Must call on ui thread; runs |
| // CastMediaShlib::Initialize on media thread. Safe to call even if media lib |
| // already initialized. |
| void InitializeMediaLib(); |
| |
| // Media resource release implementation: |
| // (1) Waits for usage count to drop to zero |
| // (2) Calls CastMediaShlib::Finalize on media thread |
| // (3) Calls completion_cb |
| // Must be called on UI thread. Only one Finalize request may be in flight |
| // at a time. |completion_cb| must not be null. |
| void FinalizeMediaLib(const base::Closure& completion_cb); |
| |
| // Shutdown process: |
| // (1) Waits for usage count to drop to zero |
| // (2) Calls CastMediaShlib::Finalize on media thread |
| // (3) Deletes this object |
| // Must be called on UI thread. No further calls should be made on UI thread |
| // after this. Delegate is implicitly cleared. |
| void FinalizeAndDestroy(); |
| |
| // Users of media resource (e.g. CMA pipeline) should call these when they |
| // start and stop using media calls (must be called on media thread). |
| void IncrementUsageCount(); |
| void DecrementUsageCount(); |
| |
| private: |
| friend class base::DeleteHelper<MediaResourceTracker>; |
| friend class TestMediaResourceTracker; |
| virtual ~MediaResourceTracker(); |
| |
| // Tasks posted to UI thread |
| void CallDelegateStartOnUiThread(); |
| void CallDelegateStopOnUiThread(); |
| |
| // Tasks posted to media thread |
| void CallInitializeOnMediaThread(); |
| void MaybeCallFinalizeOnMediaThread(const base::Closure& completion_cb); |
| void MaybeCallFinalizeOnMediaThreadAndDeleteSelf(); |
| void CallFinalizeOnMediaThread(); |
| |
| // Hooks for testing |
| virtual void DoInitializeMediaLib(); |
| virtual void DoFinalizeMediaLib(); |
| |
| // Accessed on UI thread |
| Delegate* delegate_; |
| |
| // Accessed on media thread + ctor |
| size_t media_use_count_; |
| bool media_lib_initialized_; |
| base::Closure finalize_completion_cb_; |
| bool delete_on_finalize_; |
| |
| scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_; |
| scoped_refptr<base::SingleThreadTaskRunner> media_task_runner_; |
| |
| DISALLOW_COPY_AND_ASSIGN(MediaResourceTracker); |
| }; |
| |
| } // namespace media |
| } // namespace chromecast |
| |
| #endif // CHROMECAST_MEDIA_BASE_MEDIA_RESOURCE_TRACKER_H_ |