Mercurial > vba-clojure
diff 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 |
line wrap: on
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/win32/AVIWrite.cpp Sat Mar 03 10:31:27 2012 -0600 1.3 @@ -0,0 +1,281 @@ 1.4 +#include "stdafx.h" 1.5 +#include <cstdio> 1.6 +#include <cassert> 1.7 + 1.8 +#include "AVIWrite.h" 1.9 +#include "../common/System.h" 1.10 + 1.11 +AVIWrite::AVIWrite() 1.12 +{ 1.13 + m_failed = false; 1.14 + m_file = NULL; 1.15 + m_stream = NULL; 1.16 + m_streamCompressed = NULL; 1.17 + m_streamSound = NULL; 1.18 + m_videoFrames = 0; 1.19 + m_samplesSound = 0; 1.20 + m_videoFramesTotal = 0; 1.21 + m_samplesSoundTotal= 0; 1.22 + m_totalBytes = 0; 1.23 + m_segmentNumber = 0; 1.24 + m_usePrevOptions = false; 1.25 + m_pauseRecording = false; 1.26 + 1.27 + AVIFileInit(); 1.28 +} 1.29 + 1.30 +void AVIWrite::CleanUp() 1.31 +{ 1.32 + if (m_streamSound) 1.33 + { 1.34 + AVIStreamClose(m_streamSound); 1.35 + m_streamSound = NULL; 1.36 + } 1.37 + if (m_streamCompressed) 1.38 + { 1.39 + AVIStreamClose(m_streamCompressed); 1.40 + m_streamCompressed = NULL; 1.41 + } 1.42 + if (m_stream) 1.43 + { 1.44 + AVIStreamClose(m_stream); 1.45 + m_stream = NULL; 1.46 + } 1.47 + if (m_file) 1.48 + { 1.49 + AVIFileClose(m_file); 1.50 + m_file = NULL; 1.51 + } 1.52 +} 1.53 + 1.54 +AVIWrite::~AVIWrite() 1.55 +{ 1.56 + CleanUp(); 1.57 + AVIFileExit(); 1.58 +} 1.59 + 1.60 +void AVIWrite::SetVideoFormat(BITMAPINFOHEADER *bh) 1.61 +{ 1.62 + // force size to 0x28 to avoid extra fields 1.63 + memcpy(&m_bitmap, bh, 0x28); 1.64 +} 1.65 + 1.66 +void AVIWrite::SetSoundFormat(WAVEFORMATEX *format) 1.67 +{ 1.68 + memcpy(&m_soundFormat, format, sizeof(WAVEFORMATEX)); 1.69 + ZeroMemory(&m_soundHeader, sizeof(AVISTREAMINFO)); 1.70 + // setup the sound stream header 1.71 + m_soundHeader.fccType = streamtypeAUDIO; 1.72 + m_soundHeader.dwQuality = (DWORD)-1; 1.73 + m_soundHeader.dwScale = format->nBlockAlign; 1.74 + m_soundHeader.dwInitialFrames = 1; 1.75 + m_soundHeader.dwRate = format->nAvgBytesPerSec; 1.76 + m_soundHeader.dwSampleSize = format->nBlockAlign; 1.77 + 1.78 + // create the sound stream 1.79 + if (FAILED(AVIFileCreateStream(m_file, &m_streamSound, &m_soundHeader))) 1.80 + { 1.81 + m_failed = true; 1.82 + return; 1.83 + } 1.84 + 1.85 + // setup the sound stream format 1.86 + if (FAILED(AVIStreamSetFormat(m_streamSound, 0, (void *)&m_soundFormat, 1.87 + sizeof(WAVEFORMATEX)))) 1.88 + { 1.89 + m_failed = true; 1.90 + return; 1.91 + } 1.92 +} 1.93 + 1.94 +bool AVIWrite::Open(const char *filename) 1.95 +{ 1.96 + // this is only here because AVIFileOpen doesn't seem to do it for us 1.97 + FILE*fd = fopen(filename, "wb"); 1.98 + if (!fd) 1.99 + { 1.100 + systemMessage(0, "AVI recording failed: file is read-only or already in use."); 1.101 + m_failed = true; 1.102 + return false; 1.103 + } 1.104 + fclose(fd); 1.105 + 1.106 + // create the AVI file 1.107 + if (FAILED(AVIFileOpen(&m_file, 1.108 + filename, 1.109 + OF_WRITE | OF_CREATE, 1.110 + NULL))) 1.111 + { 1.112 + m_failed = true; 1.113 + return false; 1.114 + } 1.115 + // setup the video stream information 1.116 + ZeroMemory(&m_header, sizeof(AVISTREAMINFO)); 1.117 + m_header.fccType = streamtypeVIDEO; 1.118 + m_header.dwScale = 1; 1.119 + m_header.dwRate = m_fps; 1.120 + m_header.dwSuggestedBufferSize = m_bitmap.biSizeImage; 1.121 + 1.122 + // create the video stream 1.123 + if (FAILED(AVIFileCreateStream(m_file, 1.124 + &m_stream, 1.125 + &m_header))) 1.126 + { 1.127 + m_failed = true; 1.128 + return false; 1.129 + } 1.130 + 1.131 + if (!m_usePrevOptions) 1.132 + { 1.133 + ZeroMemory(&m_options, sizeof(AVICOMPRESSOPTIONS)); 1.134 + m_arrayOptions[0] = &m_options; 1.135 + 1.136 + // call the dialog to setup the compress options to be used 1.137 + if (!AVISaveOptions(AfxGetApp()->m_pMainWnd->GetSafeHwnd(), 0, 1, &m_stream, m_arrayOptions)) 1.138 + { 1.139 + m_failed = true; 1.140 + return false; 1.141 + } 1.142 + } 1.143 + 1.144 + // create the compressed stream 1.145 + if (FAILED(AVIMakeCompressedStream(&m_streamCompressed, m_stream, &m_options, NULL))) 1.146 + { 1.147 + m_failed = true; 1.148 + return false; 1.149 + } 1.150 + 1.151 + // setup the video stream format 1.152 + if (FAILED(AVIStreamSetFormat(m_streamCompressed, 0, 1.153 + &m_bitmap, 1.154 + m_bitmap.biSize + 1.155 + m_bitmap.biClrUsed * sizeof(RGBQUAD)))) 1.156 + { 1.157 + m_failed = true; 1.158 + return false; 1.159 + } 1.160 + 1.161 + m_videoFrames = 0; 1.162 + m_samplesSound = 0; 1.163 + m_totalBytes = 0; 1.164 + if (!m_usePrevOptions) { 1.165 + m_videoFramesTotal = 0; 1.166 + m_samplesSoundTotal = 0; 1.167 + } 1.168 + 1.169 + strncpy(m_aviFileName, filename, MAX_PATH); 1.170 + strncpy(m_aviBaseName, filename, MAX_PATH); 1.171 + m_aviFileName[MAX_PATH - 1] = '\0'; 1.172 + m_aviBaseName[MAX_PATH - 1] = '\0'; 1.173 + char *dot = strrchr(m_aviBaseName, '.'); 1.174 + if (dot && dot > strrchr(m_aviBaseName, '/') && dot > strrchr(m_aviBaseName, '\\')) 1.175 + { 1.176 + strcpy(m_aviExtension, dot); 1.177 + dot[0] = '\0'; 1.178 + } 1.179 + 1.180 + return true; 1.181 +} 1.182 + 1.183 +bool AVIWrite::AddSound(const u8 *sound, int len) 1.184 +{ 1.185 + LONG byteBuffer; 1.186 + 1.187 + // return if we failed somewhere already 1.188 + if (m_failed) 1.189 + return false; 1.190 + 1.191 + assert(len % m_soundFormat.nBlockAlign == 0); 1.192 + int samples = len / m_soundFormat.nBlockAlign; 1.193 + 1.194 + if (FAILED(AVIStreamWrite(m_streamSound, 1.195 + m_samplesSound, 1.196 + samples, 1.197 + (LPVOID)sound, 1.198 + len, 1.199 + 0, 1.200 + NULL, 1.201 + &byteBuffer))) 1.202 + { 1.203 + m_failed = true; 1.204 + return false; 1.205 + } 1.206 + m_samplesSound += samples; 1.207 + m_samplesSoundTotal += samples; 1.208 + m_totalBytes += byteBuffer; 1.209 + return true; 1.210 +} 1.211 + 1.212 +bool AVIWrite::NextSegment() 1.213 +{ 1.214 + char avi_fname[MAX_PATH]; 1.215 + strcpy(avi_fname, m_aviBaseName); 1.216 + char avi_fname_temp[MAX_PATH]; 1.217 + sprintf(avi_fname_temp, "%s_part%d%s", avi_fname, m_segmentNumber+2, m_aviExtension); 1.218 + m_segmentNumber++; 1.219 + 1.220 + CleanUp(); 1.221 + 1.222 + m_usePrevOptions = true; 1.223 + bool ret = Open(avi_fname_temp); 1.224 + m_usePrevOptions = false; 1.225 + strcpy(m_aviBaseName, avi_fname); 1.226 + 1.227 + return ret; 1.228 +} 1.229 + 1.230 +bool AVIWrite::AddFrame(const u8 *bmp) 1.231 +{ 1.232 + LONG byteBuffer; 1.233 + 1.234 + if (m_failed) 1.235 + return false; 1.236 + 1.237 + // write the frame to the video stream 1.238 + if (FAILED(AVIStreamWrite(m_streamCompressed, 1.239 + m_videoFrames, 1.240 + 1, 1.241 + (LPVOID)bmp, 1.242 + m_bitmap.biSizeImage, 1.243 + AVIIF_KEYFRAME, 1.244 + NULL, 1.245 + &byteBuffer))) 1.246 + { 1.247 + m_failed = true; 1.248 + return false; 1.249 + } 1.250 + m_videoFrames++; 1.251 + m_videoFramesTotal++; 1.252 + m_totalBytes += byteBuffer; 1.253 + 1.254 + // segment / split AVI when it's almost 2 GB (2000MB, to be precise) 1.255 + if (!(m_videoFrames % 60) && m_totalBytes > 2097152000) 1.256 + return NextSegment(); 1.257 + else 1.258 + return true; 1.259 +} 1.260 + 1.261 +bool AVIWrite::IsSoundAdded() 1.262 +{ 1.263 + return m_streamSound != NULL; 1.264 +} 1.265 + 1.266 +void AVIWrite::SetFPS(int f) 1.267 +{ 1.268 + m_fps = f; 1.269 +} 1.270 + 1.271 +int AVIWrite::videoFrames() 1.272 +{ 1.273 + return m_videoFramesTotal; 1.274 +} 1.275 + 1.276 +void AVIWrite::Pause(bool pause) 1.277 +{ 1.278 + m_pauseRecording = pause; 1.279 +} 1.280 + 1.281 +bool AVIWrite::IsPaused() 1.282 +{ 1.283 + return m_pauseRecording; 1.284 +} 1.285 \ No newline at end of file