Welcome to the Official BlackBerry® Support Community Forums. This is your resource to discuss support topics with your peers, and learn from each other. New to the forum? Please visit the ‘Getting Started’ link below.
inside custom component

Java Development

Reply
Contributor
anuragm69
Posts: 21
Registered: 10-10-2011
My Carrier: developer

Re: buffering and playback pcm audio

Hi Sir,

 

can you  give me the code sample according to my above  given  RecvStream.java class because i implemented 

its many way but i unable to solve this issue. so please sir help me.

 

 

thanks

 

Saurabh

Please use plain text.
Developer
superdirt
Posts: 378
Registered: 05-17-2009

Re: buffering and playback pcm audio

I'm afraid that I do not have the time to create the code you are requesting. Have a closer look at the read() specification in the API. In the first implementation of read() you post, you return an amount for the number of bytes written into the buffer, but you do not fill the buffer (b) with that many bytes. This is guaranteed to fail. You also need to ensure your method doesn't write more than length bytes to b, and that the write to b occurs at the position defined by offset.

Maybe your code has other issues as well, but making sure your code follows exactly what the API specifies for read() is a necessary step.

Scott
Please use plain text.
New Contributor
sdcompsc
Posts: 8
Registered: 10-13-2011
My Carrier: Developer

Re: buffering and playback pcm audio

To play PCM data you can do the follwoing,

 

1. use x-wav while creating the player.

2. add wav header to the pcm data.

3. Extend ByeArrayInputStream to implement your own input stream that will be provided to player

4. In the extended class read(), reset(), skip() and available() method should be carefully implemented

5. If you want play continuous stream, available should always return a high value like 0x7fffffff

6. Any read() after a call to reset should always return the header first and then data in subsequent read call

 

Hope this helps.

Please use plain text.
Contributor
anuragm69
Posts: 21
Registered: 10-10-2011
My Carrier: developer

Re: buffering and playback pcm audio

Hi sir,

 

I want to some help only for finding the length of "buf"

          byte[] buf = buffer.dequeue();

In this line of code my rtp packet decoded and store in "buf" given in above code.

so please sir only help how to find the length of "buf"

and how to copy the array in my read() method.

 

Please sir help.

 

Thanks

Saurabh

Please use plain text.
New Contributor
sdcompsc
Posts: 8
Registered: 10-13-2011
My Carrier: Developer

Re: buffering and playback pcm audio

It is difficult to follow the code as formatting is lost. The buffer seems to be a custom class (mypackage.ByteBuffer).

 

But the strategy i think you should follow is have a byte[] of say 100000 and use it as ring buffer. Whenever player calls read return the data available from last read position to current write position.

 

So recv rtp packet and write the data in the byte[] (after the header data) and increment write position. In read just return the data between last read position and new write position. Obviously you need to take care of boundary conditions.

 

While doing createplayer()  player calls reset()->read()->reset() and read(), read() and so on. So in the first read you supply the header. Any read after reset should also provide the header.

 

Hope you are aware of the player buffering in BB also. As if you do not supply enough data to player it will stop playing

 

Also using audio/x-wav may help instead of audio/pcm.

Please use plain text.
Developer
superdirt
Posts: 378
Registered: 05-17-2009

Re: buffering and playback pcm audio

Use:

buf.length

All arrays get a member variable called length that contains the number of elements in the array.

For array copying, you can try System.arraycopy(), which I don't use myself and I'm not sure how efficient this method is. I usually use an efficient for-loop that copies something like 100 bytes per loop pass, but this requires more work to code than arraycopy() does.

Scott
Please use plain text.
Contributor
anuragm69
Posts: 21
Registered: 10-10-2011
My Carrier: developer

Re: buffering and playback pcm audio

Hi sir,

 

can you help me how to add webHeader  receving "packet" from given line.

RtpPacket packet ;
packet = mSession.recvPacket((int) mPlayerTs);

because this line return the "int packet and player time stamp."

 

 

Thanks 

 

saurabh

Please use plain text.
Contributor
anuragm69
Posts: 21
Registered: 10-10-2011
My Carrier: developer

