Mercurial > vba-clojure
comparison src/win32/AVIWrite.cpp @ 1:f9f4f1b99eed
importing src directory
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 03 Mar 2012 10:31:27 -0600 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
0:8ced16adf2e1 | 1:f9f4f1b99eed |
---|---|
1 #include "stdafx.h" | |
2 #include <cstdio> | |
3 #include <cassert> | |
4 | |
5 #include "AVIWrite.h" | |
6 #include "../common/System.h" | |
7 | |
8 AVIWrite::AVIWrite() | |
9 { | |
10 m_failed = false; | |
11 m_file = NULL; | |
12 m_stream = NULL; | |
13 m_streamCompressed = NULL; | |
14 m_streamSound = NULL; | |
15 m_videoFrames = 0; | |
16 m_samplesSound = 0; | |
17 m_videoFramesTotal = 0; | |
18 m_samplesSoundTotal= 0; | |
19 m_totalBytes = 0; | |
20 m_segmentNumber = 0; | |
21 m_usePrevOptions = false; | |
22 m_pauseRecording = false; | |
23 | |
24 AVIFileInit(); | |
25 } | |
26 | |
27 void AVIWrite::CleanUp() | |
28 { | |
29 if (m_streamSound) | |
30 { | |
31 AVIStreamClose(m_streamSound); | |
32 m_streamSound = NULL; | |
33 } | |
34 if (m_streamCompressed) | |
35 { | |
36 AVIStreamClose(m_streamCompressed); | |
37 m_streamCompressed = NULL; | |
38 } | |
39 if (m_stream) | |
40 { | |
41 AVIStreamClose(m_stream); | |
42 m_stream = NULL; | |
43 } | |
44 if (m_file) | |
45 { | |
46 AVIFileClose(m_file); | |
47 m_file = NULL; | |
48 } | |
49 } | |
50 | |
51 AVIWrite::~AVIWrite() | |
52 { | |
53 CleanUp(); | |
54 AVIFileExit(); | |
55 } | |
56 | |
57 void AVIWrite::SetVideoFormat(BITMAPINFOHEADER *bh) | |
58 { | |
59 // force size to 0x28 to avoid extra fields | |
60 memcpy(&m_bitmap, bh, 0x28); | |
61 } | |
62 | |
63 void AVIWrite::SetSoundFormat(WAVEFORMATEX *format) | |
64 { | |
65 memcpy(&m_soundFormat, format, sizeof(WAVEFORMATEX)); | |
66 ZeroMemory(&m_soundHeader, sizeof(AVISTREAMINFO)); | |
67 // setup the sound stream header | |
68 m_soundHeader.fccType = streamtypeAUDIO; | |
69 m_soundHeader.dwQuality = (DWORD)-1; | |
70 m_soundHeader.dwScale = format->nBlockAlign; | |
71 m_soundHeader.dwInitialFrames = 1; | |
72 m_soundHeader.dwRate = format->nAvgBytesPerSec; | |
73 m_soundHeader.dwSampleSize = format->nBlockAlign; | |
74 | |
75 // create the sound stream | |
76 if (FAILED(AVIFileCreateStream(m_file, &m_streamSound, &m_soundHeader))) | |
77 { | |
78 m_failed = true; | |
79 return; | |
80 } | |
81 | |
82 // setup the sound stream format | |
83 if (FAILED(AVIStreamSetFormat(m_streamSound, 0, (void *)&m_soundFormat, | |
84 sizeof(WAVEFORMATEX)))) | |
85 { | |
86 m_failed = true; | |
87 return; | |
88 } | |
89 } | |
90 | |
91 bool AVIWrite::Open(const char *filename) | |
92 { | |
93 // this is only here because AVIFileOpen doesn't seem to do it for us | |
94 FILE*fd = fopen(filename, "wb"); | |
95 if (!fd) | |
96 { | |
97 systemMessage(0, "AVI recording failed: file is read-only or already in use."); | |
98 m_failed = true; | |
99 return false; | |
100 } | |
101 fclose(fd); | |
102 | |
103 // create the AVI file | |
104 if (FAILED(AVIFileOpen(&m_file, | |
105 filename, | |
106 OF_WRITE | OF_CREATE, | |
107 NULL))) | |
108 { | |
109 m_failed = true; | |
110 return false; | |
111 } | |
112 // setup the video stream information | |
113 ZeroMemory(&m_header, sizeof(AVISTREAMINFO)); | |
114 m_header.fccType = streamtypeVIDEO; | |
115 m_header.dwScale = 1; | |
116 m_header.dwRate = m_fps; | |
117 m_header.dwSuggestedBufferSize = m_bitmap.biSizeImage; | |
118 | |
119 // create the video stream | |
120 if (FAILED(AVIFileCreateStream(m_file, | |
121 &m_stream, | |
122 &m_header))) | |
123 { | |
124 m_failed = true; | |
125 return false; | |
126 } | |
127 | |
128 if (!m_usePrevOptions) | |
129 { | |
130 ZeroMemory(&m_options, sizeof(AVICOMPRESSOPTIONS)); | |
131 m_arrayOptions[0] = &m_options; | |
132 | |
133 // call the dialog to setup the compress options to be used | |
134 if (!AVISaveOptions(AfxGetApp()->m_pMainWnd->GetSafeHwnd(), 0, 1, &m_stream, m_arrayOptions)) | |
135 { | |
136 m_failed = true; | |
137 return false; | |
138 } | |
139 } | |
140 | |
141 // create the compressed stream | |
142 if (FAILED(AVIMakeCompressedStream(&m_streamCompressed, m_stream, &m_options, NULL))) | |
143 { | |
144 m_failed = true; | |
145 return false; | |
146 } | |
147 | |
148 // setup the video stream format | |
149 if (FAILED(AVIStreamSetFormat(m_streamCompressed, 0, | |
150 &m_bitmap, | |
151 m_bitmap.biSize + | |
152 m_bitmap.biClrUsed * sizeof(RGBQUAD)))) | |
153 { | |
154 m_failed = true; | |
155 return false; | |
156 } | |
157 | |
158 m_videoFrames = 0; | |
159 m_samplesSound = 0; | |
160 m_totalBytes = 0; | |
161 if (!m_usePrevOptions) { | |
162 m_videoFramesTotal = 0; | |
163 m_samplesSoundTotal = 0; | |
164 } | |
165 | |
166 strncpy(m_aviFileName, filename, MAX_PATH); | |
167 strncpy(m_aviBaseName, filename, MAX_PATH); | |
168 m_aviFileName[MAX_PATH - 1] = '\0'; | |
169 m_aviBaseName[MAX_PATH - 1] = '\0'; | |
170 char *dot = strrchr(m_aviBaseName, '.'); | |
171 if (dot && dot > strrchr(m_aviBaseName, '/') && dot > strrchr(m_aviBaseName, '\\')) | |
172 { | |
173 strcpy(m_aviExtension, dot); | |
174 dot[0] = '\0'; | |
175 } | |
176 | |
177 return true; | |
178 } | |
179 | |
180 bool AVIWrite::AddSound(const u8 *sound, int len) | |
181 { | |
182 LONG byteBuffer; | |
183 | |
184 // return if we failed somewhere already | |
185 if (m_failed) | |
186 return false; | |
187 | |
188 assert(len % m_soundFormat.nBlockAlign == 0); | |
189 int samples = len / m_soundFormat.nBlockAlign; | |
190 | |
191 if (FAILED(AVIStreamWrite(m_streamSound, | |
192 m_samplesSound, | |
193 samples, | |
194 (LPVOID)sound, | |
195 len, | |
196 0, | |
197 NULL, | |
198 &byteBuffer))) | |
199 { | |
200 m_failed = true; | |
201 return false; | |
202 } | |
203 m_samplesSound += samples; | |
204 m_samplesSoundTotal += samples; | |
205 m_totalBytes += byteBuffer; | |
206 return true; | |
207 } | |
208 | |
209 bool AVIWrite::NextSegment() | |
210 { | |
211 char avi_fname[MAX_PATH]; | |
212 strcpy(avi_fname, m_aviBaseName); | |
213 char avi_fname_temp[MAX_PATH]; | |
214 sprintf(avi_fname_temp, "%s_part%d%s", avi_fname, m_segmentNumber+2, m_aviExtension); | |
215 m_segmentNumber++; | |
216 | |
217 CleanUp(); | |
218 | |
219 m_usePrevOptions = true; | |
220 bool ret = Open(avi_fname_temp); | |
221 m_usePrevOptions = false; | |
222 strcpy(m_aviBaseName, avi_fname); | |
223 | |
224 return ret; | |
225 } | |
226 | |
227 bool AVIWrite::AddFrame(const u8 *bmp) | |
228 { | |
229 LONG byteBuffer; | |
230 | |
231 if (m_failed) | |
232 return false; | |
233 | |
234 // write the frame to the video stream | |
235 if (FAILED(AVIStreamWrite(m_streamCompressed, | |
236 m_videoFrames, | |
237 1, | |
238 (LPVOID)bmp, | |
239 m_bitmap.biSizeImage, | |
240 AVIIF_KEYFRAME, | |
241 NULL, | |
242 &byteBuffer))) | |
243 { | |
244 m_failed = true; | |
245 return false; | |
246 } | |
247 m_videoFrames++; | |
248 m_videoFramesTotal++; | |
249 m_totalBytes += byteBuffer; | |
250 | |
251 // segment / split AVI when it's almost 2 GB (2000MB, to be precise) | |
252 if (!(m_videoFrames % 60) && m_totalBytes > 2097152000) | |
253 return NextSegment(); | |
254 else | |
255 return true; | |
256 } | |
257 | |
258 bool AVIWrite::IsSoundAdded() | |
259 { | |
260 return m_streamSound != NULL; | |
261 } | |
262 | |
263 void AVIWrite::SetFPS(int f) | |
264 { | |
265 m_fps = f; | |
266 } | |
267 | |
268 int AVIWrite::videoFrames() | |
269 { | |
270 return m_videoFramesTotal; | |
271 } | |
272 | |
273 void AVIWrite::Pause(bool pause) | |
274 { | |
275 m_pauseRecording = pause; | |
276 } | |
277 | |
278 bool AVIWrite::IsPaused() | |
279 { | |
280 return m_pauseRecording; | |
281 } |