| Index: chromecast/media/cma/ipc/media_message_fifo.cc
|
| diff --git a/chromecast/media/cma/ipc/media_message_fifo.cc b/chromecast/media/cma/ipc/media_message_fifo.cc
|
| deleted file mode 100644
|
| index 7fff0a65f0ad2ecaae3c5ea2df1e4cc4a36c2ae1..0000000000000000000000000000000000000000
|
| --- a/chromecast/media/cma/ipc/media_message_fifo.cc
|
| +++ /dev/null
|
| @@ -1,405 +0,0 @@
|
| -// Copyright 2014 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#include "chromecast/media/cma/ipc/media_message_fifo.h"
|
| -
|
| -#include <utility>
|
| -
|
| -#include "base/atomicops.h"
|
| -#include "base/bind.h"
|
| -#include "base/location.h"
|
| -#include "base/logging.h"
|
| -#include "base/macros.h"
|
| -#include "base/single_thread_task_runner.h"
|
| -#include "base/threading/thread_task_runner_handle.h"
|
| -#include "chromecast/media/cma/base/cma_logging.h"
|
| -#include "chromecast/media/cma/ipc/media_memory_chunk.h"
|
| -#include "chromecast/media/cma/ipc/media_message.h"
|
| -#include "chromecast/media/cma/ipc/media_message_type.h"
|
| -
|
| -namespace chromecast {
|
| -namespace media {
|
| -
|
| -class MediaMessageFlag
|
| - : public base::RefCountedThreadSafe<MediaMessageFlag> {
|
| - public:
|
| - // |offset| is the offset in the fifo of the media message.
|
| - explicit MediaMessageFlag(size_t offset);
|
| -
|
| - bool IsValid() const;
|
| -
|
| - void Invalidate();
|
| -
|
| - size_t offset() const { return offset_; }
|
| -
|
| - private:
|
| - friend class base::RefCountedThreadSafe<MediaMessageFlag>;
|
| - virtual ~MediaMessageFlag();
|
| -
|
| - const size_t offset_;
|
| - bool flag_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(MediaMessageFlag);
|
| -};
|
| -
|
| -MediaMessageFlag::MediaMessageFlag(size_t offset)
|
| - : offset_(offset),
|
| - flag_(true) {
|
| -}
|
| -
|
| -MediaMessageFlag::~MediaMessageFlag() {
|
| -}
|
| -
|
| -bool MediaMessageFlag::IsValid() const {
|
| - return flag_;
|
| -}
|
| -
|
| -void MediaMessageFlag::Invalidate() {
|
| - flag_ = false;
|
| -}
|
| -
|
| -class FifoOwnedMemory : public MediaMemoryChunk {
|
| - public:
|
| - FifoOwnedMemory(void* data, size_t size,
|
| - const scoped_refptr<MediaMessageFlag>& flag,
|
| - const base::Closure& release_msg_cb);
|
| - ~FifoOwnedMemory() override;
|
| -
|
| - // MediaMemoryChunk implementation.
|
| - void* data() const override { return data_; }
|
| - size_t size() const override { return size_; }
|
| - bool valid() const override { return flag_->IsValid(); }
|
| -
|
| - private:
|
| - scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
|
| - base::Closure release_msg_cb_;
|
| -
|
| - void* const data_;
|
| - const size_t size_;
|
| - scoped_refptr<MediaMessageFlag> flag_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(FifoOwnedMemory);
|
| -};
|
| -
|
| -FifoOwnedMemory::FifoOwnedMemory(void* data,
|
| - size_t size,
|
| - const scoped_refptr<MediaMessageFlag>& flag,
|
| - const base::Closure& release_msg_cb)
|
| - : task_runner_(base::ThreadTaskRunnerHandle::Get()),
|
| - release_msg_cb_(release_msg_cb),
|
| - data_(data),
|
| - size_(size),
|
| - flag_(flag) {
|
| -}
|
| -
|
| -FifoOwnedMemory::~FifoOwnedMemory() {
|
| - // Release the flag before notifying that the message has been released.
|
| - flag_ = scoped_refptr<MediaMessageFlag>();
|
| - if (!release_msg_cb_.is_null()) {
|
| - if (task_runner_->BelongsToCurrentThread()) {
|
| - release_msg_cb_.Run();
|
| - } else {
|
| - task_runner_->PostTask(FROM_HERE, release_msg_cb_);
|
| - }
|
| - }
|
| -}
|
| -
|
| -MediaMessageFifo::MediaMessageFifo(std::unique_ptr<MediaMemoryChunk> mem,
|
| - bool init)
|
| - : mem_(std::move(mem)), weak_factory_(this) {
|
| - CHECK_EQ(reinterpret_cast<uintptr_t>(mem_->data()) % ALIGNOF(Descriptor),
|
| - 0u);
|
| - CHECK_GE(mem_->size(), sizeof(Descriptor));
|
| - Descriptor* desc = static_cast<Descriptor*>(mem_->data());
|
| - base_ = static_cast<void*>(&desc->first_item);
|
| -
|
| - // TODO(damienv): remove cast when atomic size_t is defined in Chrome.
|
| - // Currently, the sign differs.
|
| - rd_offset_ = reinterpret_cast<AtomicSize*>(&(desc->rd_offset));
|
| - wr_offset_ = reinterpret_cast<AtomicSize*>(&(desc->wr_offset));
|
| -
|
| - size_t max_size = mem_->size() -
|
| - (static_cast<char*>(base_) - static_cast<char*>(mem_->data()));
|
| - if (init) {
|
| - size_ = max_size;
|
| - desc->size = size_;
|
| - internal_rd_offset_ = 0;
|
| - internal_wr_offset_ = 0;
|
| - base::subtle::Release_Store(rd_offset_, 0);
|
| - base::subtle::Release_Store(wr_offset_, 0);
|
| - } else {
|
| - size_ = desc->size;
|
| - CHECK_LE(size_, max_size);
|
| - internal_rd_offset_ = current_rd_offset();
|
| - internal_wr_offset_ = current_wr_offset();
|
| - }
|
| - CMALOG(kLogControl)
|
| - << "MediaMessageFifo:" << " init=" << init << " size=" << size_;
|
| - CHECK_GT(size_, 0u) << size_;
|
| -
|
| - weak_this_ = weak_factory_.GetWeakPtr();
|
| - thread_checker_.DetachFromThread();
|
| -}
|
| -
|
| -MediaMessageFifo::~MediaMessageFifo() {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| -}
|
| -
|
| -void MediaMessageFifo::ObserveReadActivity(
|
| - const base::Closure& read_event_cb) {
|
| - read_event_cb_ = read_event_cb;
|
| -}
|
| -
|
| -void MediaMessageFifo::ObserveWriteActivity(
|
| - const base::Closure& write_event_cb) {
|
| - write_event_cb_ = write_event_cb;
|
| -}
|
| -
|
| -std::unique_ptr<MediaMemoryChunk> MediaMessageFifo::ReserveMemory(
|
| - size_t size_to_reserve) {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| -
|
| - // Capture first both the read and write offsets.
|
| - // and exit right away if not enough free space.
|
| - size_t wr_offset = internal_wr_offset();
|
| - size_t rd_offset = current_rd_offset();
|
| - size_t allocated_size = (size_ + wr_offset - rd_offset) % size_;
|
| - size_t free_size = size_ - 1 - allocated_size;
|
| - if (free_size < size_to_reserve)
|
| - return std::unique_ptr<MediaMemoryChunk>();
|
| - CHECK_LE(MediaMessage::minimum_msg_size(), size_to_reserve);
|
| -
|
| - // Note: in the next 2 conditions, we have:
|
| - // trailing_byte_count < size_to_reserve
|
| - // and since at this stage: size_to_reserve <= free_size
|
| - // we also have trailing_byte_count <= free_size
|
| - // which means that all the trailing bytes are free space in the fifo.
|
| - size_t trailing_byte_count = size_ - wr_offset;
|
| - if (trailing_byte_count < MediaMessage::minimum_msg_size()) {
|
| - // If there is no space to even write the smallest message,
|
| - // skip the trailing bytes and come back to the beginning of the fifo.
|
| - // (no way to insert a padding message).
|
| - if (free_size < trailing_byte_count)
|
| - return std::unique_ptr<MediaMemoryChunk>();
|
| - wr_offset = 0;
|
| - CommitInternalWrite(wr_offset);
|
| -
|
| - } else if (trailing_byte_count < size_to_reserve) {
|
| - // At this point, we know we have at least the space to write a message.
|
| - // However, to avoid splitting a message, a padding message is needed.
|
| - std::unique_ptr<MediaMemoryChunk> mem(
|
| - ReserveMemoryNoCheck(trailing_byte_count));
|
| - std::unique_ptr<MediaMessage> padding_message(
|
| - MediaMessage::CreateMessage(PaddingMediaMsg, std::move(mem)));
|
| - }
|
| -
|
| - // Recalculate the free size and exit if not enough free space.
|
| - wr_offset = internal_wr_offset();
|
| - allocated_size = (size_ + wr_offset - rd_offset) % size_;
|
| - free_size = size_ - 1 - allocated_size;
|
| - if (free_size < size_to_reserve)
|
| - return std::unique_ptr<MediaMemoryChunk>();
|
| -
|
| - return ReserveMemoryNoCheck(size_to_reserve);
|
| -}
|
| -
|
| -std::unique_ptr<MediaMessage> MediaMessageFifo::Pop() {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| -
|
| - // Capture the read and write offsets.
|
| - size_t rd_offset = internal_rd_offset();
|
| - size_t wr_offset = current_wr_offset();
|
| - size_t allocated_size = (size_ + wr_offset - rd_offset) % size_;
|
| -
|
| - if (allocated_size < MediaMessage::minimum_msg_size())
|
| - return std::unique_ptr<MediaMessage>();
|
| -
|
| - size_t trailing_byte_count = size_ - rd_offset;
|
| - if (trailing_byte_count < MediaMessage::minimum_msg_size()) {
|
| - // If there is no space to even have the smallest message,
|
| - // skip the trailing bytes and come back to the beginning of the fifo.
|
| - // Note: all the trailing bytes correspond to allocated bytes since:
|
| - // trailing_byte_count < MediaMessage::minimum_msg_size() <= allocated_size
|
| - rd_offset = 0;
|
| - allocated_size -= trailing_byte_count;
|
| - trailing_byte_count = size_;
|
| - CommitInternalRead(rd_offset);
|
| - }
|
| -
|
| - // The message should not be longer than the allocated size
|
| - // but since a message is a contiguous area of memory, it should also be
|
| - // smaller than |trailing_byte_count|.
|
| - size_t max_msg_size = std::min(allocated_size, trailing_byte_count);
|
| - if (max_msg_size < MediaMessage::minimum_msg_size())
|
| - return std::unique_ptr<MediaMessage>();
|
| - void* msg_src = static_cast<uint8_t*>(base_) + rd_offset;
|
| -
|
| - // Create a flag to protect the serialized structure of the message
|
| - // from being overwritten.
|
| - // The serialized structure starts at offset |rd_offset|.
|
| - scoped_refptr<MediaMessageFlag> rd_flag(new MediaMessageFlag(rd_offset));
|
| - rd_flags_.push_back(rd_flag);
|
| - std::unique_ptr<MediaMemoryChunk> mem(new FifoOwnedMemory(
|
| - msg_src, max_msg_size, rd_flag,
|
| - base::Bind(&MediaMessageFifo::OnRdMemoryReleased, weak_this_)));
|
| -
|
| - // Create the message which wraps its the serialized structure.
|
| - std::unique_ptr<MediaMessage> message(
|
| - MediaMessage::MapMessage(std::move(mem)));
|
| - CHECK(message);
|
| -
|
| - // Update the internal read pointer.
|
| - rd_offset = (rd_offset + message->size()) % size_;
|
| - CommitInternalRead(rd_offset);
|
| -
|
| - return message;
|
| -}
|
| -
|
| -void MediaMessageFifo::Flush() {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| -
|
| - size_t wr_offset = current_wr_offset();
|
| -
|
| - // Invalidate every memory region before flushing.
|
| - while (!rd_flags_.empty()) {
|
| - CMALOG(kLogControl) << "Invalidate flag";
|
| - rd_flags_.front()->Invalidate();
|
| - rd_flags_.pop_front();
|
| - }
|
| -
|
| - // Flush by setting the read pointer to the value of the write pointer.
|
| - // Update first the internal read pointer then the public one.
|
| - CommitInternalRead(wr_offset);
|
| - CommitRead(wr_offset);
|
| -}
|
| -
|
| -std::unique_ptr<MediaMemoryChunk> MediaMessageFifo::ReserveMemoryNoCheck(
|
| - size_t size_to_reserve) {
|
| - size_t wr_offset = internal_wr_offset();
|
| -
|
| - // Memory block corresponding to the serialized structure of the message.
|
| - void* msg_start = static_cast<uint8_t*>(base_) + wr_offset;
|
| - scoped_refptr<MediaMessageFlag> wr_flag(new MediaMessageFlag(wr_offset));
|
| - wr_flags_.push_back(wr_flag);
|
| - std::unique_ptr<MediaMemoryChunk> mem(new FifoOwnedMemory(
|
| - msg_start, size_to_reserve, wr_flag,
|
| - base::Bind(&MediaMessageFifo::OnWrMemoryReleased, weak_this_)));
|
| -
|
| - // Update the internal write pointer.
|
| - wr_offset = (wr_offset + size_to_reserve) % size_;
|
| - CommitInternalWrite(wr_offset);
|
| -
|
| - return mem;
|
| -}
|
| -
|
| -void MediaMessageFifo::OnWrMemoryReleased() {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| -
|
| - if (wr_flags_.empty()) {
|
| - // Sanity check: when there is no protected memory area,
|
| - // the external write offset has no reason to be different from
|
| - // the internal write offset.
|
| - DCHECK_EQ(current_wr_offset(), internal_wr_offset());
|
| - return;
|
| - }
|
| -
|
| - // Update the external write offset.
|
| - while (!wr_flags_.empty() &&
|
| - (!wr_flags_.front()->IsValid() || wr_flags_.front()->HasOneRef())) {
|
| - // TODO(damienv): Could add a sanity check to make sure the offset is
|
| - // between the external write offset and the read offset (not included).
|
| - wr_flags_.pop_front();
|
| - }
|
| -
|
| - // Update the read offset to the first locked memory area
|
| - // or to the internal read pointer if nothing prevents it.
|
| - size_t external_wr_offset = internal_wr_offset();
|
| - if (!wr_flags_.empty())
|
| - external_wr_offset = wr_flags_.front()->offset();
|
| - CommitWrite(external_wr_offset);
|
| -}
|
| -
|
| -void MediaMessageFifo::OnRdMemoryReleased() {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| -
|
| - if (rd_flags_.empty()) {
|
| - // Sanity check: when there is no protected memory area,
|
| - // the external read offset has no reason to be different from
|
| - // the internal read offset.
|
| - DCHECK_EQ(current_rd_offset(), internal_rd_offset());
|
| - return;
|
| - }
|
| -
|
| - // Update the external read offset.
|
| - while (!rd_flags_.empty() &&
|
| - (!rd_flags_.front()->IsValid() || rd_flags_.front()->HasOneRef())) {
|
| - // TODO(damienv): Could add a sanity check to make sure the offset is
|
| - // between the external read offset and the write offset.
|
| - rd_flags_.pop_front();
|
| - }
|
| -
|
| - // Update the read offset to the first locked memory area
|
| - // or to the internal read pointer if nothing prevents it.
|
| - size_t external_rd_offset = internal_rd_offset();
|
| - if (!rd_flags_.empty())
|
| - external_rd_offset = rd_flags_.front()->offset();
|
| - CommitRead(external_rd_offset);
|
| -}
|
| -
|
| -size_t MediaMessageFifo::current_rd_offset() const {
|
| - DCHECK_EQ(sizeof(size_t), sizeof(AtomicSize));
|
| - size_t rd_offset = base::subtle::Acquire_Load(rd_offset_);
|
| - CHECK_LT(rd_offset, size_);
|
| - return rd_offset;
|
| -}
|
| -
|
| -size_t MediaMessageFifo::current_wr_offset() const {
|
| - DCHECK_EQ(sizeof(size_t), sizeof(AtomicSize));
|
| -
|
| - // When the fifo consumer acquires the write offset,
|
| - // we have to make sure that any possible following reads are actually
|
| - // returning results at least inline with the memory snapshot taken
|
| - // when the write offset was sampled.
|
| - // That's why an Acquire_Load is used here.
|
| - size_t wr_offset = base::subtle::Acquire_Load(wr_offset_);
|
| - CHECK_LT(wr_offset, size_);
|
| - return wr_offset;
|
| -}
|
| -
|
| -void MediaMessageFifo::CommitRead(size_t new_rd_offset) {
|
| - // Add a memory fence to ensure the message content is completely read
|
| - // before updating the read offset.
|
| - base::subtle::Release_Store(rd_offset_, new_rd_offset);
|
| -
|
| - // Since rd_offset_ is updated by a release_store above, any thread that
|
| - // does acquire_load is guaranteed to see the new rd_offset_ set above.
|
| - // So it is safe to send the notification.
|
| - if (!read_event_cb_.is_null()) {
|
| - read_event_cb_.Run();
|
| - }
|
| -}
|
| -
|
| -void MediaMessageFifo::CommitWrite(size_t new_wr_offset) {
|
| - // Add a memory fence to ensure the message content is written
|
| - // before updating the write offset.
|
| - base::subtle::Release_Store(wr_offset_, new_wr_offset);
|
| -
|
| - // Since wr_offset_ is updated by a release_store above, any thread that
|
| - // does acquire_load is guaranteed to see the new wr_offset_ set above.
|
| - // So it is safe to send the notification.
|
| - if (!write_event_cb_.is_null()) {
|
| - write_event_cb_.Run();
|
| - }
|
| -}
|
| -
|
| -void MediaMessageFifo::CommitInternalRead(size_t new_rd_offset) {
|
| - internal_rd_offset_ = new_rd_offset;
|
| -}
|
| -
|
| -void MediaMessageFifo::CommitInternalWrite(size_t new_wr_offset) {
|
| - internal_wr_offset_ = new_wr_offset;
|
| -}
|
| -
|
| -} // namespace media
|
| -} // namespace chromecast
|
|
|