Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
6148 serge 1
/*
2
 * Copyright (c) 2013 Nicolas George
3
 *
4
 * This file is part of FFmpeg.
5
 *
6
 * FFmpeg is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU Lesser General Public License
8
 * as published by the Free Software Foundation; either
9
 * version 2.1 of the License, or (at your option) any later version.
10
 *
11
 * FFmpeg is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public License
17
 * along with FFmpeg; if not, write to the Free Software Foundation, Inc.,
18
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
 */
20
 
21
#include "libavutil/avassert.h"
22
#include "avfilter.h"
23
#include "bufferqueue.h"
24
#include "framesync.h"
25
#include "internal.h"
26
 
27
#define OFFSET(member) offsetof(FFFrameSync, member)
28
 
29
static const char *framesync_name(void *ptr)
30
{
31
    return "framesync";
32
}
33
 
34
static const AVClass framesync_class = {
35
    .version                   = LIBAVUTIL_VERSION_INT,
36
    .class_name                = "framesync",
37
    .item_name                 = framesync_name,
38
    .category                  = AV_CLASS_CATEGORY_FILTER,
39
    .option                    = NULL,
40
    .parent_log_context_offset = OFFSET(parent),
41
};
42
 
43
enum {
44
    STATE_BOF,
45
    STATE_RUN,
46
    STATE_EOF,
47
};
48
 
49
void ff_framesync_init(FFFrameSync *fs, void *parent, unsigned nb_in)
50
{
51
    fs->class  = &framesync_class;
52
    fs->parent = parent;
53
    fs->nb_in  = nb_in;
54
}
55
 
56
static void framesync_sync_level_update(FFFrameSync *fs)
57
{
58
    unsigned i, level = 0;
59
 
60
    for (i = 0; i < fs->nb_in; i++)
61
        if (fs->in[i].state != STATE_EOF)
62
            level = FFMAX(level, fs->in[i].sync);
63
    av_assert0(level <= fs->sync_level);
64
    if (level < fs->sync_level)
65
        av_log(fs, AV_LOG_VERBOSE, "Sync level %u\n", level);
66
    if (level)
67
        fs->sync_level = level;
68
    else
69
        fs->eof = 1;
70
}
71
 
72
int ff_framesync_configure(FFFrameSync *fs)
73
{
74
    unsigned i;
75
    int64_t gcd, lcm;
76
 
77
    if (!fs->time_base.num) {
78
        for (i = 0; i < fs->nb_in; i++) {
79
            if (fs->in[i].sync) {
80
                if (fs->time_base.num) {
81
                    gcd = av_gcd(fs->time_base.den, fs->in[i].time_base.den);
82
                    lcm = (fs->time_base.den / gcd) * fs->in[i].time_base.den;
83
                    if (lcm < AV_TIME_BASE / 2) {
84
                        fs->time_base.den = lcm;
85
                        fs->time_base.num = av_gcd(fs->time_base.num,
86
                                                   fs->in[i].time_base.num);
87
                    } else {
88
                        fs->time_base.num = 1;
89
                        fs->time_base.den = AV_TIME_BASE;
90
                        break;
91
                    }
92
                } else {
93
                    fs->time_base = fs->in[i].time_base;
94
                }
95
            }
96
        }
97
        if (!fs->time_base.num) {
98
            av_log(fs, AV_LOG_ERROR, "Impossible to set time base\n");
99
            return AVERROR(EINVAL);
100
        }
101
        av_log(fs, AV_LOG_VERBOSE, "Selected %d/%d time base\n",
102
               fs->time_base.num, fs->time_base.den);
103
    }
104
 
105
    for (i = 0; i < fs->nb_in; i++)
106
        fs->in[i].pts = fs->in[i].pts_next = AV_NOPTS_VALUE;
107
    fs->sync_level = UINT_MAX;
108
    framesync_sync_level_update(fs);
109
 
110
    return 0;
111
}
112
 
