Ureader.com  
Microsoft software help and Community
   home   |   control panel login   |   archive   |  
 
Windos
win32.3rdparty
win32.directx.audio
win32.directx.ddk
win32.directx.graphics
win32.directx.input
win32.directx.managed
win32.directx.misc
win32.directx.networking
win32.directx.sdk
win32.directx.video
win32.dirx.grap.shaders
win32.gdi
win32.international
win32.kernel
win32.messaging
win32.mmedia
win32.networks
win32.ole
win32.rtc
win32.tapi
win32.tapi.beta
win32.tools
win32.ui
win32.wince
win32.wmi
windows.mediacenter
winfx.aero
winfx.announcements
winfx.avalon
winfx.collaboration
winfx.fundamentals
winfx.general
winfx.indigo
winfx.sdk
winfx.winfs
  
 
date: Sun, 20 Jul 2008 16:36:16 -0700 (PDT),    group: microsoft.public.win32.programmer.directx.video        back       


Custom WMV source filter doesn't playback after WMT_EOF   
Hi guys,

I'm trying to render WMV videos using DirectShow. I have it working,
but there's some edge cases that I'm having some problems with...

For various reasons we need to use our own networking to read files,
so we can't just use a standard WM ASF Reader filter to read videos. I
have implemented an IStream which uses our networking APIs and I have
a written a source filter  which wraps a WMReaderAdvanced2 object
which opens and reads from the IStream and pushes audio and video
streams/samples downstream using COutputQueue. I can play WMVs fine
with this filter, except short WMVs. If I Start() the WMReader and let
it read the entire video (that is let it read until I get a WMT_EOF
delivered to OnStatus()), and if I then try to start playback in the
graph using IMediaControl::Run(), only the sound plays, no video
samples are delivered to my video renderer.

My theory is that because my WMV source filter is a push filter, when
EOF comes in, the thread in COutputQueue has no more samples to send
downstream, so the thread sleeps. Then when the graph runs there's no
thread to run the renderer, since the video stream is being "pushed"
from the WMV source filter's video-stream output pin, but it has no
more samples to push, so its  thread doesn't run and doesn't service
the video-stream, and hence doesn't service the renderer and the video
stream doesn't render. Does that sound plausible?

My WMV source filter's audio stream connects downstream to a WMAudio
Decoder DMO, which connects to a Default DirectSoundDevice. My WMV
source filter's video stream connects to a WMVideo Decoder DMO, and
that connects to a VMR-7 renderer.

Do I need to rewrite my output pins on my WMV source to work in Pull
mode, so that the video rendering thread originates in the renderer?
Will the WM Decoder DMOs connect to upstream IAsyncReader pins? Or is
there some other way I can wake up the video stream's thread, or
something else I need to do?


Thanks,
Chris Pearce.
date: Sun, 20 Jul 2008 16:36:16 -0700 (PDT)   author:   Chris Pearce

Re: Custom WMV source filter doesn't playback after WMT_EOF   
From: "Chris Pearce"

[...]
> Do I need to rewrite my output pins on my WMV source to
> work in Pull mode, so that the video rendering thread
> originates in the renderer?

The stock renderers never spawn streaming threads. Streaming 
threads are typically spawned by the push-side of sources, 
like live push sources are pull-to-push parsers.

> Will the WM Decoder DMOs
> connect to upstream IAsyncReader pins?

No.


> Or is there some
> other way I can wake up the video stream's thread, or
> something else I need to do?

There is no such thing as a "video stream's thread". If you 
are the "pusher", then the threads are yours. Actually, you 
most likely own a few threads: the thread(s) spawned by the 
WMReader to call you back and the thrwad spwned by the 
COutputQueue.

From you description, it sounds like you are delivering 
samples while the graph is in a stopped (inactive) state, 
which is a error. You must deliver samples only when the 
graph is in a paused/running (active) state. If you do, the 
renderer will block your streaming thread (that is, the one 
that delivers downstream) as needed. If you use a 
COutputQueue, the streaming thread will be the queue's 
worker thread, which seems unnecessary.


-- 
// Alessandro Angeli
// MVP :: DirectShow / MediaFoundation
// mvpnews at riseoftheants dot com
// http://www.riseoftheants.com/mmx/faq.htm
date: Mon, 21 Jul 2008 12:24:24 -0400   author:   Alessandro Angeli

Re: Custom WMV source filter doesn't playback after WMT_EOF   
On Jul 22, 4:24 am, "Alessandro Angeli" 
wrote:
> [...]
> From you description, it sounds like you are delivering
> samples while the graph is in a stopped (inactive) state,
> which is a error. You must deliver samples only when the
> graph is in a paused/running (active) state. If you do, the
> renderer will block your streaming thread (that is, the one
> that delivers downstream) as needed.

