Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Audio Interleaving functions
  3.  *
  4.  * Copyright (c) 2009 Baptiste Coudurier <baptiste dot coudurier at gmail dot com>
  5.  *
  6.  * This file is part of FFmpeg.
  7.  *
  8.  * FFmpeg is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Lesser General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2.1 of the License, or (at your option) any later version.
  12.  *
  13.  * FFmpeg is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Lesser General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Lesser General Public
  19.  * License along with FFmpeg; if not, write to the Free Software
  20.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  21.  */
  22.  
  23. #include "libavutil/fifo.h"
  24. #include "libavutil/mathematics.h"
  25. #include "avformat.h"
  26. #include "audiointerleave.h"
  27. #include "internal.h"
  28.  
  29. void ff_audio_interleave_close(AVFormatContext *s)
  30. {
  31.     int i;
  32.     for (i = 0; i < s->nb_streams; i++) {
  33.         AVStream *st = s->streams[i];
  34.         AudioInterleaveContext *aic = st->priv_data;
  35.  
  36.         if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO)
  37.             av_fifo_free(aic->fifo);
  38.     }
  39. }
  40.  
  41. int ff_audio_interleave_init(AVFormatContext *s,
  42.                              const int *samples_per_frame,
  43.                              AVRational time_base)
  44. {
  45.     int i;
  46.  
  47.     if (!samples_per_frame)
  48.         return -1;
  49.  
  50.     if (!time_base.num) {
  51.         av_log(s, AV_LOG_ERROR, "timebase not set for audio interleave\n");
  52.         return -1;
  53.     }
  54.     for (i = 0; i < s->nb_streams; i++) {
  55.         AVStream *st = s->streams[i];
  56.         AudioInterleaveContext *aic = st->priv_data;
  57.  
  58.         if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
  59.             aic->sample_size = (st->codec->channels *
  60.                                 av_get_bits_per_sample(st->codec->codec_id)) / 8;
  61.             if (!aic->sample_size) {
  62.                 av_log(s, AV_LOG_ERROR, "could not compute sample size\n");
  63.                 return -1;
  64.             }
  65.             aic->samples_per_frame = samples_per_frame;
  66.             aic->samples = aic->samples_per_frame;
  67.             aic->time_base = time_base;
  68.  
  69.             aic->fifo_size = 100* *aic->samples;
  70.             aic->fifo= av_fifo_alloc(100 * *aic->samples);
  71.         }
  72.     }
  73.  
  74.     return 0;
  75. }
  76.  
  77. static int interleave_new_audio_packet(AVFormatContext *s, AVPacket *pkt,
  78.                                        int stream_index, int flush)
  79. {
  80.     AVStream *st = s->streams[stream_index];
  81.     AudioInterleaveContext *aic = st->priv_data;
  82.  
  83.     int size = FFMIN(av_fifo_size(aic->fifo), *aic->samples * aic->sample_size);
  84.     if (!size || (!flush && size == av_fifo_size(aic->fifo)))
  85.         return 0;
  86.  
  87.     if (av_new_packet(pkt, size) < 0)
  88.         return AVERROR(ENOMEM);
  89.     av_fifo_generic_read(aic->fifo, pkt->data, size, NULL);
  90.  
  91.     pkt->dts = pkt->pts = aic->dts;
  92.     pkt->duration = av_rescale_q(*aic->samples, st->time_base, aic->time_base);
  93.     pkt->stream_index = stream_index;
  94.     aic->dts += pkt->duration;
  95.  
  96.     aic->samples++;
  97.     if (!*aic->samples)
  98.         aic->samples = aic->samples_per_frame;
  99.  
  100.     return size;
  101. }
  102.  
  103. int ff_audio_rechunk_interleave(AVFormatContext *s, AVPacket *out, AVPacket *pkt, int flush,
  104.                         int (*get_packet)(AVFormatContext *, AVPacket *, AVPacket *, int),
  105.                         int (*compare_ts)(AVFormatContext *, AVPacket *, AVPacket *))
  106. {
  107.     int i;
  108.  
  109.     if (pkt) {
  110.         AVStream *st = s->streams[pkt->stream_index];
  111.         AudioInterleaveContext *aic = st->priv_data;
  112.         if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
  113.             unsigned new_size = av_fifo_size(aic->fifo) + pkt->size;
  114.             if (new_size > aic->fifo_size) {
  115.                 if (av_fifo_realloc2(aic->fifo, new_size) < 0)
  116.                     return -1;
  117.                 aic->fifo_size = new_size;
  118.             }
  119.             av_fifo_generic_write(aic->fifo, pkt->data, pkt->size, NULL);
  120.         } else {
  121.             int ret;
  122.             // rewrite pts and dts to be decoded time line position
  123.             pkt->pts = pkt->dts = aic->dts;
  124.             aic->dts += pkt->duration;
  125.             ret = ff_interleave_add_packet(s, pkt, compare_ts);
  126.             if (ret < 0)
  127.                 return ret;
  128.         }
  129.         pkt = NULL;
  130.     }
  131.  
  132.     for (i = 0; i < s->nb_streams; i++) {
  133.         AVStream *st = s->streams[i];
  134.         if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
  135.             AVPacket new_pkt;
  136.             int ret;
  137.             while ((ret = interleave_new_audio_packet(s, &new_pkt, i, flush)) > 0) {
  138.                 ret = ff_interleave_add_packet(s, &new_pkt, compare_ts);
  139.                 if (ret < 0)
  140.                     return ret;
  141.             }
  142.             if (ret < 0)
  143.                 return ret;
  144.         }
  145.     }
  146.  
  147.     return get_packet(s, out, NULL, flush);
  148. }
  149.