1 /* === S Y N F I G ========================================================= */
2 /*! \file mptr_ffmpeg.cpp
3 ** \brief ppm Target Module
8 ** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
10 ** This package is free software; you can redistribute it and/or
11 ** modify it under the terms of the GNU General Public License as
12 ** published by the Free Software Foundation; either version 2 of
13 ** the License, or (at your option) any later version.
15 ** This package is distributed in the hope that it will be useful,
16 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 ** General Public License for more details.
21 ** === N O T E S ===========================================================
23 ** ========================================================================= */
25 /* === H E A D E R S ======================================================= */
34 #include <ETL/stringf>
35 #include "mptr_ffmpeg.h"
37 #include <sys/types.h>
54 #include <ETL/stringf>
57 /* === M A C R O S ========================================================= */
59 using namespace synfig;
63 #if defined(HAVE_FORK) && defined(HAVE_PIPE) && defined(HAVE_WAITPID)
64 #define UNIX_PIPE_TO_PROCESSES
65 #elif defined(HAVE__SPAWNLP) && defined(HAVE__PIPE) && defined(HAVE_CWAIT)
66 #define WIN32_PIPE_TO_PROCESSES
69 /* === G L O B A L S ======================================================= */
71 SYNFIG_IMPORTER_INIT(ffmpeg_mptr);
72 SYNFIG_IMPORTER_SET_NAME(ffmpeg_mptr,"ffmpeg");
73 SYNFIG_IMPORTER_SET_EXT(ffmpeg_mptr,"avi");
74 SYNFIG_IMPORTER_SET_VERSION(ffmpeg_mptr,"0.1");
75 SYNFIG_IMPORTER_SET_CVS_ID(ffmpeg_mptr,"$Id$");
77 /* === M E T H O D S ======================================================= */
80 ffmpeg_mptr::seek_to(int frame)
82 if(frame<cur_frame || !file)
88 #if defined(WIN32_PIPE_TO_PROCESSES)
90 #elif defined(UNIX_PIPE_TO_PROCESSES)
91 waitpid(pid,&status,0);
95 #if defined(WIN32_PIPE_TO_PROCESSES)
98 int stdin_fileno, stdout_fileno;
100 if(_pipe(p, 512, O_BINARY | O_NOINHERIT) < 0) {
101 cerr<<"Unable to open pipe to ffmpeg"<<endl;
105 // Save stdin/stdout so we can restore them later
106 stdin_fileno = _dup(_fileno(stdin));
107 stdout_fileno = _dup(_fileno(stdout));
109 // ffmpeg should write to the pipe
110 if(_dup2(p[1], _fileno(stdout)) != 0) {
111 cerr<<"Unable to open pipe to ffmpeg"<<endl;
116 ffmpeg accepts the input filename on the command-line
117 if(_dup2(_fileno(input), _fileno(stdin)) != 0) {
118 synfig::error(_("Unable to open pipe to ffmpeg"));
123 pid = _spawnlp(_P_NOWAIT, "ffmpeg", "ffmpeg", "-i", filename.c_str(), "-an", "-f", "image2pipe", "-vcodec", "ppm", "-", (const char *)NULL);
125 cerr<<"Unable to open pipe to ffmpeg"<<endl;
129 // Restore stdin/stdout
130 if(_dup2(stdin_fileno, _fileno(stdin)) != 0) {
131 cerr<<"Unable to open pipe to ffmpeg"<<endl;
134 if(_dup2(stdout_fileno, _fileno(stdout)) != 0) {
135 cerr<<"Unable to open pipe to ffmpeg"<<endl;
139 close(stdout_fileno);
141 // Close the pipe write end - ffmpeg uses it
144 // We read data from the read end of the pipe
145 file = fdopen(p[0], "rb");
147 #elif defined(UNIX_PIPE_TO_PROCESSES)
152 cerr<<"Unable to open pipe to ffmpeg"<<endl;
159 cerr<<"Unable to open pipe to ffmpeg"<<endl;
165 // Close pipein, not needed
167 // Dup pipein to stdout
168 if( dup2( p[1], STDOUT_FILENO ) == -1 ){
169 cerr<<"Unable to open pipe to ffmpeg"<<endl;
172 // Close the unneeded pipein
174 execlp("ffmpeg", "ffmpeg", "-i", filename.c_str(), "-an", "-f", "image2pipe", "-vcodec", "ppm", "-", (const char *)NULL);
175 // We should never reach here unless the exec failed
176 cerr<<"Unable to open pipe to ffmpeg"<<endl;
180 // Close pipeout, not needed
182 // Save pipein to file handle, will read from it later
183 file = fdopen(p[0], "rb");
187 #error There are no known APIs for creating child processes
192 cerr<<"Unable to open pipe to ffmpeg"<<endl;
198 while(cur_frame<frame-1)
200 cerr<<"Seeking to..."<<frame<<'('<<cur_frame<<')'<<endl;
208 ffmpeg_mptr::grab_frame(void)
212 cerr<<"unable to open "<<filename<<endl;
218 cookie[0]=fgetc(file);
219 cookie[1]=fgetc(file);
221 if(cookie[0]!='P' || cookie[1]!='6')
223 cerr<<"stream not in PPM format \""<<cookie[0]<<cookie[1]<<'"'<<endl;
228 fscanf(file,"%d %d\n",&w,&h);
229 fscanf(file,"%f",&divisor);
238 for(y=0;y<frame.get_h();y++)
239 for(x=0;x<frame.get_w();x++)
245 (float)(unsigned char)fgetc(file)/divisor,
246 (float)(unsigned char)fgetc(file)/divisor,
247 (float)(unsigned char)fgetc(file)/divisor,
250 float r=gamma().r_U8_to_F32((unsigned char)fgetc(file));
251 float g=gamma().g_U8_to_F32((unsigned char)fgetc(file));
252 float b=gamma().b_U8_to_F32((unsigned char)fgetc(file));
264 ffmpeg_mptr::ffmpeg_mptr(const char *f)
267 #ifdef HAVE_TERMIOS_H
268 tcgetattr (0, &oldtty);
276 ffmpeg_mptr::~ffmpeg_mptr()
282 #if defined(WIN32_PIPE_TO_PROCESSES)
283 cwait(&status,pid,0);
284 #elif defined(UNIX_PIPE_TO_PROCESSES)
285 waitpid(pid,&status,0);
288 #ifdef HAVE_TERMIOS_H
289 tcsetattr(0,TCSANOW,&oldtty);
294 ffmpeg_mptr::get_frame(synfig::Surface &surface,Time time, synfig::ProgressCallback *)
296 int i=(int)(time*fps);