History

audio_frame_que: simplify

Also update libav->ffmpeg as theres pretty much no code left from libav. The new code is faster, requires fewer mallocs and less memory. Its also half the number of lines of code. This code is not 100% identical in behavior to the previous, but the differences appear to be rather limitations of the previous design than intended though i could be wrong of course.

Michael Niedermayer committed 14 years ago

Commit 36583d21 parent 364c71c2 files · +52 −104Browse files

Unified · Split

2 files
  1. libavcodec/audio_frame_queue.c +49 −101
  2. libavcodec/audio_frame_queue.h +3 −3
libavcodec/audio_frame_queue.c+49−101
@@ -2,92 +2,70 @@ · 1 unmodified line
2 * Audio Frame Queue2 * Audio Frame Queue
3 * Copyright (c) 2012 Justin Ruggles3 * Copyright (c) 2012 Justin Ruggles
4 *4 *
5 * This file is part of Libav.5 * This file is part of FFmpeg.
6 *6 *
7 * Libav is free software; you can redistribute it and/or7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.10 * version 2.1 of the License, or (at your option) any later version.
11 *11 *
12 * Libav is distributed in the hope that it will be useful,12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.15 * Lesser General Public License for more details.
16 *16 *
17 * You should have received a copy of the GNU Lesser General Public17 * You should have received a copy of the GNU Lesser General Public
18 * License along with Libav; if not, write to the Free Software18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */20 */
21 21
22#include "libavutil/mathematics.h"
23#include "internal.h"
24#include "audio_frame_queue.h"22#include "audio_frame_queue.h"
23#include "internal.h"
24#include "libavutil/avassert.h"
25 25
26void ff_af_queue_init(AVCodecContext *avctx, AudioFrameQueue *afq)26void ff_af_queue_init(AVCodecContext *avctx, AudioFrameQueue *afq)
27{27{
28 afq->avctx = avctx;28 afq->avctx = avctx;
29 afq->next_pts = AV_NOPTS_VALUE;
30 afq->remaining_delay = avctx->delay;29 afq->remaining_delay = avctx->delay;
31 afq->remaining_samples = avctx->delay;30 afq->remaining_samples = avctx->delay;
32 afq->frame_queue = NULL;31 afq->frame_count = 0;
33}
34
35static void delete_next_frame(AudioFrameQueue *afq)
36{
37 AudioFrame *f = afq->frame_queue;
38 if (f) {
39 afq->frame_queue = f->next;
40 f->next = NULL;
41 av_freep(&f);
42 }
43}32}
44 33
45void ff_af_queue_close(AudioFrameQueue *afq)34void ff_af_queue_close(AudioFrameQueue *afq)
46{35{
47 /* remove/free any remaining frames */36 if(afq->frame_count)
48 while (afq->frame_queue)37 av_log(afq->avctx, AV_LOG_WARNING, "%d frames left in que on closing\n", afq->frame_count);
49 delete_next_frame(afq);38 av_freep(&afq->frames);
50 memset(afq, 0, sizeof(*afq));39 memset(afq, 0, sizeof(*afq));
51}40}
52 41
53int ff_af_queue_add(AudioFrameQueue *afq, const AVFrame *f)42int ff_af_queue_add(AudioFrameQueue *afq, const AVFrame *f)
54{43{
55 AudioFrame *new_frame;44 AudioFrame *new = av_fast_realloc(afq->frames, &afq->frame_alloc, sizeof(*afq->frames)*(afq->frame_count+1));
56 AudioFrame *queue_end = afq->frame_queue;45 if(!new)
57
58 /* find the end of the queue */
59 while (queue_end && queue_end->next)
60 queue_end = queue_end->next;
61
62 /* allocate new frame queue entry */
63 if (!(new_frame = av_malloc(sizeof(*new_frame))))
64 return AVERROR(ENOMEM);46 return AVERROR(ENOMEM);
47 afq->frames = new;
48 new += afq->frame_count;
65 49
66 /* get frame parameters */50 /* get frame parameters */
67 new_frame->next = NULL;51 new->duration = f->nb_samples;
68 new_frame->duration = f->nb_samples;52 new->duration += afq->remaining_delay;
69 if (f->pts != AV_NOPTS_VALUE) {53 if (f->pts != AV_NOPTS_VALUE) {
70 new_frame->pts = av_rescale_q(f->pts,54 new->pts = av_rescale_q(f->pts,
71 afq->avctx->time_base,55 afq->avctx->time_base,
72 (AVRational){ 1, afq->avctx->sample_rate });56 (AVRational){ 1, afq->avctx->sample_rate });
73 afq->next_pts = new_frame->pts + new_frame->duration;57 new->pts -= afq->remaining_delay;
58 if(afq->frame_count && new[-1].pts >= new->pts)
59 av_log(afq->avctx, AV_LOG_WARNING, "Que input is backward in time\n");
74 } else {60 } else {
75 new_frame->pts = AV_NOPTS_VALUE;61 new->pts = AV_NOPTS_VALUE;
76 afq->next_pts = AV_NOPTS_VALUE;
77 }62 }
78 63 afq->remaining_delay = 0;
79 /* add new frame to the end of the queue */
80 if (!queue_end)
81 afq->frame_queue = new_frame;
82 else
83 queue_end->next = new_frame;
84 64
85 /* add frame sample count */65 /* add frame sample count */
86 afq->remaining_samples += f->nb_samples;66 afq->remaining_samples += f->nb_samples;
87 67
88#ifdef DEBUG68 afq->frame_count++;
89 ff_af_queue_log_state(afq);
90#endif
91 69
92 return 0;70 return 0;
93}71}
@@ -97,66 +75,36 @@ void ff_af_queue_remove(AudioFrameQueue *afq, int nb_samples, int64_t *pts, · 3 unmodified lines
97{75{
98 int64_t out_pts = AV_NOPTS_VALUE;76 int64_t out_pts = AV_NOPTS_VALUE;
99 int removed_samples = 0;77 int removed_samples = 0;
78 int i;
100 79
101#ifdef DEBUG80 if (afq->frame_count || afq->frame_alloc) {
102 ff_af_queue_log_state(afq);81 if (afq->frames->pts != AV_NOPTS_VALUE)
103#endif82 out_pts = afq->frames->pts;
104
105 /* get output pts from the next frame or generated pts */
106 if (afq->frame_queue) {
107 if (afq->frame_queue->pts != AV_NOPTS_VALUE)
108 out_pts = afq->frame_queue->pts - afq->remaining_delay;
109 } else {
110 if (afq->next_pts != AV_NOPTS_VALUE)
111 out_pts = afq->next_pts - afq->remaining_delay;
112 }83 }
113 if (pts) {84 if(!afq->frame_count)
114 if (out_pts != AV_NOPTS_VALUE)85 av_log(afq->avctx, AV_LOG_WARNING, "Trying to remove %d samples, but que empty\n", nb_samples);
115 *pts = ff_samples_to_time_base(afq->avctx, out_pts);86 if (pts)
116 else87 *pts = ff_samples_to_time_base(afq->avctx, out_pts);
117 *pts = AV_NOPTS_VALUE;88
89 for(i=0; nb_samples && i<afq->frame_count; i++){
90 int n= FFMIN(afq->frames[i].duration, nb_samples);
91 afq->frames[i].duration -= n;
92 nb_samples -= n;
93 removed_samples += n;
94 if(afq->frames[i].pts != AV_NOPTS_VALUE)
95 afq->frames[i].pts += n;
118 }96 }
119 97 i -= i && afq->frames[i-1].duration;
120 /* if the delay is larger than the packet duration, we use up delay samples98 memmove(afq->frames, afq->frames + i, sizeof(*afq->frames) * (afq->frame_count - i));
121 for the output packet and leave all frames in the queue */99 afq->frame_count -= i;
122 if (afq->remaining_delay >= nb_samples) {100
123 removed_samples += nb_samples;101 if(nb_samples){
124 afq->remaining_delay -= nb_samples;102 av_assert0(!afq->frame_count);
103 if(afq->frames[0].pts != AV_NOPTS_VALUE)
104 afq->frames[0].pts += nb_samples;
105 av_log(afq->avctx, AV_LOG_DEBUG, "Trying to remove %d more samples than are in the que\n", nb_samples);
125 }106 }
126 /* remove frames from the queue until we have enough to cover the
127 requested number of samples or until the queue is empty */
128 while (removed_samples < nb_samples && afq->frame_queue) {
129 removed_samples += afq->frame_queue->duration;
130 delete_next_frame(afq);
131 }
132 afq->remaining_samples -= removed_samples;
133
134 /* if there are no frames left and we have room for more samples, use
135 any remaining delay samples */
136 if (removed_samples < nb_samples && afq->remaining_samples > 0) {
137 int add_samples = FFMIN(afq->remaining_samples,
138 nb_samples - removed_samples);
139 removed_samples += add_samples;
140 afq->remaining_samples -= add_samples;
141 }
142 if (removed_samples > nb_samples)
143 av_log(afq->avctx, AV_LOG_WARNING, "frame_size is too large\n");
144 if (duration)107 if (duration)
145 *duration = ff_samples_to_time_base(afq->avctx, removed_samples);108 *duration = ff_samples_to_time_base(afq->avctx, removed_samples);
146}109}
147 110
148void ff_af_queue_log_state(AudioFrameQueue *afq)
149{
150 AudioFrame *f;
151 av_log(afq->avctx, AV_LOG_DEBUG, "remaining delay = %d\n",
152 afq->remaining_delay);
153 av_log(afq->avctx, AV_LOG_DEBUG, "remaining samples = %d\n",
154 afq->remaining_samples);
155 av_log(afq->avctx, AV_LOG_DEBUG, "frames:\n");
156 f = afq->frame_queue;
157 while (f) {
158 av_log(afq->avctx, AV_LOG_DEBUG, " [ pts=%9"PRId64" duration=%d ]\n",
159 f->pts, f->duration);
160 f = f->next;
161 }
162}
libavcodec/audio_frame_queue.h+3−3
@@ -27,15 +27,15 @@ · 26 unmodified lines
27typedef struct AudioFrame {27typedef struct AudioFrame {
28 int64_t pts;28 int64_t pts;
29 int duration;29 int duration;
30 struct AudioFrame *next;
31} AudioFrame;30} AudioFrame;
32 31
33typedef struct AudioFrameQueue {32typedef struct AudioFrameQueue {
34 AVCodecContext *avctx;33 AVCodecContext *avctx;
35 int64_t next_pts;
36 int remaining_delay;34 int remaining_delay;
37 int remaining_samples;35 int remaining_samples;
38 AudioFrame *frame_queue;36 AudioFrame *frames;
37 unsigned frame_count;
38 unsigned frame_alloc;
39} AudioFrameQueue;39} AudioFrameQueue;
40 40
41/**41/**

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t