LCOV - code coverage report
Current view: top level - src/libavfilter - framesync.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 164 192 85.4 %
Date: 2017-01-28 02:43:52 Functions: 14 15 93.3 %

          Line data    Source code
       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             : #define FF_INTERNAL_FIELDS 1
      22             : #include "framequeue.h"
      23             : 
      24             : #include "libavutil/avassert.h"
      25             : #include "avfilter.h"
      26             : #include "bufferqueue.h"
      27             : #include "framesync.h"
      28             : #include "internal.h"
      29             : 
      30             : #define OFFSET(member) offsetof(FFFrameSync, member)
      31             : 
      32           0 : static const char *framesync_name(void *ptr)
      33             : {
      34           0 :     return "framesync";
      35             : }
      36             : 
      37             : static const AVClass framesync_class = {
      38             :     .version                   = LIBAVUTIL_VERSION_INT,
      39             :     .class_name                = "framesync",
      40             :     .item_name                 = framesync_name,
      41             :     .category                  = AV_CLASS_CATEGORY_FILTER,
      42             :     .option                    = NULL,
      43             :     .parent_log_context_offset = OFFSET(parent),
      44             : };
      45             : 
      46             : enum {
      47             :     STATE_BOF,
      48             :     STATE_RUN,
      49             :     STATE_EOF,
      50             : };
      51             : 
      52          16 : int ff_framesync_init(FFFrameSync *fs, void *parent, unsigned nb_in)
      53             : {
      54          16 :     fs->class  = &framesync_class;
      55          16 :     fs->parent = parent;
      56          16 :     fs->nb_in  = nb_in;
      57             : 
      58          16 :     fs->in = av_calloc(nb_in, sizeof(*fs->in));
      59          16 :     if (!fs->in)
      60           0 :         return AVERROR(ENOMEM);
      61          16 :     return 0;
      62             : }
      63             : 
      64          46 : static void framesync_sync_level_update(FFFrameSync *fs)
      65             : {
      66          46 :     unsigned i, level = 0;
      67             : 
      68         136 :     for (i = 0; i < fs->nb_in; i++)
      69          90 :         if (fs->in[i].state != STATE_EOF)
      70          90 :             level = FFMAX(level, fs->in[i].sync);
      71          46 :     av_assert0(level <= fs->sync_level);
      72          46 :     if (level < fs->sync_level)
      73          40 :         av_log(fs, AV_LOG_VERBOSE, "Sync level %u\n", level);
      74          46 :     if (level)
      75          31 :         fs->sync_level = level;
      76             :     else
      77          15 :         fs->eof = 1;
      78          46 : }
      79             : 
      80          16 : int ff_framesync_configure(FFFrameSync *fs)
      81             : {
      82             :     unsigned i;
      83             :     int64_t gcd, lcm;
      84             : 
      85          16 :     if (!fs->time_base.num) {
      86          47 :         for (i = 0; i < fs->nb_in; i++) {
      87          31 :             if (fs->in[i].sync) {
      88          31 :                 if (fs->time_base.num) {
      89          15 :                     gcd = av_gcd(fs->time_base.den, fs->in[i].time_base.den);
      90          15 :                     lcm = (fs->time_base.den / gcd) * fs->in[i].time_base.den;
      91          15 :                     if (lcm < AV_TIME_BASE / 2) {
      92          15 :                         fs->time_base.den = lcm;
      93          15 :                         fs->time_base.num = av_gcd(fs->time_base.num,
      94          15 :                                                    fs->in[i].time_base.num);
      95             :                     } else {
      96           0 :                         fs->time_base.num = 1;
      97           0 :                         fs->time_base.den = AV_TIME_BASE;
      98           0 :                         break;
      99             :                     }
     100             :                 } else {
     101          16 :                     fs->time_base = fs->in[i].time_base;
     102             :                 }
     103             :             }
     104             :         }
     105          16 :         if (!fs->time_base.num) {
     106           0 :             av_log(fs, AV_LOG_ERROR, "Impossible to set time base\n");
     107           0 :             return AVERROR(EINVAL);
     108             :         }
     109          16 :         av_log(fs, AV_LOG_VERBOSE, "Selected %d/%d time base\n",
     110             :                fs->time_base.num, fs->time_base.den);
     111             :     }
     112             : 
     113          47 :     for (i = 0; i < fs->nb_in; i++)
     114          31 :         fs->in[i].pts = fs->in[i].pts_next = AV_NOPTS_VALUE;
     115          16 :     fs->sync_level = UINT_MAX;
     116          16 :     framesync_sync_level_update(fs);
     117             : 
     118          16 :     return 0;
     119             : }
     120             : 
     121        5197 : static void framesync_advance(FFFrameSync *fs)
     122             : {
     123             :     int latest;
     124             :     unsigned i;
     125             :     int64_t pts;
     126             : 
     127        5197 :     if (fs->eof)
     128          15 :         return;
     129       11630 :     while (!fs->frame_ready) {
     130        5382 :         latest = -1;
     131       15994 :         for (i = 0; i < fs->nb_in; i++) {
     132       10612 :             if (!fs->in[i].have_next) {
     133        5105 :                 if (latest < 0 || fs->in[i].pts < fs->in[latest].pts)
     134        4116 :                     latest = i;
     135             :             }
     136             :         }
     137        5382 :         if (latest >= 0) {
     138        4116 :             fs->in_request = latest;
     139        4116 :             break;
     140             :         }
     141             : 
     142        1266 :         pts = fs->in[0].pts_next;
     143        2482 :         for (i = 1; i < fs->nb_in; i++)
     144        1216 :             if (fs->in[i].pts_next < pts)
     145         285 :                 pts = fs->in[i].pts_next;
     146        1266 :         if (pts == INT64_MAX) {
     147           0 :             fs->eof = 1;
     148           0 :             break;
     149             :         }
     150        3748 :         for (i = 0; i < fs->nb_in; i++) {
     151        3218 :             if (fs->in[i].pts_next == pts ||
     152         736 :                 (fs->in[i].before == EXT_INFINITY &&
     153           0 :                  fs->in[i].state == STATE_BOF)) {
     154        1746 :                 av_frame_free(&fs->in[i].frame);
     155        1746 :                 fs->in[i].frame      = fs->in[i].frame_next;
     156        1746 :                 fs->in[i].pts        = fs->in[i].pts_next;
     157        1746 :                 fs->in[i].frame_next = NULL;
     158        1746 :                 fs->in[i].pts_next   = AV_NOPTS_VALUE;
     159        1746 :                 fs->in[i].have_next  = 0;
     160        1746 :                 fs->in[i].state      = fs->in[i].frame ? STATE_RUN : STATE_EOF;
     161        1746 :                 if (fs->in[i].sync == fs->sync_level && fs->in[i].frame)
     162        1166 :                     fs->frame_ready = 1;
     163        1746 :                 if (fs->in[i].state == STATE_EOF &&
     164           0 :                     fs->in[i].after == EXT_STOP)
     165           0 :                     fs->eof = 1;
     166             :             }
     167             :         }
     168        1266 :         if (fs->eof)
     169           0 :             fs->frame_ready = 0;
     170        1266 :         if (fs->frame_ready)
     171        3148 :             for (i = 0; i < fs->nb_in; i++)
     172        2082 :                 if ((fs->in[i].state == STATE_BOF &&
     173           0 :                      fs->in[i].before == EXT_STOP))
     174           0 :                     fs->frame_ready = 0;
     175        1266 :         fs->pts = pts;
     176             :     }
     177             : }
     178             : 
     179           1 : static int64_t framesync_pts_extrapolate(FFFrameSync *fs, unsigned in,
     180             :                                          int64_t pts)
     181             : {
     182             :     /* Possible enhancement: use the link's frame rate */
     183           1 :     return pts + 1;
     184             : }
     185             : 
     186        1776 : static void framesync_inject_frame(FFFrameSync *fs, unsigned in, AVFrame *frame)
     187             : {
     188             :     int64_t pts;
     189             : 
     190        1776 :     av_assert0(!fs->in[in].have_next);
     191        1776 :     if (frame) {
     192        1746 :         pts = av_rescale_q(frame->pts, fs->in[in].time_base, fs->time_base);
     193        1746 :         frame->pts = pts;
     194             :     } else {
     195          90 :         pts = fs->in[in].state != STATE_RUN || fs->in[in].after == EXT_INFINITY
     196          31 :             ? INT64_MAX : framesync_pts_extrapolate(fs, in, fs->in[in].pts);
     197          30 :         fs->in[in].sync = 0;
     198          30 :         framesync_sync_level_update(fs);
     199             :     }
     200        1776 :     fs->in[in].frame_next = frame;
     201        1776 :     fs->in[in].pts_next   = pts;
     202        1776 :     fs->in[in].have_next  = 1;
     203        1776 : }
     204             : 
     205        1776 : int ff_framesync_add_frame(FFFrameSync *fs, unsigned in, AVFrame *frame)
     206             : {
     207             :     av_assert1(in < fs->nb_in);
     208        1776 :     if (!fs->in[in].have_next)
     209        1774 :         framesync_inject_frame(fs, in, frame);
     210             :     else
     211           2 :         ff_bufqueue_add(fs, &fs->in[in].queue, frame);
     212        1776 :     return 0;
     213             : }
     214             : 
     215        5197 : void ff_framesync_next(FFFrameSync *fs)
     216             : {
     217             :     unsigned i;
     218             : 
     219        5197 :     av_assert0(!fs->frame_ready);
     220       15438 :     for (i = 0; i < fs->nb_in; i++)
     221       10241 :         if (!fs->in[i].have_next && fs->in[i].queue.available)
     222           2 :             framesync_inject_frame(fs, i, ff_bufqueue_get(&fs->in[i].queue));
     223        5197 :     fs->frame_ready = 0;
     224        5197 :     framesync_advance(fs);
     225        5197 : }
     226             : 
     227        1066 : void ff_framesync_drop(FFFrameSync *fs)
     228             : {
     229        1066 :     fs->frame_ready = 0;
     230        1066 : }
     231             : 
     232        2082 : int ff_framesync_get_frame(FFFrameSync *fs, unsigned in, AVFrame **rframe,
     233             :                            unsigned get)
     234             : {
     235             :     AVFrame *frame;
     236        2082 :     unsigned need_copy = 0, i;
     237             :     int64_t pts_next;
     238             :     int ret;
     239             : 
     240        2082 :     if (!fs->in[in].frame) {
     241           0 :         *rframe = NULL;
     242           0 :         return 0;
     243             :     }
     244        2082 :     frame = fs->in[in].frame;
     245        2082 :     if (get) {
     246             :         /* Find out if we need to copy the frame: is there another sync
     247             :            stream, and do we know if its current frame will outlast this one? */
     248         916 :         pts_next = fs->in[in].have_next ? fs->in[in].pts_next : INT64_MAX;
     249        2748 :         for (i = 0; i < fs->nb_in && !need_copy; i++)
     250        2528 :             if (i != in && fs->in[i].sync &&
     251         927 :                 (!fs->in[i].have_next || fs->in[i].pts_next < pts_next))
     252         696 :                 need_copy = 1;
     253         916 :         if (need_copy) {
     254         696 :             if (!(frame = av_frame_clone(frame)))
     255           0 :                 return AVERROR(ENOMEM);
     256         696 :             if ((ret = av_frame_make_writable(frame)) < 0) {
     257           0 :                 av_frame_free(&frame);
     258           0 :                 return ret;
     259             :             }
     260             :         } else {
     261         220 :             fs->in[in].frame = NULL;
     262             :         }
     263         916 :         fs->frame_ready = 0;
     264             :     }
     265        2082 :     *rframe = frame;
     266        2082 :     return 0;
     267             : }
     268             : 
     269          33 : void ff_framesync_uninit(FFFrameSync *fs)
     270             : {
     271             :     unsigned i;
     272             : 
     273          64 :     for (i = 0; i < fs->nb_in; i++) {
     274          31 :         av_frame_free(&fs->in[i].frame);
     275          31 :         av_frame_free(&fs->in[i].frame_next);
     276          31 :         ff_bufqueue_discard_all(&fs->in[i].queue);
     277             :     }
     278             : 
     279          33 :     av_freep(&fs->in);
     280          33 : }
     281             : 
     282        5197 : int ff_framesync_process_frame(FFFrameSync *fs, unsigned all)
     283             : {
     284        5197 :     int ret, count = 0;
     285             : 
     286        5197 :     av_assert0(fs->on_event);
     287             :     while (1) {
     288        5197 :         ff_framesync_next(fs);
     289        5197 :         if (fs->eof || !fs->frame_ready)
     290             :             break;
     291        1066 :         if ((ret = fs->on_event(fs)) < 0)
     292           0 :             return ret;
     293        1066 :         ff_framesync_drop(fs);
     294        1066 :         count++;
     295        1066 :         if (!all)
     296        1066 :             break;
     297             :     }
     298        5197 :     if (!count && fs->eof)
     299          15 :         return AVERROR_EOF;
     300        5182 :     return count;
     301             : }
     302             : 
     303        1746 : int ff_framesync_filter_frame(FFFrameSync *fs, AVFilterLink *inlink,
     304             :                               AVFrame *in)
     305             : {
     306             :     int ret;
     307             : 
     308        1746 :     if ((ret = ff_framesync_process_frame(fs, 1)) < 0)
     309           0 :         return ret;
     310        1746 :     if ((ret = ff_framesync_add_frame(fs, FF_INLINK_IDX(inlink), in)) < 0)
     311           0 :         return ret;
     312        1746 :     if ((ret = ff_framesync_process_frame(fs, 0)) < 0)
     313           0 :         return ret;
     314        1746 :     return 0;
     315             : }
     316             : 
     317        1675 : int ff_framesync_request_frame(FFFrameSync *fs, AVFilterLink *outlink)
     318             : {
     319        1675 :     AVFilterContext *ctx = outlink->src;
     320             :     int input, ret, i;
     321             : 
     322        1675 :     if ((ret = ff_framesync_process_frame(fs, 0)) < 0)
     323           0 :         return ret;
     324        1675 :     if (ret > 0)
     325           2 :         return 0;
     326        1673 :     if (fs->eof)
     327           0 :         return AVERROR_EOF;
     328        1673 :     input = fs->in_request;
     329             :     /* Detect status change early */
     330        4967 :     for (i = 0; i < fs->nb_in; i++)
     331        6588 :         if (!ff_framequeue_queued_frames(&ctx->inputs[i]->fifo) &&
     332        3571 :             ctx->inputs[i]->status_in && !ctx->inputs[i]->status_out)
     333          30 :             input = i;
     334        1673 :     ret = ff_request_frame(ctx->inputs[input]);
     335        1673 :     if (ret == AVERROR_EOF) {
     336          30 :         if ((ret = ff_framesync_add_frame(fs, input, NULL)) < 0)
     337           0 :             return ret;
     338          30 :         if ((ret = ff_framesync_process_frame(fs, 0)) < 0)
     339          15 :             return ret;
     340          15 :         ret = 0;
     341             :     }
     342        1658 :     return ret;
     343             : }

Generated by: LCOV version 1.12