Thanks for your insight Alessandro. This is happening when I've paused
the graph. When I load a WMV, I pause the graph straight away so that
I receive the "poster" frame to display. So unless the WMVideo Decoder
DMO is moving itself into stopped state if it's left too long, I don't
think that's the problem.

To my horror I've discovered that the WMVideo Decoder DMO is the
problem. If I load my WMV in GraphEdit, pause it, and wait for longer
than the duration of the movie before playing it, the video image
never updates, but sounds still plays. My WMV is a pretty simple one
produced by Windows Movie Maker on Vista SP1, and I can also reproduce
this problem with another WMV that I pulled of the 'net, so I don't
think this is caused by me playing a non-standard WMV.

When I run the graph, after it's been paused for longer than the
duration of the video, the WM Video Decoder DMO is still returning
success in its ReceiveMultiple() call, but there's no frames arriving
at the renderer. The GraphEdit doesn't report any frames dropped in
the renderer, and my NotifyPresentImage() isn't being called, so no
frames are coming in. I wonder if the WM Video Decoder DMO has a bug
in how it acts on sample time stamps.

Interestingly, I can't reproduce this problem in Windows Media Player,
so I guess they either work around it, or they don't use DirectShow to
render WMVs.

I'm not sure how I can work around this. I may try using Stop() the
graph instead of Pause()ing it, or I may have to get decompressed
frames from the WMReader and render the video using some other method.


Thanks,
Chris.



On Jul 22, 4:24 am, "Alessandro Angeli" 
wrote:
> From: "Chris Pearce"
>
> [...]
>
> > Do I need to rewrite my output pins on my WMV source to
> > work in Pull mode, so that the video rendering thread
> > originates in the renderer?
>
> The stock renderers never spawn streaming threads. Streaming
> threads are typically spawned by the push-side of sources,
> like live push sources are pull-to-push parsers.
>
> > Will the WM Decoder DMOs
> > connect to upstream IAsyncReader pins?
>
> No.
>
> > Or is there some
> > other way I can wake up the video stream's thread, or
> > something else I need to do?
>
> There is no such thing as a "video stream's thread". If you
> are the "pusher", then the threads are yours. Actually, you
> most likely own a few threads: the thread(s) spawned by the
> WMReader to call you back and the thrwad spwned by the
> COutputQueue.
>
> From you description, it sounds like you are delivering
> samples while the graph is in a stopped (inactive) state,
> which is a error. You must deliver samples only when the
> graph is in a paused/running (active) state. If you do, the
> renderer will block your streaming thread (that is, the one
> that delivers downstream) as needed. If you use a
> COutputQueue, the streaming thread will be the queue's
> worker thread, which seems unnecessary.
>
> --
> // Alessandro Angeli
> // MVP :: DirectShow / MediaFoundation
> // mvpnews at riseoftheants dot com
> //http://www.riseoftheants.com/mmx/faq.htm
date: Wed, 23 Jul 2008 19:44:33 -0700 (PDT)   author:   Chris Pearce

Re: Custom WMV source filter doesn't playback after WMT_EOF   
From: "Chris Pearce"

> Interestingly, I can't reproduce this problem in Windows
> Media Player, so I guess they either work around it, or
> they don't use DirectShow to render WMVs.

WMP uses DirectShow and a custom WMV source filter (except 
on Vista+, where it uses MF).

This is what's supposed to happen: you feed frames to the 
decoder and the decoder feeds thems to the renderer. When 
the renderer is paused, it blocks the thread that feeds it, 
which in turn makes the decoder's buffer overflow so that 
the decoder blocks your thread (depending on its buffer 
size, that may happen after several frames). When the 
decoder runs, it unblocks the thread and everything is 
delivered and unblocked, without any loss.

On the other hand, if you feed the decoder frames that must 
be dropped, nothing goes into its buffer and nothing reaches 
the renderer, ever.

The WMV decoder (like most sensible decoders do) drops 
frames that have the preroll flag set and frames that 
follows a discontinuity and are not syncpoints, until the 
first syncpoint. The beginning of a segment (the first frame 
after a stop or seek or flush) is an implicit discontinuity.

Timestamps have nothing to do with this: they are only 
really used by the renderer to keep the correct rendering 
rate relative to the graph's clock. The renderer does not 
drop frames based on the timestamps. The decoder instead may 
drop frames if the renderer sends quality message because it 
receives late samples (too slow), but that should never 
happen when the graph is paused.

