I used CSource and CSourceStream for my DirectShow source filter
to implement a transport mechanism based on the push-mode.
This is working fine, because the handling of the fillbuffer() method is
easy.
Now I also like to have support for the pull-mode IAsyncReader because
most mpeg2 demultiplexers need it.
But it seems not to be simple to do that.
So I also inherit from IAsyncReader in my outputpin class.
Now I have to implement these methods of this interface:
HRESULT IAsyncReader::RequestAllocator(IMemAllocator *,ALLOCATOR_PROPERTIES
*,IMemAllocator ** )
HRESULT IAsyncReader::Request(IMediaSample *,DWORD_PTR)
HRESULT IAsyncReader::WaitForNext(DWORD,IMediaSample ** ,DWORD_PTR *)
HRESULT IAsyncReader::SyncReadAligned(IMediaSample *)
HRESULT IAsyncReader::SyncRead(LONGLONG,LONG,BYTE *)
HRESULT IAsyncReader::Length(LONGLONG *,LONGLONG *)
HRESULT IAsyncReader::BeginFlush(void)
HRESULT IAsyncReader::EndFlush(void)
But this only is not working because in preparation phase on connecting
between my source
filter and the pull-mode demuxer (what is done by the graphbuilder) I got an
error : E_NOINTERFACE.
I have debugged it a little bit and this error occurs, because the hidden
function "AttemptConnect()"
ask for the wrong interface on the input-pin: IMemInputPin (the push model).
That's the reason for connection failure.
But it should ask for the IAsyncReader support (at least as a second try)!
So how I can adjust this?
Maybe, I cannot use CSource & CSourceStream to implement both transport
mechanisms (pull & push)
but then I have to start with CBaseFilter & CBasePin, so there is a lot of
more work to do...
for both mechanisms.
Thanks for any help.
Regards,
Robin Siegemund.
> Hello!
>
> I used CSource and CSourceStream for my DirectShow source filter
> to implement a transport mechanism based on the push-mode.
> This is working fine, because the handling of the fillbuffer() method is
> easy.
>
> Now I also like to have support for the pull-mode IAsyncReader because
> most mpeg2 demultiplexers need it.
>
> But it seems not to be simple to do that.
> So I also inherit from IAsyncReader in my outputpin class.
> Now I have to implement these methods of this interface:
This is probably a silly question, bu thave you looked at the AsyncFilter
sample? I've written one or two filters based around this and had no
particular problems doing so.
If nothing else you can compare it to what your code does...
Iain
--
Iain Downs (DirectShow MVP)
Software Product Consultant
www.idcl.co.uk
I don't see your point! The microsoft example is not using CSource and
CSourceStream.
And this is where my question occured: Can I implement the IAsyncReader
based on these classes and NOT on CBaseFilter / CBasePin like in the sample.
This should be the most easiest way to get both modes (pull/push) together.
Sorry, but do better reading (and quoting) next time, before call my
questions silly.
Robin.
> I don't see your point! The microsoft example is not
> using CSource and CSourceStream.
And that is Iain's point.
> And this is where my question occured: Can I implement
> the IAsyncReader based on these classes and NOT on
> CBaseFilter / CBasePin like in the sample. This should be
> the most easiest way to get both modes (pull/push)
> together.
CSource/CSourceStream (from the BaseClasses) are base
classes useful to write push-mode source filters that use
IMemInputPin.
CAsyncReader/CAsyncStream (from the Async sample) are base
classes useful to write pull-mode source filters that
implement IAsyncReader.
If you want to mix the 2 transports you need to write a
filter from scratch or using more primitive base classes or
you need to heavily modify one pair of the above base
classes to also support the other transport.
> Sorry, but do better reading (and quoting) next time,
What about some RTFM instead?
> before call my questions silly.
Iain didn't call *your* question silly but *his* own.
--
// Alessandro Angeli
// MVP :: Digital Media
// a dot angeli at psynet dot net
The problem on the microsoft example is, that it is using a lot
of seperated classes mixed together, so to get an overview
is not so easy.
Now I have a first implementation of IAsyncSource based
on the ideas of the mircosoft sample but I do not using their
classes.
Because I need no file access... and this is the problem now.
Are their any resource available, how it's best to use
IAsyncSource (pull mode) with network sources instead
file sources?
Because the most useful mpeg2 demultiplexers only
support the pull interface.
But I have no file access... I get a stream from network.
Regards,
Robin.
> The problem on the microsoft example is, that it is using
> a lot of seperated classes mixed together, so to get an
> overview
> is not so easy.
>
> Now I have a first implementation of IAsyncSource based
> on the ideas of the mircosoft sample but I do not using
> their classes.
> Because I need no file access... and this is the problem
> now.
From the Async sample you only need 4 files: asyncio.cpp,
asyncio.h, asyncrdr.cpp, asyncrdr.h. The only modification
needed IIRC is to comment out #include "asyncflt.h" in
asyncrdr.cpp.
Derive your filter from CAsyncReader and its output pin from
CAsyncStream.
Add whatever initialization interface you like to the filter
(I used IFileSourceFilter, but a custom interface would be
ok, too).
Override the following methods on the pin: SetPointer(),
Read(), Size(), Alignment(), Lock(), Unlock(). The
Lock()/Unlock() pair can just execute a Lock()/Unlock() on a
private member CCritSec. The Alignment() can just return 1
(or whatever packet size your network protocol requires).
SetPointer(), Read(), Size() must be implemented according
to how your protocol works (SetPointer() and Size() may need
to return an error).
> Are their any resource available, how it's best to use
> IAsyncSource (pull mode) with network sources instead
> file sources?
>
> Because the most useful mpeg2 demultiplexers only
> support the pull interface.
> But I have no file access... I get a stream from network.
Pull-mode uses random access to the source stream where all
the stream is available at any moment while a network source
is usually a sequential stream where only the current
samples are available so it is not easy to write a pull-mode
source filter for a network source, hence your problems. You
need to do any needed buffering to simulate random access:
this what the URLReader does, to the extent that it fully
transfers a stream an buffers it to disk when a request is
made to read a part of the stream that it does not yet have.
Thanks for your verbose comments.
Actually I don't implement the IAsyncReader interface in this
way, how you have described it.
I only use 2 classes with these methods (only methods declarations listed):
class CWrapperStream :
public IAsyncReader,
public CBasePin
{
CWrapperStream(HRESULT *phr, CDShowWrapper *pParent, LPCWSTR pPinName);
STDMETHODIMP NonDelegatingQueryInterface(REFIID, void**);
STDMETHODIMP Connect(IPin * pReceivePin, const AM_MEDIA_TYPE *pmt);
HRESULT InitAllocator(IMemAllocator **ppAlloc);
STDMETHODIMP RequestAllocator(IMemAllocator *,ALLOCATOR_PROPERTIES
*,IMemAllocator ** );
STDMETHODIMP Request(IMediaSample *,DWORD_PTR);
STDMETHODIMP WaitForNext(DWORD,IMediaSample ** ,DWORD_PTR *);
STDMETHODIMP SyncReadAligned(IMediaSample *);
STDMETHODIMP SyncRead(LONGLONG,LONG,BYTE *);
STDMETHODIMP Length(LONGLONG *,LONGLONG *);
STDMETHODIMP BeginFlush(void);
STDMETHODIMP EndFlush(void);
HRESULT GetMediaType(int iPosition, CMediaType *pmt);
HRESULT CheckMediaType(const CMediaType *pMediaType);
};
class CDShowWrapper :
public CBaseFilter,
public IDShowWrapper
{
CDShowWrapper(LPUNKNOWN lpunk, HRESULT *phr);
~CDShowWrapper();
static CUnknown *WINAPI CreateInstance(LPUNKNOWN punk, HRESULT *phr);
int GetPinCount(){return 1;}
CBasePin *GetPin(int n);
};
From the IAsyncInterface I have only implemented the methods
Length(), SynRead(), RequestAllocator() because the other methods
will be not called by any demultiplexer so far (I tested it with deb.
breakpoints).
As you have written, I use streaming over network and
have no file access.
So, in my application (that is using this filter) I established a simple
buffer mechanism for prebuffering data, so the demuxer
could config itself with some data before playing.
But there are 2 big problems so far:
1.
Some (pull mode, of course) demultiplexers don't connect
because the AttemptConnect() Method in the background producing this error:
"Cannot modify or delete an object that was added using the COM+ Admin SDK".
I don't understand what's going wrong here.
2.
When the demultiplexer connects (where the first problem does not occur),
it is working with file-access... BUT only with correct initialisations
in the Length() Method of the IASyncInterface.
So I have to limit the access to the size of my prebuffer, something like
this:
STDMETHODIMP CWrapperStream::Length(LONGLONG *pTotal,LONGLONG *pAvailable)
{
*pTotal=buffersize;
*pAvailable=buffersize;
return S_OK;
}
But then, it will only play the stream to the specified buffersize (some
frames).
If I specify *pTotal to a much bigger value, I have an illegal access like
problem.
The only may working trick I can see here is to set the size of pTotal later
to a very big size, after the automatic demuxer precaching/configuring.
But I have no access to this specified pTotal length, isn't it? ;-(
Regards,
Robin Siegemund
> From the Async sample you only need 4 files: asyncio.cpp,
> asyncio.h, asyncrdr.cpp, asyncrdr.h. The only modification
> needed IIRC is to comment out #include "asyncflt.h" in
> asyncrdr.cpp.
>
> Derive your filter from CAsyncReader and its output pin from
> CAsyncStream.
>
> Add whatever initialization interface you like to the filter
> (I used IFileSourceFilter, but a custom interface would be
> ok, too).
>
> Override the following methods on the pin: SetPointer(),
> Read(), Size(), Alignment(), Lock(), Unlock(). The
> Lock()/Unlock() pair can just execute a Lock()/Unlock() on a
> private member CCritSec. The Alignment() can just return 1
> (or whatever packet size your network protocol requires).
> SetPointer(), Read(), Size() must be implemented according
> to how your protocol works (SetPointer() and Size() may need
> to return an error).
>
> 1.
> Some (pull mode, of course) demultiplexers don't connect
> because the AttemptConnect() Method in the background
> producing this error: "Cannot modify or delete an object
> that was added using the COM+ Admin SDK". I don't
> understand what's going wrong here.
The HRESULT would be much more informative than the message.
> 2.
> When the demultiplexer connects (where the first problem
> does not occur), it is working with file-access... BUT
> only with correct initialisations
> in the Length() Method of the IASyncInterface.
> So I have to limit the access to the size of my
> prebuffer, something like this:
>
> STDMETHODIMP CWrapperStream::Length(LONGLONG
> *pTotal,LONGLONG *pAvailable) {
> *pTotal=buffersize;
> *pAvailable=buffersize;
> return S_OK;
> }
>
> But then, it will only play the stream to the specified
> buffersize (some frames).
> If I specify *pTotal to a much bigger value, I have an
> illegal access like problem.
Well, this looks like a bug in your implementation. Did you
check (with a debugger, maybe) where in the call stack the
exception occours?
> The only may working trick I can see here is to set the
> size of pTotal later to a very big size, after the
> automatic demuxer precaching/configuring.
I don't think you'll find many splitters (or players) that
will notice when the total length has changed. What splitter
did you try?
> But I have no access to this specified pTotal length,
> isn't it? ;-(
That depends on your protocol.
Did you try to set both the total and available sizes to the
actual length (or some large value), as if the stream where
local, then, when asked to read a segment you haven't yet
received, block until you receive it.
The problem with the size of the stream seems to be solved.
I simulated (for test purposes) a limited access to the first 100KB
of a file and it's working. So it should work with a seperated buffer later,
too.
And hey, the errormessage "Cannot modify or delete an object
that was added using the COM+ Admin SDK"
IS the HRESULT message.
Greetings,
Robin Siegemund
> And hey, the errormessage "Cannot modify or delete an
> object
> that was added using the COM+ Admin SDK"
> IS the HRESULT message.
I don't doubt that's the message associated with the HRESULT
but that's not the HRESULT itself since an HRESULT is a 32
bit integer which conveys more information than the message
and can not be really inferred from the message.
I'm implementing a source filter base on CAsyncReader/CAsyncStream for a
pull-mode MEPG2-PS source filter to work with default MPEG-2 Demultiplexer.
The problem is either my filter nor the AsyncFilter sample that implements
from the CAsyncReader/CAsyncStream are having problem to connect with
default MPEG-2 Demultiplexer. But the default File Source (Async.) doesn't
have the above problem
Is there any one knows how to make AsyncFilter sample works with properly
default MPEG-2 Demultiplexer?
Thanks for any kind of help.
Regards,
Peter
> Sorry for inserting another question here.
Please don't post the same question in different threads.
It's annoying and makes traking your problem harder.
--
// Alessandro Angeli
// MVP :: DirectShow / MediaFoundation
I need help to develop a PUSH source filter. I am getting data from a USB
device and store it in a BYTE buffer but I dont know how to give this data
to a output pin. Please guide me, I dont want to parse the data received, I
just want to deliver the data as it is from the device to the Output pin.
Please advice.
> I need help to develop a PUSH source filter. I am getting
> data from a USB device and store it in a BYTE buffer but
> I dont know how to give this data to a output pin. Please
> guide me, I dont want to parse the data received, I just
> want to deliver the data as it is from the device to the
> Output pin.
1. A push source filter does not implement IAsyncReader on
its output pins but uses the downstream IMemInputPin.
2. How should we know how your internal code works? How is
your source filter/pin implemented?
CBaseFilter/CBaseOutpuPin, CSource/CSourceStream, custom
code... Is it C++ or C# or...?
--
// Alessandro Angeli
// MVP :: DirectShow / MediaFoundation
// mvpnews at riseoftheants dot com
// http://www.riseoftheants.com/mmx/faq.htm
I am new to the DirecShow and tried the PUSH source sample filter but I am
very much confused.I understand the code but I dont know about the methods
GetDeliveryBuffer, GetBuffer, FillBuffer, GetMediaType, SetMediaType,
Deliver and DecideBufferSize what they are doing. I dont how this method has
been called and when it will be called.
In the DirectShow PUSH source sample they are converting the pixel data into
VIDEOINFO but in my case I am getting a Transport Stream data and I just
want that TS data to deliver at the output pin.
I am implementing in VC++. I just started implementing from the DirectShow
PUSH Source code.