Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Audio FIFO
  3.  * Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
  4.  *
  5.  * This file is part of FFmpeg.
  6.  *
  7.  * FFmpeg is free software; you can redistribute it and/or
  8.  * modify it under the terms of the GNU Lesser General Public
  9.  * License as published by the Free Software Foundation; either
  10.  * version 2.1 of the License, or (at your option) any later version.
  11.  *
  12.  * FFmpeg is distributed in the hope that it will be useful,
  13.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15.  * Lesser General Public License for more details.
  16.  *
  17.  * You should have received a copy of the GNU Lesser General Public
  18.  * License along with FFmpeg; if not, write to the Free Software
  19.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20.  */
  21.  
  22. /**
  23.  * @file
  24.  * Audio FIFO
  25.  */
  26.  
  27. #include "avutil.h"
  28. #include "audio_fifo.h"
  29. #include "common.h"
  30. #include "fifo.h"
  31. #include "mem.h"
  32. #include "samplefmt.h"
  33.  
  34. struct AVAudioFifo {
  35.     AVFifoBuffer **buf;             /**< single buffer for interleaved, per-channel buffers for planar */
  36.     int nb_buffers;                 /**< number of buffers */
  37.     int nb_samples;                 /**< number of samples currently in the FIFO */
  38.     int allocated_samples;          /**< current allocated size, in samples */
  39.  
  40.     int channels;                   /**< number of channels */
  41.     enum AVSampleFormat sample_fmt; /**< sample format */
  42.     int sample_size;                /**< size, in bytes, of one sample in a buffer */
  43. };
  44.  
  45. void av_audio_fifo_free(AVAudioFifo *af)
  46. {
  47.     if (af) {
  48.         if (af->buf) {
  49.             int i;
  50.             for (i = 0; i < af->nb_buffers; i++) {
  51.                 if (af->buf[i])
  52.                     av_fifo_free(af->buf[i]);
  53.             }
  54.             av_free(af->buf);
  55.         }
  56.         av_free(af);
  57.     }
  58. }
  59.  
  60. AVAudioFifo *av_audio_fifo_alloc(enum AVSampleFormat sample_fmt, int channels,
  61.                                  int nb_samples)
  62. {
  63.     AVAudioFifo *af;
  64.     int buf_size, i;
  65.  
  66.     /* get channel buffer size (also validates parameters) */
  67.     if (av_samples_get_buffer_size(&buf_size, channels, nb_samples, sample_fmt, 1) < 0)
  68.         return NULL;
  69.  
  70.     af = av_mallocz(sizeof(*af));
  71.     if (!af)
  72.         return NULL;
  73.  
  74.     af->channels    = channels;
  75.     af->sample_fmt  = sample_fmt;
  76.     af->sample_size = buf_size / nb_samples;
  77.     af->nb_buffers  = av_sample_fmt_is_planar(sample_fmt) ? channels : 1;
  78.  
  79.     af->buf = av_mallocz(af->nb_buffers * sizeof(*af->buf));
  80.     if (!af->buf)
  81.         goto error;
  82.  
  83.     for (i = 0; i < af->nb_buffers; i++) {
  84.         af->buf[i] = av_fifo_alloc(buf_size);
  85.         if (!af->buf[i])
  86.             goto error;
  87.     }
  88.     af->allocated_samples = nb_samples;
  89.  
  90.     return af;
  91.  
  92. error:
  93.     av_audio_fifo_free(af);
  94.     return NULL;
  95. }
  96.  
  97. int av_audio_fifo_realloc(AVAudioFifo *af, int nb_samples)
  98. {
  99.     int i, ret, buf_size;
  100.  
  101.     if ((ret = av_samples_get_buffer_size(&buf_size, af->channels, nb_samples,
  102.                                           af->sample_fmt, 1)) < 0)
  103.         return ret;
  104.  
  105.     for (i = 0; i < af->nb_buffers; i++) {
  106.         if ((ret = av_fifo_realloc2(af->buf[i], buf_size)) < 0)
  107.             return ret;
  108.     }
  109.     af->allocated_samples = nb_samples;
  110.     return 0;
  111. }
  112.  
  113. int av_audio_fifo_write(AVAudioFifo *af, void **data, int nb_samples)
  114. {
  115.     int i, ret, size;
  116.  
  117.     /* automatically reallocate buffers if needed */
  118.     if (av_audio_fifo_space(af) < nb_samples) {
  119.         int current_size = av_audio_fifo_size(af);
  120.         /* check for integer overflow in new size calculation */
  121.         if (INT_MAX / 2 - current_size < nb_samples)
  122.             return AVERROR(EINVAL);
  123.         /* reallocate buffers */
  124.         if ((ret = av_audio_fifo_realloc(af, 2 * (current_size + nb_samples))) < 0)
  125.             return ret;
  126.     }
  127.  
  128.     size = nb_samples * af->sample_size;
  129.     for (i = 0; i < af->nb_buffers; i++) {
  130.         ret = av_fifo_generic_write(af->buf[i], data[i], size, NULL);
  131.         if (ret != size)
  132.             return AVERROR_BUG;
  133.     }
  134.     af->nb_samples += nb_samples;
  135.  
  136.     return nb_samples;
  137. }
  138.  
  139. int av_audio_fifo_read(AVAudioFifo *af, void **data, int nb_samples)
  140. {
  141.     int i, ret, size;
  142.  
  143.     if (nb_samples < 0)
  144.         return AVERROR(EINVAL);
  145.     nb_samples = FFMIN(nb_samples, af->nb_samples);
  146.     if (!nb_samples)
  147.         return 0;
  148.  
  149.     size = nb_samples * af->sample_size;
  150.     for (i = 0; i < af->nb_buffers; i++) {
  151.         if ((ret = av_fifo_generic_read(af->buf[i], data[i], size, NULL)) < 0)
  152.             return AVERROR_BUG;
  153.     }
  154.     af->nb_samples -= nb_samples;
  155.  
  156.     return nb_samples;
  157. }
  158.  
  159. int av_audio_fifo_drain(AVAudioFifo *af, int nb_samples)
  160. {
  161.     int i, size;
  162.  
  163.     if (nb_samples < 0)
  164.         return AVERROR(EINVAL);
  165.     nb_samples = FFMIN(nb_samples, af->nb_samples);
  166.  
  167.     if (nb_samples) {
  168.         size = nb_samples * af->sample_size;
  169.         for (i = 0; i < af->nb_buffers; i++)
  170.             av_fifo_drain(af->buf[i], size);
  171.         af->nb_samples -= nb_samples;
  172.     }
  173.     return 0;
  174. }
  175.  
  176. void av_audio_fifo_reset(AVAudioFifo *af)
  177. {
  178.     int i;
  179.  
  180.     for (i = 0; i < af->nb_buffers; i++)
  181.         av_fifo_reset(af->buf[i]);
  182.  
  183.     af->nb_samples = 0;
  184. }
  185.  
  186. int av_audio_fifo_size(AVAudioFifo *af)
  187. {
  188.     return af->nb_samples;
  189. }
  190.  
  191. int av_audio_fifo_space(AVAudioFifo *af)
  192. {
  193.     return af->allocated_samples - af->nb_samples;
  194. }
  195.