Re: buffering and playback pcm audio

Hi Sir,

 

Please Sir Help me   give me some tipse to add wevHeader  in my receve voice packet.

 

Thanks 

Please use plain text.
New Contributor
sdcompsc
Posts: 8
Registered: 10-13-2011
My Carrier: Developer

Re: buffering and playback pcm audio

What you can do is as follows,

 

1. define a byte array for the header. WAV header is as follows,

private byte[] Header8K =
{
(byte)0x52, (byte)0x49, (byte)0x46, (byte)0x46,
(byte)0xff, (byte)0xff, (byte)0xff, (byte)0x07,
(byte)0x57, (byte)0x41, (byte)0x56, (byte)0x45,
(byte)0x66, (byte)0x6d, (byte)0x74, (byte)0x20,
(byte)0x10, (byte)0x00, (byte)0x00, (byte)0x00,
(byte)0x01, (byte)0x00, (byte)0x01, (byte)0x00,
(byte)0x40, (byte)0x1f, (byte)0x00, (byte)0x00, // 8000
(byte)0x80, (byte)0x3e, (byte)0x00, (byte)0x00, // 16000
(byte)0x02, (byte)0x00, (byte)0x10, (byte)0x00,
(byte)0x64, (byte)0x61, (byte)0x74, (byte)0x61,
(byte)0xdb, (byte)0xff, (byte)0xff, (byte)0x07
} ;

 

2. Store the rtp data in a separate buffer

3. Whenever inputstraem read is called after a reset() call, return the header data only (44 bytes)

4. In the subsequent read() call provide actual data. But do keep track how much is written in the buffer and how much is read. Also special care should be taken for boundary conditions.

Please use plain text.
Contributor
anuragm69
Posts: 21
Registered: 10-10-2011
My Carrier: developer

Re: buffering and playback pcm audio

Hi sir 

 

I am using your given Header But it Throough the exception please see below:--

................

Thread [jlinphone(237)id=69422080] (Suspended (exception ArrayIndexOutOfBoundsException))
RecvStream$1.read(byte[], int, int) line: 128
StreamModifyingDataSource$HeaderAddingSourceStream.read(byte[], int, int) line: 209
DataSourceInputStream.read(byte[], int, int) line: 38
RingBuffer.write(InputStream) line: 310
MediaPlayer.read() line: 458
MediaPlayer.moreData() line: 429
MediaStreamingManagerImpl$StreamingSessionImpl$ReadThread.run()

 

////////////////////////////////////////////-----------------------------------------------------------------

 

so sir please help me what can i do for resolve this isssue.

 

 

 

 

.....................................

