1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112

media / fuchsia / common / sysmem_client.h [blame]

// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef MEDIA_FUCHSIA_COMMON_SYSMEM_CLIENT_H_
#define MEDIA_FUCHSIA_COMMON_SYSMEM_CLIENT_H_

#include <fuchsia/media/cpp/fidl.h>
#include <fuchsia/sysmem2/cpp/fidl.h>

#include <string_view>
#include <vector>

#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/threading/thread_checker.h"
#include "media/base/media_export.h"

namespace media {

class VmoBuffer;

// Wrapper for fuchsia.sysmem.BufferCollection . It provides the following two
// features:
//  1. Calls Sync() and ensures that it completes before buffer constrains are
//  set and shared tokens are passed to other participants.
//  2. Provides AcquireBuffers() that allows to acquire buffers and handle
//  possible errors.
class MEDIA_EXPORT SysmemCollectionClient {
 public:
  static constexpr uint32_t kDefaultNamePriority = 100;

  // Callback for GetSharedToken().
  using GetSharedTokenCB = base::OnceCallback<void(
      fuchsia::sysmem2::BufferCollectionTokenPtr token)>;

  // Callback for AcquireBuffers(). Called with an empty |buffers| if buffers
  // allocation failed.
  using AcquireBuffersCB = base::OnceCallback<void(
      std::vector<VmoBuffer> buffers,
      const fuchsia::sysmem2::SingleBufferSettings& settings)>;

  SysmemCollectionClient(
      fuchsia::sysmem2::Allocator* allocator,
      fuchsia::sysmem2::BufferCollectionTokenPtr collection_token);
  ~SysmemCollectionClient();

  SysmemCollectionClient(const SysmemCollectionClient&) = delete;
  SysmemCollectionClient& operator=(const SysmemCollectionClient&) = delete;

  // Creates one shared token to be shared with other participants and returns
  // it asynchronously, when it's safe to pass it (i.e. after Sync()). Must be
  // called before Initialize().
  void CreateSharedToken(
      GetSharedTokenCB cb,
      std::string_view debug_client_name = std::string_view(),
      uint64_t debug_client_id = 0);

  // Initializes the collection with the given name and constraints.
  void Initialize(fuchsia::sysmem2::BufferCollectionConstraints constraints,
                  std::string_view name,
                  uint32_t name_priority = kDefaultNamePriority);

  // Create VmoBuffers to access raw memory. Should be called only after
  // GetSharedToken() has been called for all shared tokens.
  void AcquireBuffers(AcquireBuffersCB cb);

 private:
  void OnSyncComplete(fuchsia::sysmem2::Node_Sync_Result sync_result);
  void OnBuffersAllocated(
      fuchsia::sysmem2::BufferCollection_WaitForAllBuffersAllocated_Result
          wait_result);
  void OnError(zx_status_t status);

  const raw_ptr<fuchsia::sysmem2::Allocator> allocator_;
  fuchsia::sysmem2::BufferCollectionTokenPtr collection_token_;
  fuchsia::sysmem2::BufferCollectionPtr collection_;

  bool writable_ = false;
  std::vector<base::OnceClosure> shared_token_ready_closures_;
  AcquireBuffersCB acquire_buffers_cb_;

  THREAD_CHECKER(thread_checker_);
};

// Helper fuchsia.sysmem.Allocator .
class MEDIA_EXPORT SysmemAllocatorClient {
 public:
  explicit SysmemAllocatorClient(std::string_view client_name);
  ~SysmemAllocatorClient();

  SysmemAllocatorClient(const SysmemAllocatorClient&) = delete;
  SysmemAllocatorClient& operator=(const SysmemAllocatorClient&) = delete;

  fuchsia::sysmem2::BufferCollectionTokenPtr CreateNewToken();

  // Creates new buffer collection.
  std::unique_ptr<SysmemCollectionClient> AllocateNewCollection();

  // Binds the specified token to a SysmemCollectionClient.
  std::unique_ptr<SysmemCollectionClient> BindSharedCollection(
      fuchsia::sysmem2::BufferCollectionTokenPtr token);

 private:
  friend SysmemCollectionClient;

  fuchsia::sysmem2::AllocatorPtr allocator_;
};

}  // namespace media

#endif  // MEDIA_FUCHSIA_COMMON_SYSMEM_CLIENT_H_