📄 winvideods.c
字号:
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 + -