| Index: media/gpu/avda_codec_allocator.h
|
| diff --git a/media/gpu/avda_codec_allocator.h b/media/gpu/avda_codec_allocator.h
|
| index 4d2bf1d04f6cf866eac89b50c42b5d57859e2512..796efbbe69c3cdd0cdfaa2493aeb177cc2c6c631 100644
|
| --- a/media/gpu/avda_codec_allocator.h
|
| +++ b/media/gpu/avda_codec_allocator.h
|
| @@ -2,6 +2,9 @@
|
| // Use of this source code is governed by a BSD-style license that can be
|
| // found in the LICENSE file.
|
|
|
| +#ifndef MEDIA_GPU_AVDA_CODEC_ALLOCATOR_H_
|
| +#define MEDIA_GPU_AVDA_CODEC_ALLOCATOR_H_
|
| +
|
| #include <stddef.h>
|
|
|
| #include <memory>
|
| @@ -10,17 +13,101 @@
|
| #include "base/bind.h"
|
| #include "base/lazy_instance.h"
|
| #include "base/logging.h"
|
| +#include "base/synchronization/waitable_event.h"
|
| #include "base/sys_info.h"
|
| #include "base/threading/thread.h"
|
| #include "base/threading/thread_checker.h"
|
| #include "base/time/tick_clock.h"
|
| #include "base/trace_event/trace_event.h"
|
| +#include "media/base/android/media_drm_bridge_cdm_context.h"
|
| +#include "media/base/android/sdk_media_codec_bridge.h"
|
| #include "media/base/media.h"
|
| +#include "media/base/surface_manager.h"
|
| +#include "media/base/video_codecs.h"
|
| #include "media/gpu/media_gpu_export.h"
|
| +#include "ui/gfx/geometry/size.h"
|
| +#include "ui/gl/android/scoped_java_surface.h"
|
|
|
| namespace media {
|
|
|
| -class AndroidVideoDecodeAccelerator;
|
| +// For TaskRunnerFor. These are used as vector indices, so please update
|
| +// AVDACodecAllocator's constructor if you add / change them.
|
| +// TODO(watk): Hide this from AVDA now that we manage codec creation.
|
| +enum TaskType {
|
| + // Task for an autodetected MediaCodec instance.
|
| + AUTO_CODEC = 0,
|
| +
|
| + // Task for a software-codec-required MediaCodec.
|
| + SW_CODEC = 1,
|
| +
|
| + // Special value to indicate "none". This is not used as an array index. It
|
| + // must, however, be positive to keep the enum unsigned.
|
| + FAILED_CODEC = 99,
|
| +};
|
| +
|
| +// Configuration info for MediaCodec.
|
| +// This is used to shuttle configuration info between threads without needing
|
| +// to worry about the lifetime of the AVDA instance.
|
| +class CodecConfig : public base::RefCountedThreadSafe<CodecConfig> {
|
| + public:
|
| + CodecConfig();
|
| +
|
| + // Codec type. Used when we configure media codec.
|
| + VideoCodec codec_ = kUnknownVideoCodec;
|
| +
|
| + // Whether encryption scheme requires to use protected surface.
|
| + bool needs_protected_surface_ = false;
|
| +
|
| + // The surface that MediaCodec is configured to output to.
|
| + gl::ScopedJavaSurface surface_;
|
| +
|
| + int surface_id_ = SurfaceManager::kNoSurfaceID;
|
| +
|
| + // The MediaCrypto object is used in the MediaCodec.configure() in case of
|
| + // an encrypted stream.
|
| + MediaDrmBridgeCdmContext::JavaObjectPtr media_crypto_;
|
| +
|
| + // Initial coded size. The actual size might change at any time, so this
|
| + // is only a hint.
|
| + gfx::Size initial_expected_coded_size_;
|
| +
|
| + // The type of allocation to use for this. We use this to select the right
|
| + // thread for construction / destruction, and to decide if we should
|
| + // restrict the codec to be software only.
|
| + TaskType task_type_;
|
| +
|
| + // Codec specific data (SPS and PPS for H264).
|
| + std::vector<uint8_t> csd0_;
|
| + std::vector<uint8_t> csd1_;
|
| +
|
| + protected:
|
| + friend class base::RefCountedThreadSafe<CodecConfig>;
|
| + virtual ~CodecConfig();
|
| +
|
| + private:
|
| + DISALLOW_COPY_AND_ASSIGN(CodecConfig);
|
| +};
|
| +
|
| +class AVDACodecAllocatorClient {
|
| + public:
|
| + // Called when the requested SurfaceView becomes available after a call to
|
| + // AllocateSurface()
|
| + virtual void OnSurfaceAvailable(bool success) = 0;
|
| +
|
| + // Called when the allocated surface is being destroyed. This must either
|
| + // replace the surface with MediaCodec#setSurface, or release the MediaCodec
|
| + // it's attached to. The client no longer owns the surface and doesn't
|
| + // need to call DeallocateSurface();
|
| + virtual void OnSurfaceDestroyed() = 0;
|
| +
|
| + // Called on the main thread when a new MediaCodec is configured.
|
| + // |media_codec| will be null if configuration failed.
|
| + virtual void OnCodecConfigured(
|
| + std::unique_ptr<VideoCodecBridge> media_codec) = 0;
|
| +
|
| + protected:
|
| + ~AVDACodecAllocatorClient() {}
|
| +};
|
|
|
| // AVDACodecAllocator manages threads for allocating and releasing MediaCodec
|
| // instances. These activities can hang, depending on android version, due
|
| @@ -28,29 +115,48 @@ class AndroidVideoDecodeAccelerator;
|
| // on them to allow software fallback if the HW path is hung up.
|
| class MEDIA_GPU_EXPORT AVDACodecAllocator {
|
| public:
|
| - // For AVDAManager::TaskRunnerFor. These are used as vector indices, so
|
| - // please update AVDACodecAllocator's constructor if you add / change them.
|
| - enum TaskType {
|
| - // Task for an autodetected MediaCodec instance.
|
| - AUTO_CODEC = 0,
|
| + static AVDACodecAllocator* Instance();
|
|
|
| - // Task for a software-codec-required MediaCodec.
|
| - SW_CODEC = 1,
|
| + // Called synchronously when the given surface is being destroyed on the
|
| + // browser UI thread.
|
| + void OnSurfaceDestroyed(int surface_id);
|
|
|
| - // Special value to indicate "none". This is not used as an array index. It
|
| - // must, however, be positive to keep the enum unsigned.
|
| - FAILED_CODEC = 99,
|
| - };
|
| + // Make sure the construction thread is started for |client|.
|
| + bool StartThread(AVDACodecAllocatorClient* client);
|
|
|
| - // Make sure the construction thread is started for |avda|.
|
| - bool StartThread(AndroidVideoDecodeAccelerator* avda);
|
| -
|
| - void StopThread(AndroidVideoDecodeAccelerator* avda);
|
| + void StopThread(AVDACodecAllocatorClient* client);
|
|
|
| // Return the task runner for tasks of type |type|. If that thread failed
|
| // to start, then fall back to the GPU main thread.
|
| scoped_refptr<base::SingleThreadTaskRunner> TaskRunnerFor(TaskType task_type);
|
|
|
| + // Returns true if the caller now owns the surface, or false if someone else
|
| + // owns the surface. |client| will be notified when the surface is available
|
| + // via OnSurfaceAvailable().
|
| + bool AllocateSurface(AVDACodecAllocatorClient* client, int surface_id);
|
| +
|
| + // Relinquish ownership of the surface or stop waiting for it to be available.
|
| + // The caller must guarantee that when calling this the surface is either no
|
| + // longer attached to a MediaCodec, or the MediaCodec it was attached to is
|
| + // was released with ReleaseMediaCodec().
|
| + void DeallocateSurface(AVDACodecAllocatorClient* client, int surface_id);
|
| +
|
| + // Create and configure a MediaCodec synchronously.
|
| + std::unique_ptr<VideoCodecBridge> CreateMediaCodecSync(
|
| + scoped_refptr<CodecConfig> codec_config);
|
| +
|
| + // Create and configure a MediaCodec asynchronously. The result is delivered
|
| + // via OnCodecConfigured().
|
| + void CreateMediaCodecAsync(base::WeakPtr<AVDACodecAllocatorClient> client,
|
| + scoped_refptr<CodecConfig> codec_config);
|
| +
|
| + // Asynchronously release |media_codec| with the attached surface.
|
| + // TODO(watk): Bundle the MediaCodec and surface together so you can't get
|
| + // this pairing wrong.
|
| + void ReleaseMediaCodec(std::unique_ptr<VideoCodecBridge> media_codec,
|
| + TaskType task_type,
|
| + int surface_id);
|
| +
|
| // Returns a hint about whether the construction thread has hung for
|
| // |task_type|. Note that if a thread isn't started, then we'll just return
|
| // "not hung", since it'll run on the current thread anyway. The hang
|
| @@ -83,27 +189,21 @@ class MEDIA_GPU_EXPORT AVDACodecAllocator {
|
| std::unique_ptr<base::WaitableEvent> stop_event_;
|
| };
|
|
|
| - // |test_info| is owned by the unit test.
|
| - AVDACodecAllocator(TestInformation* test_info = nullptr);
|
| - ~AVDACodecAllocator();
|
| -
|
| - // Stop the thread indicated by |index|, then signal |event| if provided.
|
| - void StopThreadTask(size_t index, base::WaitableEvent* event = nullptr);
|
| -
|
| - // All registered AVDA instances.
|
| - std::set<AndroidVideoDecodeAccelerator*> thread_avda_instances_;
|
| + struct OwnerRecord {
|
| + AVDACodecAllocatorClient* owner = nullptr;
|
| + AVDACodecAllocatorClient* waiter = nullptr;
|
| + };
|
|
|
| class HangDetector : public base::MessageLoop::TaskObserver {
|
| public:
|
| HangDetector(base::TickClock* tick_clock);
|
| -
|
| void WillProcessTask(const base::PendingTask& pending_task) override;
|
| void DidProcessTask(const base::PendingTask& pending_task) override;
|
| -
|
| bool IsThreadLikelyHung();
|
|
|
| private:
|
| base::Lock lock_;
|
| +
|
| // Non-null when a task is currently running.
|
| base::TimeTicks task_start_time_;
|
|
|
| @@ -120,6 +220,25 @@ class MEDIA_GPU_EXPORT AVDACodecAllocator {
|
| HangDetector hang_detector;
|
| };
|
|
|
| + // |test_info| is owned by the unit test.
|
| + AVDACodecAllocator(TestInformation* test_info = nullptr);
|
| + ~AVDACodecAllocator();
|
| +
|
| + void OnMediaCodecAndSurfaceReleased(int surface_id);
|
| +
|
| + // Stop the thread indicated by |index|, then signal |event| if provided.
|
| + void StopThreadTask(size_t index, base::WaitableEvent* event = nullptr);
|
| +
|
| + // All registered AVDAs.
|
| + std::set<AVDACodecAllocatorClient*> clients_;
|
| +
|
| + // Indexed by surface id.
|
| + std::map<int32_t, OwnerRecord> surface_owners_;
|
| +
|
| + // Waitable events for ongoing release tasks indexed by surface id so we can
|
| + // wait on the codec release if the surface attached to it is being destroyed.
|
| + std::map<int32_t, base::WaitableEvent> pending_codec_releases_;
|
| +
|
| // Threads for each of TaskType. They are started / stopped as avda instances
|
| // show and and request them. The vector indicies must match TaskType.
|
| std::vector<ThreadAndHangDetector*> threads_;
|
| @@ -136,3 +255,5 @@ class MEDIA_GPU_EXPORT AVDACodecAllocator {
|
| };
|
|
|
| } // namespace media
|
| +
|
| +#endif // MEDIA_GPU_AVDA_CODEC_ALLOCATOR_H_
|
|
|