DirectShow: Video-Vorschau und Bild (mit funktionierenden code)
Fragen /Probleme
- Wenn jemand kann mir eine empfehlen die gut gratis-hosting-Website, die ich die ganze project-Datei.
- Wie oben im text unter dem TakePicture () - Methode nicht richtig funktioniert auf dem HTC HD 2 Gerät. Es wäre schön, wenn jemand ansehen konnte, Sie den folgenden code und Sag mir ob es falsch oder richtig ist, was ich Tue.
Einführung
Ich fragte vor kurzem ein Frage über die Anzeige eine video-Vorschau, Aufnahme-Bild der Kamera und drehen einen video-stream mit DirectShow. Die heikle Sache über das Thema ist, dass es sehr schwer ist, gute Beispiele und die Dokumentation und das framework selbst ist sehr schwer zu verstehen für jemanden der neu in der windows-Programmierung und C++ im Allgemeinen.
Trotzdem habe ich es geschafft, eine Klasse zu erstellen, die meisten dieser features und funktioniert wohl mit den meisten mobilen Geräten. Wahrscheinlich, weil die DirectShow Umsetzung hängt viel vom Gerät selbst. Ich konnte nur testen Sie es mit dem HTC HD und dem HTC HD2, die sind bekannt als ziemlich unvereinbar.
HTC HD
- Arbeiten: Video-Vorschau, schreiben, Foto-Datei
- Nicht funktioniert: video-Auflösung (CRASH), set-Foto-Auflösung (NIEDRIGE Qualität)
HTC HD 2
- Arbeiten: video-Auflösung, set-Foto-Auflösung
- Problematisch: Video-Vorschau gedreht
- Nicht arbeiten: Schreiben, Foto-Datei
Machen es einfacher für andere, indem Sie ein funktionierendes Beispiel habe ich beschlossen, zu teilen alles, was ich habe, so weit unten. Ich entfernte alle die Fehlerbehandlung für die der Einfachheit halber. Soweit Dokumentation geht, kann ich nur empfehlen, Sie zu Lesen, die MSDN-Dokumentation, nach, dass der folgende code ist ziemlich straight-forward.
void Camera::Init()
{
CreateComObjects();
_captureGraphBuilder->SetFiltergraph(_filterGraph);
InitializeVideoFilter();
InitializeStillImageFilter();
}
Dipslay eine video-Vorschau (funktioniert mit allen getesteten handheld):
void Camera::DisplayVideoPreview(HWND windowHandle)
{
IVideoWindow *_vidWin;
_filterGraph->QueryInterface(IID_IMediaControl,(void **) &_mediaControl);
_filterGraph->QueryInterface(IID_IVideoWindow, (void **) &_vidWin);
_videoCaptureFilter->QueryInterface(IID_IAMVideoControl,
(void**) &_videoControl);
_captureGraphBuilder->RenderStream(&PIN_CATEGORY_PREVIEW,
&MEDIATYPE_Video, _videoCaptureFilter, NULL, NULL);
CRect rect;
long width, height;
GetClientRect(windowHandle, &rect);
_vidWin->put_Owner((OAHWND)windowHandle);
_vidWin->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS);
_vidWin->get_Width(&width);
_vidWin->get_Height(&height);
height = rect.Height();
_vidWin->put_Height(height);
_vidWin->put_Width(rect.Width());
_vidWin->SetWindowPosition(0,0, rect.Width(), height);
_mediaControl->Run();
}
HTC HD2: Wenn gesetzt SetPhotoResolution() aufgerufen wird FindPin wird E_FAIL zurückgegeben. Wenn nicht, wird eine Datei erstellt, voll von null-bytes. HTC HD: Funktioniert
void Camera::TakePicture(WCHAR *fileName)
{
CComPtr<IFileSinkFilter> fileSink;
CComPtr<IPin> stillPin;
CComPtr<IUnknown> unknownCaptureFilter;
CComPtr<IAMVideoControl> videoControl;
_imageSinkFilter.QueryInterface(&fileSink);
fileSink->SetFileName(fileName, NULL);
_videoCaptureFilter.QueryInterface(&unknownCaptureFilter);
_captureGraphBuilder->FindPin(unknownCaptureFilter, PINDIR_OUTPUT,
&PIN_CATEGORY_STILL, &MEDIATYPE_Video, FALSE, 0, &stillPin);
_videoCaptureFilter.QueryInterface(&videoControl);
videoControl->SetMode(stillPin, VideoControlFlag_Trigger);
}
Auflösung: Funktioniert Super auf dem HTC HD2. HTC Desire HD wird nicht zulassen, SetVideoResolution() und bietet nur eine geringe Auflösung Foto-Auflösung:
void Camera::SetVideoResolution(int width, int height)
{
SetResolution(true, width, height);
}
void Camera::SetPhotoResolution(int width, int height)
{
SetResolution(false, width, height);
}
void Camera::SetResolution(bool video, int width, int height)
{
IAMStreamConfig *config;
config = NULL;
if (video)
{
_captureGraphBuilder->FindInterface(&PIN_CATEGORY_PREVIEW,
&MEDIATYPE_Video, _videoCaptureFilter, IID_IAMStreamConfig,
(void**) &config);
}
else
{
_captureGraphBuilder->FindInterface(&PIN_CATEGORY_STILL,
&MEDIATYPE_Video, _videoCaptureFilter, IID_IAMStreamConfig,
(void**) &config);
}
int resolutions, size;
VIDEO_STREAM_CONFIG_CAPS caps;
config->GetNumberOfCapabilities(&resolutions, &size);
for (int i = 0; i < resolutions; i++)
{
AM_MEDIA_TYPE *mediaType;
if (config->GetStreamCaps(i, &mediaType,
reinterpret_cast<BYTE*>(&caps)) == S_OK )
{
int maxWidth = caps.MaxOutputSize.cx;
int maxHeigth = caps.MaxOutputSize.cy;
if(maxWidth == width && maxHeigth == height)
{
VIDEOINFOHEADER *info =
reinterpret_cast<VIDEOINFOHEADER*>(mediaType->pbFormat);
info->bmiHeader.biWidth = maxWidth;
info->bmiHeader.biHeight = maxHeigth;
info->bmiHeader.biSizeImage = DIBSIZE(info->bmiHeader);
config->SetFormat(mediaType);
DeleteMediaType(mediaType);
break;
}
DeleteMediaType(mediaType);
}
}
}
Andere Methoden genutzt, um den filter-graph und erstellen Sie die COM-Objekte:
void Camera::CreateComObjects()
{
CoInitialize(NULL);
CoCreateInstance(CLSID_CaptureGraphBuilder, NULL, CLSCTX_INPROC_SERVER,
IID_ICaptureGraphBuilder2, (void **) &_captureGraphBuilder);
CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
IID_IGraphBuilder, (void **) &_filterGraph);
CoCreateInstance(CLSID_VideoCapture, NULL, CLSCTX_INPROC,
IID_IBaseFilter, (void**) &_videoCaptureFilter);
CoCreateInstance(CLSID_IMGSinkFilter, NULL, CLSCTX_INPROC,
IID_IBaseFilter, (void**) &_imageSinkFilter);
}
void Camera::InitializeVideoFilter()
{
_videoCaptureFilter->QueryInterface(&_propertyBag);
wchar_t deviceName[MAX_PATH] = L"\0";
GetDeviceName(deviceName);
CComVariant comName = deviceName;
CPropertyBag propertyBag;
propertyBag.Write(L"VCapName", &comName);
_propertyBag->Load(&propertyBag, NULL);
_filterGraph->AddFilter(_videoCaptureFilter,
L"Video Capture Filter Source");
}
void Camera::InitializeStillImageFilter()
{
_filterGraph->AddFilter(_imageSinkFilter, L"Still image filter");
_captureGraphBuilder->RenderStream(&PIN_CATEGORY_STILL,
&MEDIATYPE_Video, _videoCaptureFilter, NULL, _imageSinkFilter);
}
void Camera::GetDeviceName(WCHAR *deviceName)
{
HRESULT hr = S_OK;
HANDLE handle = NULL;
DEVMGR_DEVICE_INFORMATION di;
GUID guidCamera = { 0xCB998A05, 0x122C, 0x4166, 0x84, 0x6A, 0x93, 0x3E,
0x4D, 0x7E, 0x3C, 0x86 };
di.dwSize = sizeof(di);
handle = FindFirstDevice(DeviceSearchByGuid, &guidCamera, &di);
StringCchCopy(deviceName, MAX_PATH, di.szLegacyName);
}
Vollständigen header-Datei:
#ifndef __CAMERA_H__
#define __CAMERA_H__
class Camera
{
public:
void Init();
void DisplayVideoPreview(HWND windowHandle);
void TakePicture(WCHAR *fileName);
void SetVideoResolution(int width, int height);
void SetPhotoResolution(int width, int height);
private:
CComPtr<ICaptureGraphBuilder2> _captureGraphBuilder;
CComPtr<IGraphBuilder> _filterGraph;
CComPtr<IBaseFilter> _videoCaptureFilter;
CComPtr<IPersistPropertyBag> _propertyBag;
CComPtr<IMediaControl> _mediaControl;
CComPtr<IAMVideoControl> _videoControl;
CComPtr<IBaseFilter> _imageSinkFilter;
void GetDeviceName(WCHAR *deviceName);
void InitializeVideoFilter();
void InitializeStillImageFilter();
void CreateComObjects();
void SetResolution(bool video, int width, int height);
};
#endif
Du musst angemeldet sein, um einen Kommentar abzugeben.
Kann ich leider nicht teilen, hier die Lösung, denn aus rechtlichen Gründen.
Dennoch kann ich sagen, dass video-und Bild-Aufnahmen mit voller Auflösung-Unterstützung ist möglich auf dem HTC HD 2 ohne Verwendung des HTC HD spezifischen Bibliotheken.
Hinweis: Sie werden wahrscheinlich brauchen eine NULL-renderer.
Ich habe vor kurzem lief in ein problem mit einem Ansatz wie diesem, wo die snapshot funktionieren würde, das erste mal um, aber nicht die zweite. Das problem war ähnlich wie bei Ihnen, wo die Einstellung der Auflösung verursachen würde, die FindPin zu scheitern, aber er Tat es nur, das zweite mal.
Dem Update war die Version die config-Objekt am Ende der SetResolution!
Danach, es funktionierte jedes mal.