www.gusucode.com > eMule电驴下载VC++源代码-源码程序 > eMule电驴下载VC++源代码-源码程序\code\srchybrid\FrameGrabThread.cpp
//Download by http://www.NewXing.com //this file is part of eMule //Copyright (C)2003 Merkur ( merkur-@users.sourceforge.net / http://www.emule-project.net ) // //This program is free software; you can redistribute it and/or //modify it under the terms of the GNU General Public License //as published by the Free Software Foundation; either //version 2 of the License, or (at your option) any later version. // //This program is distributed in the hope that it will be useful, //but WITHOUT ANY WARRANTY; without even the implied warranty of //MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //GNU General Public License for more details. // //You should have received a copy of the GNU General Public License //along with this program; if not, write to the Free Software //Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #include "stdafx.h" #include "emule.h" #include "FrameGrabThread.h" #include "CxImage/xImage.h" #include "OtherFunctions.h" #include "quantize.h" // DirectShow MediaDet #include <strmif.h> //#include <uuids.h> #define _DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ EXTERN_C const GUID DECLSPEC_SELECTANY name \ = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } } _DEFINE_GUID(MEDIATYPE_Video, 0x73646976, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71); _DEFINE_GUID(MEDIATYPE_Audio, 0x73647561, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71); _DEFINE_GUID(FORMAT_VideoInfo,0x05589f80, 0xc356, 0x11ce, 0xbf, 0x01, 0x00, 0xaa, 0x00, 0x55, 0x59, 0x5a); _DEFINE_GUID(FORMAT_WaveFormatEx,0x05589f81, 0xc356, 0x11ce, 0xbf, 0x01, 0x00, 0xaa, 0x00, 0x55, 0x59, 0x5a); #include <qedit.h> typedef struct tagVIDEOINFOHEADER { RECT rcSource; // The bit we really want to use RECT rcTarget; // Where the video should go DWORD dwBitRate; // Approximate bit data rate DWORD dwBitErrorRate; // Bit error rate for this stream REFERENCE_TIME AvgTimePerFrame; // Average time per frame (100ns units) BITMAPINFOHEADER bmiHeader; } VIDEOINFOHEADER; #ifndef _CONSOLE #include "emuledlg.h" #endif #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif IMPLEMENT_DYNCREATE(CFrameGrabThread, CWinThread) CFrameGrabThread::CFrameGrabThread() { } CFrameGrabThread::~CFrameGrabThread() { } BOOL CFrameGrabThread::Run(){ DbgSetThreadName("FrameGrabThread"); imgResults = new CxImage*[nFramesToGrab]; FrameGrabResult_Struct* result = new FrameGrabResult_Struct; result->nImagesGrabbed = GrabFrames(); result->imgResults = imgResults; result->pSender = pSender; VERIFY( PostMessage(theApp.emuledlg->m_hWnd,TM_FRAMEGRABFINISHED, (WPARAM)pOwner,(LPARAM)result) ); AfxEndThread(0,true); return 0; } uint8 CFrameGrabThread::GrabFrames(){ #define TIMEBETWEENFRAMES 50.0 // could be a param later, if needed for (int i = 0; i!= nFramesToGrab; i++) imgResults[i] = NULL; try{ HRESULT hr; CComPtr<IMediaDet> pDet; CoInitialize(NULL); hr = pDet.CoCreateInstance(__uuidof(MediaDet)); if (!SUCCEEDED(hr)) return 0; // Convert the file name to a BSTR. CComBSTR bstrFilename(strFileName); hr = pDet->put_Filename(bstrFilename); long lStreams; bool bFound = false; hr = pDet->get_OutputStreams(&lStreams); for (long i = 0; i < lStreams; i++) { GUID major_type; hr = pDet->put_CurrentStream(i); hr = pDet->get_StreamType(&major_type); if (major_type == MEDIATYPE_Video) { bFound = true; break; } } if (!bFound) return 0; double dLength = 0; pDet->get_StreamLength(&dLength); if (dStartTime > dLength) dStartTime = 0; long width = 0, height = 0; AM_MEDIA_TYPE mt; hr = pDet->get_StreamMediaType(&mt); if (mt.formattype == FORMAT_VideoInfo) { VIDEOINFOHEADER *pVih = (VIDEOINFOHEADER*)(mt.pbFormat); width = pVih->bmiHeader.biWidth; height = pVih->bmiHeader.biHeight; // We want the absolute height, don't care about orientation. if (height < 0) height *= -1; } else { return 0; // Should not happen, in theory. } /*FreeMediaType(mt); = */ if (mt.cbFormat != 0){ CoTaskMemFree((PVOID)mt.pbFormat); mt.cbFormat = 0; mt.pbFormat = NULL; } if (mt.pUnk != NULL){ mt.pUnk->Release(); mt.pUnk = NULL; } /**/ long size; uint32 nFramesGrabbed; for (nFramesGrabbed = 0; nFramesGrabbed != nFramesToGrab; nFramesGrabbed++){ hr = pDet->GetBitmapBits(dStartTime + (nFramesGrabbed*TIMEBETWEENFRAMES), &size, NULL, width, height); if (SUCCEEDED(hr)) { // we could also directly create a Bitmap in memory, however this caused problems/failed with *some* movie files // when I tried it for the MMPreview, while this method works always - so I'll continue to use this one long nFullBufferLen = sizeof( BITMAPFILEHEADER ) + size; char* buffer = new char[nFullBufferLen]; BITMAPFILEHEADER bfh; memset( &bfh, 0, sizeof( bfh ) ); bfh.bfType = 'MB'; bfh.bfSize = nFullBufferLen; bfh.bfOffBits = sizeof( BITMAPINFOHEADER ) + sizeof( BITMAPFILEHEADER ); memcpy(buffer,&bfh,sizeof( bfh ) ); try { hr = pDet->GetBitmapBits(dStartTime+ (nFramesGrabbed*TIMEBETWEENFRAMES), NULL, buffer + sizeof( bfh ), width, height); } catch (...) { ASSERT(0); hr = E_FAIL; } if (SUCCEEDED(hr)) { // decode CxImage* imgResult = new CxImage(); imgResult->Decode((BYTE*)buffer, nFullBufferLen, CXIMAGE_FORMAT_BMP); delete[] buffer; if (!imgResult->IsValid()){ delete imgResult; break; } // resize if needed if (nMaxWidth > 0 && nMaxWidth < width){ float scale = (float)nMaxWidth / imgResult->GetWidth(); int nMaxHeigth = imgResult->GetHeight() * scale; imgResult->Resample(nMaxWidth, nMaxHeigth, 0); } // decrease bpp if needed if (bReduceColor){ CQuantizer q(256,8); q.ProcessImage(imgResult->GetDIB()); RGBQUAD* ppal=(RGBQUAD*)malloc(256*sizeof(RGBQUAD)); q.SetColorTable(ppal); imgResult->DecreaseBpp(8, true, ppal); free(ppal); } //CString TestName; //TestName.Format("G:\\testframe%i.png",nFramesGrabbed); //imgResult->Save(TestName,CXIMAGE_FORMAT_PNG); // done imgResults[nFramesGrabbed] = imgResult; } else{ delete[] buffer; break; } } } return nFramesGrabbed; } catch(...){ ASSERT(0); return 0; } } void CFrameGrabThread::SetValues(const CKnownFile* in_pOwner, CString in_strFileName,uint8 in_nFramesToGrab, double in_dStartTime, bool in_bReduceColor, uint16 in_nMaxWidth, void* in_pSender){ strFileName =in_strFileName; nFramesToGrab = in_nFramesToGrab; dStartTime = in_dStartTime; bReduceColor = in_bReduceColor; nMaxWidth = in_nMaxWidth; pOwner = in_pOwner; pSender = in_pSender; } BEGIN_MESSAGE_MAP(CFrameGrabThread, CWinThread) END_MESSAGE_MAP()