Art_99999

Using DirectShow on Windows Vista.

In my application, I would like to allow users to view wmv files that are on some internet server somewhere. Example:

http://download.gametrailers.com/gt_vault/t_starcraft2_gp8.wmv. To build my graph, I insert the WM ASF Reader, set its source to whatever URL I wish to read today, and render its output pins. Everything works fine.

Playback handling (starting, stopping, pausing, seeking) all occurs on a worker thread. The UI thread sends messages to this worker thread to indicate which media it wants started.

When I go to start the media, obviously it must be downloaded. Unfortunately, it seems that the initial buffering occurs entirely within the call to IMediaControl::Run. My worker thread gets stopped on this call to Run. Now when the UI thread reports the user wants to start a different piece of media, my worker thread is stuck in this call and can't respond until the first portion of the file is downloaded and playable.

In short, I need to know a way to make my call to Run asynchronous, or I need to know a way to cancel my call to Run. Can anyone help me



Re: DirectShow Development How to cancel an IMediaControl::Run call that takes too long

LGS

The only interface I know for this is IAMOpenProgress. http://msdn2.microsoft.com/en-us/library/ms784077.aspx

However, I don't see anything in the filter description that says the ASF Reader supports it. It might be worth a try to QI it and see what it says.

Failing that, maybe read thru some of the WM docs and see what you can find.





Re: DirectShow Development How to cancel an IMediaControl::Run call that takes too long

Art_99999

That's a good idea, I missed IAMOpenProgress in my scans of the interface list.

Here's what I've tried so far:

Attempt: IMediaControl->Stop from the UI thread

Result: Doesn't free the thread stuck on IMediaControl::Run, and the thread that called Stop blocks forever as well

Attempt: IGraphBuilder->Abort from the UI thread

Result: The UI thread doesn't block and returns S_OK, but thread stuck on Start doesn't do anything

Attempt: Using IWMReaderNetworkConfig to reduce the amount of buffering to one second when I build my graph

Result: The ASF Reader apparently does not support IWMReaderNetworkConfig, and neither does IGraphBuilder

Attempt: Using IAMNetShowConfig to reduce the amount of buffering to one second when I build my graph

Result: The ASF Reader apparently does not support IAMNetShowConfig, and neither does IGraphBuilder

Attempt: Retrieving IWMReaderNetworkConfig from an IServiceProvider retrieved from the ASF reader filter. I tried this because this is how you get the IWMDRMReader, so I figured I'd try it as a long shot.

Result: E_NOINTERFACE from the IServiceProvider

Attempt: Using IAMOpenProgress->AbortOperation to abort my operation
Result: I was able to retrieve the IAMOpenProgress interface from the graph, but calling AbortOperation would return E_NOINTERFACE





Re: DirectShow Development How to cancel an IMediaControl::Run call that takes too long

LGS

Re IAMOpenProgress. This sounds like some type of threading issue. Maybe you are calling abort from the "wrong" thread If it weren't implemented, I'd expect E_NOTIMPL.





Re: DirectShow Development How to cancel an IMediaControl::Run call that takes too long

Art_99999

I got the same behavior regardless of which thread I tried IAMOpenProgress->AbortOperation on. After I got the wierd E_NOINTERFACE when calling it from the UI thread (while the worker thread was stuck on Run), I tried to AbortOperation after I built the graph (on the same thread as the one that built the graph) and the same thing happened. Since all the IAMxxxxxx interfaces seem to be legacy components leftover from WMP 6.4, I imagine that it isn't playing nice with the much more recent ASF Reader.





Re: DirectShow Development How to cancel an IMediaControl::Run call that takes too long

ahmadR

Maybe inside the worker thread you could start a new thread for each file request. And inside this new thread you could call IMediaControl::Run. So each Run request is in a separate thread. Not sure how well this scales though.





Re: DirectShow Development How to cancel an IMediaControl::Run call that takes too long

Art_99999

I've thought of that and it would be an acceptable last-ditch solution I suppose, but then the issue is that you're using up the user's bandwidth until that item has loaded (since the worker's new thread would still go for the entirety of the Run call), and the user will never have a clue why, since they aren't watching that item anymore.

