comparison trunk/src/Modules/Output/Graphics/Devices/GraphicsOutputDeviceMovie.cc @ 411:a908972d234e

- Added support for movies!
author tomwalters
date Thu, 21 Oct 2010 01:46:39 +0000
parents 69466da9745e
children b6d5c0cc1849
comparison
equal deleted inserted replaced
410:7af493eb1563 411:a908972d234e
48 48
49 #include "Modules/Output/Graphics/Devices/GraphicsOutputDeviceMovie.h" 49 #include "Modules/Output/Graphics/Devices/GraphicsOutputDeviceMovie.h"
50 50
51 namespace aimc { 51 namespace aimc {
52 52
53 GraphicsOutputDeviceMovie::GraphicsOutputDeviceMovie(Parameters *pParam) 53 GraphicsOutputDeviceMovie::GraphicsOutputDeviceMovie(Parameters *parameters)
54 : GraphicsOutputDeviceCairo(pParam) { // or GraphicsOutputDevicePlotutils 54 : GraphicsOutputDeviceCairo(parameters) {
55 m_sMovieFile[0] = '\0'; 55 sound_filename_.clear();
56 m_sSoundFile[0] = '\0'; 56 movie_filename_.clear();
57 } 57 }
58 58
59 bool GraphicsOutputDeviceMovie::Initialize(const char *sSoundFile, 59 bool GraphicsOutputDeviceMovie::Initialize(Parameters *global_parameters) {
60 const char *sMovieFile) { 60 global_parameters_ = global_parameters;
61 sound_filename_ = global_parameters->GetString("input_filename");
62 string file_suffix = parameters_->DefaultString("filename_suffix", ".mov");
63 movie_filename_ = global_parameters->GetString("output_filename_base")
64 + file_suffix;
65
61 FILE *f; 66 FILE *f;
62 AIM_ASSERT(sSoundFile);
63 AIM_ASSERT(sMovieFile);
64 67
65 // Check sound file exists 68 // Check sound file exists
66 if ((f = fopen(sSoundFile, "r")) == NULL) { 69 if ((f = fopen(sound_filename_.c_str(), "r")) == NULL) {
67 LOG_ERROR(_T("Couldn't open sound file '%s' for movie creation."), 70 LOG_ERROR(_T("Couldn't open sound file '%s' for movie creation."),
68 sSoundFile); 71 sound_filename_.c_str());
72 sound_filename_.clear();
69 return false; 73 return false;
70 } 74 }
71 fclose(f); 75 fclose(f);
72 strcpy(m_sSoundFile, sSoundFile);
73 76
74 // Check movie output file can be made 77 // Check movie output file can be made
75 if ( (f=fopen(sMovieFile, "w"))==NULL ) { 78 if ((f = fopen(movie_filename_.c_str(), "w")) == NULL) {
76 LOG_ERROR(_T("Couldn't open movie file '%s' to write to."), 79 LOG_ERROR(_T("Couldn't open movie file '%s' to write to."),
77 sMovieFile); 80 movie_filename_.c_str());
81 movie_filename_.clear();
78 return false; 82 return false;
79 } 83 }
80 fclose(f); 84 fclose(f);
81 strcpy(m_sMovieFile, sMovieFile);
82 85
83 // Get a temporary image output directory 86 // Get a temporary image output directory
84 //! \warning Not really safe ... but windows has no mkdtemp() 87 //! \warning Not really safe ... but windows has no mkdtemp()
85 //! \todo Make build system check for mkdtemp() to use it when available. See TODO.txt. 88 //! \todo Make build system check for mkdtemp() to use it when available. See TODO.txt.
86 char *sTmpDir = NULL;
87 #ifdef _WINDOWS 89 #ifdef _WINDOWS
88 if ((sTmpDir = _tempnam(NULL, AIM_NAME)) 90 char *temp_dir = NULL;
89 && _mkdir(sTmpDir) >= 0) { 91 if ((temp_dir = _tempnam(NULL, AIM_NAME))
90 strcpy(m_sDir, sTmpDir); 92 && _mkdir(temp_dir) >= 0) {
91 strcat(m_sDir, "\\"); // Make sure to end with trailing slash 93 directory_ = temp_dir;
92 } else 94 directory_ += "\\"; // Make sure to end with trailing slash
93 #else 95 } else {
94 strcpy(m_sDir, "/tmp/"AIM_NAME"-movie.XXXXXX");
95 if (mkdtemp(m_sDir)) {
96 strcat(m_sDir, "/"); // Make sure to end with trailing slash
97 } else
98 #endif
99 {
100 LOG_ERROR(_T("Couldn't create a temporary directory for movie output.")); 96 LOG_ERROR(_T("Couldn't create a temporary directory for movie output."));
101 if (sTmpDir) free(sTmpDir); 97 if (temp_dir) {
102 return false; 98 free(temp_dir);
103 } 99 }
104 if (sTmpDir) { 100 return false;
105 free(sTmpDir); 101 }
106 } 102 if (temp_dir) {
107 103 free(temp_dir);
104 }
105 #else
106 char temp_dir[PATH_MAX];
107 strcpy(temp_dir, "/tmp/"AIM_NAME"-movie.XXXXXX");
108 if (mkdtemp(temp_dir)) {
109 directory_ = temp_dir;
110 directory_ += "/"; // Make sure to end with trailing slash
111 } else {
112 LOG_ERROR(_T("Couldn't create a temporary directory for movie output."));
113 return false;
114 }
115 #endif
116
108 // We want png for movie conversion 117 // We want png for movie conversion
109 //! \bug This may change the user preference in GUI, hmm what to do? See TODO.txt 118 parameters_->SetString("output.img.format", "png");
110 m_pParam->SetString("output.img.format", "png"); 119 if ( !GraphicsOutputDeviceCairo::Initialize(directory_) ) {
111 //if ( !GraphicsOutputDevicePlotutils::Initialize(m_sDir) ) { 120 return false;
112 if ( !GraphicsOutputDeviceCairo::Initialize(m_sDir) ) { 121 }
113 return false;
114 }
115
116 return true; 122 return true;
117 } 123 }
118 124
119 void GraphicsOutputDeviceMovie::Start() { 125 void GraphicsOutputDeviceMovie::Start() {
120 //GraphicsOutputDevicePlotutils::Start();
121 GraphicsOutputDeviceCairo::Start(); 126 GraphicsOutputDeviceCairo::Start();
122 // Just output a single frame to get audio/video in sync, put params in there 127 // Output a couple of frames to get audio/video in sync, put params in there.
123 gGrab(); 128 gGrab();
124 PlotParameterScreen(); 129 PlotParameterScreen();
125 gRelease(); 130 gRelease();
131 gGrab();
132 PlotParameterScreen();
133 gRelease();
126 } 134 }
127 135
128 void GraphicsOutputDeviceMovie::Stop() { 136 void GraphicsOutputDeviceMovie::Stop() {
129 // Make sure Plotutils is really done writing.
130 //GraphicsOutputDevicePlotutils::Stop();
131 GraphicsOutputDeviceCairo::Stop(); 137 GraphicsOutputDeviceCairo::Stop();
132 CloseFile(); 138 CloseFile();
133 139
134 #ifdef __WX__ 140 #ifdef __WX__
135 // GUI only: popup dialog 141 // GUI only: popup dialog
136 #else 142 #else
137 printf("Generating movie ... \n"); 143 printf("Generating movie ... \n");
138 #endif 144 #endif
139 AIM_ASSERT(m_pParam); 145 AIM_ASSERT(parameters_);
140 // Convert images and sound file to a movie 146 // Convert images and sound file to a movie.
141 //! \warning Movie files are overwritten without warning 147 //! \warning Movie files are overwritten without warning.
142 //! \bug ffmpeg only works with colour images, not with bw. So make sure to not use bw only in drawing..
143 // Always convert to audio stream of 44.1kHz or problems may occur in playing or conversio.
144 float fFps = 1000.0 / m_pParam->GetFloat("output.frameperiod");
145 char sffmpegPath[1024]; 148 char sffmpegPath[1024];
146 if (!m_pParam->IsSet("output.ffmpeg_path")) { 149 if (!parameters_->IsSet("output.ffmpeg_path")) {
147 strcpy(sffmpegPath,"ffmpeg"); 150 strcpy(sffmpegPath,"ffmpeg");
148 } else { 151 } else {
149 strcpy(sffmpegPath, m_pParam->GetString("output.ffmpeg_path")); 152 strcpy(sffmpegPath, parameters_->GetString("output.ffmpeg_path"));
150 } 153 }
151 char sCodecOptions[1024]; 154 char sCodecOptions[1024];
152 if (!m_pParam->IsSet("output.ffmpeg_codec_options")) { 155 if (!parameters_->IsSet("output.ffmpeg_codec_options")) {
153 strcpy(sCodecOptions,""); 156 strcpy(sCodecOptions,"");
154 } else { 157 } else {
155 strcpy(sCodecOptions, m_pParam->GetString("output.ffmpeg_codec_options")); 158 strcpy(sCodecOptions, parameters_->GetString("output.ffmpeg_codec_options"));
156 } 159 }
157 160 float frame_rate = global_parameters_->DefaultFloat("frame_rate", -1.0);
158 char sCmdLine[1024]; //!\todo check that snprintf does not want a larger buffer 161 char sCmdLine[1024]; //!\todo check that snprintf does not want a larger buffer
159 snprintf(sCmdLine, sizeof(sCmdLine)/sizeof(sCmdLine[0]), 162 snprintf(sCmdLine, sizeof(sCmdLine)/sizeof(sCmdLine[0]),
160 "%s -r %.2f -y -i \"%s\" -i \"%s%%06d.png\" " 163 "%s -r %.2f -y -i \"%s\" -i \"%s%%06d.png\" "
161 "-title \"%s\" -comment \"Generated by "AIM_NAME" "AIM_VERSION_STRING"\" "
162 "-sameq -r %.2f -ar 44100 -acodec pcm_s16le %s \"%s\"", 164 "-sameq -r %.2f -ar 44100 -acodec pcm_s16le %s \"%s\"",
163 sffmpegPath, fFps, m_sSoundFile, m_sDir, 165 sffmpegPath, frame_rate, sound_filename_.c_str(), directory_.c_str(),
164 m_pParam->GetString("output.movie.title"), 166 frame_rate, sCodecOptions, movie_filename_.c_str());
165 fFps, sCodecOptions, m_sMovieFile);
166 printf(sCmdLine); 167 printf(sCmdLine);
167 printf("\n"); 168 printf("\n");
168 if (system(sCmdLine)) { 169 if (system(sCmdLine)) {
169 LOG_ERROR(_T("Couldn't create movie output.")); 170 LOG_ERROR(_T("Couldn't create movie output."));
170 } 171 }
197 FindClose(hList); 198 FindClose(hList);
198 _rmdir(m_sDir); 199 _rmdir(m_sDir);
199 #else 200 #else
200 DIR *dir; 201 DIR *dir;
201 struct dirent *dirent; 202 struct dirent *dirent;
202 if (!(dir = opendir(m_sDir))) { 203 if (!(dir = opendir(directory_.c_str()))) {
203 LOG_ERROR(_T("Couldn't remove files in temporary directory.")); 204 LOG_ERROR(_T("Couldn't remove files in temporary directory."));
204 return; 205 return;
205 } 206 }
206 while ((dirent = readdir(dir))) { 207 while ((dirent = readdir(dir))) {
207 snprintf(sCmdLine, 208 snprintf(sCmdLine,
208 sizeof(sCmdLine)/sizeof(sCmdLine[0]), 209 sizeof(sCmdLine)/sizeof(sCmdLine[0]),
209 "%s%s", 210 "%s%s",
210 m_sDir, 211 directory_.c_str(),
211 dirent->d_name); 212 dirent->d_name);
212 unlink(sCmdLine); 213 unlink(sCmdLine);
213 } 214 }
214 closedir(dir); 215 closedir(dir);
215 rmdir(m_sDir); 216 rmdir(directory_.c_str());
216 #endif 217 #endif
217 } 218 }
218 219
219 void GraphicsOutputDeviceMovie::PlotParameterScreen() { 220 void GraphicsOutputDeviceMovie::PlotParameterScreen() {
220 AIM_ASSERT(m_pParam); 221 AIM_ASSERT(parameters_);
221 char sStr[50]; 222 char sStr[50];
222 int lineno = 1; 223 int lineno = 1;
223 224
224 float fMarL = m_pParam->GetFloat(_S("graph.margin.left")); 225 float fMarL = parameters_->GetFloat(_S("graph.margin.left"));
225 float fMarT = m_pParam->GetFloat(_S("graph.margin.top")); 226 float fMarT = parameters_->GetFloat(_S("graph.margin.top"));
226 float fTextHeight = 1.0f / 50.0f * 1.2; // change this when fontsizing is there! 227 float fTextHeight = 1.0f / 50.0f * 1.2; // change this when fontsizing is there!
227 228
228 gText2f(fMarL, 1-(fMarT+fTextHeight*lineno++), 229 gText2f(fMarL, 1-(fMarT+fTextHeight*lineno++),
229 _S("AIM-C")); 230 _S("AIM-C"));
230 gText2f(fMarL, 231 gText2f(fMarL,
247 }; 248 };
248 for (int i = 0; pPlotParams[i]; i++) { 249 for (int i = 0; pPlotParams[i]; i++) {
249 snprintf(sStr, 250 snprintf(sStr,
250 sizeof(sStr)/sizeof(sStr[0]), _S("%s=%s"), 251 sizeof(sStr)/sizeof(sStr[0]), _S("%s=%s"),
251 pPlotParams[i], 252 pPlotParams[i],
252 m_pParam->GetString(pPlotParams[i])); 253 parameters_->GetString(pPlotParams[i]));
253 gText2f(fMarL, 254 gText2f(fMarL,
254 1-(fMarT+fTextHeight*lineno++), 255 1-(fMarT+fTextHeight*lineno++),
255 sStr); 256 sStr);
256 } 257 }
257 } 258 }