Of course, the stock renderers behave this way while custom 
renderers can do what they want.

-- 
// Alessandro Angeli
// MVP :: DirectShow / MediaFoundation
// mvpnews at riseoftheants dot com
// http://www.riseoftheants.com/mmx/faq.htm
date: Thu, 24 Jul 2008 02:26:53 -0400   author:   Alessandro Angeli

Re: Custom WMV source filter doesn't playback after WMT_EOF   
Thanks again Alessandro.

On Jul 24, 6:26 pm, "Alessandro Angeli" 
wrote:
> This is what's supposed to happen: you feed frames to the
> decoder and the decoder feeds thems to the renderer. When
> the renderer is paused, it blocks the thread that feeds it,
> which in turn makes the decoder's buffer overflow so that
> the decoder blocks your thread (depending on its buffer
> size, that may happen after several frames). When the
> decoder runs, it unblocks the thread and everything is
> delivered and unblocked, without any loss.

Here's what I'm seeing: when I first pause the graph, my filter pushes
a bunch of frames downstream, and the pushing thread blocks in a
ReceiveMultiple() call on the downstream pin. After 11 seconds (the
duration of the video) has passed, the ReceiveMultiple() call returns
S_OK, and the thread loops around and happily continues to push frames
downstream. Subsequent calls to ReceiveMultiple() return S_OK. The
source filter pushes the entire video downstream, but no samples/
frames pushed downstream ever arrive at the renderer when I unpause.

I have avoided this problem by doing a two-staged pause. Whenever I
want to pause the graph, I first pause the pins on the source filter.
When each pin's COutputQueue's thread returns from its next
ReceiveMultiple() call, the thread goes to sleep, and doesn't push
anything downstream. Once the pins' threads are safely asleep, I pause
the graph as usual using IMediaControl::Pause(). When I unpause the
graph I wake up the threads, and they can begin pushing downstream
again. Thus the graph is never paused when a queue's thread could
block in RecieveMultiple() call on the WMVideo Decoder DMO, so I avoid
the danger zone altogether. It's ugly, but it at least resolves this
issue for me. It means samples don't buffer in the decoder, but they
can still buffer on the COutputQueue's queue. At least they still
arrive at the renderer!

Thanks your help Alessandro.

All the best,
Chris Pearce.
date: Thu, 24 Jul 2008 19:56:06 -0700 (PDT)   author:   Chris Pearce

Re: Custom WMV source filter doesn't playback after WMT_EOF   
Thanks again Alessandro.

On Jul 24, 6:26 pm, "Alessandro Angeli" 
wrote:
> This is what's supposed to happen: you feed frames to the
> decoder and the decoder feeds thems to the renderer. When
> the renderer is paused, it blocks the thread that feeds it,
> which in turn makes the decoder's buffer overflow so that
> the decoder blocks your thread (depending on its buffer
> size, that may happen after several frames). When the
> decoder runs, it unblocks the thread and everything is
> delivered and unblocked, without any loss.

Here's what I'm seeing: when I first pause the graph, my filter pushes
a bunch of frames downstream, and the pushing thread blocks in a
ReceiveMultiple() call on the downstream pin. After 11 seconds (the
duration of the video) has passed, the ReceiveMultiple() call returns
S_OK, and the thread loops around and happily continues to push frames
downstream. Subsequent calls to ReceiveMultiple() return S_OK. The
source filter pushes the entire video downstream, but no samples/
frames pushed downstream ever arrive at the renderer when I unpause.

I have avoided this problem by doing a two-staged pause. Whenever I
want to pause the graph, I first pause the pins on the source filter.
When each pin's COutputQueue's thread returns from its next
ReceiveMultiple() call, the thread goes to sleep, and doesn't push
anything downstream. Once the pins' threads are safely asleep, I pause
the graph as usual using IMediaControl::Pause(). When I unpause the
graph I wake up the threads, and they can begin pushing downstream
again. Thus the graph is never paused when a queue's thread could
block in RecieveMultiple() call on the WMVideo Decoder DMO, so I avoid
the danger zone altogether. It's ugly, but it at least resolves this
issue for me. It means samples don't buffer in the decoder, but they
can still buffer on the COutputQueue's queue. At least they still
arrive at the renderer!

Thanks your help Alessandro.

All the best,
Chris Pearce.
date: Thu, 24 Jul 2008 20:09:29 -0700 (PDT)   author:   Chris Pearce

Google
 
Web ureader.com


    COPYRIGHT 2007, YARDI TECHNOLOGY LIMITED, ALL RIGHT RESERVE  |   contact us