Zitat:
wenn du uns ein minimales Beispielprojekt sowie entsprechende Videodateien zur Verfügung stellst.
Kann ich gerne machen. Das beeinhaltet dann allerdings die Vorraussetzung der Installation des DSPack's (bekannt ?) und die Verwendung der darin enthaltenen Klassen TFilterGraph und TVideoWindow, wenn man die benannte Demo (aus dem DSPack) '\DEMOS\D6-D7\VMR\VMR9ALLOCATOR\PlayFile' zum laufen bekommen will.
Daraus mal "eben schnell was extrahieren" geht z 100% in die Hose, weil sehr komplex und sehr verflochten....
Im Prinzip ist die Demo allerdings identisch mit der MS-WIN7-
SDK Demo '\multimedia\directshow\vmr9\vmr9allocator' und betriff im wesentlichen die Dateien 'Allocator.cpp/.pas' und 'PlaneScene.cpp/.pas'.
Laufen tut die Demo mit jedem x-beliegiegen Video - wenn man wie EWeiss anmerkte, die LAV-Filter verwendet. Der LAVSplitterSource-Filter frisst fast alles. Ich habs hier mit div. .AVI, .MPG und .TS probiert.
Das Prinzip, so wie ich es bisher herausgebrezelt habe:
Das VideoWindow muss explizit zur Nutzung von VMR9 im Renderless-Mode gesetzt werden. Dazu muss man noch eine TAllocator-Klasse an's Window übergeben.
Der VMR9 ruft dann bei jedem Frame die Funktion "PresentImage" und hilfsweise die Funktion "PresentHelper" auf. Siehe hier auszugsweise im org. DSPack-File 'Allocator-
pas':
Delphi-Quellcode:
function TAllocator.PresentImage(dwUserID: DWORD;
lpPresInfo: PVMR9PresentationInfo): HResult;
var
hr: HRESULT;
AMonitor: HMONITOR;
function FailRet(hr: HResult): boolean;
begin
PresentImage := hr;
Result := Failed(hr);
end;
begin
FObjectLock.Enter;
try
// if we are in the middle of the display change
if NeedToHandleDisplayChange then
begin
// NOTE: this piece of code is left as a user exercise.
// The D3DDevice here needs to be switched
// to the device that is using another adapter
end;
hr := PresentHelper(lpPresInfo);
// IMPORTANT: device can be lost when user changes the resolution
// or when (s)he presses Ctrl + Alt + Delete.
// We need to restore our video memory after that
if (hr = D3DERR_DEVICELOST) then
begin
if (FD3DDev.TestCooperativeLevel = D3DERR_DEVICENOTRESET) then
begin
DeleteSurfaces;
if FailRet(CreateDevice) then exit;
AMonitor := FD3D.GetAdapterMonitor(D3DADAPTER_DEFAULT);
if FailRet(FlpIVMRSurfAllocNotify.ChangeD3DDevice(FD3DDev, AMonitor)) then exit;
end;
hr := S_OK;
end;
result := hr;
finally
FObjectLock.Leave;
end;
end;
function TAllocator.PresentHelper(
lpPresInfo: PVMR9PresentationInfo): HRESULT;
var
surface: IDirect3DSurface9;
texture: IDirect3DTexture9;
function FailRet(hr: HResult): boolean;
begin
PresentHelper := hr;
Result := Failed(hr);
end;
begin
// parameter validation
if (lpPresInfo = nil) then
begin
result := E_POINTER;
exit;
end else
if (lpPresInfo.lpSurf = nil) then
begin
result := E_POINTER;
exit;
end;
FObjectLock.Enter;
try
FD3DDev.SetRenderTarget(0, FrenderTarget);
// if we created a private texture
// blt the decoded image onto the texture.
if(FprivateTexture <> nil) then
begin
if FailRet(FprivateTexture.GetSurfaceLevel(0 , surface)) then exit;
// copy the full surface onto the texture's surface
if FailRet(FD3DDev.StretchRect(lpPresInfo.lpSurf, nil,
surface, nil,
D3DTEXF_NONE)) then exit;
if FailRet(Fscene.DrawScene(FD3DDev, FprivateTexture)) then exit;
end
else // this is the case where we have got the textures allocated by VMR
// all we need to do is to get them from the surface
begin
if FailRet(lpPresInfo.lpSurf.GetContainer(IID_IDirect3DTexture9, Pointer(texture))) then exit;
if FailRet(Fscene.DrawScene(FD3DDev, texture)) then exit;
end;
if FailRet(FD3DDev.Present(nil, nil, 0, nil)) then exit;
// result := hr;
finally
Pointer(texture) := nil;
FObjectLock.leave;
end;
end;
Letztendlich wird im File 'PlaneScene.pas' (Auszug) die Funktion "DrawScene" aufgerufen und dort YXZ-Werte in Matrizen und Transformationen "verwurstet", was die Drehung der "Video-Scheibe" veranlasst ..... die ich gerne da raus hätte !
Delphi-Quellcode:
function TPlaneScene.DrawScene(d3ddev: IDirect3DDevice9;
texture: IDirect3DTexture9): HRESULT;
function FailRet(hr: HResult): boolean;
begin
DrawScene := hr;
Result := Failed(hr);
end;
var
dwCurrentTime: DWord;
difference: Int64;
x, y, z: Single;
mask0, mask3: DWord;
pData: Pointer;
begin
if ((d3ddev = nil) or (texture = nil)) then
begin
Result := E_POINTER;
Exit;
end;
if( FvertexBuffer = nil) then
begin
Result := D3DERR_INVALIDCALL;
Exit;
end;
// get the difference in time
dwCurrentTime := GetTickCount;
difference := Ftime - dwCurrentTime;
// figure out the rotation of the plane
x := -cos(difference / 2000);
y := cos(difference / 2000);
z := sin(difference / 2000);
// update the two rotating vertices with the new position
Fvertices[0].position := MakePosition(x, y, z); // top left
Fvertices[3].position := MakePosition(-x, -y, -z); // bottom right
// Adjust the color so the blue is always on the bottom.
// As the corner approaches the bottom, get rid of all the other
// colors besides blue
mask0 := Trunc((255 * (( y + 1) / 2)));
mask3 := Trunc((255 * ((-y + 1) / 2)));
Fvertices[0].color := $ff0000ff or (mask0 shl 16) or (mask0 shl 8);
Fvertices[3].color := $ff0000ff or (mask3 shl 16) or (mask3 shl 8);
// write the new vertex information into the buffer
if FailRet(FvertexBuffer.Lock(0, sizeof(pData), pData, 0)) then exit;
move(Fvertices, pData^ , sizeof(Fvertices));
if FailRet(FvertexBuffer.Unlock) then exit;
// clear the scene so we don't have any articats left
d3ddev.Clear(0, nil, D3DCLEAR_TARGET, D3DCOLOR_XRGB(255,255,255), 1.0, 0);
if FailRet(d3ddev.BeginScene) then exit;
if FailRet(d3ddev.SetTexture(0, texture)) then exit;
if FailRet(d3ddev.SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE)) then exit;
if FailRet(d3ddev.SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE)) then exit;
if FailRet(d3ddev.SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE)) then exit;
if FailRet(d3ddev.SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE)) then exit;
if FailRet(d3ddev.SetStreamSource(0, FvertexBuffer, 0, sizeof(TCustomVertex))) then exit; //set next source ( NEW )
if FailRet(d3ddev.SetFVF(D3DFVF_CUSTOMVERTEX)) then exit;
if FailRet(d3ddev.DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2)) then exit; //draw quad
if FailRet(d3ddev.SetTexture(0, nil)) then exit;
if FailRet(d3ddev.EndScene) then exit;
end;
Hier endet leider mein mathematisches & delphianotisches Knoff-Hoff.