⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 winvideods.c

📁 基于osip、eXosip、speex、ffmpeg的VoIP源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	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);
	hr=CoCreateInstance (CLSID_NullRenderer,
                          NULL,
                          CLSCTX_INPROC_SERVER,
                          IID_IBaseFilter,
                          (void **)&s->m_pNullRenderer);
	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(&pPinCategory,
		&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;
	}
	memset(s->nowebcamimage, 0, sizeof(s->nowebcamimage));
	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_pGraph!=NULL)
		{
			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);
		}

		if (s->m_pNullRenderer)
			s->m_pNullRenderer->Release();
		if (s->m_pIDXFilter)
			s->m_pIDXFilter->Release();
		if (s->m_pDeviceFilter)
			s->m_pDeviceFilter->Release();

		if (s->m_pBuilder)
			s->m_pBuilder->Release();
		if (s->m_pControl)
			s->m_pControl->Release();
		if (s->m_pGraph)
			s->m_pGraph->Release();

		if (s->m_pDXFilter!=NULL)
			s->m_pDXFilter->Release();

		s->m_pNullRenderer=NULL;
		s->m_pIDXFilter=NULL;
		s->m_pDeviceFilter=NULL;
		s->m_pBuilder=NULL;
		s->m_pControl=NULL;
		s->m_pGraph=NULL;
		s->m_pDXFilter=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_pGraph!=NULL)
		{
			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);
		}

		if (s->m_pNullRenderer)
			s->m_pNullRenderer->Release();
		if (s->m_pIDXFilter)
			s->m_pIDXFilter->Release();
		if (s->m_pDeviceFilter)
			s->m_pDeviceFilter->Release();

		if (s->m_pBuilder)
			s->m_pBuilder->Release();
		if (s->m_pControl)
			s->m_pControl->Release();
		if (s->m_pGraph)
			s->m_pGraph->Release();

		if (s->m_pDXFilter!=NULL)
			s->m_pDXFilter->Release();

		s->m_pNullRenderer=NULL;
		s->m_pIDXFilter=NULL;
		s->m_pDeviceFilter=NULL;
		s->m_pBuilder=NULL;
		s->m_pControl=NULL;
		s->m_pGraph=NULL;
		s->m_pDXFilter=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_pGraph!=NULL)
		{
			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);
		}

		if (s->m_pNullRenderer)
			s->m_pNullRenderer->Release();
		if (s->m_pIDXFilter)
			s->m_pIDXFilter->Release();
		if (s->m_pDeviceFilter)
			s->m_pDeviceFilter->Release();

		if (s->m_pBuilder)
			s->m_pBuilder->Release();
		if (s->m_pControl)
			s->m_pControl->Release();
		if (s->m_pGraph)
			s->m_pGraph->Release();

		if (s->m_pDXFilter!=NULL)
			s->m_pDXFilter->Release();

		s->m_pNullRenderer=NULL;
		s->m_pIDXFilter=NULL;
		s->m_pDeviceFilter=NULL;
		s->m_pBuilder=NULL;
		s->m_pControl=NULL;
		s->m_pGraph=NULL;
		s->m_pDXFilter=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 && s->nowebcamimage[0] != '\0')
	  {
	    s->mire[0] = ms_load_jpeg_as_yuv(s->nowebcamimage,&s->vsize);
	  }
	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;
	s->start_time=0;
	s->frame_count=-1;
	flushq(&s->rq,0);
}

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);
				mblk_set_precious_flag(om,1);
			}
		}
		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);
	s->frame_count=-1; /* reset counter used for fps */
	return 0;
}


static int v4w_set_pix_fmt(MSFilter *f,void *arg){
	V4wState *s=(V4wState*)f->data;
  s->pix_fmt=*((MSPixFmt*)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 int v4w_set_image(MSFilter *f, void *arg){
	int idx;
	V4wState *s=(V4wState*)f->data;
	char *image = (char *)arg;
	ms_mutex_lock(&s->mutex);
	if (image!=NULL && image[0]!='\0')
	  snprintf(s->nowebcamimage, sizeof(s->nowebcamimage), "%s", image);
	else
	  s->nowebcamimage[0] = '\0';
	for (idx=0;idx<10;idx++)
	{
		if (s->mire[idx]==NULL)
			break;
		freemsg(s->mire[idx]);
		s->mire[idx]=NULL;
	}
	s->frame_ind=0;
	ms_mutex_unlock(&s->mutex);
	return 0;
}

static MSFilterMethod methods[]={
	{	MS_FILTER_SET_FPS	,	v4w_set_fps	},
	{	MS_FILTER_SET_PIX_FMT	,	v4w_set_pix_fmt	},
	{	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		},
	{       MS_V4L_SET_IMAGE        ,       v4w_set_image           },
	{	0								,	NULL			}
};

#ifdef _MSC_VER

MSFilterDesc 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
};

#else

MSFilterDesc 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
};

#endif

MS_FILTER_DESC_EXPORT(ms_v4w_desc)

static MSFilter *vfw_create_reader(MSWebCam *obj){
	return ms_filter_new_from_desc(&ms_v4w_desc);
}

static void vfw_detect(MSWebCamManager *obj);

static void vfw_cam_init(MSWebCam *cam){
	cam->name=ms_strdup("dx0");
}

MSWebCamDesc ms_v4w_cam_desc={
	"DirectX Video Grabber",
	&vfw_detect,
	&vfw_cam_init,
	&vfw_create_reader,
	NULL
};

static void vfw_detect(MSWebCamManager *obj){
	MSWebCam *cam=ms_web_cam_new(&ms_v4w_cam_desc);
	ms_web_cam_manager_add_cam(obj,cam);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -