11320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Copyright 2014 The Chromium Authors. All rights reserved. 21320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Use of this source code is governed by a BSD-style license that can be 31320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// found in the LICENSE file. 41320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 51320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#ifndef CHROMECAST_MEDIA_CMA_IPC_MEDIA_MESSAGE_FIFO_H_ 61320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#define CHROMECAST_MEDIA_CMA_IPC_MEDIA_MESSAGE_FIFO_H_ 71320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 81320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include <list> 91320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/atomicops.h" 111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/basictypes.h" 121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/callback.h" 131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/logging.h" 141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/macros.h" 151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/memory/ref_counted.h" 161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/memory/scoped_ptr.h" 171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/memory/weak_ptr.h" 181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/threading/thread_checker.h" 191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccinamespace chromecast { 211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccinamespace media { 221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciclass MediaMemoryChunk; 231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciclass MediaMessage; 241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciclass MediaMessageFlag; 251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// MediaMessageFifo is a lock free fifo implementation 271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// to pass audio/video data from one thread to another or from one process 281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// to another one (in that case using shared memory). 291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// 301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Assuming the feeder and the consumer have a common block of shared memory 311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// (representing the serialized structure of the fifo), 321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// the feeder (which must be running on a single thread) instantiates its own 331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// instance of MediaMessageFifo, same applies to the consumer. 341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// 351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Example: assuming the block of shared memory is given by |mem|, a typical 361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// feeder (using MediaMessageFifo instance fifo_feeder) will push messages 371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// in the following way: 381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// // Create a dummy message to calculate the size of the serialized message. 391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// scoped_ptr<MediaMessage> dummy_msg( 401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// MediaMessage::CreateDummyMessage(msg_type)); 411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// // ... 421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// // Write all the fields to the dummy message. 431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// // ... 441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// 451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// // Create the real message, once the size of the serialized message 461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// // is known. 471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// scoped_ptr<MediaMessage> msg( 481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// MediaMessage::CreateMessage( 491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// msg_type, 501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// base::Bind(&MediaMessageFifo::ReserveMemory, 511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// base::Unretained(fifo_feeder.get())), 521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// dummy_msg->content_size())); 531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// if (!msg) { 541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// // Not enough space for the message: 551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// // retry later (e.g. when receiving a read activity event, meaning 561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// // some enough space might have been release). 571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// return; 581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// } 591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// // ... 601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// // Write all the fields to the real message 611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// // in exactly the same way it was done for the dummy message. 621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// // ... 631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// // Once message |msg| is going out of scope, then MediaMessageFifo 641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// // fifo_feeder is informed that the message is not needed anymore 651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// // (i.e. it was fully written), and fifo_feeder can then update 661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// // the external write pointer of the fifo so that the consumer 671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// // can start consuming this message. 681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// 691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// A typical consumer (using MediaMessageFifo instance fifo_consumer) 701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// will retrive messages in the following way: 711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// scoped_ptr<MediaMessage> msg(fifo_consumer->Pop()); 721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// if (!msg) { 731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// // The fifo is empty, i.e. no message left. 741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// // Try reading again later (e.g. after receiving a write activity event. 751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// return; 761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// } 771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// // Parse the message using Read functions of MediaMessage: 781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// // ... 791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// // Once the message is going out of scope, MediaMessageFifo will receive 801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// // a notification that the underlying memory can be released 811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// // (i.e. the external read pointer can be updated). 821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// 831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// 841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciclass MediaMessageFifo { 851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci public: 861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Creates a media message fifo using |mem| as the underlying serialized 871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // structure. 881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // If |init| is true, the underlying fifo structure is initialized. 891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci MediaMessageFifo(scoped_ptr<MediaMemoryChunk> mem, bool init); 901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ~MediaMessageFifo(); 911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // When the consumer and the feeder are living in two different processes, 931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // we might want to convey some messages between these two processes to notify 941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // about some fifo activity. 951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci void ObserveReadActivity(const base::Closure& read_event_cb); 961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci void ObserveWriteActivity(const base::Closure& write_event_cb); 971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Reserves a writeable block of memory at the back of the fifo, 991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // corresponding to the serialized structure of the message. 1001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Returns NULL if the required size cannot be allocated. 1011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_ptr<MediaMemoryChunk> ReserveMemory(size_t size); 1021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Pop a message from the queue. 1041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Returns a null pointer if there is no message left. 1051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_ptr<MediaMessage> Pop(); 1061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Flush the fifo. 1081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci void Flush(); 1091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci private: 1111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci struct Descriptor { 1121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci size_t size; 1131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci size_t rd_offset; 1141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci size_t wr_offset; 1151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Ensure the first item has the same alignment as an int64. 1171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int64 first_item; 1181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci }; 1191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Add some accessors to ensure security on the browser process side. 1211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci size_t current_rd_offset() const; 1221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci size_t current_wr_offset() const; 1231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci size_t internal_rd_offset() const { 1241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK_LT(internal_rd_offset_, size_); 1251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return internal_rd_offset_; 1261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci size_t internal_wr_offset() const { 1281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK_LT(internal_wr_offset_, size_); 1291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return internal_wr_offset_; 1301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Reserve a block of free memory without doing any check on the available 1331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // space. Invoke this function only when all the checks have been done. 1341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_ptr<MediaMemoryChunk> ReserveMemoryNoCheck(size_t size); 1351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Invoked each time there is a memory region in the free space of the fifo 1371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // that has possibly been written. 1381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci void OnWrMemoryReleased(); 1391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Invoked each time there is a memory region in the allocated space 1411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // of the fifo that has possibly been released. 1421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci void OnRdMemoryReleased(); 1431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Functions to modify the internal/external read/write pointers. 1451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci void CommitRead(size_t new_rd_offset); 1461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci void CommitWrite(size_t new_wr_offset); 1471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci void CommitInternalRead(size_t new_rd_offset); 1481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci void CommitInternalWrite(size_t new_wr_offset); 1491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // An instance of MediaMessageFifo must be running on a single thread. 1511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // If the fifo feeder and consumer are living on 2 different threads 1521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // or 2 different processes, they must create their own instance 1531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // of MediaMessageFifo using the same underlying block of (shared) memory 1541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // in the constructor. 1551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::ThreadChecker thread_checker_; 1561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Callbacks invoked to notify either of some read or write activity on the 1581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // fifo. This is especially useful when the feeder and consumer are living in 1591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // two different processes. 1601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Closure read_event_cb_; 1611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Closure write_event_cb_; 1621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // The serialized structure of the fifo. 1641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_ptr<MediaMemoryChunk> mem_; 1651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // The size in bytes of the fifo is cached locally for security purpose. 1671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // (the renderer process cannot modify the size and make the browser process 1681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // access out of range addresses). 1691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci size_t size_; 1701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // TODO(damienv): This is a work-around since atomicops.h does not define 1721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // an atomic size_t type. 1731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if SIZE_MAX == UINT32_MAX 1741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci typedef base::subtle::Atomic32 AtomicSize; 1751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#elif SIZE_MAX == UINT64_MAX 1761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci typedef base::subtle::Atomic64 AtomicSize; 1771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#elif 1781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#error "Unsupported size_t" 1791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif 1801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci AtomicSize* rd_offset_; 1811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci AtomicSize* wr_offset_; 1821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Internal read offset: this is where data is actually read from. 1841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // The external offset |rd_offset_| is only used to protect data from being 1851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // overwritten by the feeder. 1861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // At any time, the internal read pointer must be between the external read 1871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // offset and the write offset (circular fifo definition of "between"). 1881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci size_t internal_rd_offset_; 1891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci size_t internal_wr_offset_; 1901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Note: all the memory read/write are followed by a memory fence before 1921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // updating the rd/wr pointer. 1931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci void* base_; 1941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Protects the messages that are either being read or written. 1961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci std::list<scoped_refptr<MediaMessageFlag> > rd_flags_; 1971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci std::list<scoped_refptr<MediaMessageFlag> > wr_flags_; 1981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::WeakPtrFactory<MediaMessageFifo> weak_factory_; 2001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::WeakPtr<MediaMessageFifo> weak_this_; 2011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DISALLOW_COPY_AND_ASSIGN(MediaMessageFifo); 2031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}; 2041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} // namespace media 2061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} // namespace chromecast 2071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif // CHROMECAST_MEDIA_CMA_IPC_MEDIA_MESSAGE_FIFO_H_ 209