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