1 // Copyright 2016 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 #ifndef CHROMECAST_MEDIA_BASE_MEDIA_RESOURCE_TRACKER_H_
6 #define CHROMECAST_MEDIA_BASE_MEDIA_RESOURCE_TRACKER_H_
7 
8 #include "base/callback.h"
9 #include "base/memory/ref_counted.h"
10 #include "base/sequenced_task_runner_helpers.h"
11 
12 namespace base {
13 class SingleThreadTaskRunner;
14 }
15 
16 namespace chromecast {
17 namespace media {
18 
19 // Keeps track of internal usage of resources that need access to underlying
20 // media playback hardware.  Some example users are the CMA pipeline, and the
21 // CDMs.  When it's time to release media resources, this class can be used
22 // to be wait and receive notification when all such users have stopped.
23 //
24 // Application should have one MediaResourceTracker instance and perform all
25 // CastMediaShlib::Initialize/Finalize through this interface.
26 // Threading model and lifetime:
27 // * This class interacts on both UI and media threads (task runners required
28 //   by ctor to perform thread hopping and checks). See function-level comments
29 //   on which thread to use for which operations.
30 // * The application should instantiate a single MediaResourceTracker instance.
31 //   Destruction should be performed by calling FinalizeAndDestroy from the UI
32 //   thread.
33 class MediaResourceTracker {
34  public:
35   // Helper class to manage media resource usage count.
36   // Create an instance of this class when a media resource is created.
37   // Delete the instance *after* the media resource is deleted.
38   // This class is not thread-safe. It must be created and deleted on
39   // |MediaResourceTracker::media_task_runner_|.
40   class ScopedUsage {
41    public:
42     ScopedUsage(MediaResourceTracker* tracker);
43     ~ScopedUsage();
44 
45    private:
46     MediaResourceTracker* tracker_;
47     DISALLOW_COPY_AND_ASSIGN(ScopedUsage);
48   };
49 
50   MediaResourceTracker(
51       scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
52       scoped_refptr<base::SingleThreadTaskRunner> media_task_runner);
53 
54   // Media resource acquire implementation. Must call on ui thread; runs
55   // CastMediaShlib::Initialize on media thread.  Safe to call even if media lib
56   // already initialized.
57   void InitializeMediaLib();
58 
59   // Media resource release implementation:
60   // (1) Waits for usage count to drop to zero
61   // (2) Calls CastMediaShlib::Finalize on media thread
62   // (3) Calls completion_cb
63   // Must be called on UI thread.  Only one Finalize request may be in flight
64   // at a time. |completion_cb| must not be null.
65   void FinalizeMediaLib(base::OnceClosure completion_cb);
66 
67   // Shutdown process:
68   // (1) Waits for usage count to drop to zero
69   // (2) Calls CastMediaShlib::Finalize on media thread
70   // (3) Deletes this object
71   // Must be called on UI thread. No further calls should be made on UI thread
72   // after this.
73   void FinalizeAndDestroy();
74 
75   // Users of media resource (e.g. CMA pipeline) should call these when they
76   // start and stop using media calls (must be called on media thread).
77   void IncrementUsageCount();
78   void DecrementUsageCount();
79 
80  private:
81   friend class base::DeleteHelper<MediaResourceTracker>;
82   friend class TestMediaResourceTracker;
83   virtual ~MediaResourceTracker();
84 
85   // Tasks posted to media thread
86   void CallInitializeOnMediaThread();
87   void MaybeCallFinalizeOnMediaThread(base::OnceClosure completion_cb);
88   void MaybeCallFinalizeOnMediaThreadAndDeleteSelf();
89   void CallFinalizeOnMediaThread();
90 
91   // Hooks for testing
92   virtual void DoInitializeMediaLib();
93   virtual void DoFinalizeMediaLib();
94 
95   // Accessed on media thread + ctor
96   size_t media_use_count_;
97   bool media_lib_initialized_;
98   base::OnceClosure finalize_completion_cb_;
99   bool delete_on_finalize_;
100 
101   scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_;
102   scoped_refptr<base::SingleThreadTaskRunner> media_task_runner_;
103 
104   DISALLOW_COPY_AND_ASSIGN(MediaResourceTracker);
105 };
106 
107 }  // namespace media
108 }  // namespace chromecast
109 
110 #endif  // CHROMECAST_MEDIA_BASE_MEDIA_RESOURCE_TRACKER_H_
111