public class RecvStream implements /*Runnable,*/ PlayerListener {
private Player mPlayer;
private SendStream mSendStream;
private WavHeaderAppender header;
private RtpSession mSession;
private long mStartTime=0;
private boolean mFirstRead=true;
private boolean mRunning;
private boolean mBuffering=true;
private static Logger sLogger=JOrtpFactory.instance().createLogger("RecvStream");
private long mPlayerTs=-1;
private byte[] tempBuffer = new byte[160];
private long mReturnedMs=0;
private void reset() {
mPlayer=null;
mStartTime=0;
mFirstRead=true;
mBuffering=true;
mPlayerTs=-1;
mReturnedMs=0;
}
private SourceStream mInput= new SourceStream(){
private byte[] Header8K =
{
(byte)0x52, (byte)0x49, (byte)0x46, (byte)0x46,
(byte)0xff, (byte)0xff, (byte)0xff, (byte)0x07,
(byte)0x57, (byte)0x41, (byte)0x56, (byte)0x45,
(byte)0x66, (byte)0x6d, (byte)0x74, (byte)0x20,
(byte)0x10, (byte)0x00, (byte)0x00, (byte)0x00,
(byte)0x01, (byte)0x00, (byte)0x01, (byte)0x00,
(byte)0x40, (byte)0x1f, (byte)0x00, (byte)0x00, // 8000
(byte)0x80, (byte)0x3e, (byte)0x00, (byte)0x00, // 16000
(byte)0x02, (byte)0x00, (byte)0x10, (byte)0x00,
(byte)0x64, (byte)0x61, (byte)0x74, (byte)0x61,
(byte)0xdb, (byte)0xff, (byte)0xff, (byte)0x07
} ;

private RtpPacket mTroncatedPacket;
private int mTroncatedPacketSize;
private boolean priority_set=false;

ContentDescriptor mContentDescriptor=new ContentDescriptor("audio/pcm");

public int read(byte[] b, int offset, int length) throws IOException {
int bytesToReturn=Header8K.length;

if (mBuffering){
bytesToReturn=Header8K.length*8;
}
try {

if (!priority_set && Thread.currentThread().getPriority() != Thread.MAX_PRIORITY) {
Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
priority_set=true;
}
int lWrittenLenth=0;

while(lWrittenLenth<=bytesToReturn && mRunning){
long ts=getCurTs();
if (mPlayerTs==-1) {
mPlayerTs=ts;
sLogger.info("Initializing timestamp to ["+mPlayerTs+"]");
}
RtpPacket packet=null;
try {
long diff;

while((diff=(ts-mPlayerTs))>=0){
if (diff> 400){
mPlayerTs=ts-400;
sLogger.warn("Too late, skipping "+ ((diff-400)/4) +" ms...");
}
packet=mSession.recvPacket((int)mPlayerTs);
if (packet!=null){
mReturnedMs+=20;
if (mFirstRead) {

lWrittenLenth=tempBuffer.length;
System.arraycopy(packet.getBytes(), 12,
tempBuffer, 0, 160);
byte[] dencoded = new byte[tempBuffer.length * 2];

for (int i = 0, j = 0; i < tempBuffer.length; i++) {
int s = tempBuffer[i];
int res = G711.ulaw2linear(s);
dencoded[j++] = (byte) (res);
dencoded[j++] = (byte) (res >> 8);
//header.appendWavHeader(dencoded);
}
System.arraycopy(dencoded,0, b, offset, lWrittenLenth );
length = length - lWrittenLenth;
offset+=lWrittenLenth;
mFirstRead=false;
}
if ((length < Header8K.length)) {

 

// special case for end of buffer

System.arraycopy(packet.getBytes(),packet.getDataOffset()+1, b, offset, length );
lWrittenLenth+= length;
mTroncatedPacketSize=length;
mTroncatedPacket = packet;
if (sLogger.isLevelEnabled(Logger.Warn)) sLogger.warn("End of buffer, ["+lWrittenLenth+"] bytes returned");
return lWrittenLenth;
}else{
if (mTroncatedPacket != null) {
// special case for troncated packet
int remain=mTroncatedPacket.getRealLength()-mTroncatedPacket.getDataOffset()-1- mTroncatedPacketSize;
System.arraycopy(mTroncatedPacket.getBytes(),mTroncatedPacket.getDataOffset()+1+mTroncatedPacketSize, b, offset, remain);
lWrittenLenth+= remain;
mTroncatedPacketSize=0;
mTroncatedPacket = null;
offset+= remain;
length-=remain;
}
//+1 because we need to skip the CMR bytes
int datalen=packet.getRealLength()-packet.getDataOffset()-1;
System.arraycopy(packet.getBytes(),packet.getDataOffset()+1, b, offset, datalen );
lWrittenLenth+= datalen;
length-=datalen;
offset+=datalen;
}
}
mPlayerTs+=160;
}

} catch (RtpException e) {
sLogger.error("Bad RTP packet", e);
}
if (packet==null) Thread.sleep(20);
}
if (!mRunning){
//to notify end of stream.
return -1;
}
if (sLogger.isLevelEnabled(Logger.Debug)) sLogger.debug("["+lWrittenLenth+"] bytes returned");
return lWrittenLenth;
} catch (Throwable e) {
sLogger.error("Exiting player input stream",e);
return -1;
}
finally {
if (bytesToReturn > Header8K.length) {
// we were buffering, so now it's ok resetting value
mBuffering=false;
}
}
}

 

 

Thanks

 

Please use plain text.