blob: 8a18156bc171ce60489e7f0a4850a528502d875f [file] [log] [blame]
* Copyright 2012 Google Inc. All Rights Reserved.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* See the License for the specific language governing permissions and
* limitations under the License.
#include <list>
#include <map>
#include "base/callback.h"
#include "base/memory/ref_counted.h"
#include "base/synchronization/lock.h"
#include "base/synchronization/waitable_event.h"
#include "media/base/decoder_buffer.h"
#include "media/base/media_export.h"
namespace media {
static const size_t kShellMaxArraySize = 1024 * 1024;
class DecoderBuffer;
class DecryptConfig;
class ShellBufferFactory;
// A simple scoped array class designed to re-use the memory allocated by
// ShellBufferFactory. If needed would be trivial to make generic.
class MEDIA_EXPORT ShellScopedArray
: public base::RefCountedThreadSafe<ShellScopedArray> {
uint8* Get() { return array_; }
size_t Size() { return size_; }
friend class base::RefCountedThreadSafe<ShellScopedArray>;
friend class ShellBufferFactory;
// Should only be called by ShellBufferFactory, consumers should use
// ShellBufferFactory::AllocateArray to allocate a ShellScopedArray
ShellScopedArray(uint8* resuable_buffer, size_t size);
virtual ~ShellScopedArray();
uint8* array_;
size_t size_;
scoped_refptr<ShellBufferFactory> buffer_factory_;
// Singleton instance class for the management and recycling of media-related
// buffers. It is assumed that the usage pattern of these buffers is that they
// are used for only a short amount of time, and their allocation is roughly
// cyclical. All buffers are allocated using the alignment constants defined
// above, and all buffers are allocated from the shared pool of memory of
// size defined above.
class MEDIA_EXPORT ShellBufferFactory
: public base::RefCountedThreadSafe<ShellBufferFactory> {
static void Initialize();
static inline scoped_refptr<ShellBufferFactory> Instance() {
return instance_;
typedef base::Callback<void(scoped_refptr<DecoderBuffer>)> AllocCB;
// Returns false if the allocator will never be able to allocate a buffer
// of the requested size. Note that if memory is currently available this
// function will call the callback provided _before_ returning true.
bool AllocateBuffer(size_t size, bool is_keyframe, AllocCB cb);
// This function tries to allocate a DecoderBuffer immediately. It returns
// NULL on failure.
scoped_refptr<DecoderBuffer> AllocateBufferNow(size_t size, bool is_keyframe);
// Returns a newly allocated byte field if there's room for it, or NULL if
// there isn't. Note that this raw allocation method provides no guarantee
// that ShellBufferFactory will still exist when the memory is to be freed.
// If that is important please retain a reference to the buffer factory
// (using Instance()) until the memory is to be reclaimed.
uint8* AllocateNow(size_t size);
// BLOCKS THE CALLING THREAD until an array of size is available and can be
// allocated. We only allow one thread to block on an array allocation at a
// time, all subsequents calls on other threads to AllocateArray will assert
// and return NULL.
scoped_refptr<ShellScopedArray> AllocateArray(size_t size);
// Only called by DecoderBuffer and ShellScopedArray, informs the factory
// that these objects have gone out of scoped and we can reclaim the memory
void Reclaim(uint8* p);
static void Terminate();
friend class base::RefCountedThreadSafe<ShellBufferFactory>;
uint8* Allocate_Locked(size_t aligned_size);
static scoped_refptr<ShellBufferFactory> instance_;
// protects all following members.
base::Lock lock_;
// queue of pending buffer allocation requests and their sizes
typedef std::list<std::pair<AllocCB, scoped_refptr<DecoderBuffer> > >
AllocList pending_allocs_;
// event used for blocking calls for array allocation
base::WaitableEvent array_allocation_event_;
// set to 0 when no thread is blocking on an array allocation
size_t array_requested_size_;
// set to an allocation address when allocation has succeeded
uint8* array_allocation_;
} // namespace media