📄 winvideods.c
字号:
/*mediastreamer2 library - modular sound and video processing and streamingCopyright (C) 2006 Simon MORLAT (simon.morlat@linphone.org)This program is free software; you can redistribute it and/ormodify it under the terms of the GNU General Public Licenseas published by the Free Software Foundation; either version 2of 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 ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.*/#define UNICODE#define AYMERIC_TEST#define _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA#include "mediastreamer2/msvideo.h"#include "mediastreamer2/msticker.h"#include "mediastreamer2/msv4l.h"#include "nowebcam.h"#include <ffmpeg/avcodec.h>#include <dshow.h>#include <dmodshow.h>#include <dmoreg.h>#include <streams.h>#include <initguid.h>#include "dxfilter.h"#include <qedit.h>#include <atlbase.h>#include <atlcom.h>HRESULT AddGraphToRot(IUnknown *pUnkGraph, DWORD *pdwRegister);void RemoveGraphFromRot(DWORD pdwRegister);typedef struct V4wState{ char dev[512]; int devidx; CComPtr<IGraphBuilder> m_pGraph; CComPtr<ICaptureGraphBuilder2> m_pBuilder; CComPtr<IMediaControl> m_pControl; CDXFilter *m_pDXFilter; CComPtr<IBaseFilter> m_pIDXFilter; CComPtr<IBaseFilter> m_pNullRenderer; CComPtr<IBaseFilter> m_pDeviceFilter; DWORD rotregvalue; MSVideoSize vsize; int pix_fmt; mblk_t *mire[10]; queue_t rq; ms_mutex_t mutex; int frame_ind; int frame_max; float fps; float start_time; int frame_count; bool_t running;}V4wState;static V4wState *s_callback=NULL;static void dummy(void*p){}HRESULT ( Callback)(IMediaSample* pSample, REFERENCE_TIME* sTime, REFERENCE_TIME* eTime, BOOL changed){ BYTE *byte_buf=NULL; mblk_t *buf; V4wState *s = s_callback; if (s==NULL) return S_OK; HRESULT hr = pSample->GetPointer(&byte_buf); if (FAILED(hr)) { return S_OK; } int size = pSample->GetActualDataLength(); if (size>+1000) { buf=allocb(size,0); memcpy(buf->b_wptr, byte_buf, size); if (s->pix_fmt==MS_RGB24) { /* Conversion from top down bottom up (BGR to RGB and flip) */ unsigned long Index,nPixels; unsigned char *blue; unsigned char tmp; short iPixelSize; blue=buf->b_wptr; nPixels=s->vsize.width*s->vsize.height; iPixelSize=24/8; for(Index=0;Index!=nPixels;Index++) // For each pixel { tmp=*blue; *blue=*(blue+2); *(blue+2)=tmp; blue+=iPixelSize; } unsigned char *pLine1, *pLine2; int iLineLen,iIndex; iLineLen=s->vsize.width*iPixelSize; pLine1=buf->b_wptr; pLine2=&(buf->b_wptr)[iLineLen * (s->vsize.height - 1)]; for( ;pLine1<pLine2;pLine2-=(iLineLen*2)) { for(iIndex=0;iIndex!=iLineLen;pLine1++,pLine2++,iIndex++) { tmp=*pLine1; *pLine1=*pLine2; *pLine2=tmp; } } } buf->b_wptr+=size; ms_mutex_lock(&s->mutex); putq(&s->rq, buf); ms_mutex_unlock(&s->mutex); } return S_OK;}int try_format(V4wState *s, int format){ HRESULT hr=S_OK; IEnumPins *pEnum=0; ULONG ulFound; IPin *pPin; GUID guid_format; DWORD biCompression; DWORD biBitCount; // Verify input if (!s->m_pDeviceFilter) return -1; if (format == MS_YUV420P) guid_format = (GUID)FOURCCMap(MAKEFOURCC('I','4','2','0')); else if (format == MS_YUYV) guid_format = MEDIASUBTYPE_YUYV; else if (format == MS_UYVY) guid_format = MEDIASUBTYPE_UYVY; else if (format == MS_RGB24) guid_format = MEDIASUBTYPE_RGB24; else if (format == MS_YUY2) guid_format = MEDIASUBTYPE_YUY2; if (format == MS_YUV420P) biCompression = MAKEFOURCC('I','4','2','0'); else if (format == MS_YUYV) biCompression = MAKEFOURCC('Y','U','Y','V'); else if (format == MS_UYVY) biCompression = MAKEFOURCC('U','Y','V','Y'); else if (format == MS_RGB24) biCompression = BI_RGB; else if (format == MS_YUY2) biCompression = MAKEFOURCC('Y','U','Y','2'); if (format == MS_YUV420P) biBitCount = 12; else if (format == MS_YUYV) biBitCount = 16; else if (format == MS_UYVY) biBitCount = 16; else if (format == MS_RGB24) biBitCount = 24; else if (format == MS_YUY2) biBitCount = 16; // Get pin enumerator hr = s->m_pDeviceFilter->EnumPins(&pEnum); if(FAILED(hr)) return -1; pEnum->Reset(); // Count every pin on the filter while(S_OK == pEnum->Next(1, &pPin, &ulFound)) { PIN_DIRECTION pindir = (PIN_DIRECTION) 3; hr = pPin->QueryDirection(&pindir); if(pindir != PINDIR_INPUT) { IEnumMediaTypes *ppEnum; ULONG ulFound2; hr = pPin->EnumMediaTypes(&ppEnum); if(FAILED(hr)) continue; AM_MEDIA_TYPE *ppMediaTypes; while(S_OK == ppEnum->Next(1, &ppMediaTypes, &ulFound2)) { if (ppMediaTypes->formattype != FORMAT_VideoInfo) continue; if (ppMediaTypes->majortype != MEDIATYPE_Video) continue; if (ppMediaTypes->subtype != guid_format) continue; VIDEOINFO *pvi = (VIDEOINFO *)ppMediaTypes->pbFormat; if (pvi->bmiHeader.biCompression!=biCompression) continue; if (pvi->bmiHeader.biBitCount!=biBitCount) continue; pPin->Release(); pEnum->Release(); return 0; } } pPin->Release(); } pEnum->Release(); return -1;}int try_format_size(V4wState *s, int format, int width, int height){ HRESULT hr=S_OK; IEnumPins *pEnum=0; ULONG ulFound; IPin *pPin; GUID guid_format; DWORD biCompression; DWORD biBitCount; // Verify input if (!s->m_pDeviceFilter) return -1; if (format == MS_YUV420P) guid_format = (GUID)FOURCCMap(MAKEFOURCC('I','4','2','0')); else if (format == MS_YUYV) guid_format = MEDIASUBTYPE_YUYV; else if (format == MS_UYVY) guid_format = MEDIASUBTYPE_UYVY; else if (format == MS_RGB24) guid_format = MEDIASUBTYPE_RGB24; else if (format == MS_YUY2) guid_format = MEDIASUBTYPE_YUY2; if (format == MS_YUV420P) biCompression = MAKEFOURCC('I','4','2','0'); else if (format == MS_YUYV) biCompression = MAKEFOURCC('Y','U','Y','V'); else if (format == MS_UYVY) biCompression = MAKEFOURCC('U','Y','V','Y'); else if (format == MS_RGB24) biCompression = BI_RGB; else if (format == MS_YUY2) biCompression = MAKEFOURCC('Y','U','Y','2'); if (format == MS_YUV420P) biBitCount = 12; else if (format == MS_YUYV) biBitCount = 16; else if (format == MS_UYVY) biBitCount = 16; else if (format == MS_RGB24) biBitCount = 24; else if (format == MS_YUY2) biBitCount = 16; // Get pin enumerator hr = s->m_pDeviceFilter->EnumPins(&pEnum); if(FAILED(hr)) return -1; pEnum->Reset(); // Count every pin on the filter while(S_OK == pEnum->Next(1, &pPin, &ulFound)) { PIN_DIRECTION pindir = (PIN_DIRECTION) 3; hr = pPin->QueryDirection(&pindir); if(pindir != PINDIR_INPUT) { IEnumMediaTypes *ppEnum; ULONG ulFound2; hr = pPin->EnumMediaTypes(&ppEnum); if(FAILED(hr)) continue; AM_MEDIA_TYPE *ppMediaTypes; while(S_OK == ppEnum->Next(1, &ppMediaTypes, &ulFound2)) { if (ppMediaTypes->formattype != FORMAT_VideoInfo) continue; if (ppMediaTypes->majortype != MEDIATYPE_Video) continue; if (ppMediaTypes->subtype != guid_format) continue; VIDEOINFO *pvi = (VIDEOINFO *)ppMediaTypes->pbFormat; if (pvi->bmiHeader.biCompression!=biCompression) continue; if (pvi->bmiHeader.biBitCount!=biBitCount) continue; if (pvi->bmiHeader.biHeight!=height) continue; if (pvi->bmiHeader.biWidth!=width) continue; s->vsize.width = width; s->vsize.height = height; pPin->Release(); pEnum->Release(); return 0; } } pPin->Release(); } pEnum->Release(); return -1;}static int v4w_open_videodevice(V4wState *s){ // Initialize COM CoInitialize(NULL); // get a Graph HRESULT hr=s->m_pGraph.CoCreateInstance(CLSID_FilterGraph); if(FAILED(hr)) { return -1; } // get a CaptureGraphBuilder2 hr=s->m_pBuilder.CoCreateInstance(CLSID_CaptureGraphBuilder2); if(FAILED(hr)) { return -2; } // connect capture graph builder with the graph s->m_pBuilder->SetFiltergraph(s->m_pGraph); // get mediacontrol so we can start and stop the filter graph hr=s->m_pGraph.QueryInterface(&(s->m_pControl)); if(FAILED(hr)) { return -3; }#ifdef _DEBUG HANDLE m_hLogFile=CreateFile(L"DShowGraphLog.txt",GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ,NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL); if(m_hLogFile!=INVALID_HANDLE_VALUE) { hr=s->m_pGraph->SetLogFile((DWORD_PTR)m_hLogFile); /* ASSERT(SUCCEEDED(hr)); */ } //AddGraphToRot(s->m_pGraph, &s->rotregvalue);#endif ICreateDevEnum *pCreateDevEnum = NULL; IEnumMoniker *pEnumMoniker = NULL; IMoniker *pMoniker = NULL; ULONG nFetched = 0; hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (PVOID *)&pCreateDevEnum); if(FAILED(hr)) { return -4; } hr = pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnumMoniker, 0); if (FAILED(hr) || pEnumMoniker == NULL) { //printf("no device\n"); return -5; } pEnumMoniker->Reset(); int pos=0; while(S_OK == pEnumMoniker->Next(1, &pMoniker, &nFetched) ) { if (pos>=s->devidx) break; pos++; pMoniker->Release(); pMoniker=NULL; } if(pMoniker==NULL) { return -6; } hr = pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&s->m_pDeviceFilter ); if(FAILED(hr)) { return -7; } s->m_pGraph->AddFilter(s->m_pDeviceFilter, L"Device Filter"); pMoniker->Release(); pEnumMoniker->Release(); pCreateDevEnum->Release(); if (try_format(s, s->pix_fmt)==0) s->pix_fmt = s->pix_fmt; else if (try_format(s,MS_YUV420P)==0) s->pix_fmt = MS_YUV420P; else if (try_format(s,MS_YUY2)==0) s->pix_fmt = MS_YUY2; else if (try_format(s,MS_YUYV)==0) s->pix_fmt = MS_YUYV; else if (try_format(s,MS_UYVY)==0) s->pix_fmt = MS_UYVY; else if (try_format(s,MS_RGB24)==0) s->pix_fmt = MS_RGB24; else { ms_error("Unsupported video pixel format."); return -8; } if (s->pix_fmt == MS_YUV420P) ms_message("Driver supports YUV420P, using that format."); else if (s->pix_fmt == MS_YUY2) ms_message("Driver supports YUY2 (UYVY), using that format."); else if (s->pix_fmt == MS_YUYV) ms_message("Driver supports YUV422, using that format."); else if (s->pix_fmt == MS_UYVY) ms_message("Driver supports UYVY, using that format."); else if (s->pix_fmt == MS_RGB24) ms_message("Driver supports RGB24, using that format."); if (try_format_size(s, s->pix_fmt, s->vsize.width, s->vsize.height)==0) ms_message("Selected Size: %ix%i.", s->vsize.width, s->vsize.height); else if (try_format_size(s, s->pix_fmt, MS_VIDEO_SIZE_QCIF_W, MS_VIDEO_SIZE_QCIF_H)==0) ms_message("Selected Size: %ix%i.", MS_VIDEO_SIZE_QCIF_W, MS_VIDEO_SIZE_QCIF_H); else if (try_format_size(s, s->pix_fmt, MS_VIDEO_SIZE_CIF_W, MS_VIDEO_SIZE_CIF_H)==0) ms_message("Selected Size: %ix%i.", MS_VIDEO_SIZE_CIF_W, MS_VIDEO_SIZE_CIF_H); else if (try_format_size(s, s->pix_fmt, MS_VIDEO_SIZE_4CIF_W, MS_VIDEO_SIZE_4CIF_H)==0) ms_message("Selected Size: %ix%i.", MS_VIDEO_SIZE_4CIF_W, MS_VIDEO_SIZE_4CIF_H); else if (try_format_size(s, s->pix_fmt, MS_VIDEO_SIZE_VGA_W, MS_VIDEO_SIZE_VGA_H)==0) ms_message("Selected Size: %ix%i.", MS_VIDEO_SIZE_VGA_W, MS_VIDEO_SIZE_VGA_H); else if (try_format_size(s, s->pix_fmt, MS_VIDEO_SIZE_QVGA_W, MS_VIDEO_SIZE_QVGA_H)==0) ms_message("Selected Size: %ix%i.", MS_VIDEO_SIZE_QVGA_W, MS_VIDEO_SIZE_QVGA_H); else { ms_error("No supported size found for format."); /* size not supported? */ return -9; } // get DXFilter s->m_pDXFilter = new CDXFilter(NULL, &hr, FALSE); if(s->m_pDXFilter==NULL) { return -10; } s->m_pDXFilter->AddRef(); CMediaType mt; mt.SetType(&MEDIATYPE_Video); GUID m = MEDIASUBTYPE_RGB24; if (s->pix_fmt == MS_YUV420P)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -