Enable $Id$ expansion.
[synfig.git] / synfig-core / trunk / src / modules / mod_ffmpeg / trgt_ffmpeg.cpp
1 /* === S Y N F I G ========================================================= */
2 /*!     \file trgt_ffmpeg.cpp
3 **      \brief ppm Target Module
4 **
5 **      \legal
6 **      Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
7 **
8 **      This package is free software; you can redistribute it and/or
9 **      modify it under the terms of the GNU General Public License as
10 **      published by the Free Software Foundation; either version 2 of
11 **      the License, or (at your option) any later version.
12 **
13 **      This package is distributed in the hope that it will be useful,
14 **      but WITHOUT ANY WARRANTY; without even the implied warranty of
15 **      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 **      General Public License for more details.
17 **      \endlegal
18 **
19 ** === N O T E S ===========================================================
20 **
21 ** ========================================================================= */
22
23 /* === H E A D E R S ======================================================= */
24
25 #define SYNFIG_TARGET
26
27 #ifdef USING_PCH
28 #       include "pch.h"
29 #else
30 #ifdef HAVE_CONFIG_H
31 #       include <config.h>
32 #endif
33
34 #include <ETL/stringf>
35 #include "trgt_ffmpeg.h"
36 #include <stdio.h>
37 #include <algorithm>
38 #include <functional>
39 #include <ETL/clock>
40
41 #endif
42
43 /* === M A C R O S ========================================================= */
44
45 using namespace synfig;
46 using namespace std;
47 using namespace etl;
48
49 /* === G L O B A L S ======================================================= */
50
51 SYNFIG_TARGET_INIT(ffmpeg_trgt);
52 SYNFIG_TARGET_SET_NAME(ffmpeg_trgt,"ffmpeg");
53 SYNFIG_TARGET_SET_EXT(ffmpeg_trgt,"mpg");
54 SYNFIG_TARGET_SET_VERSION(ffmpeg_trgt,"0.1");
55 SYNFIG_TARGET_SET_CVS_ID(ffmpeg_trgt,"$Id$");
56
57 /* === M E T H O D S ======================================================= */
58
59 ffmpeg_trgt::ffmpeg_trgt(const char *Filename)
60 {
61         file=NULL;
62         filename=Filename;
63         multi_image=false;
64         buffer=NULL;
65         color_buffer=0;
66         set_remove_alpha();
67 }
68
69 ffmpeg_trgt::~ffmpeg_trgt()
70 {
71         if(file)
72         {
73                 etl::yield();
74                 sleep(1);
75                 pclose(file);
76         }
77         file=NULL;
78         delete [] buffer;
79         delete [] color_buffer;
80 }
81
82 bool
83 ffmpeg_trgt::set_rend_desc(RendDesc *given_desc)
84 {
85         //given_desc->set_pixel_format(PF_RGB);
86
87         // Make sure that the width and height
88         // are multiples of 8
89         given_desc->set_w((given_desc->get_w()+4)/8*8);
90         given_desc->set_h((given_desc->get_h()+4)/8*8);
91
92         /*
93         // Valid framerates:
94         // 23.976, 24, 25, 29.97, 30, 50 ,59.94, 60
95         float fps=given_desc->get_frame_rate();
96         if(fps <24.0)
97                 given_desc->set_frame_rate(23.976);
98         if(fps>=24.0 && fps <25.0)
99                 given_desc->set_frame_rate(24);
100         if(fps>=25.0 && fps <29.97)
101                 given_desc->set_frame_rate(25);
102         if(fps>=29.97 && fps <30.0)
103                 given_desc->set_frame_rate(29.97);
104         if(fps>=29.97 && fps <30.0)
105                 given_desc->set_frame_rate(29.97);
106         if(fps>=30.0 && fps <50.0)
107                 given_desc->set_frame_rate(30.0);
108         if(fps>=50.0 && fps <59.94)
109                 given_desc->set_frame_rate(50);
110         if(fps>=59.94)
111                 given_desc->set_frame_rate(59.94);
112     */
113
114         desc=*given_desc;
115
116         return true;
117 }
118
119 bool
120 ffmpeg_trgt::init()
121 {
122         imagecount=desc.get_frame_start();
123         if(desc.get_frame_end()-desc.get_frame_start()>0)
124                 multi_image=true;
125         string command;
126
127         command=strprintf("ffmpeg -f image2pipe -vcodec ppm -an -r %f -i pipe: -loop -hq -title \"%s\" -vcodec mpeg1video -y \"%s\"\n",desc.get_frame_rate(),get_canvas()->get_name().c_str(),filename.c_str());
128
129         file=popen(command.c_str(),"w");
130
131         // etl::yield();
132
133         if(!file)
134         {
135                 synfig::error(_("Unable to open pipe to ffmpeg"));
136                 return false;
137         }
138
139         return true;
140 }
141
142 void
143 ffmpeg_trgt::end_frame()
144 {
145         //fprintf(file, " ");
146         fflush(file);
147         imagecount++;
148 }
149
150 bool
151 ffmpeg_trgt::start_frame(synfig::ProgressCallback *callback)
152 {
153         int w=desc.get_w(),h=desc.get_h();
154
155         if(!file)
156                 return false;
157
158         fprintf(file, "P6\n");
159         fprintf(file, "%d %d\n", w, h);
160         fprintf(file, "%d\n", 255);
161
162         delete [] buffer;
163         buffer=new unsigned char[3*w];
164         delete [] color_buffer;
165         color_buffer=new Color[w];
166
167         return true;
168 }
169
170 Color *
171 ffmpeg_trgt::start_scanline(int scanline)
172 {
173         return color_buffer;
174 }
175
176 bool
177 ffmpeg_trgt::end_scanline()
178 {
179         if(!file)
180                 return false;
181
182         convert_color_format(buffer, color_buffer, desc.get_w(), PF_RGB, gamma());
183
184         if(!fwrite(buffer,1,desc.get_w()*3,file))
185                 return false;
186
187         return true;
188 }