12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228 |
- #include "precompile.h"
- #include "videocap.h"
- #include "ListEntry.h"
- #include "qedit.h"
- #include <dshow.h> // need directshow sdk
- #include <videohorflip.h>
- #include "libyuv/convert.h"
- #include "libyuv/video_common.h"
- #include "libyuv/scale.h"
- // helper
- #define swap(t, x, y) \
- { \
- t v; \
- v = x; \
- x = y; \
- y = v; \
- }
- HRESULT get_output_mediatype(videocap *vcap);
- static void capDbg(videocap_param *cap, const char *fmt, ...)
- {
- va_list arg;
- va_start(arg, fmt);
- if (cap->dbg) {
- (*cap->dbg)(fmt, arg);
- }
- va_end(arg);
- }
- int I420DataSize(int height, int stride_y, int stride_u, int stride_v) {
- return stride_y * height + (stride_u + stride_v) * ((height + 1) / 2);
- }
- int RGB24DataSize(int height, int stride_y, int stride_u, int stride_v) {
- return stride_y * height * 2 + ((stride_u + stride_v) * ((height + 1) / 2) * 2);
- }
- static void capLogEvent(videocap_param *cap, int ilogtype, const char* strmessage)
- {
- if (cap->logevent) {
- (*cap->logevent)(ilogtype, cap->dev_id, strmessage);
- }
- }
- static void i420_flip_vertical(video_frame *frame)
- {
- if (frame->format == VIDEO_FORMAT_I420) {
- frame->data[0] = frame->data[0] + frame->linesize[0]*(frame->height-1);
- frame->data[1] = frame->data[1] + frame->linesize[1]*((frame->height>>1)-1);
- frame->data[2] = frame->data[2] + frame->linesize[2]*((frame->height>>1)-1);
- frame->linesize[0] = -frame->linesize[0];
- frame->linesize[1] = -frame->linesize[1];
- frame->linesize[2] = -frame->linesize[2];
- swap(unsigned char*, frame->data[1], frame->data[2]);
- swap(int, frame->linesize[1], frame->linesize[2]);
- }
- }
- static HRESULT AddToRot(IUnknown *pUnkGraph, DWORD *pdwRegister)
- {
- IMoniker * pMoniker;
- IRunningObjectTable *pROT;
- WCHAR wsz[256];
- HRESULT hr;
- if (FAILED(GetRunningObjectTable(0, &pROT))) {
- return E_FAIL;
- }
- wsprintfW(wsz, L"FilterGraph %08x pid %08x", (DWORD_PTR)pUnkGraph, GetCurrentProcessId());
- hr = CreateItemMoniker(L"!", wsz, &pMoniker);
- if (SUCCEEDED(hr)) {
- pROT->Register(ROTFLAGS_REGISTRATIONKEEPSALIVE, pUnkGraph,
- pMoniker, pdwRegister);
- pMoniker->Release();
- }
- pROT->Release();
- return hr;
- }
- static void RemoveFromRot(DWORD pdwRegister)
- {
- IRunningObjectTable *pROT;
- if (SUCCEEDED(GetRunningObjectTable(0, &pROT))) {
- pROT->Revoke(pdwRegister);
- pROT->Release();
- }
- }
- static char* GuidToString(const GUID guid)
- {
- int buf_len=64;
- char *buf =(char *)malloc(buf_len);
- _snprintf(
- buf,
- buf_len,
- "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
- guid.Data1, guid.Data2, guid.Data3,
- guid.Data4[0], guid.Data4[1],
- guid.Data4[2], guid.Data4[3],
- guid.Data4[4], guid.Data4[5],
- guid.Data4[6], guid.Data4[7]);
- //printf("%s\n",buf);
- return buf;
- }
- static void FreeMediaTypeEx(AM_MEDIA_TYPE *pmt)
- {
- if (pmt) {
- if (pmt->cbFormat) {
- CoTaskMemFree((PVOID)pmt->pbFormat);
- pmt->cbFormat = 0;
- pmt->pbFormat = NULL;
- }
- if (pmt->pUnk) {
- pmt->pUnk->Release();
- pmt->pUnk = NULL;
- }
- CoTaskMemFree(pmt);
- }
- }
- static HRESULT GetUnconnectedPin(IBaseFilter *pFilter,PIN_DIRECTION PinDir,IPin **ppPin)
- {
- IEnumPins *pEnum = 0;
- IPin *pPin = 0;
- HRESULT hr = pFilter->EnumPins(&pEnum);
- *ppPin = 0;
- if (FAILED(hr))
- return hr;
- while (pEnum->Next(1, &pPin, NULL) == S_OK) {
- PIN_DIRECTION ThisPinDir;
- pPin->QueryDirection(&ThisPinDir);
- if (ThisPinDir == PinDir) {
- IPin *pTmp = 0;
- hr = pPin->ConnectedTo(&pTmp);
- if (SUCCEEDED(hr)) // Already connected, not the pin we want.
- pTmp->Release();
- else // Unconnected, this is the pin we want.
- {
- pEnum->Release();
- *ppPin = pPin;
- return S_OK;
- }
- }
- pPin->Release();
- }
- pEnum->Release();
- // Did not find a matching pin.
- return E_FAIL;
- }
- static HRESULT ConnectFilters1(IGraphBuilder *pGraph, // Filter Graph Manager.
- IPin *pOut, // Output pin on the upstream filter.
- IBaseFilter *pDest) // Downstream filter.
- {
- IPin *pIn;
- HRESULT hr;
- if ((pGraph == NULL) || (pOut == NULL) || (pDest == NULL))
- {
- return E_POINTER;
- }
- // Find an input pin on the downstream filter.
- pIn = 0;
- hr = GetUnconnectedPin(pDest, PINDIR_INPUT, &pIn);
- if (FAILED(hr))
- {
- return hr;
- }
- // Try to connect them.
- hr = pGraph->ConnectDirect(pOut, pIn, NULL);
- if (FAILED(hr)){
- hr = pGraph->Connect(pOut, pIn);
- }
- pIn->Release();
- return hr;
- }
- static HRESULT ConnectFilters2(IGraphBuilder *pGraph, IBaseFilter *pSrc, IBaseFilter *pDest)
- {
- IPin *pOut;
- HRESULT hr;
- if ((pGraph == NULL) || (pSrc == NULL) || (pDest == NULL))
- return E_POINTER;
- // Find an output pin on the first filter.
- pOut = 0;
- hr = GetUnconnectedPin(pSrc, PINDIR_OUTPUT, &pOut);
- if (FAILED(hr))
- return hr;
- hr = ConnectFilters1(pGraph, pOut, pDest);
- pOut->Release();
- return hr;
- }
- static HRESULT WalkFilterCategory(REFCLSID category,
- HRESULT (*OnDeviceCB)(int index,IMoniker *pMoniker,VOID *pUserData1,VOID *pUserData2),
- VOID * pUserData1,
- VOID* pUserData2)
- {
- HRESULT hr;
- ICreateDevEnum *pDevEnum = NULL;
- IEnumMoniker *pEnumMoniker = NULL;
- IMoniker *pMoniker = NULL;
- BOOL quit;
- int i = 0;
- if (!OnDeviceCB)
- return E_INVALIDARG;
- hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
- IID_ICreateDevEnum, (void**)&pDevEnum);
- if (FAILED(hr))
- return hr;
- hr = pDevEnum->CreateClassEnumerator(category,
- &pEnumMoniker, 0);
- if (FAILED(hr)) {
- pDevEnum->Release();
- return hr;
- } else if (hr == S_OK) {
- pEnumMoniker->Reset();
- quit = FALSE;
- while (pEnumMoniker->Next(1, &pMoniker, NULL) == S_OK && !quit) {
- hr = OnDeviceCB(i++, pMoniker, pUserData1, pUserData2);
- quit = FAILED(hr) || (hr == S_OK);
- pMoniker->Release();
- }
- pEnumMoniker->Release();
- pDevEnum->Release();
- } else {
- if (pEnumMoniker)
- pEnumMoniker->Release();
- pDevEnum->Release();
- }
- return hr;
- }
- static HRESULT CreateFilterByFriendlyNameCB(int index, IMoniker *pMoniker, void *pUserData1, void *pUserData2)
- {
- HRESULT hr;
- IBaseFilter *pBaseFilter = NULL;
- WCHAR *szName = (WCHAR*)pUserData2;
- if (pMoniker) {
- IPropertyBag *pPropBag;
- VARIANT name;
- hr = pMoniker->BindToStorage(NULL, NULL,
- IID_IPropertyBag, (void**)&pPropBag);
- if (FAILED(hr))
- return S_FALSE;
- VariantInit(&name);
- name.vt = VT_BSTR;
- hr = pPropBag->Read( L"FriendlyName", &name, NULL);
- if (FAILED(hr)) {
- pPropBag->Release();
- VariantClear(&name);
- return S_FALSE;
- }
- if (SysStringByteLen(name.bstrVal) && wcscmp(name.bstrVal, szName)==0) {
- hr = pMoniker->BindToObject(NULL, NULL,
- IID_IBaseFilter, (void**)&pBaseFilter);
- if (SUCCEEDED(hr)) {
- *(IBaseFilter**)pUserData1 = pBaseFilter;
- hr = S_OK;
- }
- }
- pPropBag->Release();
- VariantClear(&name);
- } else {
- hr = E_POINTER;
- }
- return hr;
- }
- static HRESULT CreateFilterByFriendlyName(REFCLSID category, void **ppBaseFilter, WCHAR* szName)
- {
- HRESULT hr = WalkFilterCategory(category,
- &CreateFilterByFriendlyNameCB, ppBaseFilter, szName);
- return hr == S_FALSE ? E_NOINTERFACE : hr;
- }
- static HRESULT CreateFilterByIndexCB(int index, IMoniker *pMoniker, void *pUserData1, void *pUserData2)
- {
- HRESULT hr;
- IBaseFilter *pBaseFilter = NULL;
- int *pidx = (int*)pUserData2;
- if (pMoniker && index == *pidx) {
- hr = pMoniker->BindToObject(NULL, NULL,
- IID_IBaseFilter, (void**)&pBaseFilter);
- if (FAILED(hr))
- return hr;
- *(IBaseFilter**)pUserData1 = pBaseFilter;
- return S_OK;
- }
- return S_FALSE;
- }
- static HRESULT CreateFilterByIndex(REFCLSID category,
- void **ppBaseFilter,
- int idx)
- {
- HRESULT hr = WalkFilterCategory(category, &CreateFilterByIndexCB,
- ppBaseFilter, &idx);
- return hr == S_FALSE ? E_NOINTERFACE : hr;
- }
- static HRESULT RemoveGraphAllFilters(IGraphBuilder *pGraphBuilder)
- {
- HRESULT hr;
- IEnumFilters *pEnumFilters;
- if (!pGraphBuilder)
- return E_POINTER;
- hr = pGraphBuilder->EnumFilters(&pEnumFilters);
- if (SUCCEEDED(hr)) {
- IBaseFilter *pFilter;
- pEnumFilters->Reset();
- while (pEnumFilters->Next(1, &pFilter, NULL) == S_OK) {
- pGraphBuilder->RemoveFilter(pFilter);
- pFilter->Release();
- pEnumFilters->Reset();
- }
- pEnumFilters->Release();
- }
- return hr;
- }
- ////////////////////////////////////////////////////////////////////////////////////////////////
- static const int mode_width[VIDEOCAP_MAX_MODE] = {
- VIDEOCAP_SQCIF_WIDTH,VIDEOCAP_QQVGA_WIDTH,
- VIDEOCAP_QCIF_WIDTH,VIDEOCAP_QVGA_WIDTH,
- VIDEOCAP_CIF_WIDTH,VIDEOCAP_VGA_WIDTH,
- VIDEOCAP_4CIF_WIDTH,VIDEOCAP_SVGA_WIDTH,
- VIDEOCAP_NHD_WIDTH,VIDEOCAP_SXGA_WIDTH,
- VIDEOCAP_720P_WIDTH,VIDEOCAP_1080P_WIDTH,
- };
- static const int mode_height[VIDEOCAP_MAX_MODE] = {
- VIDEOCAP_SQCIF_HEIGHT,VIDEOCAP_QQVGA_HEIGHT,
- VIDEOCAP_QCIF_HEIGHT,VIDEOCAP_QVGA_HEIGHT,
- VIDEOCAP_CIF_HEIGHT,VIDEOCAP_VGA_HEIGHT,
- VIDEOCAP_4CIF_HEIGHT,VIDEOCAP_SVGA_HEIGHT,
- VIDEOCAP_NHD_HEIGHT,VIDEOCAP_SXGA_HEIGHT,
- VIDEOCAP_720P_HEIGHT,VIDEOCAP_1080P_HEIGHT,
- };
- typedef struct async_cap_t
- {
- LIST_ENTRY entry;
- HANDLE evt;
- int result;
- video_frame *ref_cap_frame;
- }async_cap_t;
- /**
- * we use DirectShow to capture video frames
- */
- typedef struct videocap
- {
- IBaseFilter *sourcefilter;
- IBaseFilter *cpcfilter; // color space converter if necessary
- IBaseFilter *avidecfilter;
- IBaseFilter *grabberfilter;
- IBaseFilter *horflipfilter;
- IBaseFilter *renderfilter;
- ISampleGrabber *grabber;
- IGraphBuilder *graphbuilder;
- IMediaControl *mc;
- IMediaEvent *me;
- IVideoWindow *videowindow;
- #ifdef _DEBUG
- DWORD dwROTRegister; // register RunningObjectTable
- #endif
- videocap_param param;
- int running;
- HANDLE thread_background;
- HANDLE evt_thread_exit;
- int cap_index;
- CRITICAL_SECTION cap_cs;
- video_frame cap_frame;
- CRITICAL_SECTION async_cap_cs;
- LIST_ENTRY async_cap_list;
- LONG grab_cb_count;
- CRITICAL_SECTION res_cs;
- video_frame res_frame;
- struct SwsContext *sws_context; /* for image scaling and format converting */
- int iout_width;
- int iout_height;
- bool bloged;
- } videocap;
- HRESULT set_video_source_format(videocap *);
- void release_all_interfaces(videocap *);
- typedef struct ISampleGrabberCBImpl
- {
- struct ISampleGrabberCB *pCb;
- struct videocap* vcap;
- //struct ISampleGrabberCBVtbl vtbl;
- }ISampleGrabberCBImpl;
- class RvcSampleGrabberCB : public ISampleGrabberCB
- {
- public:
- RvcSampleGrabberCB(struct videocap* vcap);
- HRESULT STDMETHODCALLTYPE SampleCB(
- double SampleTime,
- IMediaSample *pSample);
- HRESULT STDMETHODCALLTYPE BufferCB(
- double SampleTime,
- BYTE *pBuffer,
- long BufferLen);
- HRESULT STDMETHODCALLTYPE QueryInterface(
- /* [in] */ REFIID riid,
- /* [iid_is][out] */ __RPC__deref_out void __RPC_FAR *__RPC_FAR *ppvObject);
- ULONG STDMETHODCALLTYPE AddRef( void);
- ULONG STDMETHODCALLTYPE Release( void);
- private:
- struct videocap* m_vcap;
- };
- RvcSampleGrabberCB::RvcSampleGrabberCB(struct videocap* vcap)
- {
- m_vcap = vcap;
- }
- HRESULT STDMETHODCALLTYPE RvcSampleGrabberCB::SampleCB(
- double SampleTime,
- IMediaSample *pSample)
- {
- return S_OK;
- }
- static HRESULT Handle_BGR_Frame_CallBack(videocap *vcap, BYTE *pBuffer, long BufferLen)
- {
- int linesize = BufferLen / mode_height[vcap->param.cap_mode];
- struct SwsContext *sws;
- char*Buffertmp=(char*)malloc(mode_width[vcap->param.cap_mode]*mode_height[vcap->param.cap_mode]*3);
- uint8_t *src_data[4];
- int src_linesize[4];
- unsigned char *dst[4] = {(unsigned char*)Buffertmp,NULL,NULL,NULL};
- int dst_linesize[4] = {mode_width[vcap->param.cap_mode]*3,0,0,0};
- char*buffer;
- int oriLen = mode_height[vcap->param.cap_mode]*mode_width[vcap->param.cap_mode]*3;
- if (BufferLen != oriLen)
- {
- //计算目标图像比例
- int srcH;
- float fDstScale = (float)mode_width[vcap->param.cap_mode]/(float)mode_height[vcap->param.cap_mode];
- float fSrcScale = (float)vcap->iout_width /(float)vcap->iout_height;
- if (fSrcScale != fDstScale)
- {
- //计算偏移量
- int nWidth,nHeight,nOffset=0;
- if (fSrcScale > fDstScale)
- {
- return 0;
- }
- else if (fSrcScale < fDstScale)
- {
- //高度过长
- nWidth = vcap->iout_width;
- nHeight = (int)ceil(vcap->iout_width/fDstScale);
- nOffset = (vcap->iout_height -nHeight)/2*nWidth*3;
- }
- //计算等比例变换需要的SWS
- sws=sws_getContext(nWidth,nHeight,AV_PIX_FMT_BGR24, mode_width[vcap->param.cap_mode], mode_height[vcap->param.cap_mode], AV_PIX_FMT_BGR24, SWS_BICUBIC, NULL, NULL, NULL);
- av_image_alloc(src_data, src_linesize, vcap->iout_width, vcap->iout_height, AV_PIX_FMT_BGR24, 1);
- memcpy(src_data[0],pBuffer+nOffset,nWidth*nHeight*3); //Y
- srcH = nHeight;
- }
- else
- {
- //计算等比例变换需要的SWS
- sws=sws_getContext(vcap->iout_width, vcap->iout_height, AV_PIX_FMT_BGR24, mode_width[vcap->param.cap_mode], mode_height[vcap->param.cap_mode], AV_PIX_FMT_BGR24, SWS_BICUBIC, NULL, NULL, NULL);
- av_image_alloc(src_data, src_linesize, vcap->iout_width, vcap->iout_height, AV_PIX_FMT_BGR24, 1);
- memcpy(src_data[0],pBuffer,BufferLen); //Y
- srcH = vcap->iout_height;
- }
- //分辨率转换
- sws_scale(sws, src_data, src_linesize, 0, srcH, dst, dst_linesize);
- sws_freeContext(sws);
- av_freep(&src_data[0]);
- buffer = Buffertmp;
- BufferLen = mode_width[vcap->param.cap_mode]*mode_height[vcap->param.cap_mode]*3;
- }
- else
- {
- buffer = (char*)pBuffer;
- }
- linesize = BufferLen / mode_height[vcap->param.cap_mode];
- if (vcap->param.option & VIDEOCAP_OPT_ENABLE_GRAB)
- {
- if (vcap->cap_index++%3 == 0)
- { /* 3 is grabbing interval */
- EnterCriticalSection(&vcap->cap_cs);
- //memcpy(vcap->cap_frame.data[0], pBuffer, BufferLen);
- memcpy(vcap->cap_frame.data[0], buffer, BufferLen);
- LeaveCriticalSection(&vcap->cap_cs);
- }
- }
- if (vcap->grab_cb_count)
- {
- if (vcap->param.on_grab)
- {
- video_frame frm = {0};
- frm.data[0] = (unsigned char*)buffer;
- frm.linesize[0] = linesize;
- frm.width = mode_width[vcap->param.cap_mode];
- frm.height = mode_height[vcap->param.cap_mode];
- frm.format = VIDEO_FORMAT_RGB24;
- vcap->param.on_grab(vcap->param.user_data, &frm);
- }
- InterlockedDecrement(&vcap->grab_cb_count);
- }
- if (vcap->param.option & VIDEOCAP_OPT_ENABLE_ASYNC_GRAB)
- {
- async_cap_t *pos, *n;
- EnterCriticalSection(&vcap->async_cap_cs);
- ListEntry_ForEachSafe(pos, n, &vcap->async_cap_list, async_cap_t, entry)
- {
- ListEntry_DeleteNode(&pos->entry);
- pos->result = 0;
- memcpy(pos->ref_cap_frame->data[0], buffer, BufferLen);
- SetEvent(pos->evt);
- }
- LeaveCriticalSection(&vcap->async_cap_cs);
- }
- if (vcap->param.on_frame_raw)
- {
- video_frame frm = {0};
- frm.data[0] = (unsigned char*)buffer;
- frm.linesize[0] = linesize;
- frm.width = mode_width[vcap->param.cap_mode];
- frm.height = mode_height[vcap->param.cap_mode];
- frm.format = VIDEO_FORMAT_RGB24;
- vcap->param.on_frame_raw(vcap->param.user_data, &frm);
- }
- if (vcap->param.option & VIDEOCAP_OPT_EANBLE_RESIZE)
- { /* user enable resizing */
- unsigned char *src_data[4];
- int src_linesize[4] = {linesize, 0, 0, 0};
- src_data[0] = (unsigned char*)buffer;
- src_data[1] = NULL;
- src_data[2] = NULL;
- src_data[3] = NULL;
- EnterCriticalSection(&vcap->res_cs);
- if (vcap->param.option & VIDEOCAP_OPT_ENABLE_FLIP)
- {
- src_data[0] += (mode_height[vcap->param.cap_mode]-1)*src_linesize[0];
- src_linesize[0] = -src_linesize[0];
- sws_scale(vcap->sws_context, src_data, src_linesize, 0, mode_height[vcap->param.cap_mode], vcap->res_frame.data, vcap->res_frame.linesize);
- }
- else
- {
- sws_scale(vcap->sws_context, src_data, src_linesize,
- 0, mode_height[vcap->param.cap_mode], vcap->res_frame.data, vcap->res_frame.linesize);
- }
- if (vcap->param.on_frame)
- {
- vcap->param.on_frame(vcap->param.user_data, &vcap->res_frame);
- }
- LeaveCriticalSection(&vcap->res_cs);
- }
- else
- {
- if (vcap->param.on_frame)
- {
- video_frame frame;
- memset(&frame, 0, sizeof(video_frame));
- frame.width = mode_width[vcap->param.cap_mode];
- frame.height = mode_height[vcap->param.cap_mode];
- frame.data[0] = (unsigned char*)buffer;
- frame.linesize[0] = linesize;
- frame.format = VIDEO_FORMAT_RGB24;
- vcap->param.on_frame(vcap->param.user_data, &frame);
- }
- }
- free(Buffertmp);
- return S_OK;
- }
- static HRESULT Handle_YUY2_Frame_CallBack(videocap *vcap, BYTE *pBuffer, long BufferLen)
- {
- float fDstScale = (float)mode_width[vcap->param.cap_mode]/(float)mode_height[vcap->param.cap_mode];
- float fSrcScale = (float)vcap->iout_width /(float)vcap->iout_height;
- int used_width = vcap->iout_width;
- int used_height = vcap->iout_height;
- if (fSrcScale < fDstScale){
- used_height = (int)ceil(vcap->iout_width /fDstScale);
- }
- else if (fSrcScale > fDstScale){
- return S_FALSE;
- }
- int stride_y = used_width;
- int stride_u = (used_width + 1)/2;
- int stride_v = (used_width + 1)/2;
- uint8_t* m_i420 = (uint8_t*)malloc(I420DataSize(used_height, stride_y, stride_u, stride_v));
- int conversionResult = libyuv::ConvertToI420(pBuffer, BufferLen,
- m_i420,
- stride_y,
- m_i420 + stride_y * used_height,
- stride_u,
- m_i420 + stride_y * used_height + stride_u * ((used_height + 1) / 2),
- stride_v,
- 0,
- (vcap->iout_height -used_height)/2, // No Cropping
- vcap->iout_width,
- vcap->iout_height,
- vcap->iout_width,
- used_height,
- libyuv::kRotate180,
- libyuv::FOURCC_YUY2
- );
- if (0 != conversionResult) {
- //capDbg(&vcap->param, "Failed to convert capture frame from type FOURCC_YUY2, conversionResult = %d, pBuffer = 0x%08x, BufferLen = %ld.", conversionResult, pBuffer, BufferLen);
- if (NULL != m_i420){
- free(m_i420);
- m_i420 = NULL;
- }
- return S_FALSE;
- }
- char*buffertmp=(char*)malloc(mode_width[vcap->param.cap_mode]*mode_height[vcap->param.cap_mode]*3);
- char*buffer = NULL;
- //是否需要做分辨率转换
- if (used_width == mode_width[vcap->param.cap_mode]){
- conversionResult = libyuv::ConvertFromI420(m_i420,
- stride_y,
- m_i420 + stride_y * mode_height[vcap->param.cap_mode],
- stride_u,
- m_i420 + stride_y * mode_height[vcap->param.cap_mode] + stride_u * ((mode_height[vcap->param.cap_mode] + 1) / 2),
- stride_v,
- (uint8_t*)buffertmp,
- mode_width[vcap->param.cap_mode] * 3,
- mode_width[vcap->param.cap_mode],
- mode_height[vcap->param.cap_mode],
- libyuv::FOURCC_24BG);
- if (conversionResult < 0) {
- //capDbg(&vcap->param, "Failed to convert capture frame from I420 to RGB24, conversionResult = %d.", conversionResult);
- if (NULL != m_i420){
- free(m_i420);
- m_i420 = NULL;
- }
- if (NULL != buffertmp){
- free(buffertmp);
- buffertmp = NULL;
- }
- return S_FALSE;
- }
- }
- else{
- int dest_stride_y = mode_width[vcap->param.cap_mode];
- int dest_stride_u = (mode_width[vcap->param.cap_mode] + 1)/2;
- int dest_stride_v = (mode_width[vcap->param.cap_mode] + 1)/2;
- uint8_t* m_desti420 = (uint8_t*)malloc(I420DataSize(mode_height[vcap->param.cap_mode], dest_stride_y, dest_stride_u, dest_stride_v));
- conversionResult = libyuv::I420Scale(m_i420, used_width,
- m_i420 + used_width * used_height, used_width / 2,
- m_i420 + used_width * used_height * 5 / 4, used_width / 2,
- used_width, used_height,
- m_desti420, mode_width[vcap->param.cap_mode],
- m_desti420 + mode_width[vcap->param.cap_mode] * mode_height[vcap->param.cap_mode], mode_width[vcap->param.cap_mode] / 2,
- m_desti420 + mode_width[vcap->param.cap_mode] * mode_height[vcap->param.cap_mode] * 5 / 4, mode_width[vcap->param.cap_mode] / 2,
- mode_width[vcap->param.cap_mode], mode_height[vcap->param.cap_mode],
- libyuv::kFilterNone);
- if (conversionResult < 0) {
- //capDbg(&vcap->param, "Failed to I420Scale, conversionResult = %d.", conversionResult);
- if (NULL != m_desti420){
- free(m_desti420);
- m_desti420 = NULL;
- }
- if (NULL != buffertmp){
- free(buffertmp);
- buffertmp = NULL;
- }
- if (NULL != m_i420){
- free(m_i420);
- m_i420 = NULL;
- }
- return S_FALSE;
- }
- conversionResult = libyuv::ConvertFromI420(m_desti420,
- dest_stride_y,
- m_desti420 + dest_stride_y * mode_height[vcap->param.cap_mode],
- dest_stride_u,
- m_desti420 + dest_stride_y * mode_height[vcap->param.cap_mode] + dest_stride_u * ((mode_height[vcap->param.cap_mode] + 1) / 2),
- dest_stride_v,
- (uint8_t*)buffertmp,
- mode_width[vcap->param.cap_mode] * 3,
- mode_width[vcap->param.cap_mode],
- mode_height[vcap->param.cap_mode],
- libyuv::FOURCC_24BG);
- if (NULL != m_desti420){
- free(m_desti420);
- m_desti420 = NULL;
- }
- if (conversionResult < 0) {
- //capDbg(&vcap->param, "Failed to convert capture frame from I420 to RGB24, conversionResult = %d.", conversionResult);
- if (NULL != buffertmp){
- free(buffertmp);
- buffertmp = NULL;
- }
- if (NULL != m_i420){
- free(m_i420);
- m_i420 = NULL;
- }
- return S_FALSE;
- }
- }
- buffer = buffertmp;
- if (NULL != m_i420){
- free(m_i420);
- m_i420 = NULL;
- }
- if (vcap->param.on_frame)
- {
- video_frame frame;
- memset(&frame, 0, sizeof(video_frame));
- frame.width = mode_width[vcap->param.cap_mode];
- frame.height = mode_height[vcap->param.cap_mode];
- frame.data[0] = (unsigned char*)buffer;
- frame.linesize[0] = mode_width[vcap->param.cap_mode]*3;
- frame.format = VIDEO_FORMAT_RGB24;
- vcap->param.on_frame(vcap->param.user_data, &frame);
- }
- if (NULL != buffertmp){
- free(buffertmp);
- buffertmp = NULL;
- }
- return S_OK;
- }
- HRESULT STDMETHODCALLTYPE RvcSampleGrabberCB::BufferCB(
- double SampleTime,
- BYTE *pBuffer,
- long BufferLen)
- {
- if (false== m_vcap->bloged){
- get_output_mediatype(m_vcap);
- m_vcap->bloged = true;
- }
- if ((m_vcap->iout_width > 3 * mode_width[m_vcap->param.cap_mode]) && (m_vcap->iout_height > 3* mode_height[m_vcap->param.cap_mode])) {
- return S_FALSE;
- }
- if (VIDEO_FORMAT_YUY2 == m_vcap->param.cap_frame_format){
- return Handle_YUY2_Frame_CallBack(m_vcap, pBuffer, BufferLen);
- }
- else if(VIDEO_FORMAT_RGB24 == m_vcap->param.cap_frame_format){
- return Handle_BGR_Frame_CallBack(m_vcap, pBuffer, BufferLen);
- }
- else{
- return S_FALSE;
- }
- }
- HRESULT STDMETHODCALLTYPE RvcSampleGrabberCB::QueryInterface(
- /* [in] */ REFIID riid,
- /* [iid_is][out] */ __RPC__deref_out void __RPC_FAR *__RPC_FAR *ppvObject)
- {
- if (ppvObject == NULL || *ppvObject == NULL)
- return E_POINTER;
- if (IsEqualIID(riid, IID_IUnknown)) {
- *ppvObject = (void*)this;
- return S_OK;
- } else if (IsEqualIID(riid, IID_ISampleGrabberCB)) {
- *ppvObject = (void*)this;
- return S_OK;
- }
- return E_NOTIMPL;
- }
- ULONG STDMETHODCALLTYPE RvcSampleGrabberCB::AddRef( void)
- {
- return 1;
- }
- ULONG STDMETHODCALLTYPE RvcSampleGrabberCB::Release( void)
- {
- delete this;
- return 0;
- }
- static HRESULT STDMETHODCALLTYPE QueryInterface(ISampleGrabberCB * This,
- REFIID riid,
- void** ppvObject)
- {
- if (This == NULL || ppvObject == NULL || *ppvObject == NULL)
- return E_POINTER;
- if (IsEqualIID(riid, IID_IUnknown)) {
- *ppvObject = (void*)This;
- return S_OK;
- } else if (IsEqualIID(riid, IID_ISampleGrabberCB)) {
- *ppvObject = (void*)This;
- return S_OK;
- }
- return E_NOTIMPL;
- }
- static ULONG STDMETHODCALLTYPE AddRef(ISampleGrabberCB * This)
- {
- return 1;
- }
- static ULONG STDMETHODCALLTYPE Release(ISampleGrabberCB * This)
- {
- free(This);
- return 0;
- }
- static HRESULT STDMETHODCALLTYPE SampleCB(ISampleGrabberCB * This, double SampleTime,IMediaSample *pSample)
- {
- return E_NOTIMPL;
- }
- static HRESULT STDMETHODCALLTYPE BufferCB(ISampleGrabberCB * This, double SampleTime,BYTE *pBuffer,long BufferLen)
- {
- ISampleGrabberCBImpl *pImpl = (ISampleGrabberCBImpl *)This;
- videocap *vcap = pImpl->vcap;
- int linesize = BufferLen / mode_height[vcap->param.cap_mode];
- struct SwsContext *sws;
- int ibitcount = vcap->param.cap_frame_format == VIDEO_FORMAT_RGB24 ? 3 : 2;
- char*Buffertmp=(char*)malloc(mode_width[vcap->param.cap_mode]*mode_height[vcap->param.cap_mode]*3);
- uint8_t *src_data[4];
- int src_linesize[4];
- unsigned char *dst[4] = {(unsigned char*)Buffertmp,NULL,NULL,NULL};
- int dst_linesize[4] = {mode_width[vcap->param.cap_mode]*3,0,0,0};
- char*buffer;
- int oriLen = mode_height[vcap->param.cap_mode]*mode_width[vcap->param.cap_mode]*3;
-
- if (false == vcap->bloged){
- get_output_mediatype(vcap);
- vcap->bloged = true;
- }
- if (BufferLen != oriLen)
- {
- //计算目标图像比例
- int srcH;
- float fDstScale = (float)mode_width[vcap->param.cap_mode]/(float)mode_height[vcap->param.cap_mode];
- float fSrcScale = (float)vcap->iout_width/(float)vcap->iout_height;
- if (fSrcScale != fDstScale)
- {
- //计算偏移量
- int nWidth,nHeight,nOffset=0;
- if (fSrcScale > fDstScale)
- {
- return 0;
- }
- else if (fSrcScale < fDstScale)
- {
- //高度过长
- nWidth = vcap->iout_width;
- nHeight = (int)ceil(vcap->iout_width/fDstScale);
- nOffset = (vcap->iout_height -nHeight)/2*nWidth*3;
- }
- //计算等比例变换需要的SWS
- sws=sws_getContext(nWidth,nHeight,AV_PIX_FMT_BGR24, mode_width[vcap->param.cap_mode], mode_height[vcap->param.cap_mode], AV_PIX_FMT_BGR24, SWS_BICUBIC, NULL, NULL, NULL);
- av_image_alloc(src_data, src_linesize, vcap->iout_width , vcap->iout_height, AV_PIX_FMT_BGR24, 1);
- memcpy(src_data[0],pBuffer+nOffset,nWidth*nHeight*3); //Y
- srcH = nHeight;
- }
- else
- {
- //计算等比例变换需要的SWS
- sws=sws_getContext(vcap->iout_width, vcap->iout_height,AV_PIX_FMT_BGR24, mode_width[vcap->param.cap_mode], mode_height[vcap->param.cap_mode], AV_PIX_FMT_BGR24, SWS_BICUBIC, NULL, NULL, NULL);
- av_image_alloc(src_data, src_linesize, vcap->iout_width, vcap->iout_height, AV_PIX_FMT_BGR24, 1);
- memcpy(src_data[0],pBuffer,BufferLen); //Y
- srcH = vcap->iout_height;
- }
- //分辨率转换
- sws_scale(sws, src_data, src_linesize, 0, srcH, dst, dst_linesize);
- sws_freeContext(sws);
- av_freep(&src_data[0]);
- buffer = Buffertmp;
- BufferLen = mode_width[vcap->param.cap_mode]*mode_height[vcap->param.cap_mode]*3;
- }
- else
- {
- buffer = (char*)pBuffer;
- }
- linesize = BufferLen / mode_height[vcap->param.cap_mode];
- if (vcap->param.option & VIDEOCAP_OPT_ENABLE_GRAB)
- {
- if (vcap->cap_index++%3 == 0)
- { /* 3 is grabbing interval */
- EnterCriticalSection(&vcap->cap_cs);
- //memcpy(vcap->cap_frame.data[0], pBuffer, BufferLen);
- memcpy(vcap->cap_frame.data[0], buffer, BufferLen);
- LeaveCriticalSection(&vcap->cap_cs);
- }
- }
- if (vcap->grab_cb_count)
- {
- if (vcap->param.on_grab)
- {
- video_frame frm = {0};
- frm.data[0] = (unsigned char*)buffer;
- frm.linesize[0] = linesize;
- frm.width = mode_width[vcap->param.cap_mode];
- frm.height = mode_height[vcap->param.cap_mode];
- frm.format = VIDEO_FORMAT_RGB24;
- vcap->param.on_grab(vcap->param.user_data, &frm);
- }
- InterlockedDecrement(&vcap->grab_cb_count);
- }
- if (vcap->param.option & VIDEOCAP_OPT_ENABLE_ASYNC_GRAB)
- {
- async_cap_t *pos, *n;
- EnterCriticalSection(&vcap->async_cap_cs);
- ListEntry_ForEachSafe(pos, n, &vcap->async_cap_list, async_cap_t, entry)
- {
- ListEntry_DeleteNode(&pos->entry);
- pos->result = 0;
- memcpy(pos->ref_cap_frame->data[0], buffer, BufferLen);
- SetEvent(pos->evt);
- }
- LeaveCriticalSection(&vcap->async_cap_cs);
- }
- if (vcap->param.on_frame_raw)
- {
- video_frame frm = {0};
- frm.data[0] = (unsigned char*)buffer;
- frm.linesize[0] = linesize;
- frm.width = mode_width[vcap->param.cap_mode];
- frm.height = mode_height[vcap->param.cap_mode];
- frm.format = VIDEO_FORMAT_RGB24;
- vcap->param.on_frame_raw(vcap->param.user_data, &frm);
- }
- if (vcap->param.option & VIDEOCAP_OPT_EANBLE_RESIZE)
- { /* user enable resizing */
- unsigned char *src_data[4];
- int src_linesize[4] = {linesize, 0, 0, 0};
- src_data[0] = (unsigned char*)buffer;
- src_data[1] = NULL;
- src_data[2] = NULL;
- src_data[3] = NULL;
- EnterCriticalSection(&vcap->res_cs);
- if (vcap->param.option & VIDEOCAP_OPT_ENABLE_FLIP)
- {
- src_data[0] += (mode_height[vcap->param.cap_mode]-1)*src_linesize[0];
- src_linesize[0] = -src_linesize[0];
- sws_scale(vcap->sws_context, src_data, src_linesize, 0, mode_height[vcap->param.cap_mode], vcap->res_frame.data, vcap->res_frame.linesize);
- }
- else
- {
- sws_scale(vcap->sws_context, src_data, src_linesize,
- 0, mode_height[vcap->param.cap_mode], vcap->res_frame.data, vcap->res_frame.linesize);
- }
- if (vcap->param.on_frame)
- {
- vcap->param.on_frame(vcap->param.user_data, &vcap->res_frame);
- }
- LeaveCriticalSection(&vcap->res_cs);
- }
- else
- {
- if (vcap->param.on_frame)
- {
- video_frame frame;
- memset(&frame, 0, sizeof(video_frame));
- frame.width = mode_width[vcap->param.cap_mode];
- frame.height = mode_height[vcap->param.cap_mode];
- frame.data[0] = (unsigned char*)buffer;
- frame.linesize[0] = linesize;
- frame.format = VIDEO_FORMAT_RGB24;
- vcap->param.on_frame(vcap->param.user_data, &frame);
- }
- }
- free(Buffertmp);
- return S_OK;
- }
- static HRESULT TryConnectFilters(IGraphBuilder *pGraphBuilder, int cnt, IBaseFilter *pFilters[])
- {
- HRESULT hr = S_OK;
- int i;
- if (!pGraphBuilder)
- return E_POINTER;
- if (cnt == 0)
- return S_OK;
- if (!pFilters)
- return E_POINTER;
- for (i = 1; i < cnt; ++i)
- {
- IBaseFilter *src = pFilters[i-1];
- IBaseFilter *dst = pFilters[i];
- if (!src || !dst)
- return E_POINTER;
- hr = ConnectFilters2(pGraphBuilder, src, dst);
-
- if (FAILED(hr))
- {
- return hr;
- }
- }
- return hr;
- }
- ////////////////////////////////////////////////////////////////////////////////////////////////
- /* used for device lost event listenning */
- static DWORD WINAPI BackgroundThread(LPVOID *param)
- {
- struct videocap *vcap = (struct videocap *)param;
- int quit = 0;
- HANDLE t;
- HANDLE evts[2] = {0};
- HANDLE hProcess = GetCurrentProcess();
- HRESULT hr;
- hr = vcap->me->GetEventHandle((OAEVENT*)&t);
- if (FAILED(hr))
- return 0;
- if (DuplicateHandle(hProcess, t, hProcess, &evts[0], DUPLICATE_SAME_ACCESS, FALSE, DUPLICATE_SAME_ACCESS) == FALSE)
- return 0;
- evts[1] = vcap->evt_thread_exit;
- while (!quit)
- {
- DWORD dwResult = WaitForMultipleObjects(2, evts, FALSE, INFINITE) - WAIT_OBJECT_0;
- if (0 == dwResult)
- {
- long lEventCode;
- LONG_PTR lParam1;
- LONG_PTR lParam2;
- vcap->me->GetEvent(&lEventCode, &lParam1, &lParam2, INFINITE);
- if (lEventCode == EC_DEVICE_LOST || lEventCode == EC_ERRORABORT)
- {
- if (vcap->param.on_device_lost)
- (*vcap->param.on_device_lost)(vcap->param.user_data);
- quit = 1;
- }
- vcap->me->FreeEventParams(lEventCode, lParam1, lParam2);
- }
- else
- {
- quit = 1;
- }
- }
- CloseHandle(evts[0]);
- return 0;
- }
- ////////////////////////////////////////////////////////////////////////////////////////////////
- int videocap_create(videocap_t *h ,videocap_param *param)
- {
- videocap *vcap;
- //capDbg(param,"videocap_create, fps = %f.", param->fps);
- /* check param */
- if (!param)
- return -1;
- if (param->cap_mode < 0 || param->cap_mode >= VIDEOCAP_MAX_MODE)
- return -1;
- if (param->frame_fmt != VIDEO_FORMAT_I420 && param->frame_fmt != VIDEO_FORMAT_RGB24)
- return -1;
- if (param->fps < 1.0 ||
- param->fps > 100.0)
- return -1;
- if (param->pre_hwnd)
- {
- if (!IsWindow(param->pre_hwnd))
- return -1;
- if (param->pre_width < 0)
- return -1;
- if (param->pre_height < 0)
- return -1;
- }
- if (param->dev_id < 0)
- return -1;
- if (param->frame_fmt == VIDEO_FORMAT_I420 && !(param->option&VIDEOCAP_OPT_EANBLE_RESIZE)) {
- param->res_mode = param->cap_mode;
- param->option |= VIDEOCAP_OPT_EANBLE_RESIZE;
- }
- if (param->option & VIDEOCAP_OPT_EANBLE_RESIZE) {
- if (param->res_mode < VIDEOCAP_FRAME_SQCIF || param->res_mode > VIDEOCAP_FRAME_SVGA)
- return -1;
- }
- vcap = (videocap*)malloc(sizeof(videocap));
- if (!vcap)
- return -1;
- ZeroMemory((void*)vcap, sizeof(videocap));
- memcpy(&vcap->param, param, sizeof(videocap_param));
- if (param->option & VIDEOCAP_OPT_ENABLE_GRAB) {
- int width = mode_width[param->cap_mode];
- int height = mode_height[param->cap_mode];
- if (video_frame_alloc(width, height, VIDEO_FORMAT_RGB24, &vcap->cap_frame) != 0) {
- free(vcap);
- return -1;
- }
- video_frame_fill_black(&vcap->cap_frame);
- InitializeCriticalSection(&vcap->cap_cs);
- }
- if (param->option & VIDEOCAP_OPT_ENABLE_ASYNC_GRAB) {
- InitializeCriticalSection(&vcap->async_cap_cs);
- }
- if (param->option & VIDEOCAP_OPT_EANBLE_RESIZE) {
- int width = mode_width[param->res_mode];
- int height = mode_height[param->res_mode];
- if (video_frame_alloc(width, height, param->frame_fmt, &vcap->res_frame) != 0) {
- if (param->option & VIDEOCAP_OPT_ENABLE_GRAB) {
- DeleteCriticalSection(&vcap->cap_cs);
- video_frame_free(&vcap->cap_frame);
- }
- free(vcap);
- return -1;
- }
- video_frame_fill_black(&vcap->res_frame);
- vcap->sws_context = sws_getContext(mode_width[param->cap_mode],
- mode_height[param->cap_mode],
- AV_PIX_FMT_BGR24,
- mode_width[param->res_mode],
- mode_height[param->res_mode],
- vcap->param.frame_fmt==VIDEO_FORMAT_RGB24 ? AV_PIX_FMT_BGR24 : AV_PIX_FMT_YUV420P,
- SWS_FAST_BILINEAR,
- NULL,
- NULL,
- NULL);
- if (!vcap->sws_context) {
- video_frame_free(&vcap->res_frame);
- if (param->option & VIDEOCAP_OPT_ENABLE_GRAB) {
- DeleteCriticalSection(&vcap->cap_cs);
- video_frame_free(&vcap->cap_frame);
- }
- free(vcap);
- return -1;
- }
- InitializeCriticalSection(&vcap->res_cs);
- }
- vcap->bloged = false;
- vcap->iout_width = mode_width[param->cap_mode];
- vcap->iout_height = mode_height[param->cap_mode];
- *h = vcap;
- return 0;
- }
- void videocap_destroy(videocap_t h)
- {
- if (h->param.option & VIDEOCAP_OPT_ENABLE_GRAB) {
- DeleteCriticalSection(&h->cap_cs);
- video_frame_free(&h->cap_frame);
- }
- if (h->param.option & VIDEOCAP_OPT_ENABLE_ASYNC_GRAB) {
- DeleteCriticalSection(&h->async_cap_cs);
- }
- if (h->param.option & VIDEOCAP_OPT_EANBLE_RESIZE) {
- sws_freeContext(h->sws_context);
- DeleteCriticalSection(&h->res_cs);
- video_frame_free(&h->res_frame);
- }
- free(h);
- }
- //100 to real brightness value
- static int transtorealbrightnessvalue(int ibright, int imaxbrightness, int iminbrightness)
- {
- float fvalue = ibright * (imaxbrightness - iminbrightness) / 10;
- int ivalue = fvalue;
- int ilast = ivalue % 10;
- int inum = ivalue / 10;
- if (ilast >= 5) {
- inum++;
- }
- inum += iminbrightness;
- if (inum < iminbrightness) {
- inum = iminbrightness;
- }
- if (inum > imaxbrightness) {
- inum = imaxbrightness;
- }
- return inum;
- }
- //real brightness value to [0-100]
- static int transfromrealbrightnessvalue(int ibright, int imaxbrightness, int iminbrightness)
- {
- int itotal = imaxbrightness - iminbrightness;
- int ivalue = ibright - iminbrightness;
- float fvalue = ivalue * 1000 / itotal;
- ivalue = fvalue;
- int ilast = ivalue % 10;
- int inum = ivalue / 10;
- if (ilast >= 5) {
- inum++;
- }
- return inum;
- }
- int videocap_adj_brightness(videocap_t h, int nValue)
- {
- if (NULL == h) {
- return S_FALSE;
- }
- IAMVideoProcAmp *pProcAmp = 0;
- HRESULT hr = h->sourcefilter->QueryInterface(IID_IAMVideoProcAmp, (void**)&pProcAmp);
- if(SUCCEEDED(hr))
- {
- long Min, Max, Step, Default, Flags, Val;
- // 亮度.
- if(( nValue >= 0 )&&(nValue <= 100 ))
- {
- hr = pProcAmp->GetRange(VideoProcAmp_Brightness, &Min, &Max, &Step,
- &Default, &Flags);
- if(SUCCEEDED(hr))
- {
- Flags = VideoProcAmp_Flags_Manual;
- hr = pProcAmp->Get(VideoProcAmp_Brightness, &Val, &Flags);
- Val = transtorealbrightnessvalue((int)nValue, (int)Max, (int)Min);
- hr = pProcAmp->Set(VideoProcAmp_Brightness, Val, Flags);
- }
- }
- }
- return hr;
- }
- int videocap_set_autobrightness(videocap_t h)
- {
- if (NULL == h) {
- return S_FALSE;
- }
- IAMVideoProcAmp *pProcAmp = 0;
- HRESULT hr = h->sourcefilter->QueryInterface(IID_IAMVideoProcAmp, (void**)&pProcAmp);
- if(SUCCEEDED(hr))
- {
- long Min, Max, Step, Default, Flags, Val;
- // 亮度.
- hr = pProcAmp->GetRange(VideoProcAmp_Brightness, &Min, &Max, &Step,
- &Default, &Flags);
- if(SUCCEEDED(hr))
- {
- Flags = VideoProcAmp_Flags_Auto;
- Val = Min + (Max-Min)/2;
- hr = pProcAmp->Set(VideoProcAmp_Brightness, Val, Flags);
- }
- }
- return hr;
- }
- int videocap_get_brightness(videocap_t h,int*nValue)
- {
- if (NULL == h) {
- return S_FALSE;
- }
- IAMVideoProcAmp *pProcAmp = 0;
- HRESULT hr = h->sourcefilter->QueryInterface(IID_IAMVideoProcAmp, (void**)&pProcAmp);
- if(SUCCEEDED(hr))
- {
- long Min, Max, Step, Default, Flags, Val;
- // 亮度.
- hr = pProcAmp->GetRange(VideoProcAmp_Brightness, &Min, &Max, &Step, &Default, &Flags);
- if(SUCCEEDED(hr))
- {
- hr = pProcAmp->Get(VideoProcAmp_Brightness, &Val, &Flags);
- *nValue = transfromrealbrightnessvalue((int)Val, (int)Max, (int)Min);
- }
- }
- return hr;
- }
- int videocap_start(videocap_t h)
- {
- HRESULT hr = S_OK;
- if (!h) {
- return VIDEOCAP_ERROR;
- }
-
- h->grab_cb_count = 0;
- ListEntry_InitHead(&h->async_cap_list);
- // create filter graph
- hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
- IID_IGraphBuilder, (void**)&h->graphbuilder);
- if (FAILED(hr)){
- capDbg(&h->param,"CoCreateInstance failed.");
- goto on_error;
- }
- //else{
- // capDbg(&h->param,"CoCreateInstance success, and fps = %f.", h->param.fps);
- //}
- hr = h->graphbuilder->QueryInterface(
- IID_IMediaControl, (void**)&h->mc);
- if (FAILED(hr)){
- capDbg(&h->param,"QueryInterface failed.");
- goto on_error;
- }
- hr = h->graphbuilder->QueryInterface(
- IID_IMediaEvent, (void**)&h->me);
- if (FAILED(hr)){
- capDbg(&h->param,"QueryInterface IID_IMediaEvent failed.");
- goto on_error;
- }
- #ifdef _DEBUG
- {
- IUnknown *pUnk;
- hr = h->graphbuilder->QueryInterface(
- IID_IUnknown, (void**)&pUnk);
- if (FAILED(hr)){
- goto on_error;
- }
- hr = AddToRot(pUnk, &h->dwROTRegister);
- pUnk->Release();
- if (FAILED(hr)){
- goto on_error;
- }
- }
- #endif
- /* create video source filter and add to graph */
- hr = CreateFilterByIndex(CLSID_VideoInputDeviceCategory,
- (void**)&h->sourcefilter, h->param.dev_id);
- if (FAILED(hr)){
- goto on_error;
- }
- hr = h->graphbuilder->AddFilter(h->sourcefilter, L"videosource");
- if (FAILED(hr)){
- goto on_error;
- }
- hr = set_video_source_format((videocap*)h);
- if (FAILED(hr)){
- goto on_error;
- }
- hr = CoCreateInstance(CLSID_Colour, NULL, CLSCTX_INPROC_SERVER,
- IID_IBaseFilter, (void**) &h->cpcfilter);
- if (FAILED(hr)){
- goto on_error;
- }
- hr = h->graphbuilder->AddFilter(h->cpcfilter, L"cpcfilter");
- if (FAILED(hr)){
- goto on_error;
- }
- hr = CoCreateInstance(CLSID_AVIDec, NULL, CLSCTX_INPROC_SERVER,
- IID_IBaseFilter, (void**) &h->avidecfilter);
- if (FAILED(hr)){
- goto on_error;
- }
- hr = h->graphbuilder->AddFilter(h->avidecfilter, L"avidecfilter");
- if (FAILED(hr)){
- goto on_error;
- }
- // create grabber filter and add to graph
- hr = CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER,
- IID_IBaseFilter, (void**) &h->grabberfilter);
- if (FAILED(hr)){
- goto on_error;
- }
- hr = h->graphbuilder->AddFilter(h->grabberfilter, L"grabber");
- if (FAILED(hr)){
- goto on_error;
- }
- hr = h->grabberfilter->QueryInterface(
- IID_ISampleGrabber, (void**)&h->grabber);
- if (FAILED(hr)){
- goto on_error;
- }
- {
- int ibitcount = 3;
- int width = mode_width[h->param.cap_mode];
- int height = mode_height[h->param.cap_mode];
- AM_MEDIA_TYPE *mt = (AM_MEDIA_TYPE*)CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE));
- VIDEOINFOHEADER *pvi = (VIDEOINFOHEADER*)CoTaskMemAlloc(sizeof(VIDEOINFOHEADER));
- if (VIDEO_FORMAT_YUY2 == h->param.cap_frame_format){
- ibitcount = 2;
- }
- memset(mt, 0, sizeof(AM_MEDIA_TYPE));
- memset(pvi, 0, sizeof(VIDEOINFOHEADER));
- mt->lSampleSize = width * height * ibitcount;
- mt->majortype = MEDIATYPE_Video;
- mt->subtype = MEDIASUBTYPE_RGB24;
- if (VIDEO_FORMAT_YUY2 == h->param.cap_frame_format){
- mt->subtype = MEDIASUBTYPE_YUY2;
- }
- mt->formattype = FORMAT_VideoInfo;
- mt->bFixedSizeSamples = TRUE;
- mt->bTemporalCompression = FALSE;
- mt->cbFormat = sizeof(VIDEOINFOHEADER);
- mt->pbFormat = (BYTE*)pvi;
- pvi->bmiHeader.biWidth = width;
- pvi->bmiHeader.biHeight = height;
- pvi->bmiHeader.biSizeImage = width * height * ibitcount;
- pvi->bmiHeader.biBitCount = ibitcount*8;
- pvi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
- pvi->AvgTimePerFrame = (REFERENCE_TIME)(10000000 / h->param.fps);
- pvi->dwBitRate = (DWORD)(width*height*ibitcount*8*h->param.fps);
- //capDbg(&h->param,"width = %d, height = %d, BitRate = %d, fps = %f.", width, height, pvi->dwBitRate, h->param.fps);
- hr = h->grabber->SetMediaType(mt);
- FreeMediaTypeEx(mt);
- if (FAILED(hr)){
- capDbg(&h->param,"SetMediaType error, err=0x%08x", hr);
- goto on_error;
- }
- }
- h->grabber->SetOneShot(FALSE);
- {
- ISampleGrabberCB *pImpl = new RvcSampleGrabberCB(h);
- if (!pImpl)
- goto on_error;
- // 0: SampleCB
- // 1: BufferCB
- h->grabber->SetCallback( pImpl, 1);////////////////////////
- }
- if (h->param.option & VIDEOCAP_OPT_HOZFLIP) {
- h->horflipfilter = (IBaseFilter*)videohorflip_create_filter();
- if (!h->horflipfilter){
- capDbg(&h->param,"videohorflip_create_filter error");
- goto on_error;
- }
- hr = h->graphbuilder->AddFilter(h->horflipfilter, L"horflip");
- if (FAILED(hr)){
- capDbg(&h->param,"AddFilter error, err=0x%08x", hr);
- goto on_error;
- }
- }
- // create render filter and add to graph
- {
- hr = CoCreateInstance(h->param.pre_hwnd ? CLSID_VideoRendererDefault : CLSID_NullRenderer,
- NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**) &h->renderfilter);
- if (FAILED(hr)){
- capDbg(&h->param,"CoCreateInstance error, err=0x%08x", hr);
- goto on_error;
- }
- }
- hr = h->graphbuilder->AddFilter(h->renderfilter, L"renderfilter");
- if (FAILED(hr)){
- capDbg(&h->param,"AddFilter error, err=0x%08x", hr);
- goto on_error;
- }
- // try connect filters
- if (!(h->param.option & VIDEOCAP_OPT_HOZFLIP)) {
- IBaseFilter *Filter1[] = {h->sourcefilter, h->grabberfilter, h->renderfilter};
- IBaseFilter *Filter2[] = {h->sourcefilter, h->cpcfilter, h->grabberfilter, h->renderfilter};
- IBaseFilter *Filter3[] = {h->sourcefilter, h->avidecfilter, h->grabberfilter, h->renderfilter};
- IBaseFilter *Filter4[] = {h->sourcefilter, h->avidecfilter, h->cpcfilter, h->grabberfilter, h->renderfilter};
- struct {
- int cnt;
- IBaseFilter **Filters;
- } tpl[] = {
- {ARRAYSIZE(Filter1), Filter1},
- {ARRAYSIZE(Filter2), Filter2},
- {ARRAYSIZE(Filter3), Filter3},
- {ARRAYSIZE(Filter4), Filter4},
- };
- int i;
- for (i = 0; i < ARRAYSIZE(tpl); ++i) {
- Sleep(50);
- hr = TryConnectFilters(h->graphbuilder, tpl[i].cnt, tpl[i].Filters);
- if (SUCCEEDED(hr)) {
- break;
- }
- }
- if (i == ARRAYSIZE(tpl)) {
- char strinfo[MAX_PATH] = { 0 };
- _snprintf(strinfo, MAX_PATH, "!(h->param.option & VIDEOCAP_OPT_HOZFLIP) TryConnectFilters failed and lResult = 0x%08x.", hr);
- capDbg(&h->param, strinfo);
- capLogEvent(&h->param, 2, strinfo);
- goto on_error;
- }
- }
- else {
- IBaseFilter *Filter1[] = {h->sourcefilter, h->grabberfilter, h->horflipfilter, h->renderfilter};
- IBaseFilter *Filter2[] = {h->sourcefilter, h->cpcfilter, h->grabberfilter, h->horflipfilter, h->renderfilter};
- IBaseFilter *Filter3[] = {h->sourcefilter, h->avidecfilter, h->grabberfilter, h->horflipfilter, h->renderfilter};
- IBaseFilter *Filter4[] = {h->sourcefilter, h->avidecfilter, h->cpcfilter, h->grabberfilter, h->horflipfilter, h->renderfilter};
- struct {
- int cnt;
- IBaseFilter **Filters;
- } tpl[] = {
- {ARRAYSIZE(Filter1), Filter1},
- {ARRAYSIZE(Filter2), Filter2},
- {ARRAYSIZE(Filter3), Filter3},
- {ARRAYSIZE(Filter4), Filter4},
- };
- int i;
- for (i = 0; i < ARRAYSIZE(tpl); ++i) {
- Sleep(50);
- hr = TryConnectFilters(h->graphbuilder, tpl[i].cnt, tpl[i].Filters);
- if (SUCCEEDED(hr)) {
- break;
- }
- }
- if (i == ARRAYSIZE(tpl)) {
- char strerror[MAX_PATH] = { 0 };
- _snprintf(strerror, MAX_PATH, "TryConnectFilters failed and lResult = 0x%08x.", hr);
- capDbg(&h->param, strerror);
- capLogEvent(&h->param, 2, strerror);
- goto on_error;
- }
- }
- if (h->param.pre_hwnd) {
- RECT rc;
- hr = h->renderfilter->QueryInterface(
- IID_IVideoWindow, (void**)&h->videowindow);
- if (FAILED(hr)){
- capDbg(&h->param,"renderfilter QueryInterface failed!");
- goto on_error;
- }
- GetClientRect(h->param.pre_hwnd, &rc);
- h->videowindow->put_Owner((OAHWND)h->param.pre_hwnd);
- h->videowindow->put_Visible(OAFALSE);
- h->videowindow->put_Left(0);
- h->videowindow->put_Top(0);
- h->videowindow->put_Height(min(h->param.pre_height, rc.bottom-rc.top));
- h->videowindow->put_Width(min(h->param.pre_width, rc.right - rc.left));
- h->videowindow->put_WindowStyle(
- WS_CHILD|WS_VISIBLE|WS_CLIPCHILDREN|WS_CLIPSIBLINGS);
- h->videowindow->put_MessageDrain((OAHWND)h->param.pre_hwnd);
- h->videowindow->put_Visible(OATRUE);
- }
- if (h->param.on_device_lost) {
- //h->thread_background = CreateThread(NULL, 0, &BackgroundThread, h, 0, 0);
- //h->evt_thread_exit = CreateEvent(NULL, FALSE, FALSE, NULL);
- }
- hr = h->mc->Run();
- if (FAILED(hr)){
- char strmsg[MAX_PATH] = {0};
- _snprintf(strmsg, MAX_PATH, "h->mc->Run() failed and lResult = 0x%08x.", hr);
- capDbg(&h->param, strmsg);
- capLogEvent(&h->param, 2, strmsg);
- goto on_error;
- }
- h->running = TRUE;
- return VIDEOCAP_OK;
- on_error:
- release_all_interfaces(h);
- return VIDEOCAP_ERROR;
- }
- int videocap_stop(videocap_t h)
- {
- long code;
-
- if (!h->running)
- return -1;
- if (h->param.on_device_lost) {
- SetEvent(h->evt_thread_exit);
- WaitForSingleObject(h->thread_background, INFINITE);
- CloseHandle(h->thread_background);
- h->thread_background = NULL;
- CloseHandle(h->evt_thread_exit);
- h->evt_thread_exit = NULL;
- }
- h->mc->Stop();
- h->me->WaitForCompletion(INFINITE, &code);
- h->running = 0;
- if (h->param.option & VIDEOCAP_OPT_ENABLE_ASYNC_GRAB) {
- EnterCriticalSection(&h->async_cap_cs);
- {
- async_cap_t *pos, *n;
- ListEntry_ForEachSafe(pos, n, &h->async_cap_list, async_cap_t, entry) {
- ListEntry_DeleteNode(&pos->entry);
- pos->result = -1; // cancel
- SetEvent(pos->evt);
- }
- }
- LeaveCriticalSection(&h->async_cap_cs);
- }
- #ifdef _DEBUG
- RemoveFromRot(h->dwROTRegister);
- h->dwROTRegister = 0;
- #endif
- release_all_interfaces(h);
- return VIDEOCAP_OK;
- }
- int videocap_grab(videocap_t h, video_frame *frame)
- {
- int ret;
- if (!h)
- return -1;
- if (!h->running)
- return -1;
- if (!(h->param.option & VIDEOCAP_OPT_ENABLE_GRAB)) /* initialize without grabbing option */
- return -1;
- EnterCriticalSection(&h->cap_cs);
- ret = video_frame_copy(frame, &h->cap_frame);
- LeaveCriticalSection(&h->cap_cs);
- return ret;
- }
- int videocap_async_grab(videocap_t h, video_frame *frame)
- {
- async_cap_t *ac;
- if (!h)
- return -1;
- if (!h->running)
- return -1;
- if (!(h->param.option & VIDEOCAP_OPT_ENABLE_ASYNC_GRAB)) /* initialize without grabbing option */
- return -1;
- ac = (async_cap_t*)malloc(sizeof(async_cap_t));
- ac->evt = CreateEvent(NULL, FALSE, FALSE, NULL);
- ac->ref_cap_frame = frame;
- EnterCriticalSection(&h->async_cap_cs);
- ListEntry_AddTail(&h->async_cap_list, &ac->entry);
- LeaveCriticalSection(&h->async_cap_cs);
- WaitForSingleObject(ac->evt, INFINITE);
- CloseHandle(ac->evt);
- free(ac);
- return 0;
- }
- int videocap_incrment_grab_cb(videocap_t h)
- {
- if (!h)
- return -1;
- if (!h->running)
- return -1;
- InterlockedIncrement(&h->grab_cb_count);
- return 0;
- }
- int videocap_get_frame(videocap_t h, video_frame *frame)
- {
- int ret;
- if (!h)
- return -1;
- if (!(h->param.option & VIDEOCAP_OPT_EANBLE_RESIZE))
- return -1;
- if (!h->running)
- return -1;
- EnterCriticalSection(&h->res_cs);
- ret = video_frame_copy(frame, &h->res_frame);
- LeaveCriticalSection(&h->res_cs);
- return ret;
- }
- int videocap_is_running(videocap_t h, BOOL *state)
- {
- if (!h)
- return VIDEOCAP_ERROR;
- return h->running;
- }
- int videocap_set_preview_wnd_visible(videocap_t h, BOOL visible)
- {
- if (!h || !h->videowindow)
- return VIDEOCAP_ERROR;
- h->videowindow->put_Visible(
- visible ? OATRUE : OAFALSE);
- return VIDEOCAP_OK;
- }
- int videocap_get_preview_wnd_visible(videocap_t h, BOOL *visible)
- {
- long l = OAFALSE;
- if (!h || !h->videowindow)
- return VIDEOCAP_ERROR;
- h->videowindow->get_Visible(&l);
- *visible = l ? TRUE : FALSE;
- return VIDEOCAP_OK;
- }
- int videocap_set_preview_wnd_width(videocap_t h, int width)
- {
- if (!h)
- return -1;
- if (!h->param.pre_hwnd)
- return -1;
- h->videowindow->put_Width(width);
- return 0;
- }
- int videocap_set_preview_wnd_height(videocap_t h, int height)
- {
- if (!h)
- return -1;
- if (!h->param.pre_hwnd)
- return -1;
- h->videowindow->put_Height(height);
- return 0;
- }
- static HRESULT set_video_source_format(videocap *vcap)
- {
- HRESULT hr;
- IAMStreamConfig *config;
- ICaptureGraphBuilder2 *capturebuilder;
- VIDEOINFOHEADER *pvi;
- int i, count, size = 0;
- BOOL alreadyset = FALSE;
- // create capture builder
- hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC_SERVER,
- IID_ICaptureGraphBuilder2, (void**)&capturebuilder);
- if (FAILED(hr))
- return hr;
- hr = capturebuilder->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, vcap->sourcefilter,
- IID_IAMStreamConfig, (void**)&config);
- if (FAILED(hr))
- return hr;
- config->GetNumberOfCapabilities(&count, &size);
- if (size == sizeof(VIDEO_STREAM_CONFIG_CAPS)) {
- int width = mode_width[vcap->param.cap_mode];
- int height = mode_height[vcap->param.cap_mode];
- for (i = 0; i < count && !alreadyset; ++i)
- {
- VIDEO_STREAM_CONFIG_CAPS scc;
- AM_MEDIA_TYPE *pmtConfig;
- hr = config->GetStreamCaps(i, &pmtConfig, (BYTE*)&scc);
- if (FAILED(hr))
- continue;
- if (IsEqualIID(pmtConfig->majortype, MEDIATYPE_Video) &&
- IsEqualIID(pmtConfig->formattype, FORMAT_VideoInfo) &&
- (pmtConfig->cbFormat >= sizeof(VIDEOINFOHEADER)) &&
- pmtConfig->pbFormat != NULL
- )
- {
- if (vcap->param.cap_frame_format == VIDEO_FORMAT_YUY2){
- if (!IsEqualIID(pmtConfig->subtype, MEDIASUBTYPE_YUY2)){
- continue;
- }
- }
- pvi = (VIDEOINFOHEADER*)pmtConfig->pbFormat;
- if (pvi->bmiHeader.biWidth == width && pvi->bmiHeader.biHeight == height)
- {
- pvi->AvgTimePerFrame = (REFERENCE_TIME)(10000000 / vcap->param.fps);
- hr = config->SetFormat(pmtConfig);
- if (SUCCEEDED(hr))
- {
- char *subtype_str=GuidToString(pmtConfig->subtype);
- //char strmsg[MAX_PATH] = {0};
- //_snprintf(strmsg, MAX_PATH,"[{32595559-0000-0010-8000-00AA00389B71->MEDIASUBTYPE_YUY2},{e436eb7d-524f-11ce-9f53-0020af0ba770->MEDIASUBTYPE_RGB24}]match video format is %s, width is %d, height is %d.", subtype_str, pvi->bmiHeader.biWidth, pvi->bmiHeader.biHeight);
- //capLogEvent(&vcap->param, 0, strmsg);
- free(subtype_str);
- alreadyset = TRUE;
- }
- else
- {
- alreadyset = FALSE;
- }
- }
- }
- FreeMediaTypeEx(pmtConfig);
- }
- }
- config->Release();
- capturebuilder->Release();
- return hr;
- }
- HRESULT get_output_mediatype(videocap *vcap)
- {
- AM_MEDIA_TYPE mt;
- HRESULT hr;
- VIDEOINFOHEADER *videoHeader = NULL;
- ZeroMemory(&mt, sizeof(AM_MEDIA_TYPE));
- hr = vcap->grabber->GetConnectedMediaType(&mt);
- if(FAILED(hr))
- {
- capDbg(&vcap->param,"GetConnectedMediaType Failed, hr=0x%08x!",hr);
- return hr;
- }
-
- videoHeader = (VIDEOINFOHEADER*)(mt.pbFormat);
- vcap->iout_width = videoHeader->bmiHeader.biWidth;
- vcap->iout_height = videoHeader->bmiHeader.biHeight;
- if ((mode_width[vcap->param.cap_mode] != videoHeader->bmiHeader.biWidth) || (mode_height[vcap->param.cap_mode] != videoHeader->bmiHeader.biHeight)) {
- char* subtype_str = NULL;
- char strmsg[MAX_PATH * 2] = { 0 };
- subtype_str = GuidToString(mt.subtype);
- _snprintf(strmsg, MAX_PATH * 2, "grabber Format Width=%d, Height=%d, biBitCount=%d, biSizeImage=%d, biCompression=%d, biPlanes=%d, biSize=%d, subtype=%s, newPmt->lSampleSize=%d, newPmt->bFixedSizeSamples=%d, newPmt->bTemporalCompression=%d",
- videoHeader->bmiHeader.biWidth,
- videoHeader->bmiHeader.biHeight,
- videoHeader->bmiHeader.biBitCount,
- videoHeader->bmiHeader.biSizeImage,
- videoHeader->bmiHeader.biCompression,
- videoHeader->bmiHeader.biPlanes,
- videoHeader->bmiHeader.biSize,
- subtype_str,
- mt.lSampleSize,
- mt.bFixedSizeSamples,
- mt.bTemporalCompression);
- capLogEvent(&vcap->param, 1, strmsg);
- if ((mode_width[vcap->param.cap_mode] != videoHeader->bmiHeader.biWidth) && (mode_height[vcap->param.cap_mode] != videoHeader->bmiHeader.biHeight)) {
- capLogEvent(&vcap->param, 3, strmsg);
- }
- }
-
- return S_OK;
- }
- static void release_all_interfaces(videocap *h)
- {
- if (h->mc) {
- h->mc->Release();
- h->mc = NULL;
- }
- if (h->me) {
- h->me->Release();
- h->me = NULL;
- }
- if (h->videowindow) {
- h->videowindow->put_Owner((OAHWND)NULL);
- h->videowindow->Release();
- h->videowindow = NULL;
- }
- if (h->graphbuilder) {
- RemoveGraphAllFilters(h->graphbuilder);
- h->graphbuilder->Release();
- h->graphbuilder = NULL;
- }
- if (h->sourcefilter) {
- h->sourcefilter->Release();
- h->sourcefilter = NULL;
- }
- if (h->avidecfilter) {
- h->avidecfilter->Release();
- h->avidecfilter = NULL;
- }
- if (h->cpcfilter) {
- h->cpcfilter->Release();
- h->cpcfilter = NULL;
- }
- if (h->grabber) {
- h->grabber->Release();
- h->grabber = NULL;
- }
- if (h->grabberfilter) {
- h->grabberfilter->Release();
- h->grabberfilter = NULL;
- }
- if (h->horflipfilter) {
- h->horflipfilter->Release();
- h->horflipfilter = NULL;
- }
- if (h->renderfilter) {
- h->renderfilter->Release();
- h->renderfilter = NULL;
- }
- }
- ////////////////////////////////////////////////////////////
- static HRESULT get_device_count_cb(int index, IMoniker *pMoniker, void *pUserData1, void *pUserData2)
- {
- if (pMoniker)
- ++*(int*)pUserData1;
- return S_FALSE;
- }
- int videocap_get_device_count()
- {
- int count = 0;
- HRESULT hr = WalkFilterCategory(CLSID_VideoInputDeviceCategory,
- &get_device_count_cb, &count, NULL);
- return SUCCEEDED(hr) ? count : 0;
- }
- struct _buf {
- WCHAR *buf;
- int len;
- };
- static HRESULT get_device_name_cb(int index, IMoniker *pMoniker, void *pUserData1, void *pUserData2)
- {
- if (pMoniker) {
- int *p_id = (int*)pUserData1;
- struct _buf *buf = (struct _buf*)pUserData2;
- HRESULT hr;
- if (index == *p_id) {
- IPropertyBag *pPropBag;
- VARIANT name;
- hr = pMoniker->BindToStorage(NULL, NULL,
- IID_IPropertyBag, (void**)&pPropBag);
- if (FAILED(hr)) {
- buf->len = -1; /* failed */
- return hr;
- }
- VariantInit(&name);
- name.vt = VT_BSTR;
- hr = pPropBag->Read(L"FriendlyName", &name, NULL);
- if (FAILED(hr)) {
- pPropBag->Release();
- VariantClear(&name);
- buf->len = -1;
- return hr;
- }
- buf->len = SysStringByteLen(name.bstrVal) + 2;
- if (buf)
- memcpy(buf->buf, name.bstrVal, buf->len);
- pPropBag->Release();
- VariantClear(&name);
- return S_OK;
- }
- }
- return S_FALSE;
- }
- int videocap_get_device_name(int device_id, WCHAR *buf, int len)
- {
- struct _buf x = {buf, len};
- int dev_id = device_id;
- HRESULT hr = WalkFilterCategory(CLSID_VideoInputDeviceCategory,
- &get_device_name_cb, &dev_id, &x);
- if (hr == S_OK)
- return x.len;
- return -1;
- }
- static HRESULT get_device_path_cb(int index, IMoniker *pMoniker, void *pUserData1, void *pUserData2)
- {
- if (pMoniker) {
- int *p_id = (int*)pUserData1;
- struct _buf *buf = (struct _buf*)pUserData2;
- HRESULT hr;
- if (index == *p_id) {
- IPropertyBag *pPropBag;
- VARIANT path;
- hr = pMoniker->BindToStorage(NULL, NULL,
- IID_IPropertyBag, (void**)&pPropBag);
- if (FAILED(hr)) {
- buf->len = -1; /* failed */
- return hr;
- }
- VariantInit(&path);
- path.vt = VT_BSTR;
- hr = pPropBag->Read(L"DevicePath", &path, NULL);
- if (FAILED(hr)) {
- pPropBag->Release();
- VariantClear(&path);
- buf->len = -1;
- return hr;
- }
- buf->len = SysStringByteLen(path.bstrVal) + 2;
- if (buf)
- memcpy(buf->buf, path.bstrVal, buf->len);
- pPropBag->Release();
- VariantClear(&path);
- return S_OK;
- }
- }
- return S_FALSE;
- }
- int videocap_get_device_path(int device_id, WCHAR *buf, int len)
- {
- struct _buf x = {buf, len};
- int dev_id = device_id;
- HRESULT hr = WalkFilterCategory(CLSID_VideoInputDeviceCategory,
- &get_device_path_cb, &dev_id, &x);
- if (hr == S_OK)
- return x.len;
- return -1;
- }
- static HRESULT get_device_instanceid_cb(int index, IMoniker* pMoniker, void* pUserData1, void* pUserData2)
- {
- if (pMoniker) {
- int* p_id = (int*)pUserData1;
- struct _buf* buf = (struct _buf*)pUserData2;
- HRESULT hr;
- if (index == *p_id) {
- IPropertyBag* pPropBag;
- VARIANT path;
- hr = pMoniker->BindToStorage(NULL, NULL,
- IID_IPropertyBag, (void**)&pPropBag);
- if (FAILED(hr)) {
- buf->len = -1; /* failed */
- return hr;
- }
- VariantInit(&path);
- path.vt = VT_BSTR;
- hr = pPropBag->Read(L"InstanceId", &path, NULL);
- if (FAILED(hr)) {
- pPropBag->Release();
- VariantClear(&path);
- buf->len = -1;
- return hr;
- }
- buf->len = SysStringByteLen(path.bstrVal) + 2;
- if (buf)
- memcpy(buf->buf, path.bstrVal, buf->len);
- pPropBag->Release();
- VariantClear(&path);
- return S_OK;
- }
- }
- return S_FALSE;
- }
- int videocap_get_device_instanceid(int device_id, WCHAR* buf, int len)
- {
- struct _buf x = { buf, len };
- int dev_id = device_id;
- HRESULT hr = WalkFilterCategory(CLSID_VideoInputDeviceCategory,
- &get_device_instanceid_cb, &dev_id, &x);
- if (hr == S_OK)
- return x.len;
- return -1;
- }
- static int is_support(int min, int max, int granularity, int x)
- {
- if (x < min || x > max)
- return 0;
- if (x == min || x == max)
- return 1;
- if (granularity == 0)
- return 0;
- if ((x-min)/granularity*granularity != (x-min))
- return 0;
- if ((max-x)/granularity*granularity != (max-x))
- return 0;
- return 1;
- }
- static int is_support_size(VIDEO_STREAM_CONFIG_CAPS *pscc, int width, int height)
- {
- return is_support(pscc->MinOutputSize.cx, pscc->MaxOutputSize.cx, pscc->OutputGranularityX, width) &&
- is_support(pscc->MinOutputSize.cy, pscc->MaxOutputSize.cy, pscc->OutputGranularityY, height);
- }
- int videocap_get_device_cap(int device_id, videocap_device_cap *cap)
- {
- int error = -1, i, count, size = 0, j;
- HRESULT hr;
- ICaptureGraphBuilder2 *pBuilder = NULL;
- IBaseFilter *pSourceFilter = NULL;
- IAMStreamConfig *config = NULL;
- videocap_device_cap tmp_cap = {0};
- if (!cap)
- return error;
- hr = CreateFilterByIndex(CLSID_VideoInputDeviceCategory, (void**)&pSourceFilter, device_id);
- if (FAILED(hr))
- return error;
- hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC_SERVER,
- IID_ICaptureGraphBuilder2, (void**)&pBuilder);
- if (FAILED(hr))
- return error;
- ZeroMemory(cap, sizeof(videocap_device_cap));
- hr = pBuilder->FindInterface( &PIN_CATEGORY_CAPTURE,
- &MEDIATYPE_Video, pSourceFilter, IID_IAMStreamConfig, (void**)&config);
- if (FAILED(hr))
- goto on_error;
- config->GetNumberOfCapabilities( &count, &size);
- if (size == sizeof(VIDEO_STREAM_CONFIG_CAPS)) {
- for (i = 0; i < count; ++i) {
- VIDEO_STREAM_CONFIG_CAPS scc;
- AM_MEDIA_TYPE *pmtConfig;
- VIDEOINFOHEADER *pvi = NULL;
- hr = config->GetStreamCaps(i, &pmtConfig, (BYTE*)&scc);
- if (FAILED(hr))
- continue;
- if (IsEqualIID(pmtConfig->majortype, MEDIATYPE_Video) &&
- IsEqualIID(pmtConfig->formattype, FORMAT_VideoInfo) &&
- (pmtConfig->cbFormat >= sizeof(VIDEOINFOHEADER)) &&
- pmtConfig->pbFormat != NULL) {
- if (IsEqualIID(pmtConfig->subtype, MEDIASUBTYPE_RGB24)) {
- for (j = 0; j < VIDEOCAP_MAX_MODE; ++j) {
- if (is_support_size(&scc, mode_width[j], mode_height[j])) {
- tmp_cap.mode[j] = 1;
- tmp_cap.min_frame_interval[j] = (int)scc.MinFrameInterval;
- tmp_cap.max_frame_interval[j] = (int)scc.MaxFrameInterval;
- }
- }
- }
- }
- FreeMediaTypeEx(pmtConfig);
- }
- }
- config->Release();
- for (i = 0, j = 0; i < VIDEOCAP_MAX_MODE; ++i) {
- if (tmp_cap.mode[i]) {
- cap->mode[j] = i;
- cap->min_frame_interval[j] = cap->min_frame_interval[i];
- cap->max_frame_interval[j] = cap->max_frame_interval[i];
- j++;
- }
- }
- cap->mode_cnt = j;
- error = 0;
- on_error:
- if (pBuilder)
- pBuilder->Release();
- if (pSourceFilter)
- pSourceFilter->Release();
- return error;
- }
- int videocap_get_mode_width(int mode)
- {
- return mode_width[mode];
- }
- int videocap_get_mode_height(int mode)
- {
- return mode_height[mode];
- }
|