// 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.

#ifndef MEDIA_BASE_AUDIO_BLOCK_FIFO_H_
#define MEDIA_BASE_AUDIO_BLOCK_FIFO_H_

#include "base/macros.h"
#include "base/memory/scoped_vector.h"
#include "media/base/audio_bus.h"
#include "media/base/media_export.h"

namespace media {

// First-in first-out container for AudioBus elements.
// The FIFO is composed of blocks of AudioBus elements, it accepts interleaved
// data as input and will deinterleave it into the FIFO, and it only allows
// consuming a whole block of AudioBus element.
// This class is thread-unsafe.
class MEDIA_EXPORT AudioBlockFifo {
 public:
  // Creates a new AudioBlockFifo and allocates |blocks| memory, each block
  // of memory can store |channels| of length |frames| data.
  AudioBlockFifo(int channels, int frames, int blocks);
  virtual ~AudioBlockFifo();

  // Pushes interleaved audio data from |source| to the FIFO.
  // The method will deinterleave the data into a audio bus.
  // Push() will crash if the allocated space is insufficient.
  void Push(const void* source, int frames, int bytes_per_sample);

  // Consumes a block of audio from the FIFO.  Returns an AudioBus which
  // contains the consumed audio data to avoid copying.
  // Consume() will crash if the FIFO does not contain a block of data.
  const AudioBus* Consume();

  // Empties the FIFO without deallocating any memory.
  void Clear();

  // Number of available block of memory ready to be consumed in the FIFO.
  int available_blocks() const { return available_blocks_; }

  // Number of available frames of data in the FIFO.
  int GetAvailableFrames() const;

  // Number of unfilled frames in the whole FIFO.
  int GetUnfilledFrames() const;

  // Dynamically increase |blocks| of memory to the FIFO.
  void IncreaseCapacity(int blocks);

 private:
  // The actual FIFO is a vector of audio buses.
  ScopedVector<AudioBus> audio_blocks_;

  // Number of channels in AudioBus.
  const int channels_;

  // Maximum number of frames of data one block of memory can contain.
  // This value is set by |frames| in the constructor.
  const int block_frames_;

  // Used to keep track which block of memory to be written.
  int write_block_;

  // Used to keep track which block of memory to be consumed.
  int read_block_;

  // Number of available blocks of memory to be consumed.
  int available_blocks_;

  // Current write position in the current written block.
  int write_pos_;

  DISALLOW_COPY_AND_ASSIGN(AudioBlockFifo);
};

}  // namespace media

#endif  // MEDIA_BASE_AUDIO_BLOCK_FIFO_H_
