Dmitry Vergeles (SolveigMM) wrote: > Is there any way to play ASF file to contain any > compressed data (to say H264) with Windows Media Player > having usual DirectShow decoder (not DMO).
> If so, what software has to be installed (f.e. WMF > Runtime or WM Player )? Thanks in advance.
WMP7+ will read and parse the ASF using the WMASFReader and decode the audio and video streams using any DirectShow-compatible decoder, that is a DirectShow transform filter, a DMO or a VCM/ACM codec. This works as long as the correct media type is associated with the stream and the stream is either audio or video.
No special software is required but the usual DirectShow and WMF runtimes, which are already installed if WMP works.
Is there a specific problem you are having?
--
// Alessandro Angeli // MVP :: Digital Media // a dot angeli at psynet dot net
May be I've missed some key things from my last dealing with Winows Media 7.1 SDK. In this key could you please refer to a documentation article that says about decoders for ASF playing in windows media technologies may be DirectShow filters?
there is a section " Reading Windows Media files with the Windows Media Format SDK" that says -
the process of reading and decoding Windows Media is supported directly through the Windows Media Format SDK using codecs that are implemented as either Audio Codec Manager (ACM) or Video Codec Manager (VCM) installable codecs, or DirectX Media Objects (DMOs).
Moreover, since WMP player 6.4 had a different behaveour with WMP 7+ while playing Windows Media, it was possible to play ASF with usuall DirectShow decoder with 6.4 version but from WMP 7.0 only DMO decoders were used.
So, it herhaps that my concept are obsolete...
> Is there a specific problem you are having?
Yes I can't play ASF with h264 both by WMPlayer 9.0 and 10. It says that there is no appropreated codec. But if I render it in GraphEdit it is played properly. What cause for the problem may be?
> WMP7+ will read and parse the ASF using the WMASFReader and > decode the audio and video streams using any > DirectShow-compatible decoder, that is a DirectShow > transform filter, a DMO or a VCM/ACM codec. This works as > long as the correct media type is associated with the stream > and the stream is either audio or video.
> No special software is required but the usual DirectShow and > WMF runtimes, which are already installed if WMP works.
> Is there a specific problem you are having?
> --
> // Alessandro Angeli > // MVP :: Digital Media > // a dot angeli at psynet dot net
Dmitry Vergeles (SolveigMM) wrote: > May be I've missed some key things from my last dealing > with Winows Media > 7.1 SDK. In this key could you please refer to a > documentation article that says > about decoders for ASF playing in windows media > technologies may be DirectShow > filters?
There is none. Read below.
> In the article- "Microsoft Windows Media and DirectShow: > Options for Application Developers"
> there is a section " Reading Windows Media files with the > Windows Media Format > SDK" that says -
> the process of reading and decoding Windows Media is > supported directly through the Windows Media Format SDK > using codecs that are implemented as either Audio Codec > Manager (ACM) or Video Codec Manager (VCM) installable > codecs, or DirectX Media Objects (DMOs).
As far I understand it, this article refers to the WMReader object of the WMFSDK and not the WMASFReader filter in DirectShow. The WMReader object delivers decompressed data by default and it internally decompresses the stream using either DMOs or ACM/VCM codecs (this last bit is new to me, but let's believe what the article says).
WMP7+ uses the WMASFReader source filter which delivers compressed data instead, which is then decoded by a DirectShow filter in the playback graph (since you can only add filters to a graph). This filter can be the DMOWrapper, the ACMWrapper or the AVIDecompressor, but it should be possible to use any other filter, as your successful attempts in GraphEdit and WMP6.4 show.
> Moreover, since WMP player 6.4 had a different behaveour > with WMP 7+ while playing Windows Media, it was possible > to play ASF with usuall DirectShow decoder with 6.4 > version but from WMP 7.0 only DMO decoders were used.
> So, it herhaps that my concept are obsolete...
>> Is there a specific problem you are having?
> Yes I can't play ASF with h264 both by WMPlayer 9.0 and > 10. It says that there is no appropreated codec. > But if I render it in GraphEdit it is played properly. > What cause for the problem may be?
There are 3 known behaviors:
1. (WMP6.4) RenderFile() on a FilterGraphNoThread using the WMSourceFilter
2. (GE) RenderFile() on a FilterGraph using the WMASFReader
3. (WMP7+) semi-manual graph building in a FilterGraphNoThread using the WMASFReader
If your decoding filter works in GE and WMP6.4 (and you have both WMP9 and DX9 installed, otherwise there may be other issues), then the problem is how WMP7+ messes with the graph, which is mostly unknown, and the solution would be to find out what WMP7+ does that prevents your filter from working.
If you're game, I can provide techniques (which require C/C++) and tools to help troubleshoot this and I can help you do it, but there is no guarantee and no foreseeable time frame, unless someone from MSFT barges in and tells us the solution.
--
// Alessandro Angeli // MVP :: Digital Media // a dot angeli at psynet dot net
Alessandro, first of all thank you for the so detailed explanation..
> As far I understand it, this article refers to the WMReader > object of the WMFSDK and not the WMASFReader filter in > DirectShow. The WMReader object delivers decompressed data > by default and it internally decompresses the stream using > either DMOs or ACM/VCM codecs (this last bit is new to me, > but let's believe what the article says).
Hmm.. It sounds
> WMP7+ uses the WMASFReader source filter which delivers > compressed data instead, which is then decoded by a > DirectShow filter in the playback graph (since you can only > add filters to a graph). This filter can be the DMOWrapper, > the ACMWrapper or the AVIDecompressor, but it should be > possible to use any other filter, as your successful > attempts in GraphEdit and WMP6.4 show.
> There are 3 known behaviors:
> 1. (WMP6.4) RenderFile() on a FilterGraphNoThread using the > WMSourceFilter
I think indeed!
> 2. (GE) RenderFile() on a FilterGraph using the WMASFReader > 3. (WMP7+) semi-manual graph building in a > FilterGraphNoThread using the WMASFReader
One more thing is that except GraphEdit, the ASF files are played with DSPlay sample to be shipped with WMFSDK 9.
> If your decoding filter works in GE and WMP6.4 (and you have > both WMP9 and DX9 installed, otherwise there may be other > issues), then the problem is how WMP7+ messes with the > graph, which is mostly unknown, and the solution would be to > find out what WMP7+ does that prevents your filter from > working.
> If you're game, I can provide techniques (which require > C/C++) and tools to help troubleshoot this and I can help > you do it, but there is no guarantee and no foreseeable time > frame, unless someone from MSFT barges in and tells us the > solution.
[Sorry for the text/richtext, but it is better to preserve the code and the links.]
Dmitry Vergeles (SolveigMM) wrote: >> 2. (GE) RenderFile() on a FilterGraph using the >> WMASFReader >> 3. (WMP7+) semi-manual graph building in a >> FilterGraphNoThread using the WMASFReader
> One more thing is that except GraphEdit, the ASF files > are played with DSPlay sample to be shipped with WMFSDK 9.
DSPlay behaves exactly like GE.
> It sounds to be designing :) > I'm ready to try...
I'll explain about hooking and logging later. As a convention, I prefix hook function names with 'new' and the original function names with 'old'.
You need to create a C++ project for a DLL. This is the pseudo-code:
You need to inject this DLL inside the WMP process before it builds the graph: a good idea is to inject it when the process is created.
The easiest way to hook functions and inject DLLs into processes is to use Detours, a library from http://research.microsoft.com/sn/detours/ (the free 1.5 version is ok). It is possible to do it without, but it's not nearly as easy.
The withdll.exe sample can be used to create a process with an injected DLL (just remember to use the absolute path of the DLL or to put the DLL somewhere in the system %PATH%).
The first way is useful to hook API entrypoints, as shown, the second is more useful with interface methods (notice that an interface method always has a hidden first argument that is the this pointer to the interface, as shown).
Since I still haven't found a way to get a pointer to a virtual method in C++ that works, I just cast it to something the C++ compiler won't pester me about and get to it walking the vtable myself, as shown. You need to know the METHOD_OFFSET in the vtable, which you can find out easily by counting the methods in the interface definition (inluding inherited interfaces) so QueryInterface() in IUnknown (and thus in any COM interface) has offset 0 and, for example, RenderFile() in IGraphBuilder() is at offset 13.
Since C is much easier to deal with when it comes to vtables, you may choose to mix C and C++ (in which case I'll explain how to get a pointer to a method in C).
Now you know how to inject a DLL, hook an API entrypoint or hook an interface method.
To log, you can use any way you like. I write to a text file because this kind of I/O has no risk of a deadlock like GUI operations (since both the GUI and the graph will use the message pump, unless you use different synchronized threads) and is easier that network I/O, like pipes or sockets or whatever, and shared memory (however, network I/O and shared memory would allow you to write an external logging UI that shows the log in real-time). To implement logging to a file, you need an extern file handle and an extern mutex to prevent write operations in different threads to overlap.
---------------------------------------- FILE* f = NULL; HANDLE m = NULL;
OpenLogChannel() { f = fopen(...); m = CreateMutex(NULL,FALSE,NULL);
}
CloseLogChannel() { fclose(f); CloseHandle(m);
}
LogMessage(LPCSTR format, ...) { va_list va; va_start(va,format); WaitForSingleObject(m,INFINITE); vfprintf(f,format,va); ReleaseMutex(m);
}
----------------------------------------
This way LogMessage() works like printf() and it is very flexible. You can use the Unicode variants if you prefer a Unicode build.
And now all the building pieces are in place so, what should you log? That is, what should you do inside the routine I called HookGraphBuilder()?
For example, you could hook IGraphBuilder::RenderFile() in order to dump the graph contents before and after the actual call to the original method. You can dump the graph yourself or save it to a GRF file:
You can hook IFilterGraph::AddFilter(), IGraphBuilder::AddSourceFilter() and IFilterGraph2::AddSourceFilterForMoniker() to log whether WMP adds filters on its own.
You can also set your IAMFilterGraphCallback and IAMGraphBuilderCallback callbacks to be notified by the graph of errors in rendering the graph. If you do, call IObjectWithSite::GetSite() before IObjectWithSite::SetSite() to see whether WMP installed its own callbacks: if it did, cache the references and call them when your callbacks are called.
You can also ask the graph to log what it does on its own with IGraphBuilder::SetLogFile().
You can do all of this for a file that works and one that doesn't, to see what's different. You can do the same with WMP7+ and GE and WMP6.4... If you spy GE or DSPlay or other programs, in newCoCreateInstance() you should also accept CLSID_FilterGraph in addition to CLSID_FilterGraphNoThread().
This was a long message to write :-)
If you need support when you try this out, just ask on this same thread.
--
// Alessandro Angeli // MVP :: Digital Media // a dot angeli at psynet dot net
"Alessandro Angeli [MVP::DigitalMedia]" <nob...@nowhere.in.the.net> wrote in message news:u$AeuffNFHA.688@TK2MSFTNGP10.phx.gbl... [Sorry for the text/richtext, but it is better to preserve the code and the links.]
Dmitry Vergeles (SolveigMM) wrote:
>> 2. (GE) RenderFile() on a FilterGraph using the >> WMASFReader >> 3. (WMP7+) semi-manual graph building in a >> FilterGraphNoThread using the WMASFReader > > One more thing is that except GraphEdit, the ASF files > are played with DSPlay sample to be shipped with WMFSDK 9.
DSPlay behaves exactly like GE.
> It sounds to be designing :) > I'm ready to try...
I'll explain about hooking and logging later. As a convention, I prefix hook function names with 'new' and the original function names with 'old'.
You need to create a C++ project for a DLL. This is the pseudo-code:
You need to inject this DLL inside the WMP process before it builds the graph: a good idea is to inject it when the process is created.
The easiest way to hook functions and inject DLLs into processes is to use Detours, a library from http://research.microsoft.com/sn/detours/ (the free 1.5 version is ok). It is possible to do it without, but it's not nearly as easy.
The withdll.exe sample can be used to create a process with an injected DLL (just remember to use the absolute path of the DLL or to put the DLL somewhere in the system %PATH%).
The first way is useful to hook API entrypoints, as shown, the second is more useful with interface methods (notice that an interface method always has a hidden first argument that is the this pointer to the interface, as shown).
Since I still haven't found a way to get a pointer to a virtual method in C++ that works, I just cast it to something the C++ compiler won't pester me about and get to it walking the vtable myself, as shown. You need to know the METHOD_OFFSET in the vtable, which you can find out easily by counting the methods in the interface definition (inluding inherited interfaces) so QueryInterface() in IUnknown (and thus in any COM interface) has offset 0 and, for example, RenderFile() in IGraphBuilder() is at offset 13.
Since C is much easier to deal with when it comes to vtables, you may choose to mix C and C++ (in which case I'll explain how to get a pointer to a method in C).
Now you know how to inject a DLL, hook an API entrypoint or hook an interface method.
To log, you can use any way you like. I write to a text file because this kind of I/O has no risk of a deadlock like GUI operations (since both the GUI and the graph will use the message pump, unless you use different synchronized threads) and is easier that network I/O, like pipes or sockets or whatever, and shared memory (however, network I/O and shared memory would allow you to write an external logging UI that shows the log in real-time). To implement logging to a file, you need an extern file handle and an extern mutex to prevent write operations in different threads to overlap.
---------------------------------------- FILE* f = NULL; HANDLE m = NULL;
OpenLogChannel() { f = fopen(...); m = CreateMutex(NULL,FALSE,NULL); } CloseLogChannel() { fclose(f); CloseHandle(m); } LogMessage(LPCSTR format, ...) { va_list va; va_start(va,format); WaitForSingleObject(m,INFINITE); vfprintf(f,format,va); ReleaseMutex(m); } ----------------------------------------
This way LogMessage() works like printf() and it is very flexible. You can use the Unicode variants if you prefer a Unicode build.
And now all the building pieces are in place so, what should you log? That is, what should you do inside the routine I called HookGraphBuilder()?
For example, you could hook IGraphBuilder::RenderFile() in order to dump the graph contents before and after the actual call to the original method. You can dump the graph yourself or save it to a GRF file:
You can hook IFilterGraph::AddFilter(), IGraphBuilder::AddSourceFilter() and IFilterGraph2::AddSourceFilterForMoniker() to log whether WMP adds filters on its own.
You can also set your IAMFilterGraphCallback and IAMGraphBuilderCallback callbacks to be notified by the graph of errors in rendering the graph. If you do, call IObjectWithSite::GetSite() before IObjectWithSite::SetSite() to see whether WMP installed its own callbacks: if it did, cache the references and call them when your callbacks are called.
You can also ask the graph to log what it does on its own with IGraphBuilder::SetLogFile().
You can do all of this for a file that works and one that doesn't, to see what's different. You can do the same with WMP7+ and GE and WMP6.4... If you spy GE or DSPlay or other programs, in newCoCreateInstance() you should also accept CLSID_FilterGraph in addition to CLSID_FilterGraphNoThread().
This was a long message to write :-)
If you need support when you try this out, just ask on this same thread.
--
// Alessandro Angeli // MVP :: Digital Media // a dot angeli at psynet dot net
WMP 7+ always uses the WMF SDK to do decoding, which is restricted to VCM or DMO decoders. So hooking the DLLs below might be informative, but I'm not sure if you'll find anything too helpful. Maybe you'll find some way to hack the system, but it won't be an official, supported way to do things.
The "official" way to do what you want is to write the codec as a DMO.
Thanks, Geoff
-- This posting is provided "AS IS" with no warranties, and confers no rights.
"Dmitry Vergeles (SolveigMM)" <dark...@elecard.net.ru> wrote in message news:uYdtJynNFHA.1476@TK2MSFTNGP09.phx.gbl... wow, it looks to be impressive.. >>This was a long message to write :-) One may assume :))
"Alessandro Angeli [MVP::DigitalMedia]" <nob...@nowhere.in.the.net> wrote in message news:u$AeuffNFHA.688@TK2MSFTNGP10.phx.gbl... [Sorry for the text/richtext, but it is better to preserve the code and the links.]
Dmitry Vergeles (SolveigMM) wrote:
>> 2. (GE) RenderFile() on a FilterGraph using the >> WMASFReader >> 3. (WMP7+) semi-manual graph building in a >> FilterGraphNoThread using the WMASFReader > > One more thing is that except GraphEdit, the ASF files > are played with DSPlay sample to be shipped with WMFSDK 9.
DSPlay behaves exactly like GE.
> It sounds to be designing :) > I'm ready to try...
I'll explain about hooking and logging later. As a convention, I prefix hook function names with 'new' and the original function names with 'old'.
You need to create a C++ project for a DLL. This is the pseudo-code:
You need to inject this DLL inside the WMP process before it builds the graph: a good idea is to inject it when the process is created.
The easiest way to hook functions and inject DLLs into processes is to use Detours, a library from http://research.microsoft.com/sn/detours/ (the free 1.5 version is ok). It is possible to do it without, but it's not nearly as easy.
The withdll.exe sample can be used to create a process with an injected DLL (just remember to use the absolute path of the DLL or to put the DLL somewhere in the system %PATH%).
The first way is useful to hook API entrypoints, as shown, the second is more useful with interface methods (notice that an interface method always has a hidden first argument that is the this pointer to the interface, as shown).
Since I still haven't found a way to get a pointer to a virtual method in C++ that works, I just cast it to something the C++ compiler won't pester me about and get to it walking the vtable myself, as shown. You need to know the METHOD_OFFSET in the vtable, which you can find out easily by counting the methods in the interface definition (inluding inherited interfaces) so QueryInterface() in IUnknown (and thus in any COM interface) has offset 0 and, for example, RenderFile() in IGraphBuilder() is at offset 13.
Since C is much easier to deal with when it comes to vtables, you may choose to mix C and C++ (in which case I'll explain how to get a pointer to a method in C).
Now you know how to inject a DLL, hook an API entrypoint or hook an interface method.
To log, you can use any way you like. I write to a text file because this kind of I/O has no risk of a deadlock like GUI operations (since both the GUI and the graph will use the message pump, unless you use different synchronized threads) and is easier that network I/O, like pipes or sockets or whatever, and shared memory (however, network I/O and shared memory would allow you to write an external logging UI that shows the log in real-time). To implement logging to a file, you need an extern file handle and an extern mutex to prevent write operations in different threads to overlap.
---------------------------------------- FILE* f = NULL; HANDLE m = NULL;
OpenLogChannel() { f = fopen(...); m = CreateMutex(NULL,FALSE,NULL); } CloseLogChannel() { fclose(f); CloseHandle(m); } LogMessage(LPCSTR format, ...) { va_list va; va_start(va,format); WaitForSingleObject(m,INFINITE); vfprintf(f,format,va); ReleaseMutex(m); } ----------------------------------------
This way LogMessage() works like printf() and it is very flexible. You can use the Unicode variants if you prefer a Unicode build.
And now all the building pieces are in place so, what should you log? That is, what should you do inside the routine I called HookGraphBuilder()?
For example, you could hook IGraphBuilder::RenderFile() in order to dump the graph contents before and after the actual call to the original method. You can dump the graph yourself or save it to a GRF file:
You can hook IFilterGraph::AddFilter(), IGraphBuilder::AddSourceFilter() and IFilterGraph2::AddSourceFilterForMoniker() to log whether WMP adds filters on its own.
You can also set your IAMFilterGraphCallback and IAMGraphBuilderCallback callbacks to be notified by the graph of errors in rendering the graph. If you do, call IObjectWithSite::GetSite() before IObjectWithSite::SetSite() to see whether WMP installed its own callbacks: if it did, cache the references and call them when your callbacks are called.
You can also ask the graph to log what it does on its own with IGraphBuilder::SetLogFile().
You can do all of this for a file that works and one that doesn't, to see what's different. You can do the same with WMP7+ and GE and WMP6.4... If you spy GE or DSPlay or other programs, in newCoCreateInstance() you should also accept CLSID_FilterGraph in addition to CLSID_FilterGraphNoThread().
This was a long message to write :-)
If you need support when you try this out, just ask on this same thread.
--
// Alessandro Angeli // MVP :: Digital Media // a dot angeli at psynet dot net
Geoff Dunbar [MSFT] wrote: > WMP 7+ always uses the WMF SDK to do decoding, which is > restricted to VCM or DMO decoders. So hooking the DLLs > below might be informative, but I'm not sure if you'll > find anything too helpful.
Geoff, you're being a bit cryptic :-) However, I had a second look at what WMP9 does and it was *very* informative: it uses an undocumented private "WMRenderer Source Filter" which delivers uncompressed samples. So it behaves very differently from both the global (and documented) WM source filters used by GraphEdit, WMP6.4 and WMP7, which deliver compressed samples to be decompressed by whatever decoding filter there is (including, but not limited to, wrapped VCM/ACM/DMO decoders).
(* = undocumented private filters/DMOs; their name is quoted because it is the instance's name and not the class' friendly name, which is unknown since they have no entry in the registry)
> Maybe you'll find some way to > hack the system, but it won't be an official, supported > way to do things.
Since the source filter is not the WMASFReader and the decoding is done *inside* the source filter, it would be very hard to hack it to make it use a general DirectShow filter.
> The "official" way to do what you want is to write the > codec as a DMO.
The WMP, WMF *and* DirectShow SDKs should clearly state that WMP9+ does not use either the WMSourceFilter or the WMASFReader but it uses an internal source filter that behaves in a very different way, that is it performs the decoding internally using WMF instead of externally, deferring it to DirectShow like previous WMP versions and other DirectShow-based applications do, and so it is limited to installed VCM/ACM/DMO decoders and incapable of taking advantage of DirectShow filters as one would expect.
--
// Alessandro Angeli // MVP :: Digital Media // a dot angeli at psynet dot net
At last I have found the time to realize the things you have described me. I have some troubles (probably with my understanding). I wrote my dll (denote it my_library.dll) and was trying to trace by debugger (MS VC++ 6.0) DllEntryPoint of my DLL.
I set the following parameters :
Executable for debug session: E:\PROJECTS\Misk\detours\samples\bin\withdll.exe
Program arguments: -d:E:\PROJECTS\Misk\my_library\Debug\my_library.dll C:\Program Files\Windows Media Player\wmplayer.exe
When I start debugging, withdll.exe runs wmplayer.exe but doesn't call my DllMain routine. Moreover I have a look at withdll sources and haven't found an obvious calling of LoadLibrary routine...
Dmitry Vergeles (SolveigMM) wrote: > Hi Allesandro,
> At last I have found the time to realize the things you > have described me. > I have some troubles (probably with my understanding). > I wrote my dll (denote it my_library.dll) and was trying > to trace by debugger (MS VC++ 6.0) DllEntryPoint of my > DLL.
> I set the following parameters :
> Executable for debug session: > E:\PROJECTS\Misk\detours\samples\bin\withdll.exe
> Program arguments: > -d:E:\PROJECTS\Misk\my_library\Debug\my_library.dll > C:\Program Files\Windows Media Player\wmplayer.exe
> When I start debugging, withdll.exe runs wmplayer.exe but > doesn't call my DllMain routine. > Moreover I have a look at withdll sources and haven't > found an obvious calling of LoadLibrary routine...
> Could you please explain me what is wrong?
I don't think anything is wrong.
withdll.exe uses Detours' DetourCreateProcessWithDll() to create another process for wmplayer.exe, completely independent, and quits immediately after that. The created process is however altered to cause wmplayer.exe to load your DLL, that's why withdll.exe never loads it: it is loaded in the spawned wmplayer.exe process. That was the whole point: run wmplayer.exe and spy on it by loading a DLL in *its* process space.
I think you will have a hard time using a debugger to cross process boundaries, hence the easier file logging technique :-)
Anyway, if you are trying this out of curiosity, go ahead (it's an interesting exercise in system hacking :-)), otherwise take a look at my reply to Geoff to have the solution to your original problem served to you.
--
// Alessandro Angeli // MVP :: Digital Media // a dot angeli at psynet dot net
> withdll.exe uses Detours' DetourCreateProcessWithDll() to > create another process for wmplayer.exe, completely > independent, and quits immediately after that. The created > process is however altered to cause wmplayer.exe to load > your DLL, that's why withdll.exe never loads it: it is > loaded in the spawned wmplayer.exe process. That was the > whole point: run wmplayer.exe and spy on it by loading a DLL > in *its* process space.
> I think you will have a hard time using a debugger to cross > process boundaries, hence the easier file logging technique > :-)
> Anyway, if you are trying this out of curiosity, go ahead > (it's an interesting exercise in system hacking :-)), > otherwise take a look at my reply to Geoff to have the > solution to your original problem served to you.
I understood about my debugging faults. As for your reply to Geoff, you write:
>>However, I had asecond look at what WMP9 does and it was *very* informative: >>it uses an undocumented private "WMRenderer Source Filter" >>which delivers uncompressed samples.
Was you look as you described (with detours lib)?
>>it performs the decoding internally using WMF instead of externally, >>deferring it to DirectShow like previous WMP versions and >>other DirectShow-based applications do, and so it is limited >>to installed VCM/ACM/DMO decoders and incapable of taking >>advantage of DirectShow filters as one would expect.
As far as I understand that is the answer for my initial question. And it sounds as: only VCM/DMO video decoders are used by WMP to play ASF. Isn't it?
If so, there is one interesting thing have happened during this thread evolution. We have performed some tests on various PCs and found two PCs where our ASF contained H264 was normally played by WMP with DirectShow decoder... One PC had WMP9, another WMP10.
This fact, your and Geoff's conclusions have confused all finally :)
Dmitry Vergeles (SolveigMM) wrote: >>> However, I had asecond look at what WMP9 does and it >>> was *very* informative: it uses an undocumented private >>> "WMRenderer Source Filter" >>> which delivers uncompressed samples.
> Was you look as you described (with detours lib)?
Yes.
>>> it performs the decoding internally using WMF instead >>> of externally, deferring it to DirectShow like previous >>> WMP versions and >>> other DirectShow-based applications do, and so it is >>> limited >>> to installed VCM/ACM/DMO decoders and incapable of >>> taking >>> advantage of DirectShow filters as one would expect.
> As far as I understand that is the answer for my initial > question. > And it sounds as: only VCM/DMO video decoders are used by > WMP to play ASF. > Isn't it?
With WMP9+, yes, only WMM codecs and DMOs. With any other DirectShow-based application, including WMP6.4 and WMP7 (IIRC, but I don't know and WMP8), a filter should be fine. That's because WMP9+ does not use DirectShow to decode the streams but only to render them.
> If so, there is one interesting thing have happened > during this thread evolution. > We have performed some tests on various PCs and found two > PCs where our ASF contained H264 was normally played by > WMP with DirectShow decoder... > One PC had WMP9, another WMP10.
> This fact, your and Geoff's conclusions have confused all > finally :)
That's "interesting" :-) Let's see if I can send you a small tool that will tell us what filters are used on those 2 PCs. Did you install something different on each PC or do all of them have the same configuration, apart from the version of WMP?
--
// Alessandro Angeli // MVP :: Digital Media // a dot angeli at psynet dot net
> Dmitry Vergeles (SolveigMM) wrote: *snip* > > If so, there is one interesting thing have happened > > during this thread evolution. > > We have performed some tests on various PCs and found two > > PCs where our ASF contained H264 was normally played by > > WMP with DirectShow decoder... > > One PC had WMP9, another WMP10.
> > This fact, your and Geoff's conclusions have confused all > > finally :)
> That's "interesting" :-) Let's see if I can send you a small > tool that will tell us what filters are used on those 2 PCs. > Did you install something different on each PC or do all of > them have the same configuration, apart from the version of > WMP?
I'm not quite sure how that could be working, but I certainly can't disprove what you've seen with your own two eyes. In any case, I encourage you to work towards a DMO solution as that is the officially supported solution.
Geoff
-- This posting is provided "AS IS" with no warranties, and confers no rights.
> Geoff, you're being a bit cryptic :-) However, I had a > second look at what WMP9 does and it was *very* informative: > it uses an undocumented private "WMRenderer Source Filter" > which delivers uncompressed samples. So it behaves very > differently from both the global (and documented) WM source > filters used by GraphEdit, WMP6.4 and WMP7, which deliver > compressed samples to be decompressed by whatever decoding > filter there is (including, but not limited to, wrapped > VCM/ACM/DMO decoders).
*snip*
Sorry for being cryptic... it is not my intention. As you say below WMP uses its own private filter for rendering ASF files, and this filter always uses codec decoders _inside_ the WMF SDK. Which means only ACM/VCM/DMO are supported.
Also, a small correction... WMP 7 also uses the private filter. The big change was between WMP 6.4 and WMP 7. It is possible that WMP 7 and WMP 9 have different behaviors in the codec area, though nothing springs to mind immediately.
*snip*
> The WMP, WMF *and* DirectShow SDKs should clearly state that > WMP9+ does not use either the WMSourceFilter or the > WMASFReader but it uses an internal source filter that > behaves in a very different way, that is it performs the > decoding internally using WMF instead of externally, > deferring it to DirectShow like previous WMP versions and > other DirectShow-based applications do, and so it is limited > to installed VCM/ACM/DMO decoders and incapable of taking > advantage of DirectShow filters as one would expect.
*snip*
I agree that the documentation could be more clear in this area; the best I can advise is to ask questions in this forum.
Also to anyone reading this discussion, I wrote a fair amount of the code in question, so in theory I know what I'm talking about. But I often find that the MVPs like Alessandro have a better grasp on how things work in the real world. :-)
Geoff
-- This posting is provided "AS IS" with no warranties, and confers no rights.
> > That's "interesting" :-) Let's see if I can send you a small > tool that will tell us what filters are used on those 2 PCs. > Did you install something different on each PC or do all of > them have the same configuration, apart from the version of > WMP?
After my investigation with help of the spy dll you've sent me I have to admit that I was wrong. Both PCs had VFW decoders installed that we've noticed after the spy dll logs reading. I'm sorry for you spent your time because of my carelessnes :)
Dmitry Vergeles (SolveigMM) wrote: > After my investigation with help of the spy dll you've > sent me I have to admit that I was wrong. > Both PCs had VFW decoders installed that we've noticed > after the spy dll logs reading. > I'm sorry for you spent your time because of my > carelessnes :)
Never mind, at least the DLL was useful to you and the result is coherent with what Geoff told us :-)
--
// Alessandro Angeli // MVP :: Digital Media // a dot angeli at psynet dot net
Geoff Dunbar [MSFT] wrote: > Also, a small correction... WMP 7 also uses the private > filter. The big change was between WMP 6.4 and WMP 7. It > is possible that WMP 7 and WMP 9 have different behaviors > in the codec area, though nothing springs to mind > immediately.
Of course you're right: WMP7 behaves like WMP9 and doesn't use the WMASFReader but its own source filter.
--
// Alessandro Angeli // MVP :: Digital Media // a dot angeli at psynet dot net