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

Side by Side Diff: media/gpu/avda_codec_allocator.h

Issue 2508053002: media: Do a TimedWait() for video surface teardown in AVDA (Closed)
Patch Set: Created 4 years, 1 month 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
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 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 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 #ifndef MEDIA_GPU_AVDA_CODEC_ALLOCATOR_H_
6 #define MEDIA_GPU_AVDA_CODEC_ALLOCATOR_H_
7
5 #include <stddef.h> 8 #include <stddef.h>
6 9
7 #include <memory> 10 #include <memory>
8 11
9 #include "base/android/build_info.h" 12 #include "base/android/build_info.h"
10 #include "base/bind.h" 13 #include "base/bind.h"
11 #include "base/lazy_instance.h" 14 #include "base/lazy_instance.h"
12 #include "base/logging.h" 15 #include "base/logging.h"
16 #include "base/synchronization/waitable_event.h"
13 #include "base/sys_info.h" 17 #include "base/sys_info.h"
14 #include "base/threading/thread.h" 18 #include "base/threading/thread.h"
15 #include "base/threading/thread_checker.h" 19 #include "base/threading/thread_checker.h"
16 #include "base/time/tick_clock.h" 20 #include "base/time/tick_clock.h"
17 #include "base/trace_event/trace_event.h" 21 #include "base/trace_event/trace_event.h"
22 #include "media/base/android/media_drm_bridge_cdm_context.h"
23 #include "media/base/android/sdk_media_codec_bridge.h"
18 #include "media/base/media.h" 24 #include "media/base/media.h"
25 #include "media/base/surface_manager.h"
26 #include "media/base/video_codecs.h"
19 #include "media/gpu/media_gpu_export.h" 27 #include "media/gpu/media_gpu_export.h"
28 #include "ui/gfx/geometry/size.h"
29 #include "ui/gl/android/scoped_java_surface.h"
20 30
21 namespace media { 31 namespace media {
22 32
23 class AndroidVideoDecodeAccelerator; 33 class AndroidVideoDecodeAccelerator;
34 class VideoCodecBridge;
35
36 // For TaskRunnerFor. These are used as vector indices, so please update
37 // AVDACodecAllocator's constructor if you add / change them.
38 enum TaskType {
39 // Task for an autodetected MediaCodec instance.
40 AUTO_CODEC = 0,
41
42 // Task for a software-codec-required MediaCodec.
43 SW_CODEC = 1,
44
45 // Special value to indicate "none". This is not used as an array index. It
46 // must, however, be positive to keep the enum unsigned.
47 FAILED_CODEC = 99,
48 };
49
50 // Configuration info for MediaCodec.
51 // This is used to shuttle configuration info between threads without needing
52 // to worry about the lifetime of the AVDA instance.
53 class CodecConfig : public base::RefCountedThreadSafe<CodecConfig> {
54 public:
55 CodecConfig();
56
57 // Codec type. Used when we configure media codec.
58 VideoCodec codec_ = kUnknownVideoCodec;
59
60 // Whether encryption scheme requires to use protected surface.
61 bool needs_protected_surface_ = false;
62
63 // The surface that MediaCodec is configured to output to.
64 gl::ScopedJavaSurface surface_;
65
66 int surface_id_ = SurfaceManager::kNoSurfaceID;
67
68 // The MediaCrypto object is used in the MediaCodec.configure() in case of
69 // an encrypted stream.
70 MediaDrmBridgeCdmContext::JavaObjectPtr media_crypto_;
71
72 // Initial coded size. The actual size might change at any time, so this
73 // is only a hint.
74 gfx::Size initial_expected_coded_size_;
75
76 // The type of allocation to use for this. We use this to select the right
77 // thread for construction / destruction, and to decide if we should
78 // restrict the codec to be software only.
79 TaskType task_type_;
80
81 // Codec specific data (SPS and PPS for H264).
82 std::vector<uint8_t> csd0_;
83 std::vector<uint8_t> csd1_;
84
85 protected:
86 friend class base::RefCountedThreadSafe<CodecConfig>;
87 virtual ~CodecConfig();
88
89 private:
90 DISALLOW_COPY_AND_ASSIGN(CodecConfig);
91 };
92
93 class AVDACodecAllocatorClient {
liberato (no reviews please) 2016/11/17 07:28:19 +1
94 public:
95 // Called when the requested SurfaceView becomes available after a call to
96 // AllocateSurface()
97 virtual void OnSurfaceAvailable(bool success) = 0;
98
99 // Called when the allocated surface is being destroyed. This must either
100 // release the surface, or release the MediaCodec it's attached to.
101 virtual void OnSurfaceDestroyed() = 0;
102
103 // Called on the main thread when a new MediaCodec is configured.
104 // |media_codec| will be null if configuration failed.
105 virtual void OnCodecConfigured(
106 std::unique_ptr<VideoCodecBridge> media_codec) = 0;
107
108 protected:
109 ~AVDACodecAllocatorClient() {}
110 };
24 111
25 // AVDACodecAllocator manages threads for allocating and releasing MediaCodec 112 // AVDACodecAllocator manages threads for allocating and releasing MediaCodec
26 // instances. These activities can hang, depending on android version, due 113 // instances. These activities can hang, depending on android version, due
27 // to mediaserver bugs. AVDACodecAllocator detects these cases, and reports 114 // to mediaserver bugs. AVDACodecAllocator detects these cases, and reports
28 // on them to allow software fallback if the HW path is hung up. 115 // on them to allow software fallback if the HW path is hung up.
29 class MEDIA_GPU_EXPORT AVDACodecAllocator { 116 class MEDIA_GPU_EXPORT AVDACodecAllocator {
30 public: 117 public:
31 // For AVDAManager::TaskRunnerFor. These are used as vector indices, so 118 static AVDACodecAllocator& Get();
32 // please update AVDACodecAllocator's constructor if you add / change them.
33 enum TaskType {
34 // Task for an autodetected MediaCodec instance.
35 AUTO_CODEC = 0,
36 119
37 // Task for a software-codec-required MediaCodec. 120 // Called synchronously when the given surface is being destroyed on the
38 SW_CODEC = 1, 121 // browser UI thread.
122 void OnSurfaceDestroyed(int surface_id);
39 123
40 // Special value to indicate "none". This is not used as an array index. It 124 // Make sure the construction thread is started for |client|.
41 // must, however, be positive to keep the enum unsigned. 125 bool StartThread(AVDACodecAllocatorClient* client);
42 FAILED_CODEC = 99,
43 };
44 126
45 // Make sure the construction thread is started for |avda|. 127 void StopThread(AVDACodecAllocatorClient* client);
46 bool StartThread(AndroidVideoDecodeAccelerator* avda);
47
48 void StopThread(AndroidVideoDecodeAccelerator* avda);
49 128
50 // Return the task runner for tasks of type |type|. If that thread failed 129 // Return the task runner for tasks of type |type|. If that thread failed
51 // to start, then fall back to the GPU main thread. 130 // to start, then fall back to the GPU main thread.
52 scoped_refptr<base::SingleThreadTaskRunner> TaskRunnerFor(TaskType task_type); 131 scoped_refptr<base::SingleThreadTaskRunner> TaskRunnerFor(TaskType task_type);
53 132
133 bool AllocateSurface(AVDACodecAllocatorClient* client, int surface_id);
134
135 void DeallocateSurface(AVDACodecAllocatorClient* client, int surface_id);
136
137 std::unique_ptr<VideoCodecBridge> CreateMediaCodecSync(
138 scoped_refptr<CodecConfig> codec_config);
139
140 void CreateMediaCodecAsync(base::WeakPtr<AVDACodecAllocatorClient> client,
141 scoped_refptr<CodecConfig> codec_config);
142
143 void ReleaseMediaCodec(std::unique_ptr<VideoCodecBridge> media_codec,
144 TaskType task_type,
145 int surface_id);
146
54 // Returns a hint about whether the construction thread has hung for 147 // Returns a hint about whether the construction thread has hung for
55 // |task_type|. Note that if a thread isn't started, then we'll just return 148 // |task_type|. Note that if a thread isn't started, then we'll just return
56 // "not hung", since it'll run on the current thread anyway. The hang 149 // "not hung", since it'll run on the current thread anyway. The hang
57 // detector will see no pending jobs in that case, so it's automatic. 150 // detector will see no pending jobs in that case, so it's automatic.
58 bool IsThreadLikelyHung(TaskType task_type); 151 bool IsThreadLikelyHung(TaskType task_type);
59 152
60 // Return true if and only if there is any AVDA registered. 153 // Return true if and only if there is any AVDA registered.
61 bool IsAnyRegisteredAVDA(); 154 bool IsAnyRegisteredAVDA();
62 155
63 // Return the task type to use for a new codec allocation, or FAILED_CODEC if 156 // Return the task type to use for a new codec allocation, or FAILED_CODEC if
(...skipping 12 matching lines...) Expand all
76 struct TestInformation { 169 struct TestInformation {
77 TestInformation(); 170 TestInformation();
78 ~TestInformation(); 171 ~TestInformation();
79 // Optional clock source. 172 // Optional clock source.
80 std::unique_ptr<base::TickClock> tick_clock_; 173 std::unique_ptr<base::TickClock> tick_clock_;
81 174
82 // Optional event that we'll signal when stopping the AUTO_CODEC thread. 175 // Optional event that we'll signal when stopping the AUTO_CODEC thread.
83 std::unique_ptr<base::WaitableEvent> stop_event_; 176 std::unique_ptr<base::WaitableEvent> stop_event_;
84 }; 177 };
85 178
86 // |test_info| is owned by the unit test. 179 struct OwnerRecord {
87 AVDACodecAllocator(TestInformation* test_info = nullptr); 180 AVDACodecAllocatorClient* owner = nullptr;
88 ~AVDACodecAllocator(); 181 AVDACodecAllocatorClient* waiter = nullptr;
182 };
89 183
90 // Stop the thread indicated by |index|, then signal |event| if provided. 184 struct CodecReleaseTask {
91 void StopThreadTask(size_t index, base::WaitableEvent* event = nullptr); 185 CodecReleaseTask()
92 186 : codec_released_event(
93 // All registered AVDA instances. 187 base::WaitableEvent::ResetPolicy::MANUAL,
94 std::set<AndroidVideoDecodeAccelerator*> thread_avda_instances_; 188 base::WaitableEvent::InitialState::NOT_SIGNALED) {}
189 base::WaitableEvent codec_released_event;
190 };
95 191
96 class HangDetector : public base::MessageLoop::TaskObserver { 192 class HangDetector : public base::MessageLoop::TaskObserver {
97 public: 193 public:
98 HangDetector(base::TickClock* tick_clock); 194 HangDetector(base::TickClock* tick_clock);
99
100 void WillProcessTask(const base::PendingTask& pending_task) override; 195 void WillProcessTask(const base::PendingTask& pending_task) override;
101 void DidProcessTask(const base::PendingTask& pending_task) override; 196 void DidProcessTask(const base::PendingTask& pending_task) override;
102
103 bool IsThreadLikelyHung(); 197 bool IsThreadLikelyHung();
104 198
105 private: 199 private:
106 base::Lock lock_; 200 base::Lock lock_;
201
107 // Non-null when a task is currently running. 202 // Non-null when a task is currently running.
108 base::TimeTicks task_start_time_; 203 base::TimeTicks task_start_time_;
109 204
110 base::TickClock* tick_clock_; 205 base::TickClock* tick_clock_;
111 206
112 DISALLOW_COPY_AND_ASSIGN(HangDetector); 207 DISALLOW_COPY_AND_ASSIGN(HangDetector);
113 }; 208 };
114 209
115 // Handy combination of a thread and hang detector for it. 210 // Handy combination of a thread and hang detector for it.
116 struct ThreadAndHangDetector { 211 struct ThreadAndHangDetector {
117 ThreadAndHangDetector(const std::string& name, base::TickClock* tick_clock) 212 ThreadAndHangDetector(const std::string& name, base::TickClock* tick_clock)
118 : thread(name), hang_detector(tick_clock) {} 213 : thread(name), hang_detector(tick_clock) {}
119 base::Thread thread; 214 base::Thread thread;
120 HangDetector hang_detector; 215 HangDetector hang_detector;
121 }; 216 };
122 217
218 // |test_info| is owned by the unit test.
219 AVDACodecAllocator(TestInformation* test_info = nullptr);
220 ~AVDACodecAllocator();
221
222 void OnMediaCodecAndSurfaceReleased(int surface_id);
223
224 // Stop the thread indicated by |index|, then signal |event| if provided.
225 void StopThreadTask(size_t index, base::WaitableEvent* event = nullptr);
226
227 // All registered AVDAs.
228 std::set<AVDACodecAllocatorClient*> clients_;
229
230 // Indexed by surface id.
231 std::map<int32_t, OwnerRecord> surface_owners_;
232
233 // Release tasks indexed by surface id so we can wait on the codec release if
234 // the surface attached to it is being destroyed.
235 std::map<int32_t, CodecReleaseTask> codec_release_tasks_;
236
123 // Threads for each of TaskType. They are started / stopped as avda instances 237 // Threads for each of TaskType. They are started / stopped as avda instances
124 // show and and request them. The vector indicies must match TaskType. 238 // show and and request them. The vector indicies must match TaskType.
125 std::vector<ThreadAndHangDetector*> threads_; 239 std::vector<ThreadAndHangDetector*> threads_;
126 240
127 base::ThreadChecker thread_checker_; 241 base::ThreadChecker thread_checker_;
128 242
129 // Optional, used for unit testing. We do not own this. 243 // Optional, used for unit testing. We do not own this.
130 TestInformation* test_info_; 244 TestInformation* test_info_;
131 245
132 // For canceling pending StopThreadTask()s. 246 // For canceling pending StopThreadTask()s.
133 base::WeakPtrFactory<AVDACodecAllocator> weak_this_factory_; 247 base::WeakPtrFactory<AVDACodecAllocator> weak_this_factory_;
134 248
135 DISALLOW_COPY_AND_ASSIGN(AVDACodecAllocator); 249 DISALLOW_COPY_AND_ASSIGN(AVDACodecAllocator);
136 }; 250 };
137 251
138 } // namespace media 252 } // namespace media
253
254 #endif // MEDIA_GPU_AVDA_CODEC_ALLOCATOR_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698