3 * Copyright (c) 2012 Justin Ruggles
5 * This file is part of Libav.
7 * Libav 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 * Libav 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 Libav; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 #include "libavutil/common.h"
23 #include "libavutil/mathematics.h"
25 #include "audio_frame_queue.h"
27 void ff_af_queue_init(AVCodecContext
*avctx
, AudioFrameQueue
*afq
)
30 afq
->next_pts
= AV_NOPTS_VALUE
;
31 afq
->remaining_delay
= avctx
->delay
;
32 afq
->remaining_samples
= avctx
->delay
;
33 afq
->frame_queue
= NULL
;
36 static void delete_next_frame(AudioFrameQueue
*afq
)
38 AudioFrame
*f
= afq
->frame_queue
;
40 afq
->frame_queue
= f
->next
;
46 void ff_af_queue_close(AudioFrameQueue
*afq
)
48 /* remove/free any remaining frames */
49 while (afq
->frame_queue
)
50 delete_next_frame(afq
);
51 memset(afq
, 0, sizeof(*afq
));
55 static void af_queue_log_state(AudioFrameQueue
*afq
)
58 av_dlog(afq
->avctx
, "remaining delay = %d\n", afq
->remaining_delay
);
59 av_dlog(afq
->avctx
, "remaining samples = %d\n", afq
->remaining_samples
);
60 av_dlog(afq
->avctx
, "frames:\n");
63 av_dlog(afq
->avctx
, " [ pts=%9"PRId64
" duration=%d ]\n",
70 int ff_af_queue_add(AudioFrameQueue
*afq
, const AVFrame
*f
)
72 AudioFrame
*new_frame
;
73 AudioFrame
*queue_end
= afq
->frame_queue
;
75 /* find the end of the queue */
76 while (queue_end
&& queue_end
->next
)
77 queue_end
= queue_end
->next
;
79 /* allocate new frame queue entry */
80 if (!(new_frame
= av_malloc(sizeof(*new_frame
))))
81 return AVERROR(ENOMEM
);
83 /* get frame parameters */
84 new_frame
->next
= NULL
;
85 new_frame
->duration
= f
->nb_samples
;
86 if (f
->pts
!= AV_NOPTS_VALUE
) {
87 new_frame
->pts
= av_rescale_q(f
->pts
,
88 afq
->avctx
->time_base
,
89 (AVRational
){ 1, afq
->avctx
->sample_rate
});
90 afq
->next_pts
= new_frame
->pts
+ new_frame
->duration
;
92 new_frame
->pts
= AV_NOPTS_VALUE
;
93 afq
->next_pts
= AV_NOPTS_VALUE
;
96 /* add new frame to the end of the queue */
98 afq
->frame_queue
= new_frame
;
100 queue_end
->next
= new_frame
;
102 /* add frame sample count */
103 afq
->remaining_samples
+= f
->nb_samples
;
106 af_queue_log_state(afq
);
112 void ff_af_queue_remove(AudioFrameQueue
*afq
, int nb_samples
, int64_t *pts
,
115 int64_t out_pts
= AV_NOPTS_VALUE
;
116 int removed_samples
= 0;
119 af_queue_log_state(afq
);
122 /* get output pts from the next frame or generated pts */
123 if (afq
->frame_queue
) {
124 if (afq
->frame_queue
->pts
!= AV_NOPTS_VALUE
)
125 out_pts
= afq
->frame_queue
->pts
- afq
->remaining_delay
;
127 if (afq
->next_pts
!= AV_NOPTS_VALUE
)
128 out_pts
= afq
->next_pts
- afq
->remaining_delay
;
131 if (out_pts
!= AV_NOPTS_VALUE
)
132 *pts
= ff_samples_to_time_base(afq
->avctx
, out_pts
);
134 *pts
= AV_NOPTS_VALUE
;
137 /* if the delay is larger than the packet duration, we use up delay samples
138 for the output packet and leave all frames in the queue */
139 if (afq
->remaining_delay
>= nb_samples
) {
140 removed_samples
+= nb_samples
;
141 afq
->remaining_delay
-= nb_samples
;
143 /* remove frames from the queue until we have enough to cover the
144 requested number of samples or until the queue is empty */
145 while (removed_samples
< nb_samples
&& afq
->frame_queue
) {
146 removed_samples
+= afq
->frame_queue
->duration
;
147 delete_next_frame(afq
);
149 afq
->remaining_samples
-= removed_samples
;
151 /* if there are no frames left and we have room for more samples, use
152 any remaining delay samples */
153 if (removed_samples
< nb_samples
&& afq
->remaining_samples
> 0) {
154 int add_samples
= FFMIN(afq
->remaining_samples
,
155 nb_samples
- removed_samples
);
156 removed_samples
+= add_samples
;
157 afq
->remaining_samples
-= add_samples
;
159 if (removed_samples
> nb_samples
)
160 av_log(afq
->avctx
, AV_LOG_WARNING
, "frame_size is too large\n");
162 *duration
= ff_samples_to_time_base(afq
->avctx
, removed_samples
);