📄 winvideods.c
字号:
m = (GUID)FOURCCMap(MAKEFOURCC('I','4','2','0')); else if (s->pix_fmt == MS_YUY2) m = MEDIASUBTYPE_YUY2; else if (s->pix_fmt == MS_YUYV) m = MEDIASUBTYPE_YUYV; else if (s->pix_fmt == MS_UYVY) m = MEDIASUBTYPE_UYVY; else if (s->pix_fmt == MS_RGB24) m = MEDIASUBTYPE_RGB24; mt.SetSubtype(&m); mt.formattype = FORMAT_VideoInfo; mt.SetTemporalCompression(FALSE); VIDEOINFO *pvi = (VIDEOINFO *) mt.AllocFormatBuffer(sizeof(VIDEOINFO)); if (NULL == pvi) return -11; ZeroMemory(pvi, sizeof(VIDEOINFO)); if (s->pix_fmt == MS_YUV420P) pvi->bmiHeader.biCompression = MAKEFOURCC('I','4','2','0'); else if (s->pix_fmt == MS_YUY2) pvi->bmiHeader.biCompression = MAKEFOURCC('Y','U','Y','2'); else if (s->pix_fmt == MS_YUYV) pvi->bmiHeader.biCompression = MAKEFOURCC('Y','U','Y','V'); else if (s->pix_fmt == MS_UYVY) pvi->bmiHeader.biCompression = MAKEFOURCC('U','Y','V','Y'); else if (s->pix_fmt == MS_RGB24) pvi->bmiHeader.biCompression = BI_RGB; if (s->pix_fmt == MS_YUV420P) pvi->bmiHeader.biBitCount = 12; else if (s->pix_fmt == MS_YUY2) pvi->bmiHeader.biBitCount = 16; else if (s->pix_fmt == MS_YUYV) pvi->bmiHeader.biBitCount = 16; else if (s->pix_fmt == MS_UYVY) pvi->bmiHeader.biBitCount = 16; else if (s->pix_fmt == MS_RGB24) pvi->bmiHeader.biBitCount = 24; pvi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); pvi->bmiHeader.biWidth = s->vsize.width; pvi->bmiHeader.biHeight = s->vsize.height; pvi->bmiHeader.biPlanes = 1; pvi->bmiHeader.biSizeImage = GetBitmapSize(&pvi->bmiHeader); pvi->bmiHeader.biClrImportant = 0; mt.SetSampleSize(pvi->bmiHeader.biSizeImage); mt.SetFormat((BYTE*)pvi, sizeof(VIDEOINFO)); hr = s->m_pDXFilter->SetAcceptedMediaType(&mt); if(FAILED(hr)) { return -12; } hr = s->m_pDXFilter->SetCallback(Callback); if(FAILED(hr)) { return -13; } hr = s->m_pDXFilter->QueryInterface(IID_IBaseFilter, (LPVOID *)&s->m_pIDXFilter); if(FAILED(hr)) { return -14; } hr = s->m_pGraph->AddFilter(s->m_pIDXFilter, L"DXFilter Filter"); if(FAILED(hr)) { return -15; } // get null renderer hr=s->m_pNullRenderer.CoCreateInstance(CLSID_NullRenderer); if(FAILED(hr)) { return -16; } if (s->m_pNullRenderer!=NULL) { s->m_pGraph->AddFilter(s->m_pNullRenderer, L"Null Renderer"); } hr = s->m_pBuilder->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video, s->m_pDeviceFilter, s->m_pIDXFilter, s->m_pNullRenderer); if (FAILED(hr)) { //hr = s->m_pBuilder->RenderStream(&PIN_CATEGORY_CAPTURE, // &MEDIATYPE_Video, s->m_pDeviceFilter, s->m_pIDXFilter, s->m_pNullRenderer); if (FAILED(hr)) { return -17; } } //m_pDXFilter->SetBufferSamples(TRUE); s_callback = s; hr = s->m_pControl->Run(); if(FAILED(hr)) { return -18; } s->rotregvalue=1; return 0;}/****************************************************************************FUNCTION: AddGraphToRot.DESCRIPTION: Adds a DirectShow filter graph to the Running Object Table, allowing GraphEdit to "spy" on a remote filter graph.PARAMETERS:RETURNS: . 0 for success, otherwise an error #. . Standard COM/HRESULT error numbers are returned if a COM/HRESULT error was encountered.****************************************************************************/HRESULT AddGraphToRot(IUnknown *pUnkGraph, DWORD *pdwRegister){ IMoniker * pMoniker; IRunningObjectTable *pROT; WCHAR wsz[128]; HRESULT hr; if (FAILED(GetRunningObjectTable(0, &pROT))) return E_FAIL; wsprintfW(wsz, L"FilterGraph %08x pid %08x", (DWORD_PTR)pUnkGraph, GetCurrentProcessId()); wsprintfW(wsz, L"FilterGraph %08x pid %08x", (DWORD_PTR)pUnkGraph, GetCurrentProcessId()); hr = CreateItemMoniker(L"!", wsz, &pMoniker); if (SUCCEEDED(hr)) { hr = pROT->Register(0, pUnkGraph, pMoniker, pdwRegister); pMoniker->Release(); } pROT->Release(); return hr;}/****************************************************************************FUNCTION: RemoveGraphFromRot.DESCRIPTION: Removes a filter graph from the Running Object Table.PARAMETERS:****************************************************************************/void RemoveGraphFromRot(DWORD pdwRegister){ IRunningObjectTable *pROT; if (SUCCEEDED(GetRunningObjectTable(0, &pROT))) { pROT->Revoke(pdwRegister); pROT->Release(); }}static void v4w_init(MSFilter *f){ V4wState *s=(V4wState *)ms_new0(V4wState,1); int idx; s->devidx=0; s->vsize.width=MS_VIDEO_SIZE_CIF_W; s->vsize.height=MS_VIDEO_SIZE_CIF_H; //s->pix_fmt=MS_RGB24; s->pix_fmt=MS_YUV420P; s->rotregvalue = 0; s->m_pGraph=NULL; s->m_pBuilder=NULL; s->m_pControl=NULL; s->m_pDXFilter=NULL; s->m_pIDXFilter=NULL; s->m_pDeviceFilter=NULL; qinit(&s->rq); for (idx=0;idx<10;idx++) { s->mire[idx]=NULL; } ms_mutex_init(&s->mutex,NULL); s->start_time=0; s->frame_count=-1; s->fps=15; f->data=s;}static int _v4w_start(V4wState *s, void *arg){ int i; s->frame_count=-1; i = v4w_open_videodevice(s); if (s->rotregvalue==0){ //RemoveGraphFromRot(s->rotregvalue); if (s->m_pNullRenderer!=NULL) s->m_pGraph->RemoveFilter(s->m_pNullRenderer); if (s->m_pIDXFilter!=NULL) s->m_pGraph->RemoveFilter(s->m_pIDXFilter); if (s->m_pDeviceFilter!=NULL) s->m_pGraph->RemoveFilter(s->m_pDeviceFilter); s->m_pBuilder=NULL; s->m_pControl=NULL; s->m_pIDXFilter=NULL; if (s->m_pDXFilter!=NULL) s->m_pDXFilter->Release(); s->m_pDXFilter=NULL; s->m_pGraph=NULL; s->m_pNullRenderer=NULL; s->m_pDeviceFilter=NULL; CoUninitialize(); s_callback = NULL; flushq(&s->rq,0); ms_message("v4w: graph not started (err=%i)", i); s->rotregvalue=0; s->pix_fmt = MS_YUV420P; } return i;}static int _v4w_stop(V4wState *s, void *arg){ s->frame_count=-1; if (s->rotregvalue>0){ HRESULT hr = s->m_pControl->Stop(); if(FAILED(hr)) { ms_message("v4w: could not stop graph"); } if (s->m_pNullRenderer!=NULL) s->m_pGraph->RemoveFilter(s->m_pNullRenderer); if (s->m_pIDXFilter!=NULL) s->m_pGraph->RemoveFilter(s->m_pIDXFilter); if (s->m_pDeviceFilter!=NULL) s->m_pGraph->RemoveFilter(s->m_pDeviceFilter); //RemoveGraphFromRot(s->rotregvalue); s->m_pBuilder=NULL; s->m_pControl=NULL; s->m_pIDXFilter=NULL; if (s->m_pDXFilter!=NULL) s->m_pDXFilter->Release(); s->m_pDXFilter=NULL; s->m_pGraph=NULL; s->m_pNullRenderer=NULL; s->m_pDeviceFilter=NULL; CoUninitialize(); s_callback = NULL; flushq(&s->rq,0); ms_message("v4w: graph destroyed"); s->rotregvalue=0; } return 0;}static int v4w_start(MSFilter *f, void *arg){ V4wState *s=(V4wState*)f->data; _v4w_start(s, NULL); return 0;}static int v4w_stop(MSFilter *f, void *arg){ V4wState *s=(V4wState*)f->data; _v4w_stop(s, NULL); return 0;}static void v4w_uninit(MSFilter *f){ V4wState *s=(V4wState*)f->data; int idx; flushq(&s->rq,0); ms_mutex_destroy(&s->mutex); for (idx=0;idx<10;idx++) { if (s->mire[idx]==NULL) break; freemsg(s->mire[idx]); } if (s->rotregvalue>0){ HRESULT hr = s->m_pControl->Stop(); if(FAILED(hr)) { ms_message("v4w: could not stop graph"); } if (s->m_pNullRenderer!=NULL) s->m_pGraph->RemoveFilter(s->m_pNullRenderer); if (s->m_pIDXFilter!=NULL) s->m_pGraph->RemoveFilter(s->m_pIDXFilter); if (s->m_pDeviceFilter!=NULL) s->m_pGraph->RemoveFilter(s->m_pDeviceFilter); //RemoveGraphFromRot(s->rotregvalue); s->m_pBuilder=NULL; s->m_pControl=NULL; s->m_pIDXFilter=NULL; if (s->m_pDXFilter!=NULL) s->m_pDXFilter->Release(); s->m_pDXFilter=NULL; s->m_pGraph=NULL; s->m_pNullRenderer=NULL; s->m_pDeviceFilter=NULL; CoUninitialize(); s_callback = NULL; flushq(&s->rq,0); ms_message("v4w: graph destroyed"); s->rotregvalue=0; } ms_free(s);}static mblk_t * v4w_make_nowebcam(V4wState *s){#if defined(_WIN32_WCE) return NULL;#else int idx; int count; if (s->mire[0]==NULL && s->frame_ind==0){ /* load several images to fake a movie */ for (idx=0;idx<10;idx++) { s->mire[idx]=ms_load_nowebcam(&s->vsize, idx); if (s->mire[idx]==NULL) break; } if (idx==0) s->mire[0]=ms_load_nowebcam(&s->vsize, -1); } for (count=0;count<10;count++) { if (s->mire[count]==NULL) break; } s->frame_ind++; if (count==0) return NULL; idx = s->frame_ind%count; if (s->mire[idx]!=NULL) return s->mire[idx]; return s->mire[0];#endif}static void v4w_preprocess(MSFilter * obj){ V4wState *s=(V4wState*)obj->data; s->running=TRUE; if (s->rotregvalue==0) s->fps=1;}static void v4w_postprocess(MSFilter * obj){ V4wState *s=(V4wState*)obj->data; s->running=FALSE;}static void v4w_process(MSFilter * obj){ V4wState *s=(V4wState*)obj->data; mblk_t *m; uint32_t timestamp; int cur_frame; if (s->frame_count==-1){ s->start_time=obj->ticker->time; s->frame_count=0; } cur_frame=((obj->ticker->time-s->start_time)*s->fps/1000.0); if (cur_frame>s->frame_count){ mblk_t *om=NULL; ms_mutex_lock(&s->mutex); /*keep the most recent frame if several frames have been captured */ if (s->rotregvalue!=0){ while((m=getq(&s->rq))!=NULL){ if (om!=NULL) freemsg(om); om=m; } }else { mblk_t *nowebcam = v4w_make_nowebcam(s); if (nowebcam!=NULL) om=dupmsg(nowebcam); } ms_mutex_unlock(&s->mutex); if (om!=NULL){ timestamp=obj->ticker->time*90;/* rtp uses a 90000 Hz clockrate for video*/ mblk_set_timestamp_info(om,timestamp); ms_queue_put(obj->outputs[0],om); /*ms_message("picture sent");*/ } s->frame_count++; }}static int v4w_set_fps(MSFilter *f, void *arg){ V4wState *s=(V4wState*)f->data; s->fps=*((float*)arg); return 0;}static int v4w_get_pix_fmt(MSFilter *f,void *arg){ V4wState *s=(V4wState*)f->data; *((MSPixFmt*)arg) = (MSPixFmt)s->pix_fmt; return 0;}static int v4w_set_vsize(MSFilter *f, void *arg){ V4wState *s=(V4wState*)f->data; s->vsize=*((MSVideoSize*)arg); return 0;}static int v4w_get_vsize(MSFilter *f, void *arg){ V4wState *s=(V4wState*)f->data; MSVideoSize *vs=(MSVideoSize*)arg; vs->width=s->vsize.width; vs->height=s->vsize.height; return 0;}static int v4w_set_device(MSFilter *f, void *arg){ V4wState *s=(V4wState*)f->data; s->devidx=*((int*)arg); return 0;}static MSFilterMethod methods[]={ { MS_FILTER_SET_FPS , v4w_set_fps }, { MS_FILTER_GET_PIX_FMT , v4w_get_pix_fmt }, { MS_FILTER_SET_VIDEO_SIZE, v4w_set_vsize }, { MS_FILTER_GET_VIDEO_SIZE, v4w_get_vsize }, { MS_V4L_START , v4w_start }, { MS_V4L_STOP , v4w_stop }, { MS_V4L_SET_DEVICE , v4w_set_device }, { 0 , NULL }};#ifdef _MSC_VERMSFilterDesc ms_v4w_desc={ MS_V4L_ID, "MSV4w", "A video4windows compatible source filter to stream pictures.", MS_FILTER_OTHER, NULL, 0, 1, v4w_init, v4w_preprocess, v4w_process, v4w_postprocess, v4w_uninit, methods};#elseMSFilterDesc ms_v4w_desc={ .id=MS_V4L_ID, .name="MSV4w", .text="A video4windows compatible source filter to stream pictures.", .ninputs=0, .noutputs=1, .category=MS_FILTER_OTHER, .init=v4w_init, .preprocess=v4w_preprocess, .process=v4w_process, .postprocess=v4w_postprocess, .uninit=v4w_uninit, .methods=methods};#endifMS_FILTER_DESC_EXPORT(ms_v4w_desc)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -