3 * Copyright (c) 2012 Justin Ruggles
5 * This file is part of FFmpeg.
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.
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.
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
22 #include "libavutil/attributes.h"
23 #include "libavutil/common.h"
24 #include "audio_frame_queue.h"
26 #include "libavutil/avassert.h"
28 av_cold
void ff_af_queue_init(AVCodecContext
*avctx
, AudioFrameQueue
*afq
)
31 afq
->remaining_delay
= avctx
->initial_padding
;
32 afq
->remaining_samples
= avctx
->initial_padding
;
36 void ff_af_queue_close(AudioFrameQueue
*afq
)
39 av_log(afq
->avctx
, AV_LOG_WARNING
, "%d frames left in the queue on closing\n", afq
->frame_count
);
40 av_freep(&afq
->frames
);
41 memset(afq
, 0, sizeof(*afq
));
44 int ff_af_queue_add(AudioFrameQueue
*afq
, const AVFrame
*f
)
46 AudioFrame
*new = av_fast_realloc(afq
->frames
, &afq
->frame_alloc
, sizeof(*afq
->frames
)*(afq
->frame_count
+1));
48 return AVERROR(ENOMEM
);
50 new += afq
->frame_count
;
52 /* get frame parameters */
53 new->duration
= f
->nb_samples
;
54 new->duration
+= afq
->remaining_delay
;
55 if (f
->pts
!= AV_NOPTS_VALUE
) {
56 new->pts
= av_rescale_q(f
->pts
,
57 afq
->avctx
->time_base
,
58 (AVRational
){ 1, afq
->avctx
->sample_rate
});
59 new->pts
-= afq
->remaining_delay
;
60 if(afq
->frame_count
&& new[-1].pts
>= new->pts
)
61 av_log(afq
->avctx
, AV_LOG_WARNING
, "Queue input is backward in time\n");
63 new->pts
= AV_NOPTS_VALUE
;
65 afq
->remaining_delay
= 0;
67 /* add frame sample count */
68 afq
->remaining_samples
+= f
->nb_samples
;
75 void ff_af_queue_remove(AudioFrameQueue
*afq
, int nb_samples
, int64_t *pts
,
78 int64_t out_pts
= AV_NOPTS_VALUE
;
79 int removed_samples
= 0;
82 if (afq
->frame_count
|| afq
->frame_alloc
) {
83 if (afq
->frames
->pts
!= AV_NOPTS_VALUE
)
84 out_pts
= afq
->frames
->pts
;
87 av_log(afq
->avctx
, AV_LOG_WARNING
, "Trying to remove %d samples, but the queue is empty\n", nb_samples
);
89 *pts
= ff_samples_to_time_base(afq
->avctx
, out_pts
);
91 for(i
=0; nb_samples
&& i
<afq
->frame_count
; i
++){
92 int n
= FFMIN(afq
->frames
[i
].duration
, nb_samples
);
93 afq
->frames
[i
].duration
-= n
;
96 if(afq
->frames
[i
].pts
!= AV_NOPTS_VALUE
)
97 afq
->frames
[i
].pts
+= n
;
99 afq
->remaining_samples
-= removed_samples
;
100 i
-= i
&& afq
->frames
[i
-1].duration
;
101 memmove(afq
->frames
, afq
->frames
+ i
, sizeof(*afq
->frames
) * (afq
->frame_count
- i
));
102 afq
->frame_count
-= i
;
105 av_assert0(!afq
->frame_count
);
106 av_assert0(afq
->remaining_samples
== afq
->remaining_delay
);
107 if(afq
->frames
&& afq
->frames
[0].pts
!= AV_NOPTS_VALUE
)
108 afq
->frames
[0].pts
+= nb_samples
;
109 av_log(afq
->avctx
, AV_LOG_DEBUG
, "Trying to remove %d more samples than there are in the queue\n", nb_samples
);
112 *duration
= ff_samples_to_time_base(afq
->avctx
, removed_samples
);