12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#ifndef CONTENT_BROWSER_RENDERER_HOST_MEDIA_VIDEO_CAPTURE_BUFFER_POOL_H_
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_VIDEO_CAPTURE_BUFFER_POOL_H_
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
81e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include <map>
91e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/basictypes.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/memory/ref_counted.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/memory/scoped_vector.h"
137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "base/memory/shared_memory.h"
14a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch#include "base/process/process.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/synchronization/lock.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/common/content_export.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/size.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
19eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochnamespace media {
20eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
21eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochclass VideoFrame;
22eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
23eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}  // namespace media
24eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace content {
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// A thread-safe class that does the bookkeeping and lifetime management for a
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// pool of shared-memory pixel buffers cycled between an in-process producer
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// (e.g. a VideoCaptureDevice) and a set of out-of-process consumers. The pool
301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// is intended to be orchestrated by a VideoCaptureController, but is designed
311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// to outlive the controller if necessary.
321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)//
331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// Producers get a buffer by calling ReserveForProducer(), and may pass on their
341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// ownership to the consumer by calling HoldForConsumers(), or drop the buffer
351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// (without further processing) by calling RelinquishProducerReservation().
361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// Consumers signal that they are done with the buffer by calling
371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// RelinquishConsumerHold().
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// Buffers are allocated on demand, but there will never be more than |count|
401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// buffers in existence at any time. Buffers are identified by an int value
411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// called |buffer_id|. -1 (kInvalidId) is never a valid ID, and is returned by
421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// some methods to indicate failure. The active set of buffer ids may change
431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// over the lifetime of the buffer pool, as existing buffers are freed and
441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// reallocated at larger size. When reallocation occurs, new buffer IDs will
451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// circulate.
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class CONTENT_EXPORT VideoCaptureBufferPool
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : public base::RefCountedThreadSafe<VideoCaptureBufferPool> {
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  static const int kInvalidId;
501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  explicit VideoCaptureBufferPool(int count);
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // One-time (per client/per-buffer) initialization to share a particular
531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // buffer to a process. The size of the allocation is returned as
541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // |memory_size|.
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::SharedMemoryHandle ShareToProcess(int buffer_id,
561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                          base::ProcessHandle process_handle,
571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                          size_t* memory_size);
581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
59f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Query the memory parameters of |buffer_id|. Fills in parameters in the
60f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // pointer arguments, and returns true iff the buffer exists.
61f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  bool GetBufferInfo(int buffer_id, void** memory, size_t* size);
62f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Reserve or allocate a buffer of at least |size| bytes and return its id.
641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // This will fail (returning kInvalidId) if the pool already is at its |count|
651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // limit of the number of allocations, and all allocated buffers are in use by
661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // the producer and/or consumers.
671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  //
681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // If successful, the reserved buffer remains reserved (and writable by the
69eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // producer) until ownership is transferred either to the consumer via
70eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // HoldForConsumers(), or back to the pool with
71eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // RelinquishProducerReservation().
721e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  //
731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // On occasion, this call will decide to free an old buffer to make room for a
741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // new allocation at a larger size. If so, the ID of the destroyed buffer is
751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // returned via |buffer_id_to_drop|.
761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  int ReserveForProducer(size_t size, int* buffer_id_to_drop);
77eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
78eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Indicate that a buffer held for the producer should be returned back to the
79eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // pool without passing on to the consumer. This effectively is the opposite
80eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // of ReserveForProducer().
81eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  void RelinquishProducerReservation(int buffer_id);
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Transfer a buffer from producer to consumer ownership.
84eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // |buffer_id| must be a buffer index previously returned by
85eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // ReserveForProducer(), and not already passed to HoldForConsumers().
86eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  void HoldForConsumers(int buffer_id, int num_clients);
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Indicate that one or more consumers are done with a particular buffer. This
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // effectively is the opposite of HoldForConsumers(). Once the consumers are
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // done, a buffer is returned to the pool for reuse.
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void RelinquishConsumerHold(int buffer_id, int num_clients);
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int count() const { return count_; }
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  friend class base::RefCountedThreadSafe<VideoCaptureBufferPool>;
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Per-buffer state.
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  struct Buffer {
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Buffer();
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // The memory created to be shared with renderer processes.
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::SharedMemory shared_memory;
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Tracks whether this buffer is currently referenced by the producer.
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool held_by_producer;
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Number of consumer processes which hold this shared memory.
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int consumer_hold_count;
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  typedef std::map<int, Buffer*> BufferMap;
1131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~VideoCaptureBufferPool();
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  int ReserveForProducerInternal(size_t size, int* buffer_id_to_drop);
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  Buffer* GetBuffer(int buffer_id);
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // The max number of buffers that the pool is allowed to have at any moment.
1211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  const int count_;
1221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Protects everything below it.
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::Lock lock_;
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // The ID of the next buffer.
1271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  int next_buffer_id_;
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // The buffers, indexed by |buffer_id|.
1301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  BufferMap buffers_;
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DISALLOW_IMPLICIT_CONSTRUCTORS(VideoCaptureBufferPool);
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace content
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif  // CONTENT_BROWSER_RENDERER_HOST_MEDIA_VIDEO_CAPTURE_BUFFER_POOL_H_
138