00001 /* 00002 * filter to ouput only 1 every n frame, or only the I (key)frame 00003 * 00004 * The parameters are: 00005 * 00006 * [I] | [i]num 00007 * 00008 * if you call the filter with I (uppercase) as the parameter 00009 * ... -vf framestep=I ... 00010 * then ONLY the keyframes are outputted. 00011 * For DVD it means, generally, one every 15 frames (IBBPBBPBBPBBPBB), for avi it means 00012 * every scene change or every keyint value (see -lavcopts). 00013 * 00014 * if you call the filter with the i (lowercase) 00015 * ... -vf framestep=i ... 00016 * then a I! followed by a cr is printed when a key frame (eg Intra frame) is 00017 * found, leaving the current line of mplayer/mencoder, where you got the 00018 * time, in seconds, and frame of the key. Use this information to split the 00019 * AVI. 00020 * 00021 * After the i or alone you can put a positive number and only one frame every 00022 * x (the number you set) is passed on the filter chain, limiting the output 00023 * of the frame. 00024 * 00025 * Example 00026 * ... -vf framestep=i20 ... 00027 * Dump one every 20 frames, printing on the console when a I-Frame is encounter. 00028 * 00029 * ... -vf framestep=25 00030 * Dump one every 25 frames. 00031 * 00032 * If you call the filter without parameter it does nothing (except using memory 00033 * and resource of your system,. of course). 00034 * 00035 * This filter doesn' t work like the option -sstep seconds. 00036 * 00037 * The -sstep seek to the new position, without decoding all frames but, 00038 * expecially on avi file coded whith mpeg4 (lavc or xvid or divx), the 00039 * seek is not always too much precise. 00040 * 00041 * This filter simply discard the unwanted frames, so you are very precise in 00042 * counting the frame but sometime you use a lot of CPU for nothing. 00043 * 00044 * As usual it depends on what you're doing. 00045 * 00046 * copyright (c) 2003 Daniele Forghieri ( guru@digitalfantasy.it ) 00047 * 00048 * This file is part of MPlayer. 00049 * 00050 * MPlayer is free software; you can redistribute it and/or modify 00051 * it under the terms of the GNU General Public License as published by 00052 * the Free Software Foundation; either version 2 of the License, or 00053 * (at your option) any later version. 00054 * 00055 * MPlayer is distributed in the hope that it will be useful, 00056 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00057 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00058 * GNU General Public License for more details. 00059 * 00060 * You should have received a copy of the GNU General Public License along 00061 * with MPlayer; if not, write to the Free Software Foundation, Inc., 00062 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 00063 */ 00064 00065 #include <stdio.h> 00066 #include <stdlib.h> 00067 #include <string.h> 00068 00069 #include "config.h" 00070 #include "mp_msg.h" 00071 #include "help_mp.h" 00072 #include "cpudetect.h" 00073 00074 #include "img_format.h" 00075 #include "mp_image.h" 00076 #include "vf.h" 00077 00078 /* Uncomment if you want to print some info on the format */ 00079 // #define DUMP_FORMAT_DATA 00080 00081 /* Private data */ 00082 struct vf_priv_s { 00083 /* Current frame */ 00084 int frame_cur; 00085 /* Frame output step, 0 = all */ 00086 int frame_step; 00087 /* Only I-Frame (2), print on I-Frame (1) */ 00088 int dump_iframe; 00089 }; 00090 00091 /* Filter handler */ 00092 static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts) 00093 { 00094 mp_image_t *dmpi; 00095 struct vf_priv_s *priv; 00096 int skip; 00097 00098 priv = vf->priv; 00099 00100 /* Print the 'I' if is a intra frame. The \n advance the current line so you got the 00101 * current file time (in second) and the frame number on the console ;-) 00102 */ 00103 if (priv->dump_iframe) { 00104 if (mpi->pict_type == 1) { 00105 mp_msg(MSGT_VFILTER, MSGL_INFO, "I!\n"); 00106 } 00107 } 00108 00109 /* decide if frame must be shown */ 00110 if (priv->dump_iframe == 2) { 00111 /* Only key frame */ 00112 skip = mpi->pict_type == 1 ? 0 : 1; 00113 } 00114 else { 00115 /* Only 1 every frame_step */ 00116 skip = 0; 00117 if ((priv->frame_step != 0) && ((priv->frame_cur % priv->frame_step) != 0)) { 00118 skip = 1; 00119 } 00120 } 00121 /* Increment current frame */ 00122 ++priv->frame_cur; 00123 00124 if (skip == 0) { 00125 /* Get image, export type (we don't modify tghe image) */ 00126 dmpi=vf_get_image(vf->next, mpi->imgfmt, 00127 MP_IMGTYPE_EXPORT, 0, 00128 mpi->w, mpi->h); 00129 /* Copy only the pointer ( MP_IMGTYPE_EXPORT ! ) */ 00130 dmpi->planes[0] = mpi->planes[0]; 00131 dmpi->planes[1] = mpi->planes[1]; 00132 dmpi->planes[2] = mpi->planes[2]; 00133 00134 dmpi->stride[0] = mpi->stride[0]; 00135 dmpi->stride[1] = mpi->stride[1]; 00136 dmpi->stride[2] = mpi->stride[2]; 00137 00138 dmpi->width = mpi->width; 00139 dmpi->height = mpi->height; 00140 00141 /* Chain to next filter / output ... */ 00142 return vf_next_put_image(vf, dmpi, pts); 00143 } 00144 00145 /* Skip the frame */ 00146 return 0; 00147 } 00148 00149 static void uninit(struct vf_instance *vf) 00150 { 00151 /* Free private data */ 00152 free(vf->priv); 00153 } 00154 00155 /* Main entry funct for the filter */ 00156 static int vf_open(vf_instance_t *vf, char *args) 00157 { 00158 struct vf_priv_s *p; 00159 00160 vf->put_image = put_image; 00161 vf->uninit = uninit; 00162 vf->default_reqs = VFCAP_ACCEPT_STRIDE; 00163 vf->priv = p = calloc(1, sizeof(struct vf_priv_s)); 00164 if (p == NULL) { 00165 return 0; 00166 } 00167 00168 if (args != NULL) { 00169 #ifdef DUMP_FORMAT_DATA 00170 if (*args == 'd') { 00171 p->dump_iframe = 3; 00172 } 00173 else 00174 #endif 00175 if (*args == 'I') { 00176 /* Dump only KEY (ie INTRA) frame */ 00177 p->dump_iframe = 2; 00178 } 00179 else { 00180 if (*args == 'i') { 00181 /* Print a 'I!' when a i-frame is encounter */ 00182 p->dump_iframe = 1; 00183 ++args; 00184 } 00185 00186 if (*args != '\0') { 00187 p->frame_step = atoi(args); 00188 if (p->frame_step <= 0) { 00189 mp_msg(MSGT_VFILTER, MSGL_WARN, MSGTR_MPCODECS_ErrorParsingArgument); 00190 return 0; 00191 } 00192 } 00193 } 00194 } 00195 return 1; 00196 } 00197 00198 const vf_info_t vf_info_framestep = { 00199 "Dump one every n / key frames", 00200 "framestep", 00201 "Daniele Forghieri", 00202 "", 00203 vf_open, 00204 NULL 00205 };