This source file includes following definitions.
- next_buffer_id_
- ShareToProcess
- GetBufferInfo
- ReserveForProducer
- RelinquishProducerReservation
- HoldForConsumers
- RelinquishConsumerHold
- consumer_hold_count
- ReserveForProducerInternal
- GetBuffer
#include "content/browser/renderer_host/media/video_capture_buffer_pool.h"
#include "base/bind.h"
#include "base/callback.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/stl_util.h"
#include "media/base/video_frame.h"
#include "media/base/video_util.h"
namespace content {
const int VideoCaptureBufferPool::kInvalidId = -1;
VideoCaptureBufferPool::VideoCaptureBufferPool(int count)
: count_(count),
next_buffer_id_(0) {
}
VideoCaptureBufferPool::~VideoCaptureBufferPool() {
STLDeleteValues(&buffers_);
}
base::SharedMemoryHandle VideoCaptureBufferPool::ShareToProcess(
int buffer_id,
base::ProcessHandle process_handle,
size_t* memory_size) {
base::AutoLock lock(lock_);
Buffer* buffer = GetBuffer(buffer_id);
if (!buffer) {
NOTREACHED() << "Invalid buffer_id.";
return base::SharedMemory::NULLHandle();
}
base::SharedMemoryHandle remote_handle;
buffer->shared_memory.ShareToProcess(process_handle, &remote_handle);
*memory_size = buffer->shared_memory.requested_size();
return remote_handle;
}
bool VideoCaptureBufferPool::GetBufferInfo(int buffer_id,
void** memory,
size_t* size) {
base::AutoLock lock(lock_);
Buffer* buffer = GetBuffer(buffer_id);
if (!buffer) {
NOTREACHED() << "Invalid buffer_id.";
return false;
}
DCHECK(buffer->held_by_producer);
*memory = buffer->shared_memory.memory();
*size = buffer->shared_memory.mapped_size();
return true;
}
int VideoCaptureBufferPool::ReserveForProducer(size_t size,
int* buffer_id_to_drop) {
base::AutoLock lock(lock_);
return ReserveForProducerInternal(size, buffer_id_to_drop);
}
void VideoCaptureBufferPool::RelinquishProducerReservation(int buffer_id) {
base::AutoLock lock(lock_);
Buffer* buffer = GetBuffer(buffer_id);
if (!buffer) {
NOTREACHED() << "Invalid buffer_id.";
return;
}
DCHECK(buffer->held_by_producer);
buffer->held_by_producer = false;
}
void VideoCaptureBufferPool::HoldForConsumers(
int buffer_id,
int num_clients) {
base::AutoLock lock(lock_);
Buffer* buffer = GetBuffer(buffer_id);
if (!buffer) {
NOTREACHED() << "Invalid buffer_id.";
return;
}
DCHECK(buffer->held_by_producer);
DCHECK(!buffer->consumer_hold_count);
buffer->consumer_hold_count = num_clients;
}
void VideoCaptureBufferPool::RelinquishConsumerHold(int buffer_id,
int num_clients) {
base::AutoLock lock(lock_);
Buffer* buffer = GetBuffer(buffer_id);
if (!buffer) {
NOTREACHED() << "Invalid buffer_id.";
return;
}
DCHECK_GE(buffer->consumer_hold_count, num_clients);
buffer->consumer_hold_count -= num_clients;
}
VideoCaptureBufferPool::Buffer::Buffer()
: held_by_producer(false), consumer_hold_count(0) {}
int VideoCaptureBufferPool::ReserveForProducerInternal(size_t size,
int* buffer_id_to_drop) {
lock_.AssertAcquired();
*buffer_id_to_drop = kInvalidId;
size_t realloc_size = 0;
BufferMap::iterator realloc = buffers_.end();
for (BufferMap::iterator it = buffers_.begin(); it != buffers_.end(); ++it) {
Buffer* buffer = it->second;
if (!buffer->consumer_hold_count && !buffer->held_by_producer) {
if (buffer->shared_memory.requested_size() >= size) {
buffer->held_by_producer = true;
return it->first;
}
if (buffer->shared_memory.requested_size() > realloc_size) {
realloc_size = buffer->shared_memory.requested_size();
realloc = it;
}
}
}
if (buffers_.size() == static_cast<size_t>(count_)) {
if (realloc == buffers_.end()) {
return kInvalidId;
}
*buffer_id_to_drop = realloc->first;
delete realloc->second;
buffers_.erase(realloc);
}
int buffer_id = next_buffer_id_++;
scoped_ptr<Buffer> buffer(new Buffer());
if (size) {
if (!buffer->shared_memory.CreateAndMapAnonymous(size))
return kInvalidId;
}
buffer->held_by_producer = true;
buffers_[buffer_id] = buffer.release();
return buffer_id;
}
VideoCaptureBufferPool::Buffer* VideoCaptureBufferPool::GetBuffer(
int buffer_id) {
BufferMap::iterator it = buffers_.find(buffer_id);
if (it == buffers_.end())
return NULL;
return it->second;
}
}