-/*! ========================================================================
-** Synfig
-** ppm Target Module
-** $Id: mptr_ffmpeg.cpp,v 1.1.1.1 2005/01/04 01:23:10 darco Exp $
+/* === S Y N F I G ========================================================= */
+/*! \file mptr_ffmpeg.cpp
+** \brief ppm Target Module
**
-** Copyright (c) 2002 Robert B. Quattlebaum Jr.
+** $Id$
**
-** This software and associated documentation
-** are CONFIDENTIAL and PROPRIETARY property of
-** the above-mentioned copyright holder.
+** \legal
+** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
+** Copyright (c) 2007 Chris Moore
**
-** You may not copy, print, publish, or in any
-** other way distribute this software without
-** a prior written agreement with
-** the copyright holder.
+** This package is free software; you can redistribute it and/or
+** modify it under the terms of the GNU General Public License as
+** published by the Free Software Foundation; either version 2 of
+** the License, or (at your option) any later version.
+**
+** This package is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+** General Public License for more details.
+** \endlegal
**
** === N O T E S ===========================================================
**
#include <ETL/stringf>
#include "mptr_ffmpeg.h"
#include <stdio.h>
+#include <sys/types.h>
+#if HAVE_SYS_WAIT_H
+ #include <sys/wait.h>
+#endif
+#if HAVE_IO_H
+ #include <io.h>
+#endif
+#if HAVE_PROCESS_H
+ #include <process.h>
+#endif
+#if HAVE_FCNTL_H
+ #include <fcntl.h>
+#endif
+#include <unistd.h>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
using namespace etl;
+#if defined(HAVE_FORK) && defined(HAVE_PIPE) && defined(HAVE_WAITPID)
+ #define UNIX_PIPE_TO_PROCESSES
+#else
+ #define WIN32_PIPE_TO_PROCESSES
+#endif
+
/* === G L O B A L S ======================================================= */
SYNFIG_IMPORTER_INIT(ffmpeg_mptr);
SYNFIG_IMPORTER_SET_NAME(ffmpeg_mptr,"ffmpeg");
SYNFIG_IMPORTER_SET_EXT(ffmpeg_mptr,"avi");
SYNFIG_IMPORTER_SET_VERSION(ffmpeg_mptr,"0.1");
-SYNFIG_IMPORTER_SET_CVS_ID(ffmpeg_mptr,"$Id: mptr_ffmpeg.cpp,v 1.1.1.1 2005/01/04 01:23:10 darco Exp $");
+SYNFIG_IMPORTER_SET_CVS_ID(ffmpeg_mptr,"$Id$");
/* === M E T H O D S ======================================================= */
+bool ffmpeg_mptr::is_animated()
+{
+ return true;
+}
+
bool
ffmpeg_mptr::seek_to(int frame)
{
{
if(file)
{
- pclose(file);
+#if defined(WIN32_PIPE_TO_PROCESSES)
+ pclose(file);
+#elif defined(UNIX_PIPE_TO_PROCESSES)
+ fclose(file);
+ int status;
+ waitpid(pid,&status,0);
+#endif
}
+#if defined(WIN32_PIPE_TO_PROCESSES)
+
string command;
-
- command=strprintf("ffmpeg -i \"%s\" -an -f ppmpipe -\n",filename.c_str());
-
- file=popen(command.c_str(),"r");
-
+
+ command=strprintf("ffmpeg -i \"%s\" -an -f image2pipe -vcodec ppm -\n",filename.c_str());
+
+ file=popen(command.c_str(),POPEN_BINARY_READ_TYPE);
+
+#elif defined(UNIX_PIPE_TO_PROCESSES)
+
+ int p[2];
+
+ if (pipe(p)) {
+ cerr<<"Unable to open pipe to ffmpeg"<<endl;
+ return false;
+ };
+
+ pid = fork();
+
+ if (pid == -1) {
+ cerr<<"Unable to open pipe to ffmpeg"<<endl;
+ return false;
+ }
+
+ if (pid == 0){
+ // Child process
+ // Close pipein, not needed
+ close(p[0]);
+ // Dup pipein to stdout
+ if( dup2( p[1], STDOUT_FILENO ) == -1 ){
+ cerr<<"Unable to open pipe to ffmpeg"<<endl;
+ return false;
+ }
+ // Close the unneeded pipein
+ close(p[1]);
+ execlp("ffmpeg", "ffmpeg", "-i", filename.c_str(), "-an", "-f", "image2pipe", "-vcodec", "ppm", "-", (const char *)NULL);
+ // We should never reach here unless the exec failed
+ cerr<<"Unable to open pipe to ffmpeg"<<endl;
+ _exit(1);
+ } else {
+ // Parent process
+ // Close pipeout, not needed
+ close(p[1]);
+ // Save pipein to file handle, will read from it later
+ file = fdopen(p[0], "rb");
+ }
+
+#else
+ #error There are no known APIs for creating child processes
+#endif
+
if(!file)
{
cerr<<"Unable to open pipe to ffmpeg"<<endl;
}
cur_frame=-1;
}
-
+
while(cur_frame<frame-1)
{
cerr<<"Seeking to..."<<frame<<'('<<cur_frame<<')'<<endl;
float divisor;
char cookie[2];
cookie[0]=fgetc(file);
+
+ if(feof(file))
+ return false;
+
cookie[1]=fgetc(file);
-
+
if(cookie[0]!='P' || cookie[1]!='6')
{
cerr<<"stream not in PPM format \""<<cookie[0]<<cookie[1]<<'"'<<endl;
return false;
}
-
+
fgetc(file);
fscanf(file,"%d %d\n",&w,&h);
fscanf(file,"%f",&divisor);
fgetc(file);
-
+
if(feof(file))
return false;
-
+
int x;
int y;
frame.set_wh(w,h);
1.0
);
}
- cur_frame++;
+ cur_frame++;
return true;
}
ffmpeg_mptr::ffmpeg_mptr(const char *f)
{
+ pid=-1;
#ifdef HAVE_TERMIOS_H
tcgetattr (0, &oldtty);
#endif
ffmpeg_mptr::~ffmpeg_mptr()
{
if(file)
- pclose(file);
+ {
+#if defined(WIN32_PIPE_TO_PROCESSES)
+ pclose(file);
+#elif defined(UNIX_PIPE_TO_PROCESSES)
+ fclose(file);
+ int status;
+ waitpid(pid,&status,0);
+#endif
+ }
#ifdef HAVE_TERMIOS_H
tcsetattr(0,TCSANOW,&oldtty);
#endif
{
if(!seek_to(i))
return false;
- if(!grab_frame());
+ if(!grab_frame())
return false;
}
-
+
surface=frame;
- return false;
+ return true;
}