GUID videoInputCamera::getMediaSubtype(int type) { int iCount = 0; int iSize = 0; HRESULT hr = pStreamConfig->GetNumberOfCapabilities(&iCount, &iSize); if (iSize == sizeof(VIDEO_STREAM_CONFIG_CAPS)) { GUID lastFormat = MEDIASUBTYPE_None; for (int iFormat = 0; iFormat < iCount; iFormat+=2) { VIDEO_STREAM_CONFIG_CAPS scc; AM_MEDIA_TYPE *pmtConfig; hr = pStreamConfig->GetStreamCaps(iFormat, &pmtConfig, (BYTE*)&scc); if (SUCCEEDED(hr)){ if ( pmtConfig->subtype != lastFormat) { if (type == getMediaSubtype(pmtConfig->subtype)) { GUID mediaSubtype = pmtConfig->subtype; deleteMediaType(pmtConfig); return mediaSubtype; } lastFormat = pmtConfig->subtype; } deleteMediaType(pmtConfig); } } } return MEDIASUBTYPE_NULL; }
bool VideoCaptureDirectShow2::setDeviceFilterMediaType(ICaptureGraphBuilder2* captureBuilder, IBaseFilter* deviceFilter, AVCapability cap) { if(!captureBuilder) { RX_ERROR("Cannot set device filter media type because the given ICaptureGraphBuilder* is invalid"); return false; } if(!deviceFilter) { RX_ERROR("Cannot set the media type for the device filter because the device filter is invalid"); return false; } if(cap.index < 0) { RX_ERROR("Cannot set the media type for the device filter because the given AVCapability has not index. Iterate over the stream caps to retrieve the caps index that we need"); return false; } IAMStreamConfig* conf = NULL; HRESULT hr = captureBuilder->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, deviceFilter, IID_IAMStreamConfig, (void**)&conf); if(FAILED(hr)) { RX_ERROR("Failed to retrieve a IAMStreamConfig to set the device filter media type"); return false; } bool result = true; AM_MEDIA_TYPE* mt; VIDEO_STREAM_CONFIG_CAPS caps; hr = conf->GetStreamCaps(cap.index, &mt, (BYTE*)&caps); if(FAILED(hr)) { RX_ERROR("Failed to retrieve the AM_MEDIA_TYPE for the AVCapabiltiy with stream caps index: %d", cap.index); result = false; goto done; } if(mt->majortype != MEDIATYPE_Video) { RX_ERROR("The AM_MEDIA_TYPE we found is not an Video type so we cannot use it to set the media format of the device filter"); result = false; goto done; } if(mt->formattype != FORMAT_VideoInfo) { RX_ERROR("The AM_MEDIA_TYPE we found is not a Format_VideoInfo, so cannot set media type of device filter"); result = false; goto done; } if(mt->cbFormat < sizeof(VIDEOINFOHEADER)) { RX_ERROR("The AMD_MEDIA_TYPE has an invalid cbFormat size"); result = false; goto done; } if(mt->pbFormat == NULL) { RX_ERROR("The AM_MEDIA_TYPE.pbFormat is NULL; cannot set type of device filter"); result = false; goto done; } GUID guid_pixfmt = libavPixelFormatToMediaSubTypeGUID(cap.pixel_format); if(mt->subtype != guid_pixfmt) { RX_ERROR("The AM_MEDIA_TYPE.subtype is not the same as the one we want.."); result = false; goto done; } hr = conf->SetFormat(mt); if(FAILED(hr)) { RX_ERROR("Failed to set the AM_MEDIA_TYPE for the device filter"); result = false; goto done; } done: deleteMediaType(mt); safeReleaseDirectShow(&conf); return result; }
// Capabilities // -------------------------------------------------------------------------------------- std::vector<AVCapability> VideoCaptureDirectShow2::getCapabilities(int device) { std::vector<AVCapability> result; IAMStreamConfig* cap_stream_config = NULL; IGraphBuilder* cap_graph_builder = NULL; ICaptureGraphBuilder2* cap_capture_graph_builder = NULL; IBaseFilter* cap_device_filter = NULL; // Create a IGraphBuilder for the device if(!initCaptureGraphBuilderForDevice(device, &cap_device_filter, &cap_graph_builder, &cap_capture_graph_builder)) { RX_ERROR("Cannot setup the IGraphBuilder/ICaptureGraphBuilder/IBaseFilter (device)"); goto done; } // Get the StreamConfig object for the capture device filter which contains info on this device if(!createStreamConfig(cap_capture_graph_builder, cap_device_filter, &cap_stream_config)) { RX_ERROR("Cannot create the IAMStreamConfig to query capabilities"); goto done; } int count = 0; int size = 0; HRESULT hr = cap_stream_config->GetNumberOfCapabilities(&count, &size); if(SUCCEEDED(hr)) { for(int i = 0; i < count; ++i) { VIDEO_STREAM_CONFIG_CAPS caps; AM_MEDIA_TYPE* mt; hr = cap_stream_config->GetStreamCaps(i, &mt, (BYTE*)&caps); if(FAILED(hr)) { RX_ERROR("GetStreamCaps() failed"); continue; } if(mt->majortype == MEDIATYPE_Video && mt->formattype == FORMAT_VideoInfo && mt->cbFormat >= sizeof(VIDEOINFOHEADER) && mt->pbFormat != NULL) { VIDEOINFOHEADER* info = (VIDEOINFOHEADER*)mt->pbFormat; AVPixelFormat av_pix_fmt = mediaSubTypeGUIDToLibavPixelFormat(mt->subtype); AVCapability cap; cap.size.width = info->bmiHeader.biWidth; cap.size.height = info->bmiHeader.biHeight; cap.pixel_format = av_pix_fmt; cap.framerate.num = info->AvgTimePerFrame; cap.framerate.den = 10000000; cap.index = i; result.push_back(cap); } deleteMediaType(mt); } } done: safeReleaseDirectShow(&cap_graph_builder); safeReleaseDirectShow(&cap_capture_graph_builder); safeReleaseDirectShow(&cap_device_filter); safeReleaseDirectShow(&cap_stream_config); return result; }
std::vector<CameraConfig> videoInputCamera::getCameraConfigs(int dev_id) { std::vector<CameraConfig> cfg_list; int count = getDeviceCount(); if (count==0) return cfg_list; comInit(); HRESULT hr; ICaptureGraphBuilder2 *lpCaptureGraphBuilder; IGraphBuilder *lpGraphBuilder; IBaseFilter *lpInputFilter; IAMStreamConfig *lpStreamConfig; char nDeviceName[255]; WCHAR wDeviceName[255]; for (int cam_id=0;cam_id<count;cam_id++) { if ((dev_id>=0) && (dev_id!=cam_id)) continue; hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2, (void **)&lpCaptureGraphBuilder); if (FAILED(hr)) // FAILED is a macro that tests the return value { printf("ERROR - Could not create the Filter Graph Manager\n"); comUnInit(); return cfg_list; } // Create the Filter Graph Manager. hr = CoCreateInstance(CLSID_FilterGraph, 0, CLSCTX_INPROC_SERVER,IID_IGraphBuilder, (void**)&lpGraphBuilder); if (FAILED(hr)) { printf("ERROR - Could not add the graph builder!\n"); lpCaptureGraphBuilder->Release(); comUnInit(); return cfg_list; } hr = lpCaptureGraphBuilder->SetFiltergraph(lpGraphBuilder); if (FAILED(hr)) { printf("ERROR - Could not set filtergraph\n"); lpGraphBuilder->Release(); lpCaptureGraphBuilder->Release(); comUnInit(); return cfg_list; } memset(wDeviceName, 0, sizeof(WCHAR) * 255); memset(nDeviceName, 0, sizeof(char) * 255); hr = getDevice(&lpInputFilter, cam_id, wDeviceName, nDeviceName); if (SUCCEEDED(hr)){ hr = lpGraphBuilder->AddFilter(lpInputFilter, wDeviceName); }else{ printf("ERROR - Could not find specified video device\n"); lpGraphBuilder->Release(); lpCaptureGraphBuilder->Release(); comUnInit(); return cfg_list; } hr = lpCaptureGraphBuilder->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, lpInputFilter, IID_IAMStreamConfig, (void **)&lpStreamConfig); if(FAILED(hr)){ printf("ERROR: Couldn't config the stream!\n"); lpInputFilter->Release(); lpGraphBuilder->Release(); lpCaptureGraphBuilder->Release(); comUnInit(); return cfg_list; } CameraConfig cam_cfg; CameraTool::initCameraConfig(&cam_cfg); cam_cfg.driver = DRIVER_DEFAULT; cam_cfg.device = cam_id; sprintf(cam_cfg.name, "%s", nDeviceName); int iCount = 0; int iSize = 0; hr = lpStreamConfig->GetNumberOfCapabilities(&iCount, &iSize); std::vector<CameraConfig> fmt_list; if (iSize == sizeof(VIDEO_STREAM_CONFIG_CAPS)) { GUID lastFormat = MEDIASUBTYPE_None; for (int iFormat = 0; iFormat < iCount; iFormat+=2) { VIDEO_STREAM_CONFIG_CAPS scc; AM_MEDIA_TYPE *pmtConfig; hr = lpStreamConfig->GetStreamCaps(iFormat, &pmtConfig, (BYTE*)&scc); if (SUCCEEDED(hr)){ if ( pmtConfig->subtype != lastFormat) { if (fmt_list.size()>0) { std::sort(fmt_list.begin(), fmt_list.end()); cfg_list.insert( cfg_list.end(), fmt_list.begin(), fmt_list.end() ); fmt_list.clear(); } cam_cfg.cam_format = getMediaSubtype(pmtConfig->subtype); lastFormat = pmtConfig->subtype; } int stepX = scc.OutputGranularityX; int stepY = scc.OutputGranularityY; if(stepX < 1 || stepY < 1) continue; else if ((stepX==1) && (stepY==1)) { cam_cfg.cam_width = scc.InputSize.cx; cam_cfg.cam_height = scc.InputSize.cy; int maxFrameInterval = scc.MaxFrameInterval; if (maxFrameInterval==0) maxFrameInterval = 10000000; float last_fps=-1; VIDEOINFOHEADER *pVih = (VIDEOINFOHEADER*)pmtConfig->pbFormat; for (int iv=scc.MinFrameInterval;iv<=maxFrameInterval;iv=iv*2) { pVih->AvgTimePerFrame = iv; hr = lpStreamConfig->SetFormat(pmtConfig); if (hr==S_OK) { hr = lpStreamConfig->GetFormat(&pmtConfig); float fps = ((int)floor(100000000.0f/(float)pVih->AvgTimePerFrame + 0.5f))/10.0f; if (fps!=last_fps) { cam_cfg.cam_fps = fps; fmt_list.push_back(cam_cfg); last_fps=fps; } } } } else { int x,y; for (x=scc.MinOutputSize.cx,y=scc.MinOutputSize.cy;x<=scc.MaxOutputSize.cx,y<=scc.MaxOutputSize.cy;x+=stepX,y+=stepY) { cam_cfg.cam_width = x; cam_cfg.cam_height = y; int maxFrameInterval = scc.MaxFrameInterval; if (maxFrameInterval==0) maxFrameInterval = 10000000; float last_fps=-1; VIDEOINFOHEADER *pVih = (VIDEOINFOHEADER*)pmtConfig->pbFormat; for (int iv=scc.MinFrameInterval;iv<=maxFrameInterval;iv=iv*2) { pVih->AvgTimePerFrame = iv; hr = lpStreamConfig->SetFormat(pmtConfig); if (hr==S_OK) { hr = lpStreamConfig->GetFormat(&pmtConfig); float fps = ((int)floor(100000000.0f/(float)pVih->AvgTimePerFrame + 0.5f))/10.0f; if (fps!=last_fps) { cam_cfg.cam_fps = fps; fmt_list.push_back(cam_cfg); last_fps=fps; } } } } } deleteMediaType(pmtConfig); } } } if (fmt_list.size()>0) { std::sort(fmt_list.begin(), fmt_list.end()); cfg_list.insert( cfg_list.end(), fmt_list.begin(), fmt_list.end() ); fmt_list.clear(); } lpStreamConfig->Release(); lpInputFilter->Release(); lpGraphBuilder->Release(); lpCaptureGraphBuilder->Release(); } comUnInit(); return cfg_list; }
HRESULT videoInputCamera::stopDevice() { HRESULT HR = NULL; //Stop the callback and free it if( (sgCallback) && (pSampleGrabber) ) { //printf("SETUP: freeing Grabber Callback\n"); pSampleGrabber->SetCallback(NULL, 1); sgCallback->Release(); delete sgCallback; sgCallback = NULL; } //Check to see if the graph is running, if so stop it. if( (pMediaControl) ) { HR = pMediaControl->Pause(); if (FAILED(HR)) printf("ERROR - Could not pause pControl\n"); HR = pMediaControl->Stop(); if (FAILED(HR)) printf("ERROR - Could not stop pControl\n"); } //Disconnect filters from capture device if( (pInputFilter) ) NukeDownstream(pInputFilter); //Release and zero pointers to our filters etc if (pDestFilter) { //printf("SETUP: freeing Renderer \n"); pDestFilter->Release(); pDestFilter = NULL; } if (pInputFilter) { //printf("SETUP: freeing Capture Source \n"); pInputFilter->Release(); pInputFilter = NULL; } if (pGrabberFilter) { //printf("SETUP: freeing Grabber Filter \n"); pGrabberFilter->Release(); pGrabberFilter = NULL; } if (pSampleGrabber) { //printf("SETUP: freeing Grabber \n"); pSampleGrabber->Release(); pSampleGrabber = NULL; } if (pMediaControl) { //printf("SETUP: freeing Control \n"); pMediaControl->Release(); pMediaControl = NULL; } if (pStreamConfig) { //printf("SETUP: freeing Stream \n"); pStreamConfig->Release(); pStreamConfig = NULL; } if (pAmMediaType) { //printf("SETUP: freeing Media Type \n"); deleteMediaType(pAmMediaType); } //Destroy the graph if (pGraphBuilder) destroyGraph(); //Release and zero our capture graph and our main graph if (pCaptureGraphBuilder) { //printf("SETUP: freeing Capture Graph \n"); pCaptureGraphBuilder->Release(); pCaptureGraphBuilder = NULL; } if (pGraphBuilder) { //printf("SETUP: freeing Main Graph \n"); pGraphBuilder->Release(); pGraphBuilder = NULL; } comUnInit(); return S_OK; }