4bf64961 |
/*
* Audio Frame Queue
* Copyright (c) 2012 Justin Ruggles
* |
36583d23 |
* This file is part of FFmpeg. |
4bf64961 |
* |
36583d23 |
* FFmpeg is free software; you can redistribute it and/or |
4bf64961 |
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
* |
36583d23 |
* FFmpeg is distributed in the hope that it will be useful, |
4bf64961 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public |
36583d23 |
* License along with FFmpeg; if not, write to the Free Software |
4bf64961 |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "audio_frame_queue.h" |
36583d23 |
#include "internal.h"
#include "libavutil/avassert.h" |
4bf64961 |
void ff_af_queue_init(AVCodecContext *avctx, AudioFrameQueue *afq)
{ |
36583d23 |
afq->avctx = avctx; |
4bf64961 |
afq->remaining_delay = avctx->delay;
afq->remaining_samples = avctx->delay; |
36583d23 |
afq->frame_count = 0; |
4bf64961 |
}
void ff_af_queue_close(AudioFrameQueue *afq)
{ |
36583d23 |
if(afq->frame_count)
av_log(afq->avctx, AV_LOG_WARNING, "%d frames left in que on closing\n", afq->frame_count);
av_freep(&afq->frames); |
4bf64961 |
memset(afq, 0, sizeof(*afq));
}
int ff_af_queue_add(AudioFrameQueue *afq, const AVFrame *f)
{ |
36583d23 |
AudioFrame *new = av_fast_realloc(afq->frames, &afq->frame_alloc, sizeof(*afq->frames)*(afq->frame_count+1));
if(!new) |
4bf64961 |
return AVERROR(ENOMEM); |
36583d23 |
afq->frames = new;
new += afq->frame_count; |
4bf64961 |
/* get frame parameters */ |
36583d23 |
new->duration = f->nb_samples;
new->duration += afq->remaining_delay; |
4bf64961 |
if (f->pts != AV_NOPTS_VALUE) { |
36583d23 |
new->pts = av_rescale_q(f->pts, |
4bf64961 |
afq->avctx->time_base,
(AVRational){ 1, afq->avctx->sample_rate }); |
36583d23 |
new->pts -= afq->remaining_delay;
if(afq->frame_count && new[-1].pts >= new->pts)
av_log(afq->avctx, AV_LOG_WARNING, "Que input is backward in time\n"); |
4bf64961 |
} else { |
36583d23 |
new->pts = AV_NOPTS_VALUE; |
4bf64961 |
} |
36583d23 |
afq->remaining_delay = 0; |
4bf64961 |
/* add frame sample count */
afq->remaining_samples += f->nb_samples;
|
36583d23 |
afq->frame_count++; |
4bf64961 |
return 0;
}
void ff_af_queue_remove(AudioFrameQueue *afq, int nb_samples, int64_t *pts,
int *duration)
{
int64_t out_pts = AV_NOPTS_VALUE;
int removed_samples = 0; |
36583d23 |
int i; |
4bf64961 |
|
36583d23 |
if (afq->frame_count || afq->frame_alloc) {
if (afq->frames->pts != AV_NOPTS_VALUE)
out_pts = afq->frames->pts; |
4bf64961 |
} |
36583d23 |
if(!afq->frame_count)
av_log(afq->avctx, AV_LOG_WARNING, "Trying to remove %d samples, but que empty\n", nb_samples);
if (pts)
*pts = ff_samples_to_time_base(afq->avctx, out_pts);
for(i=0; nb_samples && i<afq->frame_count; i++){
int n= FFMIN(afq->frames[i].duration, nb_samples);
afq->frames[i].duration -= n;
nb_samples -= n;
removed_samples += n;
if(afq->frames[i].pts != AV_NOPTS_VALUE)
afq->frames[i].pts += n; |
4bf64961 |
} |
36583d23 |
i -= i && afq->frames[i-1].duration;
memmove(afq->frames, afq->frames + i, sizeof(*afq->frames) * (afq->frame_count - i));
afq->frame_count -= i;
if(nb_samples){
av_assert0(!afq->frame_count); |
3938a0ee |
if(afq->frames && afq->frames[0].pts != AV_NOPTS_VALUE) |
36583d23 |
afq->frames[0].pts += nb_samples;
av_log(afq->avctx, AV_LOG_DEBUG, "Trying to remove %d more samples than are in the que\n", nb_samples); |
4bf64961 |
}
if (duration)
*duration = ff_samples_to_time_base(afq->avctx, removed_samples);
}
|