| 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 // For TaskRunnerFor. These are used as vector indices, so please update |
| 34 // AVDACodecAllocator's constructor if you add / change them. |
| 35 // TODO(watk): Hide this from AVDA now that we manage codec creation. |
| 36 enum TaskType { |
| 37 // Task for an autodetected MediaCodec instance. |
| 38 AUTO_CODEC = 0, |
| 39 |
| 40 // Task for a software-codec-required MediaCodec. |
| 41 SW_CODEC = 1, |
| 42 |
| 43 // Special value to indicate "none". This is not used as an array index. It |
| 44 // must, however, be positive to keep the enum unsigned. |
| 45 FAILED_CODEC = 99, |
| 46 }; |
| 47 |
| 48 // Configuration info for MediaCodec. |
| 49 // This is used to shuttle configuration info between threads without needing |
| 50 // to worry about the lifetime of the AVDA instance. |
| 51 class CodecConfig : public base::RefCountedThreadSafe<CodecConfig> { |
| 52 public: |
| 53 CodecConfig(); |
| 54 |
| 55 // Codec type. Used when we configure media codec. |
| 56 VideoCodec codec_ = kUnknownVideoCodec; |
| 57 |
| 58 // Whether encryption scheme requires to use protected surface. |
| 59 bool needs_protected_surface_ = false; |
| 60 |
| 61 // The surface that MediaCodec is configured to output to. |
| 62 gl::ScopedJavaSurface surface_; |
| 63 |
| 64 int surface_id_ = SurfaceManager::kNoSurfaceID; |
| 65 |
| 66 // The MediaCrypto object is used in the MediaCodec.configure() in case of |
| 67 // an encrypted stream. |
| 68 MediaDrmBridgeCdmContext::JavaObjectPtr media_crypto_; |
| 69 |
| 70 // Initial coded size. The actual size might change at any time, so this |
| 71 // is only a hint. |
| 72 gfx::Size initial_expected_coded_size_; |
| 73 |
| 74 // The type of allocation to use for this. We use this to select the right |
| 75 // thread for construction / destruction, and to decide if we should |
| 76 // restrict the codec to be software only. |
| 77 TaskType task_type_; |
| 78 |
| 79 // Codec specific data (SPS and PPS for H264). |
| 80 std::vector<uint8_t> csd0_; |
| 81 std::vector<uint8_t> csd1_; |
| 82 |
| 83 protected: |
| 84 friend class base::RefCountedThreadSafe<CodecConfig>; |
| 85 virtual ~CodecConfig(); |
| 86 |
| 87 private: |
| 88 DISALLOW_COPY_AND_ASSIGN(CodecConfig); |
| 89 }; |
| 90 |
| 91 class AVDACodecAllocatorClient { |
| 92 public: |
| 93 // Called when the requested SurfaceView becomes available after a call to |
| 94 // AllocateSurface() |
| 95 virtual void OnSurfaceAvailable(bool success) = 0; |
| 96 |
| 97 // Called when the allocated surface is being destroyed. This must either |
| 98 // replace the surface with MediaCodec#setSurface, or release the MediaCodec |
| 99 // it's attached to. The client no longer owns the surface and doesn't |
| 100 // need to call DeallocateSurface(); |
| 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* Instance(); |
| 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 // Returns true if the caller now owns the surface, or false if someone else |
| 134 // owns the surface. |client| will be notified when the surface is available |
| 135 // via OnSurfaceAvailable(). |
| 136 bool AllocateSurface(AVDACodecAllocatorClient* client, int surface_id); |
| 137 |
| 138 // Relinquish ownership of the surface or stop waiting for it to be available. |
| 139 // The caller must guarantee that when calling this the surface is either no |
| 140 // longer attached to a MediaCodec, or the MediaCodec it was attached to is |
| 141 // was released with ReleaseMediaCodec(). |
| 142 void DeallocateSurface(AVDACodecAllocatorClient* client, int surface_id); |
| 143 |
| 144 // Create and configure a MediaCodec synchronously. |
| 145 std::unique_ptr<VideoCodecBridge> CreateMediaCodecSync( |
| 146 scoped_refptr<CodecConfig> codec_config); |
| 147 |
| 148 // Create and configure a MediaCodec asynchronously. The result is delivered |
| 149 // via OnCodecConfigured(). |
| 150 void CreateMediaCodecAsync(base::WeakPtr<AVDACodecAllocatorClient> client, |
| 151 scoped_refptr<CodecConfig> codec_config); |
| 152 |
| 153 // Asynchronously release |media_codec| with the attached surface. |
| 154 // TODO(watk): Bundle the MediaCodec and surface together so you can't get |
| 155 // this pairing wrong. |
| 156 void ReleaseMediaCodec(std::unique_ptr<VideoCodecBridge> media_codec, |
| 157 TaskType task_type, |
| 158 int surface_id); |
| 159 |
| 54 // Returns a hint about whether the construction thread has hung for | 160 // 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 | 161 // |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 | 162 // "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. | 163 // detector will see no pending jobs in that case, so it's automatic. |
| 58 bool IsThreadLikelyHung(TaskType task_type); | 164 bool IsThreadLikelyHung(TaskType task_type); |
| 59 | 165 |
| 60 // Return true if and only if there is any AVDA registered. | 166 // Return true if and only if there is any AVDA registered. |
| 61 bool IsAnyRegisteredAVDA(); | 167 bool IsAnyRegisteredAVDA(); |
| 62 | 168 |
| 63 // Return the task type to use for a new codec allocation, or FAILED_CODEC if | 169 // 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 { | 182 struct TestInformation { |
| 77 TestInformation(); | 183 TestInformation(); |
| 78 ~TestInformation(); | 184 ~TestInformation(); |
| 79 // Optional clock source. | 185 // Optional clock source. |
| 80 std::unique_ptr<base::TickClock> tick_clock_; | 186 std::unique_ptr<base::TickClock> tick_clock_; |
| 81 | 187 |
| 82 // Optional event that we'll signal when stopping the AUTO_CODEC thread. | 188 // Optional event that we'll signal when stopping the AUTO_CODEC thread. |
| 83 std::unique_ptr<base::WaitableEvent> stop_event_; | 189 std::unique_ptr<base::WaitableEvent> stop_event_; |
| 84 }; | 190 }; |
| 85 | 191 |
| 86 // |test_info| is owned by the unit test. | 192 struct OwnerRecord { |
| 87 AVDACodecAllocator(TestInformation* test_info = nullptr); | 193 AVDACodecAllocatorClient* owner = nullptr; |
| 88 ~AVDACodecAllocator(); | 194 AVDACodecAllocatorClient* waiter = nullptr; |
| 89 | 195 }; |
| 90 // Stop the thread indicated by |index|, then signal |event| if provided. | |
| 91 void StopThreadTask(size_t index, base::WaitableEvent* event = nullptr); | |
| 92 | |
| 93 // All registered AVDA instances. | |
| 94 std::set<AndroidVideoDecodeAccelerator*> thread_avda_instances_; | |
| 95 | 196 |
| 96 class HangDetector : public base::MessageLoop::TaskObserver { | 197 class HangDetector : public base::MessageLoop::TaskObserver { |
| 97 public: | 198 public: |
| 98 HangDetector(base::TickClock* tick_clock); | 199 HangDetector(base::TickClock* tick_clock); |
| 99 | |
| 100 void WillProcessTask(const base::PendingTask& pending_task) override; | 200 void WillProcessTask(const base::PendingTask& pending_task) override; |
| 101 void DidProcessTask(const base::PendingTask& pending_task) override; | 201 void DidProcessTask(const base::PendingTask& pending_task) override; |
| 102 | |
| 103 bool IsThreadLikelyHung(); | 202 bool IsThreadLikelyHung(); |
| 104 | 203 |
| 105 private: | 204 private: |
| 106 base::Lock lock_; | 205 base::Lock lock_; |
| 206 |
| 107 // Non-null when a task is currently running. | 207 // Non-null when a task is currently running. |
| 108 base::TimeTicks task_start_time_; | 208 base::TimeTicks task_start_time_; |
| 109 | 209 |
| 110 base::TickClock* tick_clock_; | 210 base::TickClock* tick_clock_; |
| 111 | 211 |
| 112 DISALLOW_COPY_AND_ASSIGN(HangDetector); | 212 DISALLOW_COPY_AND_ASSIGN(HangDetector); |
| 113 }; | 213 }; |
| 114 | 214 |
| 115 // Handy combination of a thread and hang detector for it. | 215 // Handy combination of a thread and hang detector for it. |
| 116 struct ThreadAndHangDetector { | 216 struct ThreadAndHangDetector { |
| 117 ThreadAndHangDetector(const std::string& name, base::TickClock* tick_clock) | 217 ThreadAndHangDetector(const std::string& name, base::TickClock* tick_clock) |
| 118 : thread(name), hang_detector(tick_clock) {} | 218 : thread(name), hang_detector(tick_clock) {} |
| 119 base::Thread thread; | 219 base::Thread thread; |
| 120 HangDetector hang_detector; | 220 HangDetector hang_detector; |
| 121 }; | 221 }; |
| 122 | 222 |
| 223 // |test_info| is owned by the unit test. |
| 224 AVDACodecAllocator(TestInformation* test_info = nullptr); |
| 225 ~AVDACodecAllocator(); |
| 226 |
| 227 void OnMediaCodecAndSurfaceReleased(int surface_id); |
| 228 |
| 229 // Stop the thread indicated by |index|, then signal |event| if provided. |
| 230 void StopThreadTask(size_t index, base::WaitableEvent* event = nullptr); |
| 231 |
| 232 // All registered AVDAs. |
| 233 std::set<AVDACodecAllocatorClient*> clients_; |
| 234 |
| 235 // Indexed by surface id. |
| 236 std::map<int32_t, OwnerRecord> surface_owners_; |
| 237 |
| 238 // Waitable events for ongoing release tasks indexed by surface id so we can |
| 239 // wait on the codec release if the surface attached to it is being destroyed. |
| 240 std::map<int32_t, base::WaitableEvent> pending_codec_releases_; |
| 241 |
| 123 // Threads for each of TaskType. They are started / stopped as avda instances | 242 // Threads for each of TaskType. They are started / stopped as avda instances |
| 124 // show and and request them. The vector indicies must match TaskType. | 243 // show and and request them. The vector indicies must match TaskType. |
| 125 std::vector<ThreadAndHangDetector*> threads_; | 244 std::vector<ThreadAndHangDetector*> threads_; |
| 126 | 245 |
| 127 base::ThreadChecker thread_checker_; | 246 base::ThreadChecker thread_checker_; |
| 128 | 247 |
| 129 // Optional, used for unit testing. We do not own this. | 248 // Optional, used for unit testing. We do not own this. |
| 130 TestInformation* test_info_; | 249 TestInformation* test_info_; |
| 131 | 250 |
| 132 // For canceling pending StopThreadTask()s. | 251 // For canceling pending StopThreadTask()s. |
| 133 base::WeakPtrFactory<AVDACodecAllocator> weak_this_factory_; | 252 base::WeakPtrFactory<AVDACodecAllocator> weak_this_factory_; |
| 134 | 253 |
| 135 DISALLOW_COPY_AND_ASSIGN(AVDACodecAllocator); | 254 DISALLOW_COPY_AND_ASSIGN(AVDACodecAllocator); |
| 136 }; | 255 }; |
| 137 | 256 |
| 138 } // namespace media | 257 } // namespace media |
| 258 |
| 259 #endif // MEDIA_GPU_AVDA_CODEC_ALLOCATOR_H_ |
| OLD | NEW |