| OLD | NEW | 
| (Empty) |  | 
 |    1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 
 |    2 // Use of this source code is governed by a BSD-style license that can be | 
 |    3 // found in the LICENSE file. | 
 |    4  | 
 |    5 #include "media/base/audio_fifo.h" | 
 |    6  | 
 |    7 #include "base/logging.h" | 
 |    8  | 
 |    9 namespace media { | 
 |   10  | 
 |   11 // Given current position in the FIFO, the maximum number of elements in the | 
 |   12 // FIFO and the size of the input; this method provides two output results: | 
 |   13 // |size| and |wrap_size|. These two results can then be utilized for memcopy | 
 |   14 // operations to and from the FIFO. | 
 |   15 // Under "normal" circumstances, |size| will be equal to |in_size| and | 
 |   16 // |wrap_size| will be zero. This case corresponding to the non-wrapping case | 
 |   17 // where we have not yet reached the "edge" of the FIFO. If |pos| + |in_size| | 
 |   18 // exceeds the total size of the FIFO, we must wrap around and start reusing | 
 |   19 // a part the allocated memory. The size of this part is given by |wrap_size|. | 
 |   20 static void GetSizes( | 
 |   21     int pos, int max_size, int in_size, int* size, int* wrap_size) { | 
 |   22   if (pos + in_size > max_size) { | 
 |   23     // Wrapping is required => derive size of each segment. | 
 |   24     *size = max_size - pos; | 
 |   25     *wrap_size = in_size - *size; | 
 |   26   } else { | 
 |   27     // Wrapping is not required. | 
 |   28     *size = in_size; | 
 |   29     *wrap_size = 0; | 
 |   30   } | 
 |   31 } | 
 |   32  | 
 |   33 // Updates the read/write position with |step| modulo the maximum number of | 
 |   34 // elements in the FIFO to ensure that the position counters wraps around at | 
 |   35 // the endpoint. | 
 |   36 static int UpdatePos(int pos, int step, int max_size) { | 
 |   37   return ((pos + step) % max_size); | 
 |   38 } | 
 |   39  | 
 |   40 AudioFifo::AudioFifo(int channels, int frames) | 
 |   41     : audio_bus_(AudioBus::Create(channels, frames)), | 
 |   42       max_frames_in_fifo_(frames), | 
 |   43       frames_in_fifo_(0), | 
 |   44       read_pos_(0), | 
 |   45       write_pos_(0) {} | 
 |   46  | 
 |   47 AudioFifo::~AudioFifo() {} | 
 |   48  | 
 |   49 bool AudioFifo::Push(const AudioBus* source) { | 
 |   50   DCHECK(source); | 
 |   51   DCHECK_EQ(source->channels(), audio_bus_->channels()); | 
 |   52  | 
 |   53   // Ensure that there is space for the new data in the FIFO. | 
 |   54   const int source_size = source->frames(); | 
 |   55   if (frames_in_fifo_ + source_size > max_frames()) { | 
 |   56     DLOG(ERROR) << "FIFO overflow."; | 
 |   57     return false; | 
 |   58   } | 
 |   59  | 
 |   60   // Figure out if wrapping is needed and if so what segment sizes we need | 
 |   61   // when adding the new audio bus content to the FIFO. | 
 |   62   int append_size = 0; | 
 |   63   int wrap_size = 0; | 
 |   64   GetSizes(write_pos_, max_frames(), source_size, &append_size, &wrap_size); | 
 |   65  | 
 |   66   // Copy all channels from the source to the FIFO. Wrap around if needed. | 
 |   67   for (int ch = 0; ch < source->channels(); ++ch) { | 
 |   68     float* dest = audio_bus_->channel(ch); | 
 |   69     const float* src = source->channel(ch); | 
 |   70  | 
 |   71     // Append part of (or the complete) source to the FIFO. | 
 |   72     memcpy(&dest[write_pos_], &src[0], append_size * sizeof(src[0])); | 
 |   73     if (wrap_size > 0) { | 
 |   74       // Wrapping is needed: copy remaining part from the source to the FIFO. | 
 |   75       memcpy(&dest[0], &src[append_size], wrap_size * sizeof(src[0])); | 
 |   76     } | 
 |   77   } | 
 |   78  | 
 |   79   frames_in_fifo_ += source_size; | 
 |   80   DCHECK_LE(frames_in_fifo_, max_frames()); | 
 |   81   write_pos_ = UpdatePos(write_pos_, source_size, max_frames()); | 
 |   82   return true; | 
 |   83 } | 
 |   84  | 
 |   85 bool AudioFifo::Consume(AudioBus* destination, int frames_to_consume) { | 
 |   86   DCHECK(destination); | 
 |   87   DCHECK_EQ(destination->channels(), audio_bus_->channels()); | 
 |   88  | 
 |   89   // It is not possible to ask for more data than what is available in the FIFO. | 
 |   90   if (frames_to_consume > frames_in_fifo_) { | 
 |   91     DLOG(ERROR) << "FIFO underrun."; | 
 |   92     return false; | 
 |   93   } | 
 |   94  | 
 |   95   // A copy from the FIFO to |destination| will only be performed if the | 
 |   96   // allocated memory in |destination| is sufficient. | 
 |   97   if (frames_to_consume > destination->frames()) { | 
 |   98     DLOG(ERROR) << "Insufficient space in destination."; | 
 |   99     return false; | 
 |  100   } | 
 |  101  | 
 |  102   // Figure out if wrapping is needed and if so what segment sizes we need | 
 |  103   // when removing audio bus content from the FIFO. | 
 |  104   int consume_size = 0; | 
 |  105   int wrap_size = 0; | 
 |  106   GetSizes(read_pos_, max_frames(), frames_to_consume, | 
 |  107            &consume_size, &wrap_size); | 
 |  108  | 
 |  109   // For all channels, remove the requested amount of data from the FIFO | 
 |  110   // and copy the content to the destination. Wrap around if needed. | 
 |  111   for (int ch = 0; ch < destination->channels(); ++ch) { | 
 |  112     float* dest = destination->channel(ch); | 
 |  113     const float* src = audio_bus_->channel(ch); | 
 |  114  | 
 |  115     // Copy a selected part of the FIFO to the destination. | 
 |  116     memcpy(&dest[0], &src[read_pos_], consume_size * sizeof(src[0])); | 
 |  117     if (wrap_size > 0) { | 
 |  118       // Wrapping is needed: copy remaining part to the destination. | 
 |  119       memcpy(&dest[consume_size], &src[0], wrap_size * sizeof(src[0])); | 
 |  120     } | 
 |  121   } | 
 |  122  | 
 |  123   frames_in_fifo_ -= frames_to_consume; | 
 |  124   read_pos_ = UpdatePos(read_pos_, frames_to_consume, max_frames()); | 
 |  125   return true; | 
 |  126 } | 
 |  127  | 
 |  128 void AudioFifo::Clear() { | 
 |  129   frames_in_fifo_ = 0; | 
 |  130   read_pos_ = 0; | 
 |  131   write_pos_ = 0; | 
 |  132 } | 
 |  133  | 
 |  134 }  // namespace media | 
| OLD | NEW |