// --[ Method ]--------------------------------------------------------------- // // - Class : CAviRenderer // - prototype : bool CAviRenderer::SaveFrame() // // - Purpose : Captures a frame and saves it into the avi file. // // ----------------------------------------------------------------------------- bool CAviRenderer::SaveFrame() { if(!IsValid()) { return false; } // Get an image and stuff it into a bitmap. HRESULT hr; HBITMAP bmp; if((bmp = LoadBMPFromFB(m_pWindowGL)) == NULL) { return false; } LPBITMAPINFOHEADER lpInfoHeader = (LPBITMAPINFOHEADER)GlobalLock(MakeDib(bmp, 32)); DeleteObject(bmp); if(lpInfoHeader == NULL) { LOG.Write("\nERROR - CAviRenderer::SaveFrame(). GlobalLock() failed."); return false; } if(m_nWidth != lpInfoHeader->biWidth) { LOG.Write("\nERROR - CAviRenderer::SaveFrame(): mismatched window width / info header width."); GlobalFreePtr(lpInfoHeader); return false; } if(m_nHeight != lpInfoHeader->biHeight) { LOG.Write("\nERROR - CAviRenderer::SaveFrame(): mismatched window height / info header height."); GlobalFreePtr(lpInfoHeader); return false; } // Save frame hr = AVIStreamWrite(m_pAviStreamCompressed, // stream pointer m_nFrameCount, // frame 1, // number of frames to write (LPBYTE) lpInfoHeader + // pointer to data lpInfoHeader->biSize + lpInfoHeader->biClrUsed * sizeof(RGBQUAD), lpInfoHeader->biSizeImage, // size of this frame AVIIF_KEYFRAME, // flags.... NULL, NULL); if(hr != AVIERR_OK) { CLogger::ErrorWindow("CAviRenderer::SaveFrame(). AVIStreamWrite() failed."); GlobalFreePtr(lpInfoHeader); return false; } GlobalFreePtr(lpInfoHeader); m_nFrameCount++; return true; }
// --[ Method ]--------------------------------------------------------------- // // - Class : CAviRenderer // - prototype : bool StartRender(CWindowGL *pWindowGL, std::string strAviFile, int nFramerate) // // - Purpose : Prepares the object for capturing the opengl window to an AVI. // // ----------------------------------------------------------------------------- bool CAviRenderer::StartRender(CWindowGL *pWindowGL, std::string strAviFile, int nFramerate) { assert(pWindowGL); m_pWindowGL = NULL; m_bIsWorking = false; // Check VFW version. WORD wVer = HIWORD(VideoForWindowsVersion()); if(wVer < 0x010A) { CLogger::ErrorWindow("Video For Windows outdated version"); return false; } // Init library AVIFileInit(); // Get an image and stuff it into a bitmap. HRESULT hr; HBITMAP bmp; if((bmp = LoadBMPFromFB(pWindowGL)) == NULL) { return false; } LPBITMAPINFOHEADER lpInfoHeader = (LPBITMAPINFOHEADER)GlobalLock(MakeDib(bmp, 32)); DeleteObject(bmp); if(lpInfoHeader == NULL) { LOG.Write("\nERROR - CAviRenderer::StartRender(): GlobalLock() failed."); return false; } m_nWidth = (int)lpInfoHeader->biWidth; m_nHeight = (int)lpInfoHeader->biHeight; // Open an avi file for writing hr = AVIFileOpen( &m_pAviFile, // returned file pointer strAviFile.data(), // file name OF_WRITE | OF_CREATE, // mode to open file with NULL); // use handler determined // from file extension.... if (hr != AVIERR_OK) { LOG.Write("\nERROR - CAviRenderer::StartRender(): AVIFileOpen() failed."); GlobalFreePtr(lpInfoHeader); return false; } // Configure the stream _fmemset(&m_aviStreamInfo, 0, sizeof(m_aviStreamInfo)); m_aviStreamInfo.fccType = streamtypeVIDEO; // stream type m_aviStreamInfo.fccHandler = 0; m_aviStreamInfo.dwScale = 1; m_aviStreamInfo.dwRate = nFramerate; m_aviStreamInfo.dwSuggestedBufferSize = lpInfoHeader->biSizeImage; SetRect(&m_aviStreamInfo.rcFrame, 0, 0, // rectangle for stream (int)lpInfoHeader->biWidth, (int)lpInfoHeader->biHeight); // And create the stream hr = AVIFileCreateStream(m_pAviFile, // file pointer &m_pAviStream, // returned stream pointer &m_aviStreamInfo); // stream header if(hr != AVIERR_OK) { LOG.Write("\nERROR - CAviRenderer::StartRender(): AVIFileCreateStream() failed."); GlobalFreePtr(lpInfoHeader); return false; } // Get save options (prompt dialog) _fmemset(&m_aviOptions, 0, sizeof(m_aviOptions)); if(!AVISaveOptions(NULL, 0, 1, &m_pAviStream, (LPAVICOMPRESSOPTIONS FAR *) &m_pAviOptions)) { LOG.Write("\nERROR - CAviRenderer::StartRender(): AVISaveOptions() failed."); GlobalFreePtr(lpInfoHeader); return false; } // Create compressed stream hr = AVIMakeCompressedStream(&m_pAviStreamCompressed, m_pAviStream, &m_aviOptions, NULL); if(hr != AVIERR_OK) { LOG.Write("\nERROR - CAviRenderer::StartRender(): AVIMakeCompressedStream() failed."); GlobalFreePtr(lpInfoHeader); return false; } // Set it's format hr = AVIStreamSetFormat(m_pAviStreamCompressed, 0, lpInfoHeader, // stream format lpInfoHeader->biSize + // format size lpInfoHeader->biClrUsed * sizeof(RGBQUAD)); if(hr != AVIERR_OK) { LOG.Write("\nERROR - CAviRenderer::StartRender(): AVIStreamSetFormat() failed."); GlobalFreePtr(lpInfoHeader); return false; } m_pWindowGL = pWindowGL; m_bIsWorking = true; UpdateWindow(pWindowGL->GetHWND()); return true; }
bool MovieMaker::Snap() { HRESULT hr; if (!bOK) return false; // Get an image and stuff it into a bitmap. HBITMAP bmp; bmp = LoadBMPFromFB( width, height ); LPBITMAPINFOHEADER alpbi = (LPBITMAPINFOHEADER)GlobalLock(MakeDib(bmp, 32)); DeleteObject( bmp ); if (alpbi == NULL) { bOK = false; return false; } if (width>=0 && width != alpbi->biWidth) { GlobalFreePtr(alpbi); bOK = false; return false; } if (height>=0 && height != alpbi->biHeight) { GlobalFreePtr(alpbi); bOK = false; return false; } width = alpbi->biWidth; height = alpbi->biHeight; if (nFrames == 0) { hr = AVIFileOpenA(&pfile, // returned file pointer fname, // file name OF_WRITE | OF_CREATE, // mode to open file with NULL); // use handler determined // from file extension.... if (hr != AVIERR_OK) { GlobalFreePtr(alpbi); bOK = false; return false; } _fmemset(&strhdr, 0, sizeof(strhdr)); strhdr.fccType = streamtypeVIDEO;// stream type strhdr.fccHandler = 0; strhdr.dwScale = 1; strhdr.dwRate = 15; strhdr.dwSuggestedBufferSize = alpbi->biSizeImage; SetRect(&strhdr.rcFrame, 0, 0, // rectangle for stream (int) alpbi->biWidth, (int) alpbi->biHeight); // And create the stream; hr = AVIFileCreateStream(pfile, // file pointer &ps, // returned stream pointer &strhdr); // stream header if (hr != AVIERR_OK) { GlobalFreePtr(alpbi); bOK = false; return false; } _fmemset(&opts, 0, sizeof(opts)); if (!AVISaveOptions(NULL, ICMF_CHOOSE_KEYFRAME, 1, &ps, (LPAVICOMPRESSOPTIONS FAR *) &aopts)) { fprintf( stderr, "AVISaveOptions failed.\n" ); GlobalFreePtr(alpbi); bOK = false; return false; } hr = AVIMakeCompressedStream(&psCompressed, ps, &opts, NULL); if (hr != AVIERR_OK) { fprintf( stderr, "AVIMakeCompressedStream failed.\n" ); GlobalFreePtr(alpbi); bOK = false; return false; } hr = AVIStreamSetFormat(psCompressed, 0, alpbi, // stream format alpbi->biSize + // format size alpbi->biClrUsed * sizeof(RGBQUAD)); if (hr != AVIERR_OK) { fprintf( stderr, "AVIStreamSetFormat failed.\n" ); GlobalFreePtr(alpbi); bOK = false; return false; } // Fill in the stream header for the text stream.... // The text stream is in 60ths of a second.... /* _fmemset(&strhdr, 0, sizeof(strhdr)); strhdr.fccType = streamtypeTEXT; strhdr.fccHandler = mmioFOURCC('D', 'R', 'A', 'W'); strhdr.dwScale = 1; strhdr.dwRate = 60; strhdr.dwSuggestedBufferSize = sizeof(szText); SetRect(&strhdr.rcFrame, 0, (int) alpbi->biHeight, (int) alpbi->biWidth, (int) alpbi->biHeight + TEXT_HEIGHT); // ....and create the stream. hr = AVIFileCreateStream(pfile, &psText, &strhdr); if (hr != AVIERR_OK) { GlobalFreePtr(alpbi); bOK = false; return false; } dwTextFormat = sizeof(dwTextFormat); hr = AVIStreamSetFormat(psText, 0, &dwTextFormat, sizeof(dwTextFormat)); if (hr != AVIERR_OK) { GlobalFreePtr(alpbi); bOK = false; return false; } */ } // Now actual writing hr = AVIStreamWrite(psCompressed, // stream pointer nFrames * 1, // 10, // time of this frame 1, // number to write (LPBYTE) alpbi + // pointer to data alpbi->biSize + alpbi->biClrUsed * sizeof(RGBQUAD), alpbi->biSizeImage, // size of this frame AVIIF_KEYFRAME, // flags.... NULL, NULL); if (hr != AVIERR_OK) { fprintf( stderr, "AVIStreamWrite failed.\n" ); GlobalFreePtr(alpbi); bOK = false; return false; } // Make some text to put in the file ... //LoadString(hInstance, IDS_TEXTFORMAT, szMessage, BUFSIZE ); /* strcpy(szMessage, "This is frame #%d"); int iLen = wsprintf(szText, szMessage, (int)(nFrames + 1)); // ... and write it as well. hr = AVIStreamWrite(psText, nFrames * 40, 1, szText, iLen + 1, AVIIF_KEYFRAME, NULL, NULL); if (hr != AVIERR_OK) { GlobalFreePtr(alpbi); bOK = false; return false; } */ GlobalFreePtr(alpbi); nFrames++; fprintf( stderr, "Wrote frame %d.\r", nFrames ); return true; }