Shreenivasa Prasad wrote:
3."> once IoCallDriver to USBD is returned STATUS_SUCCESS,that means i have data written in Leading -> StreamHeader -> Data.
> Maybe."
>
=>you said “Maybe”,i did not get what you intend to say here…did you mean that even if it is STATUS_SUCCESS from USBD,the data read could be a whole packet or a short packet or a zero length packet??
Yes, exactly that.
4.“Where on earth did you get that code? It’s certainly not in any of the samples. An AVStream driver never touches the IRP, and you don’t return STATUS_PENDING.”
=>yes ,the code shown is not there in any of the samples.i just tried it as i had seen these API information in the DDK and few other blogs on the web.
i have a doubt here,
a.how do i intimate the layer above me that the buffer given to me is filled with audio data and it is ready foryou to render it?
You advance the stream’s leading edge pointer, either by advancing the
pointer or closing the last clone to the buffer. The avshws sample does
exactly this. The Process callback (which gets called when there is a
new buffer) makes a clone of the leading edge, which locks it, thereby
preventing it from advancing. The simulated interrupt process, which
actually gets the data, fetches the oldest clone, copies data into it,
and deletes the clone. That releases the last reference to that first
buffer, so AVStream can return it to the caller.
b.how would i be able to get back another call to my process,for the next set of data to be transferred?(sample uses timer and on the invoke of TimerDPC it calls KsFilterAttemptProcessing).i tired the same and i do get calls into my process function once i use timerdpc,but i am not able to intimate that data read is ready for it to be rendered to default directsound device.
When a new empty buffer is available, your Process callback will be
called. That won’t happen unless you have successfully released the
buffers you were given originally. There is a limited supply of empty
buffers, and they circulate around the graph. When the data has been
removed, the empty will be handed back to your Process callback.
6.i have posted my audio streaming implementation here,could you plz give a suggestion as to what more to be done?
and i am not cloning the stream pointer as i have asked for a single buffer in allocator framing structure,.it is as shown below.
That’s a very bad idea. It means that you will not get another buffer
to fill until this one has been completely processed by the downstream
filters. Although, since the framing requirements are only suggestions,
the graph is free to ignore them and give you whatever it wants.
NTSTATUS CCLAVRequest::CLStartAudioStreaming(IN PKSDEVICE m_Device,ULONG buffer_size,PVOID pdata_buffer)
//NTSTATUS CCLAVRequest::CLStartAudioStreaming(IN PKSDEVICE m_Device)
…
for ( i = 0; i < no_of_pkts; ++i)//, buffer_size -= audio_packet_size)
{
if(!(i%2))
{
piso_urb->UrbIsochronousTransfer.IsoPacket[i].Offset = (ULONG)((index1) * audio_packet_size);
index1++;
}
else
{
piso_urb->UrbIsochronousTransfer.IsoPacket[i].Offset = (ULONG)((index2) * audio_packet_size);
index2++;
}
}
Here, you are ASSUMING that your buffer contains room for at least 500+x
packets. That’s very dangerous. Also remember that USB is not an
entirely reliable bus. You cannot guarantee that your packets will stay
in lockstep with the real data stream. If you should happen to miss one
frame because of a glitch, your data might be transfered to an odd
packet number. You really need to have the packets run in address order
here, and pack the data later.
Also remember that you can’t include more than 255 frames worth of
packets in a single ISO URB.
KdPrint((“P2”));
status = SendAwaitUrb(m_Device,piso_urb,NULL);
You are sending this synchronously? (That is, you wait for the
result?) That’s not good. You need to submit this asynchronously, then
handle the returned data in the completion routine.
if(piso_urb->UrbIsochronousTransfer.IsoPacket[0].Length)
{
KdPrint((“e\n”));
for(i=0;i<500;i++)//for(i=0;i<128;i++)
{
*((PUCHAR)pdata_buffer+i)=*((PUCHAR)pstream_buf+i);
}
}
else
{
KdPrint((“o\n”));
for(i=0;i<500;i++)//for(i=0;i<128;i++)
{
*((PUCHAR)pdata_buffer+i)=*((PUCHAR)pstream_buf+(i+500));
}
}
This is wrong, in several ways. IsoPacket[0].Length tells you how many
bytes you got during the first frame. You need to check EACH PACKET
separately and copy the data. Further, it’s a very bad idea to do
copies like this manually, in a loop, one byte at a time. You should
use RtlMoveMemory, which is able to do memory copies in a much smarter way.
You need something like this:
PUCHAR Dst = pdata_buffer;
for( i = 0; i < num_pkts; i++ )
{
if( piso_urb->UrbIsochronousTransfer.IsoPacket[i].Length )
{
RtlMoveMemory( Dst,
pstream_buf +
piso_urb->UrbIsochronousTransfer.IsoPacket[i].Offset,
piso_urb->UrbIsochronousTransfer.IsoPacket[i].Length
);
Dst += piso_urb->UrbIsochronousTransfer.IsoPacket[i].Length;
}
}
pdata_buffer=(PUCHAR)pdata_buffer+500;
Where does the 500 come from? The buffer size is being sent to you by
the caller. You can’t make assumptions here.
read_data_size=read_data_size + (500*8);
if(read_data_size<(500*8))
goto create_request;
I don’t understand why there’s a “goto” here at all, but it won’t really
matter because it can never get hit. You added 500*8 in the line above,
so the value will always be >= 500*8. And again, where did the 500 come
from?
plz let me know if you feel anything is missed out…
i am new to this AVStream Driver implementation.any inputs from you will definitily be helpful.
You are not looking at the WAY things are done in avshws. You are just
hacking things in here.
–
Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.