📄 wincevideods.c
字号:
//hr = s->m_pBuilder->RenderStream(&PIN_CATEGORY_CAPTURE, // &MEDIATYPE_Video, s->m_pDeviceFilter, s->m_pIDXFilter, s->m_pNullRenderer); if (FAILED(hr)) { return -14; } } //m_pDXFilter->SetBufferSamples(TRUE); // Create the System Device Enumerator.IFilterMapper *pMapper = NULL;//IEnumMoniker *pEnum = NULL;IEnumRegFilters *pEnum = NULL;hr = CoCreateInstance(CLSID_FilterMapper, NULL, CLSCTX_INPROC, IID_IFilterMapper, (void **) &pMapper);if (FAILED(hr)){ // Error handling omitted for clarity.}GUID arrayInTypes[2];arrayInTypes[0] = MEDIATYPE_Video;arrayInTypes[1] = MEDIASUBTYPE_dvsd;hr = pMapper->EnumMatchingFilters( &pEnum, MERIT_HW_COMPRESSOR, // Minimum merit. FALSE, // At least one input pin? MEDIATYPE_NULL, MEDIASUBTYPE_NULL, FALSE, // Must be a renderer? FALSE, // At least one output pin? MEDIATYPE_NULL, MEDIASUBTYPE_NULL); // Enumerate the monikers.//IMoniker *pMoniker;REGFILTER *pMoniker;ULONG cFetched;while (pEnum->Next(1, &pMoniker, &cFetched) == S_OK){ IPropertyBag *pPropBag = NULL;#if 0 hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pPropBag); if (SUCCEEDED(hr)) { // To retrieve the friendly name of the filter, do the following: VARIANT varName; VariantInit(&varName); hr = pPropBag->Read(L"FriendlyName", &varName, 0); if (SUCCEEDED(hr)) { // Display the name in your UI somehow. } VariantClear(&varName); // To create an instance of the filter, do the following: IBaseFilter *pFilter; hr = pMoniker->BindToObject(NULL, NULL, IID_IBaseFilter, (void**)&pFilter); // Now add the filter to the graph. Remember to release pFilter later. // Clean up. pPropBag->Release(); } pMoniker->Release();#endif}// Clean up.pMapper->Release();pEnum->Release(); s_callback = s; hr = s->m_pControl->Run(); if(FAILED(hr)) { return -15; } s->rotregvalue=1; s->pix_fmt = format; s->vsize.height = vsize->height; s->vsize.width = vsize->width; return 0;}static void v4w_init(MSFilter *f){ V4wState *s=(V4wState *)ms_new0(V4wState,1); int idx; 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 try_format(V4wState *s, int format, MSVideoSize *vsize){ int i = v4w_open_videodevice(s, format, vsize); if (i==-14) { 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(); } return i;}static int _v4w_start(V4wState *s, void *arg){ MSVideoSize try_vsize; int tryformat; int i; s->frame_count=-1; if (s->pix_fmt==MS_YUV420P) tryformat = MS_RGB24; else if (s->pix_fmt==MS_RGB24) tryformat = MS_YUV420P; try_vsize.height = s->vsize.height; try_vsize.width = s->vsize.width; i = try_format(s, s->pix_fmt, &try_vsize); if (i==-14) { /* try second format with same size */ i = try_format(s, tryformat, &try_vsize); } /* try both format with CIF size */ if (i==-14 && s->vsize.height!=MS_VIDEO_SIZE_CIF_H) { try_vsize.height = MS_VIDEO_SIZE_CIF_H; try_vsize.width = MS_VIDEO_SIZE_CIF_W; i = try_format(s, s->pix_fmt, &try_vsize); if (i==-14) { i = try_format(s, tryformat, &try_vsize); } } if (i==-14 && s->vsize.height!=MS_VIDEO_SIZE_QCIF_H) { try_vsize.height = MS_VIDEO_SIZE_QCIF_H; try_vsize.width = MS_VIDEO_SIZE_QCIF_W; i = try_format(s, s->pix_fmt, &try_vsize); if (i==-14) { i = try_format(s, tryformat, &try_vsize); } } if (i==-14 && s->vsize.height!=MS_VIDEO_SIZE_VGA_H) { try_vsize.height = MS_VIDEO_SIZE_VGA_H; try_vsize.width = MS_VIDEO_SIZE_VGA_W; i = try_format(s, s->pix_fmt, &try_vsize); if (i==-14) { i = try_format(s, tryformat, &try_vsize); } } if (i==-14 && s->vsize.height!=MS_VIDEO_SIZE_QVGA_H) { try_vsize.height = MS_VIDEO_SIZE_QVGA_H; try_vsize.width = MS_VIDEO_SIZE_QVGA_W; i = try_format(s, s->pix_fmt, &try_vsize); if (i==-14) { i = try_format(s, tryformat, &try_vsize); } } if (i==0) { if (s->pix_fmt==MS_YUV420P) ms_message("Using YUV420P"); else if (s->pix_fmt==MS_RGB24) ms_message("Using RGB24"); } 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; } 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 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 }, { 0 , NULL }};#ifdef _MSC_VERMSFilterDesc ms_v4w_desc={ MS_V4L_ID, "MSV4w", N_("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=N_("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 + -