113
static void framesync_advance(FFFrameSync *fs)
114
{
115
    int latest;
116
    unsigned i;
117
    int64_t pts;
118
 
119
    if (fs->eof)
120
        return;
121
    while (!fs->frame_ready) {
122
        latest = -1;
123
        for (i = 0; i < fs->nb_in; i++) {
124
            if (!fs->in[i].have_next) {
125
                if (latest < 0 || fs->in[i].pts < fs->in[latest].pts)
126
                    latest = i;
127
            }
128
        }
129
        if (latest >= 0) {
130
            fs->in_request = latest;
131
            break;
132
        }
133
 
134
        pts = fs->in[0].pts_next;
135
        for (i = 1; i < fs->nb_in; i++)
136
            if (fs->in[i].pts_next < pts)
137
                pts = fs->in[i].pts_next;
138
        if (pts == INT64_MAX) {
139
            fs->eof = 1;
140
            break;
141
        }
142
        for (i = 0; i < fs->nb_in; i++) {
143
            if (fs->in[i].pts_next == pts ||
144
                (fs->in[i].before == EXT_INFINITY &&
145
                 fs->in[i].state == STATE_BOF)) {
146
                av_frame_free(&fs->in[i].frame);
147
                fs->in[i].frame      = fs->in[i].frame_next;
148
                fs->in[i].pts        = fs->in[i].pts_next;
149
                fs->in[i].frame_next = NULL;
150
                fs->in[i].pts_next   = AV_NOPTS_VALUE;
151
                fs->in[i].have_next  = 0;
152
                fs->in[i].state      = fs->in[i].frame ? STATE_RUN : STATE_EOF;
153
                if (fs->in[i].sync == fs->sync_level && fs->in[i].frame)
154
                    fs->frame_ready = 1;
155
                if (fs->in[i].state == STATE_EOF &&
156
                    fs->in[i].after == EXT_STOP)
157
                    fs->eof = 1;
158
            }
159
        }
160
        if (fs->eof)
161
            fs->frame_ready = 0;
162
        if (fs->frame_ready)
163
            for (i = 0; i < fs->nb_in; i++)
164
                if ((fs->in[i].state == STATE_BOF &&
165
                     fs->in[i].before == EXT_STOP))
166
                    fs->frame_ready = 0;
167
        fs->pts = pts;
168
    }
169
}
170
 
171
static int64_t framesync_pts_extrapolate(FFFrameSync *fs, unsigned in,
172
                                         int64_t pts)
173
{
174
    /* Possible enhancement: use the link's frame rate */
175
    return pts + 1;
176
}
177
 
178
static void framesync_inject_frame(FFFrameSync *fs, unsigned in, AVFrame *frame)
179
{
180
    int64_t pts;
181
 
182
    av_assert0(!fs->in[in].have_next);
183
    if (frame) {
184
        pts = av_rescale_q(frame->pts, fs->in[in].time_base, fs->time_base);
185
        frame->pts = pts;
186
    } else {
187
        pts = fs->in[in].state != STATE_RUN || fs->in[in].after == EXT_INFINITY
188
            ? INT64_MAX : framesync_pts_extrapolate(fs, in, fs->in[in].pts);
189
        fs->in[in].sync = 0;
190
        framesync_sync_level_update(fs);
191
    }
192
    fs->in[in].frame_next = frame;
193
    fs->in[in].pts_next   = pts;
194
    fs->in[in].have_next  = 1;
195
}
196
 
197
int ff_framesync_add_frame(FFFrameSync *fs, unsigned in, AVFrame *frame)
198
{
199
    av_assert1(in < fs->nb_in);
200
    if (!fs->in[in].have_next)
201
        framesync_inject_frame(fs, in, frame);
202
    else
203
        ff_bufqueue_add(fs, &fs->in[in].queue, frame);
204
    return 0;
205
}
206
 
207
void ff_framesync_next(FFFrameSync *fs)
208
{
209
    unsigned i;
210
 
211
    av_assert0(!fs->frame_ready);
212
    for (i = 0; i < fs->nb_in; i++)
213
        if (!fs->in[i].have_next && fs->in[i].queue.available)
214
            framesync_inject_frame(fs, i, ff_bufqueue_get(&fs->in[i].queue));
215
    fs->frame_ready = 0;
216
    framesync_advance(fs);
217
}
218
 
219
void ff_framesync_drop(FFFrameSync *fs)
220
{
221
    fs->frame_ready = 0;
222
}
223
 
224
int ff_framesync_get_frame(FFFrameSync *fs, unsigned in, AVFrame **rframe,
225
                           unsigned get)
226
{
227
    AVFrame *frame;
228
    unsigned need_copy = 0, i;
229
    int64_t pts_next;
230
    int ret;
231
 
232
    if (!fs->in[in].frame) {
233
        *rframe = NULL;
234
        return 0;
235
    }
236
    frame = fs->in[in].frame;
237
    if (get) {
238
        /* Find out if we need to copy the frame: is there another sync
239
           stream, and do we know if its current frame will outlast this one? */
240
        pts_next = fs->in[in].have_next ? fs->in[in].pts_next : INT64_MAX;
241
        for (i = 0; i < fs->nb_in && !need_copy; i++)
242
            if (i != in && fs->in[i].sync &&
243
                (!fs->in[i].have_next || fs->in[i].pts_next < pts_next))
244
                need_copy = 1;
245
        if (need_copy) {
246
            if (!(frame = av_frame_clone(frame)))
247
                return AVERROR(ENOMEM);
248
            if ((ret = av_frame_make_writable(frame)) < 0) {
249
                av_frame_free(&frame);
250
                return ret;
251
            }
252
        } else {
253
            fs->in[in].frame = NULL;
254
        }
255
        fs->frame_ready = 0;
256
    }
257
    *rframe = frame;
258
    return 0;
259
}
260
 
261
void ff_framesync_uninit(FFFrameSync *fs)
262
{
263
    unsigned i;
264
 
265
    for (i = 0; i < fs->nb_in; i++) {
266
        av_frame_free(&fs->in[i].frame);
267
        av_frame_free(&fs->in[i].frame_next);
268
        ff_bufqueue_discard_all(&fs->in[i].queue);
269
    }
270
}
271
 
272
int ff_framesync_process_frame(FFFrameSync *fs, unsigned all)
273
{
274
    int ret, count = 0;
275
 
276
    av_assert0(fs->on_event);
277
    while (1) {
278
        ff_framesync_next(fs);
279
        if (fs->eof || !fs->frame_ready)
280
            break;
281
        if ((ret = fs->on_event(fs)) < 0)
282
            return ret;
283
        ff_framesync_drop(fs);
284
        count++;
285
        if (!all)
286
            break;
287
    }
288
    if (!count && fs->eof)
289
        return AVERROR_EOF;
290
    return count;
291
}
292
 
293
int ff_framesync_filter_frame(FFFrameSync *fs, AVFilterLink *inlink,
294
                              AVFrame *in)
295
{
296
    int ret;
297
 
298
    if ((ret = ff_framesync_process_frame(fs, 1)) < 0)
299
        return ret;
300
    if ((ret = ff_framesync_add_frame(fs, FF_INLINK_IDX(inlink), in)) < 0)
301
        return ret;
302
    if ((ret = ff_framesync_process_frame(fs, 0)) < 0)
303
        return ret;
304
    return 0;
305
}
306
 
307
int ff_framesync_request_frame(FFFrameSync *fs, AVFilterLink *outlink)
308
{
309
    AVFilterContext *ctx = outlink->src;
310
    int input, ret;
311
 
312
    if ((ret = ff_framesync_process_frame(fs, 0)) < 0)
313
        return ret;
314
    if (ret > 0)
315
        return 0;
316
    if (fs->eof)
317
        return AVERROR_EOF;
318
    outlink->flags |= FF_LINK_FLAG_REQUEST_LOOP;
319
    input = fs->in_request;
320
    ret = ff_request_frame(ctx->inputs[input]);
321
    if (ret == AVERROR_EOF) {
322
        if ((ret = ff_framesync_add_frame(fs, input, NULL)) < 0)
323
            return ret;
324
        if ((ret = ff_framesync_process_frame(fs, 0)) < 0)
325
            return ret;
326
        ret = 0;
327
    }
328
    return ret;
329
}