Statistics
| Branch: | Revision:

ffmpeg / libavfilter / libmpcodecs / vf_framestep.c @ e4852fb3

History | View | Annotate | Download (5.96 KB)

1
/*
2
 * filter to ouput only 1 every n frame, or only the I (key)frame
3
 *
4
 * The parameters are:
5
 *
6
 *    [I] | [i]num
7
 *
8
 * if you call the filter with I (uppercase) as the parameter
9
 *    ... -vf framestep=I ...
10
 * then ONLY the keyframes are outputted.
11
 * For DVD it means, generally, one every 15 frames (IBBPBBPBBPBBPBB), for avi it means
12
 * every scene change or every keyint value (see -lavcopts).
13
 *
14
 * if you call the filter with the i (lowercase)
15
 *    ... -vf framestep=i ...
16
 * then a I! followed by a cr is printed when a key frame (eg Intra frame) is
17
 * found, leaving the current line of mplayer/mencoder, where you got the
18
 * time, in seconds, and frame of the key. Use this information to split the
19
 * AVI.
20
 *
21
 * After the i or alone you can put a positive number and only one frame every
22
 * x (the number you set) is passed on the filter chain, limiting the output
23
 * of the frame.
24
 *
25
 * Example
26
 *    ... -vf framestep=i20 ...
27
 * Dump one every 20 frames, printing on the console when a I-Frame is encounter.
28
 *
29
 *    ... -vf framestep=25
30
 * Dump one every 25 frames.
31
 *
32
 * If you call the filter without parameter it does nothing (except using memory
33
 * and resource of your system,. of course).
34
 *
35
 * This filter doesn' t work like the option -sstep seconds.
36
 *
37
 * The -sstep seek to the new position, without decoding all frames but,
38
 * expecially on avi file coded whith mpeg4 (lavc or xvid or divx), the
39
 * seek is not always too much precise.
40
 *
41
 * This filter simply discard the unwanted frames, so you are very precise in
42
 * counting the frame but sometime you use a lot of CPU for nothing.
43
 *
44
 * As usual it depends on what you're doing.
45
 *
46
 * copyright (c) 2003 Daniele Forghieri ( guru@digitalfantasy.it )
47
 *
48
 * This file is part of MPlayer.
49
 *
50
 * MPlayer is free software; you can redistribute it and/or modify
51
 * it under the terms of the GNU General Public License as published by
52
 * the Free Software Foundation; either version 2 of the License, or
53
 * (at your option) any later version.
54
 *
55
 * MPlayer is distributed in the hope that it will be useful,
56
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
57
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
58
 * GNU General Public License for more details.
59
 *
60
 * You should have received a copy of the GNU General Public License along
61
 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
62
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
63
 */
64

    
65
#include <stdio.h>
66
#include <stdlib.h>
67
#include <string.h>
68

    
69
#include "config.h"
70
#include "mp_msg.h"
71
#include "help_mp.h"
72
#include "cpudetect.h"
73

    
74
#include "img_format.h"
75
#include "mp_image.h"
76
#include "vf.h"
77

    
78
/* Uncomment if you want to print some info on the format */
79
// #define DUMP_FORMAT_DATA
80

    
81
/* Private data */
82
struct vf_priv_s {
83
    /* Current frame */
84
    int  frame_cur;
85
    /* Frame output step, 0 = all */
86
    int  frame_step;
87
    /* Only I-Frame (2), print on I-Frame (1) */
88
    int  dump_iframe;
89
};
90

    
91
/* Filter handler */
92
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
93
{
94
    mp_image_t        *dmpi;
95
    struct vf_priv_s  *priv;
96
    int               skip;
97

    
98
    priv = vf->priv;
99

    
100
    /* Print the 'I' if is a intra frame. The \n advance the current line so you got the
101
     * current file time (in second) and the frame number on the console ;-)
102
     */
103
    if (priv->dump_iframe) {
104
        if (mpi->pict_type == 1) {
105
            mp_msg(MSGT_VFILTER, MSGL_INFO, "I!\n");
106
        }
107
    }
108

    
109
    /* decide if frame must be shown */
110
    if (priv->dump_iframe == 2) {
111
        /* Only key frame */
112
        skip = mpi->pict_type == 1 ? 0 : 1;
113
    }
114
    else {
115
        /* Only 1 every frame_step */
116
        skip = 0;
117
        if ((priv->frame_step != 0) && ((priv->frame_cur % priv->frame_step) != 0)) {
118
            skip = 1;
119
        }
120
    }
121
    /* Increment current frame */
122
    ++priv->frame_cur;
123

    
124
    if (skip == 0) {
125
        /* Get image, export type (we don't modify tghe image) */
126
        dmpi=vf_get_image(vf->next, mpi->imgfmt,
127
                      MP_IMGTYPE_EXPORT, 0,
128
                      mpi->w, mpi->h);
129
        /* Copy only the pointer ( MP_IMGTYPE_EXPORT ! ) */
130
        dmpi->planes[0] = mpi->planes[0];
131
        dmpi->planes[1] = mpi->planes[1];
132
        dmpi->planes[2] = mpi->planes[2];
133

    
134
        dmpi->stride[0] = mpi->stride[0];
135
        dmpi->stride[1] = mpi->stride[1];
136
        dmpi->stride[2] = mpi->stride[2];
137

    
138
        dmpi->width     = mpi->width;
139
        dmpi->height    = mpi->height;
140

    
141
        /* Chain to next filter / output ... */
142
        return vf_next_put_image(vf, dmpi, pts);
143
    }
144

    
145
    /* Skip the frame */
146
    return 0;
147
}
148

    
149
static void uninit(struct vf_instance *vf)
150
{
151
    /* Free private data */
152
    free(vf->priv);
153
}
154

    
155
/* Main entry funct for the filter */
156
static int vf_open(vf_instance_t *vf, char *args)
157
{
158
        struct vf_priv_s *p;
159

    
160
        vf->put_image = put_image;
161
        vf->uninit = uninit;
162
        vf->default_reqs = VFCAP_ACCEPT_STRIDE;
163
        vf->priv = p = calloc(1, sizeof(struct vf_priv_s));
164
        if (p == NULL) {
165
            return 0;
166
        }
167

    
168
        if (args != NULL) {
169
#ifdef DUMP_FORMAT_DATA
170
            if (*args == 'd') {
171
                p->dump_iframe = 3;
172
            }
173
            else
174
#endif
175
            if (*args == 'I') {
176
                /* Dump only KEY (ie INTRA) frame */
177
                p->dump_iframe = 2;
178
            }
179
            else {
180
                if (*args == 'i') {
181
                    /* Print a 'I!' when a i-frame is encounter */
182
                    p->dump_iframe = 1;
183
                    ++args;
184
                }
185

    
186
                if (*args != '\0') {
187
                    p->frame_step = atoi(args);
188
                    if (p->frame_step <= 0) {
189
                        mp_msg(MSGT_VFILTER, MSGL_WARN, MSGTR_MPCODECS_ErrorParsingArgument);
190
                        return 0;
191
                    }
192
                }
193
            }
194
        }
195
        return 1;
196
}
197

    
198
const vf_info_t vf_info_framestep = {
199
    "Dump one every n / key frames",
200
    "framestep",
201
    "Daniele Forghieri",
202
    "",
203
    vf_open,
204
    NULL
205
};