Bob Dellaca
2005-01-12 02:38:42 UTC
This is a follow-up to a thread started in this group last October by
Dale Ingold (now lost from my news server).
Here is one way to get the WM ASF Reader filter in a filter graph to
accept WMV or ASF input from a stream. In brief, it involves defining
your own "custom file type" as a "protocol" and getting the ASF Reader
filter to accept an IStream from your application when the filter is
asked to render a file of that custom protocol. Two registry keys need
to be added and a short DLL needs to be written; other than that, the
application needs to be able to supply an IStream interface object
when the filter graph is built.
This works with version 9 of DirectX.
Select your own protocol name such as "myProt", so that the ASF Reader
filter can be asked to render a file such as "myProt://something".
1. As listed in the DirectShow SDK Help, register the protocol under
the key
HKEY_CLASSES_ROOT\myProt
with a (string) entry named "Source Filter" for the GUID for the WM
ASF Reader filter
Source Filter = {187463A0-5BB7-11D3-ACBE-0080C75E246E}
2. As listed in the WM SDK WMFormat Help, register a DLL as a Source
Plug-in for the myProt protocol under the key
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows Media\WMSDK\sources
with a (string) entry, let's call it "myProt", for the full filename
of the DLL (here named "myProt")
myProt = c:\fullpathname\myProt.dll
3. Create a DLL, here named myProt, that exports the function
WMCreateStreamForURL
library myProt;
function WMCreateStreamForURL(pwszURL: PWideChar;
out pfCorrectSource: BOOL;
var pStream: IStream): HRESULT; stdcall;
exports
WMCreateStreamForURL;
As listed in the WM SDK, WMCreateStreamForURL has to output a pointer
to an IStream if it can handle the input "file". Thus, if the myProt
DLL sees a file named "myProt://something" it should set
pfCorrectSource to True and set pStream to point to the IStream;
otherwise it should set pfCorrectSource to False and set pStream to
nil.
4. In the application, define an IStream interface object, create an
instance of it, create a filter graph, and render a "file" of the
"myProt" protocol "somehow" passing the derived IStream object pointer
to the WMCreateStreamForURL function in the DLL (one method is to
include the address of the IStream in the file "name" - the "file"
might then be for example "myProt://$9e4238")
type
TmyProtStream = class(TInterfacedObject, IStream)
[...]
end;
var
myProtStream: TmyProtStream;
pBuild: ICaptureGraphBuilder2;
pGraph: IGraphBuilder;
aFileName: string;
wFileName: WideString;
begin
myProtStream := TmyProtStream.Create(...);
CoCreateInstance(CLSID_FilterGraph, nil, CLSCTX_INPROC_SERVER,
IID_IFilterGraph2, pGraph);
CoCreateInstance(CLSID_CaptureGraphBuilder2, nil,
CLSCTX_INPROC_SERVER,
IID_ICaptureGraphBuilder2, pBuild);
pBuild.SetFiltergraph(pGraph);
[add other filters]
aFileName := Format('myProt://$%x', [Integer(myProtStream as
IStream)]);
wFileName := aFileName;
pGraph.RenderFile(@wFileName[1], nil);
[...]
pGraph := nil;
The IStream methods Read, Seek & Stat are called by the ASF Reader
filter; it appears that the other methods can be written as not
implemented. It also appears that the ASF Reader filter releases the
IStream interface when the filter graph is released (as one might hope
for but not necessarily see), so that there is no need to free or
release myProtStream in the above example.
If anyone is interested, I can post some sample code.
Bob Dellaca
Dale Ingold (now lost from my news server).
Here is one way to get the WM ASF Reader filter in a filter graph to
accept WMV or ASF input from a stream. In brief, it involves defining
your own "custom file type" as a "protocol" and getting the ASF Reader
filter to accept an IStream from your application when the filter is
asked to render a file of that custom protocol. Two registry keys need
to be added and a short DLL needs to be written; other than that, the
application needs to be able to supply an IStream interface object
when the filter graph is built.
This works with version 9 of DirectX.
Select your own protocol name such as "myProt", so that the ASF Reader
filter can be asked to render a file such as "myProt://something".
1. As listed in the DirectShow SDK Help, register the protocol under
the key
HKEY_CLASSES_ROOT\myProt
with a (string) entry named "Source Filter" for the GUID for the WM
ASF Reader filter
Source Filter = {187463A0-5BB7-11D3-ACBE-0080C75E246E}
2. As listed in the WM SDK WMFormat Help, register a DLL as a Source
Plug-in for the myProt protocol under the key
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows Media\WMSDK\sources
with a (string) entry, let's call it "myProt", for the full filename
of the DLL (here named "myProt")
myProt = c:\fullpathname\myProt.dll
3. Create a DLL, here named myProt, that exports the function
WMCreateStreamForURL
library myProt;
function WMCreateStreamForURL(pwszURL: PWideChar;
out pfCorrectSource: BOOL;
var pStream: IStream): HRESULT; stdcall;
exports
WMCreateStreamForURL;
As listed in the WM SDK, WMCreateStreamForURL has to output a pointer
to an IStream if it can handle the input "file". Thus, if the myProt
DLL sees a file named "myProt://something" it should set
pfCorrectSource to True and set pStream to point to the IStream;
otherwise it should set pfCorrectSource to False and set pStream to
nil.
4. In the application, define an IStream interface object, create an
instance of it, create a filter graph, and render a "file" of the
"myProt" protocol "somehow" passing the derived IStream object pointer
to the WMCreateStreamForURL function in the DLL (one method is to
include the address of the IStream in the file "name" - the "file"
might then be for example "myProt://$9e4238")
type
TmyProtStream = class(TInterfacedObject, IStream)
[...]
end;
var
myProtStream: TmyProtStream;
pBuild: ICaptureGraphBuilder2;
pGraph: IGraphBuilder;
aFileName: string;
wFileName: WideString;
begin
myProtStream := TmyProtStream.Create(...);
CoCreateInstance(CLSID_FilterGraph, nil, CLSCTX_INPROC_SERVER,
IID_IFilterGraph2, pGraph);
CoCreateInstance(CLSID_CaptureGraphBuilder2, nil,
CLSCTX_INPROC_SERVER,
IID_ICaptureGraphBuilder2, pBuild);
pBuild.SetFiltergraph(pGraph);
[add other filters]
aFileName := Format('myProt://$%x', [Integer(myProtStream as
IStream)]);
wFileName := aFileName;
pGraph.RenderFile(@wFileName[1], nil);
[...]
pGraph := nil;
The IStream methods Read, Seek & Stat are called by the ASF Reader
filter; it appears that the other methods can be written as not
implemented. It also appears that the ASF Reader filter releases the
IStream interface when the filter graph is released (as one might hope
for but not necessarily see), so that there is no need to free or
release myProtStream in the above example.
If anyone is interested, I can post some sample code.
Bob Dellaca