# Playing AVI Files using DirectShow

This topic is 4456 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Hi, I need to Playblack AVI Videos in my Application and need support to step trough the Movie Frame by Frame. Currently I'm using the VFW-API for this, works very well but doesn't support all Codecs (i.E. xVid videos doesn't work).. so I thought I could switch over to DirectX for this. But, I now searched the whole web I think.. how can I step trough an Video like I can in VFW??! I have no problems Playing the AVI Video and grav the Frames via SampleGrabber, but FrameStepping.. - no chance :( I tried using the IVideoFrameStep Interface, but it seems like it doesn't work. The best thing would be, if I could call "getFrame(int frame)" and would get the data for this Frame, like in VFW. (This can be done using this Poster-Frame Interface, but that's way to slow) So, if anyone have any Idea how to do this.. please help me :) Au'revoir, Aya~

##### Share on other sites
IVideoFrameStep seems to be exactly what you want to use, so I would search out any documentation/samples/forum posts related to that. Alternatively, you could try IMediaSeeking. Here is an MSDN post that kind of sounds like your problem.

##### Share on other sites
Hi,

I don't know what I am doing wrong, but when I try to seek the Video with the IMediaSeeking Interface it allways jumps back to Frame 0.

This is my Initialisation:

  CoCreateInstance(CLSID_FilterGraph, nil, CLSCTX_INPROC, IID_IGraphBuilder, pGraph);  CoCreateInstance(CLSID_SampleGrabber, nil, CLSCTX_INPROC_SERVER, IID_IBaseFilter, pGrabberF);  CoCreateInstance(CLSID_NullRenderer, nil, CLSCTX_INPROC_SERVER, IID_IBaseFilter, pNull);  pGraph.QueryInterface(IID_IMediaControl, pControl);  pGraph.QueryInterface(IID_IMediaEvent, pEvent);  pGraph.QueryInterface(IID_IMediaSeeking, pSeeking);  pGraph.QueryInterface(IID_IMediaFilter, pFilter);  pSeeking.SetTimeFormat(TIME_FORMAT_FRAME);  pFilter.SetSyncSource(nil);  pGraph.AddFilter(pGrabberF, 'Sample Grabber');  pGraph.AddFilter(pNull, 'Null Render');  pGrabberF.QueryInterface(IID_ISampleGrabber, pGrabber);  ZeroMemory(@mType, SizeOf(AM_MEDIA_TYPE));    mType.majortype := MEDIATYPE_Video;    mType.subtype   := MEDIASUBTYPE_RGB24;  pGrabber.SetMediaType(mType);  pGraph.AddSourceFilter(Filename, 'Source', pSrc);  ConnectFilters(pGraph, pSrc, pGrabberF);  ConnectFilters(pGraph, pGrabberF, pNull);  pGrabber.SetOneShot(false);  pGrabber.SetBufferSamples(true);  GrabberCB:=TSampleGrabberCB.Create;  GrabberCB.Parent:=Self;  pGrabber.SetCallback(GrabberCB, 1);

When I now use:
  pControl.Run;

the Video is Played back.

But when I call
  pSeeking.SetPositions(XXX, AM_SEEKING_AbsolutePositioning, 0, AM_SEEKING_NoPositioning);

where XXX is any number you want, it just jumps back to Frame 0.

Does anyone know, why?

Aya~

##### Share on other sites
Noone knows where I made a mistake? :(

##### Share on other sites
As Circlesoft says, you could use IVideoFrameStep for this. However, I don't recommend that for two reasons:

1. It only supports forward stepping

2. It isn't necessarily consistent in stepping. For example, one step may jump 1001 reference time units. The next step would jump around 300,000 time units (which, in my case, was actually close to the number of reference time units representing one frame).

Regarding your code, there are two problems I see:

1. You don't query the seeking interface to see whether it supports TIME_FORMAT_FRAME. Many filters don't--for example, WMV filters on my PC don't.

2. Even if TIME_FORMAT_FRAME is supported, some filters always return 0 as the current position, as well as silently fail to seek to any position as you have encountered (that is, returning S_OK even though they didn't seek).

In conclusion, use manual seeking instead:
void MediaPlayer::StepFrames(int numFrames){	if(m_state != MediaPlayerState::Paused)		Pause();	LONGLONG timePerFrame = ReferenceTimePerSecond / FrameRate();					LONGLONG currentPos;	DSE(m_mediaSeeking->GetCurrentPosition(&currentPos));	LONGLONG timeDelta = timePerFrame * abs(numFrames);		if(numFrames > 0)	{		currentPos += timeDelta;				if(currentPos > Duration())			currentPos = Duration();	}	else	{		currentPos -= timeDelta;				if(currentPos < 0)			currentPos = 0;	}	DSE(m_mediaSeeking->SetPositions(&currentPos, AM_SEEKING_AbsolutePositioning,		0, AM_SEEKING_NoPositioning));}

In the above code, DSE is simply a macro that checks for failure and throws an exception.

##### Share on other sites
I know this is not an answer to your question, but I have been trying very very hard to playback videos in my game with DirectShow.
It never really worked as it should have. I mean: SLOW SLOW SLOW!
Even when you give the video stream enough time to work, it still skips frames, because of its internal low priority threads which you can 't change in a normal way.

I've tried using VFW (Video For Windows), of course this only works on windows, but it works much better. Only problem there is codecs, it doesn't play everything and if it plays, it sometimes doesn't really work as it should.

The final and really successful try was: FFMpeg, and this is REALLY good! I don't say it's flawless, but after including the libraries and compiling the example you see on the website, I had enough info to play back video's of lots of supported video formats, even without their codecs. Plus: it's fast!

Don't know if you needed this info, but if you're trying to implement videos in your game and want them to be smooth... don't go with DirectShow.

##### Share on other sites
Hi,

scippie: Sound's cool, I'll take a look at it :)

Aya~

##### Share on other sites
Quote:

//	Constant: ReferenceTimePerSecond//		The number of reference time units per second. DirectShow uses a time unit where each//		corresponds to 100 nanoseconds. The media player uses the same units.//static const LONGLONG ReferenceTimePerSecond = 1e7;

Quote:
 I know this is not an answer to your question, but I have been trying very very hard to playback videos in my game with DirectShow.It never really worked as it should have. I mean: SLOW SLOW SLOW!

I'm curious--how do you use DirectShow in your game? Do you use it to play cutscenes, or are you using it to render to textures mid-game?

If it's for cutscenes, it should be fast enough--there should be nothing else working in the background. As far as rendering-to-texture using VMR, I recall that there was a D3D sample that did this, and was fast as well.

##### Share on other sites
Hi,

thanks, Seeking works now. But.. it's not Frame by Frame.. more like 20 Frame Jumps or something :(

Aya~

##### Share on other sites
Quote:
 Original post by AyaKoshigayaHi,thanks, Seeking works now. But.. it's not Frame by Frame.. more like 20 Frame Jumps or something :(

The time delta jumped per-frame depends on your frame rate. Are you sure the frame rate value you use is correct?

1. 1
2. 2
Rutin
20
3. 3
khawk
17
4. 4
A4L
14
5. 5

• 12
• 16
• 26
• 10
• 44
• ### Forum Statistics

• Total Topics
633759
• Total Posts
3013717
×