Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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_ | |
| OLD | NEW |