It is starting to look like my best solution would be to write my own directshow source filter using an IWMReader (so I can access all the buffer-configuration capabilities available with IWMReaderNetworkConfig), or not use directshow at all.





Re: DirectShow Development How to cancel an IMediaControl::Run call that takes too long

ahmadR

Just throwing out an idea:

- What if you explicitly destroy the new worker thread (even if the Run call takes too long) - will that be effective in

resolving the bandwidth usage





Re: DirectShow Development How to cancel an IMediaControl::Run call that takes too long

Mt. Rabbit

I've had similar problem.

I put IMediaControl::Run() and IWMReaderAdvanced2::GetBufferProgress() methods to worker thread.

But when I call Run in worker thread. UI thread(primary thread) had frozen.(didn't response)

(They are separate thread...)

Finally, before Run() is finished, some calls to FilterGraph can't finish.

ex 1)

IMediaSeeking::GetCurrentPosition()

- I used to indicate current position.

- It is called in timer callback.

ex 2)

When video window is invalidated(need to repaint), user interface is frozen until Run() call finishes.

So you need to hide video window.





Re: DirectShow Development How to cancel an IMediaControl::Run call that takes too long

Art_99999

Just throwing out an idea:

- What if you explicitly destroy the new worker thread (even if the Run call takes too long) - will that be effective in

resolving the bandwidth usage

I'm not absolutely certain about this, but wouldn't that result in COM leaks if I don't ever release the IMediaControl interface that I'd need to call run on Also, I can imagine that within Run, there would be a bunch of interfaces it is using to download that would all be Addref'd and never released.

Like if I had code like:

Code Snippet

int ThreadProc(IGraphBuilder* piBuilder)

{

HRESULT hr = S_OK;

IMediaControl* piControl = NULL;

hr = piBuilder->QueryInterface(IID_IMediaControl,(void**)&piControl);

if(SUCCEEDED(hr))

{

hr = piControl->Run() // stops here forever, thread is killed here

}

piControl->Release();

}

If the thread was killed in the middle of Run, I'd think the IGraphBuilder would still have the outstanding reference from getting the piControl, and would never be properly releasable. Is this right Is there a way to design this so that I can release everything with having a crash I'm just a student, so my COM experience is limited.





Re: DirectShow Development How to cancel an IMediaControl::Run call that takes too long

ahmadR

I had imagined piControl to have the same scope as IGraphBuilder so it could be released outside of ThreadProc. But you're right, this can probably get messy wrt Run. I guess I would have to defer to someone else who could respond with greater knowledge of the consequences of this kind of thread termination. Still, it would be an interesting experiment to try.





Re: DirectShow Development How to cancel an IMediaControl::Run call that takes too long

Mt. Rabbit

You can get IWMReaderAdvanced2 interface from WMAsfReader source filter.

And that interface exposes IWMReaderAdvanced2:Tongue TiedtopBuffering() method.

I'm not sure that method will work. Good luck.





Re: DirectShow Development How to cancel an IMediaControl::Run call that takes too long


Re: DirectShow Development How to cancel an IMediaControl::Run call that takes too long

uglykid

Hi,

well in general it should be possible to get direct access to the internal WM reader object that is encapsulated by the WMASF Reader Filter.

Take a look at msdn for accessing the

IWMDRMReader-interface

through the service provider interface calling

"QueryService" function

From the resulting DRM interface instance you will then be able to directly access the internal WMAdvancedReader2 interface that is exposed by the WM reader object that is only encaspulated by the ASF fiter by calling the

QueryInterface

function with the advanced reader interface2 id as parameter.

I tested a call to stopbuffering on that reader2 interface and it returned S_OK (and not "E_NOT_IMPLEMENTED" or similar error) so i guess it is not 100% right that accessing these function is not possible! It might be right when using the filter's interface directloy but not for the native WM interface.

Keep me informed what you experienced!





Re: DirectShow Development How to cancel an IMediaControl::Run call that takes too long

Art_99999

Wow, what a chain of things to do! I'll try that right now. Thank you.

Edit:

That worked perfectly, thank you very much.