Peter Meier
2012-02-10
Hello everyone,
I have a WinForms application which uses the DirectShow.NET library to play
media files. But whenever I load a file and play it (using Run() from
IMediaControl), the 1st frame (indexed with 0) is being skipped. I included
the SampleGrabber filter with its Callback Events and the first time a
callback event is triggered it's already frame 1. The same is true when I try
to seek to the beginning by using IMediaSeeking.
It happens even if I have a raw RGB24 avi. Also Media Player Classic is able
show me frame 0, even though the graphs are almost identical.
My graph: Haali MS 1.11.96.14 --> SampleGrabber --> Color Space Converter -->
VMR Renderer
MPC graph is the same except for a different source filter. The renderer is
set to "System Default", so it should be the same one, I guess.
Regards
Squall
Peter Meier
2012-02-13
I am one step further. Apparently, GraphEdit has the very same problem. Choose
any media file where you painted the frame numbers or something like that on
each frame, open it with GraphEdit and you're probably going to see the very
same effect.
However, MPC does not have this problem, like I mentioned above.
Also, if you don't use a Renderer, but a file writer instead, then all frames
will be written to the file. This is also true for both GraphEdit and my
application which uses the DirectShow.NET library.
Peter Meier
2012-02-15
I found out that the problem doesn't happen in the C++ application found here:
http://www.flipcode.com/archives/DirectShow_For_Media_Playback_In_Windows-
Part_I_Basics.shtml
When I created a WinForms C++/CLI app and copied the code from the main
function into it, I was able to see the 1st frame, too.
Could it be that GraphEdit was written in C# as well and that this is a
general C# problem?
snarfle
2012-02-16
Umm. I can say, with a very high degree of confidence, that GraphEdt was NOT
written in c# (or any .Net language).
Also, while I cannot positively say that this behavior doesn't somehow stem
from .Net, I will say that it seems unlikely. You have to understand that
there is (almost) no executable code in the DS.Net library. It is (almost) all
just definitions: Enums, Structs and Interfaces.
Have you tried translating that exact c++ code into c#? If you want to compare
behaviors, starting with the same code seems like a place to start.
Peter Meier
2012-02-16
Ok, it's good to hear that the DS.Net lib is unlikely to have anything to do
with it. That way I can keep using C#. :-) Indeed I can see the first frame if
I put a button in my GUI that does the following:
private void buttonTest_Click(object sender, EventArgs e)
{
int hr;
IGraphBuilder pGraphBuilder = (IGraphBuilder)new FilterGraph();
IMediaControl pMediaControl;
hr = pGraphBuilder.RenderFile("D:/Video/testvideoRgb24.avi", null);
pMediaControl = pGraphBuilder as IMediaControl;
hr = pMediaControl.Run();
pMediaControl.Pause();
}
I guess I have to look through my code after all. When I saw GraphEdit had the
same problem I just kind of assumed it had to do with DS. I'll post again once
I know more.
Thanks for the help! This forum would be dead without you.
Peter Meier
2012-02-16
Well, there seems to be a problem with the seeking function. Since the
stop()-command doesn't rewind the graph I have to do it via a seek-call
IMediaSeeking pMS = pGraphBuilder as IMediaSeeking;
pMS.GetDuration(out length);
pMS.SetPositions(0, AMSeekingSeekingFlags.AbsolutePositioning, length,
AMSeekingSeekingFlags.AbsolutePositioning);
and this is what causes my problem. This happens in C++ as well, when I use
this code:
System::Void Form1::buttonTest_Click(System::Object^ sender,
System::EventArgs^ e)
{
HRESULT hr;
IGraphBuilder pGraphBuilder;
IMediaControl pMediaControl;
IMediaSeeking* pMS;
WCHAR MediaFile; // MAX_PATH is defined as 260 in WinDef.h
LPSTR lpCmdLine = "D:/Video/testvideoRgb24.avi";
MultiByteToWideChar(CP_ACP, 0, lpCmdLine, -1, MediaFile, MAX_PATH);
// Creation of the graph, rendering and linking the control and seek
interfaces to it.
hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_ALL, IID_IGraphBuilder,
(void)&pGraphBuilder);
hr = pGraphBuilder->RenderFile(MediaFile, NULL);
hr = pGraphBuilder->QueryInterface(IID_IMediaControl, (void)&pMediaControl);
hr = pGraphBuilder->QueryInterface(IID_IMediaSeeking, (void**)&pMS);
pMediaControl->Pause();
// calling the seek function
LONGLONG duration;
LONGLONG start = 0;
pMS->GetDuration(&duration);
pMS->SetPositions(&start, 0, &duration, 0);
Sleep(2000);
pMediaControl->Stop();
pMediaControl->Release();
pGraphBuilder->Release();
}
So I guess it's because of the seeking-function. Am I using this function in a
wrong manner or do I have to work around this problem?
snarfle
2012-02-17
While you can't ever say absolutely that .Net didn't introduce some behavior,
that hasn't usually been my experience with DS .Net (.Net v4.0 being an
exception). Glad to hear your observations bear this out.
Looking at your c# code, I would probably do this as:
pMS.SetPositions(0, AMSeekingSeekingFlags.AbsolutePositioning, 0, AMSeekingSeekingFlags.NoPositioning);
It might also be interesting to experiment with the modifiers (NoFlush and
ReturnTime).
Looking at your c++ code, I wouldn't expect the SetPositions call to do
anything. Isn't NoPositioning == 0? If you were going to be doing a c++
solution, I'd probably have a few other comments about your Release calls.
Peter Meier
2012-02-17
Was .net 4.0 an exception in some parts that are important to the DS.NET lib?
.net framework 4.0 is the most recent one and therefore I have it installed.
If there's a serious problem I'm switching back to 3.5.
The release-calls are part of the code from flipcode (see above) which was in
a main function. I just copied it and made a few small changes where necessary
in order to have a quick result. I didn't care at all whether or not I
released anything properly.
According to the documentation, "NoPositioning" means "don't change anything".
But in fact, putting it into the stop position didn't give me a different
behaviour. I then used
int result = m_objMediaSeeking.SetPositions(lTime,
AMSeekingSeekingFlags.AbsolutePositioning,
0, AMSeekingSeekingFlags.NoPositioning | AMSeekingSeekingFlags.NoFlush);
in order to test the flush function, but to no avail. Concerning Return_Time I
have the problem that in the documentation it says that the time is being
returned in one of the time parameters I pass to the function. But in C#
they're not passed as pointers but as values.
Peter Meier
2012-05-10
I finally found the answer:
It's Haali Media Splitter's fault. If I uninstall it, then I can see frame 0
just fine. Probably MPC and Zoom Player use different source filters, while in
GraphEdit Haali is my default one as well.