Discussion:
IAsyncReader implementation
(too old to reply)
Robin
2005-04-01 15:49:28 UTC
Permalink
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:

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.
Iain
2005-04-02 10:00:03 UTC
Permalink
Post by Robin
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.
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
Robin
2005-04-04 08:29:14 UTC
Permalink
Post by Iain
Post by Robin
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.
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
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.
Alessandro Angeli [MVP::DigitalMedia]
2005-04-04 10:41:30 UTC
Permalink
Post by Robin
I don't see your point! The microsoft example is not
using CSource and CSourceStream.
And that is Iain's point.
Post by Robin
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.
Post by Robin
Sorry, but do better reading (and quoting) next time,
What about some RTFM instead?
Post by Robin
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
Robin
2005-04-05 08:57:17 UTC
Permalink
Ok, thanks and sorry for my mistake on the silly thing...

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.
Post by Alessandro Angeli [MVP::DigitalMedia]
Post by Robin
I don't see your point! The microsoft example is not
using CSource and CSourceStream.
And that is Iain's point.
Post by Robin
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.
Post by Robin
Sorry, but do better reading (and quoting) next time,
What about some RTFM instead?
Post by Robin
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
Alessandro Angeli [MVP::DigitalMedia]
2005-04-05 10:28:04 UTC
Permalink
Post by 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).
Post by Robin
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.
--
// Alessandro Angeli
// MVP :: Digital Media
// a dot angeli at psynet dot net
Robin
2005-04-05 12:14:00 UTC
Permalink
Hello Alessandro!

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
Post by Alessandro Angeli [MVP::DigitalMedia]
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).
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
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.
Alessandro Angeli [MVP::DigitalMedia]
2005-04-05 13:35:27 UTC
Permalink
Post by Robin
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.
Post by Robin
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
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?
Post by Robin
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?
Post by Robin
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.
--
// Alessandro Angeli
// MVP :: Digital Media
// a dot angeli at psynet dot net
Robin
2005-04-07 08:26:32 UTC
Permalink
Hi Alessandro!
Thanks for answer.

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
Post by Alessandro Angeli [MVP::DigitalMedia]
Post by Robin
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.
Alessandro Angeli [MVP::DigitalMedia]
2005-04-07 08:44:50 UTC
Permalink
Post by Robin
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.
--
// Alessandro Angeli
// MVP :: Digital Media
// a dot angeli at psynet dot net
Peter Sun
2006-07-25 09:08:35 UTC
Permalink
Sorry for inserting another question here.

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
Alessandro Angeli [MVP::DS/MF]
2006-07-25 11:33:03 UTC
Permalink
Post by Peter Sun
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
// a dot angeli at psynet dot net
Gajendran
2008-05-30 15:27:20 UTC
Permalink
Hello

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.

url:http://www.ureader.com/msg/1471149.aspx
Alessandro Angeli
2008-05-30 15:38:08 UTC
Permalink
From: "Gajendran"
Post by Gajendran
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
Gajendran
2008-05-31 06:10:56 UTC
Permalink
Hello,

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.

url:http://www.ureader.com/msg/1471149.aspx
x***@gmail.com
2015-07-03 05:51:33 UTC
Permalink
This post might be inappropriate. Click to display it.
Loading...