C# and Java how to convert bytes for stream - java

I made few attempts at sending data from C# UDP server to Java client with no luck. I know that there is difference between bytes in Java and C# however do not fully understand how to implement it. Any help would be great.
Below is my C# code:
TimeSpan t = DateTime.UtcNow - new DateTime(1970, 1, 1);
int secondsSinceEpoch = (int)t.TotalSeconds;
{
byte[] data = new byte[1024];
IPAddress UDP_local_add = IPAddress.Parse("127.0.0.1");
IPEndPoint endpoint = new IPEndPoint(UDP_local_add, 37);
UdpClient UDPSocket = new UdpClient(endpoint);
Console.WriteLine("UDP Server awaiting connections...");
IPEndPoint sender = new IPEndPoint(UDP_local_add, 0);
data = UDPSocket.Receive(ref sender);
Console.WriteLine("Message received from {0}:", sender.ToString());
Console.WriteLine(Encoding.ASCII.GetString(data, 0, data.Length));
data =System.Text.Encoding.ASCII.GetBytes(secondsSinceEpoch.ToString());
Console.WriteLine(secondsSinceEpoch);
int converted = DecodeInt32(data);
Console.WriteLine(converted);
UDPSocket.Send(data, data.Length, sender);
UDPSocket.Close();
}
and below is Java client code:
public class TimeUDPClient {
private static final int PORT_TIME = 37;
private static final String QUERY = "Ktora godzina?";
private static final int LINELEN = 5;
private static final long UNIXEPOCH = 2208988800L;
public static void main(String[] args) {
try {
byte[] buffer = new byte[LINELEN];
DatagramSocket sock = new DatagramSocket();
DatagramPacket dp = new DatagramPacket(QUERY.getBytes(), 0,
QUERY.length(), InetAddress.getByName(args[0]), PORT_TIME);
sock.send(dp);
dp = new DatagramPacket(buffer, LINELEN);
sock.receive(dp);
long time = 0;
int i;
for (i = 0; i < 4; i++) {
time *= 256;
time += (buffer[i] & 255);
}
time -= UNIXEPOCH;
time *= 1000;
Date d = new Date(time);
System.out.println(d);
sock.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}

Related

Capturing Buffering playing live Audio Streaming

I am getting live audio streaming over the network in the form of RTP packets and I have to write a code to Capture, Buffer and play the audio stream.
Problem
Now to solve this problem I have written two threads one for capture the audio and another for playing it. Now when I start both the threads my capture threads running slower than playing thread :(
Buffer Requirement
RTP Audio Packets.
8kHz, 16-bit Linear Samples (Linear PCM).
4 frames of 20ms audio will be sent in each RTP Packet.
Do not play until AudioStart=24 (# of 20ms frames) have arrived.
While playing ... if the # of 20ms frames in buffer reaches 0 ...
stop playing until AudioStart frames are buffered then restart.
While playing ... if the # of 20ms frames in buffer exceeds
AudioBufferHigh=50 then delete 24 frames (in easiest manner -- delete
from buffer or just drop next 6 RTP messages).
What I have done so far..
Code
BufferManager.java
public abstract class BufferManager {
protected static final Integer ONE = new Integer(1);
protected static final Integer TWO = new Integer(2);
protected static final Integer THREE = new Integer(3);
protected static final Integer BUFFER_SIZE = 5334;//5.334KB
protected static volatile Map<Integer, ByteArrayOutputStream> bufferPool = new ConcurrentHashMap<>(3, 0.9f, 2);
protected static volatile Integer captureBufferKey = ONE;
protected static volatile Integer playingBufferKey = ONE;
protected static Boolean running;
protected static volatile Integer noOfFrames = 0;
public BufferManager() {
//captureBufferKey = ONE;
//playingBufferKey = ONE;
//noOfFrames = new Integer(0);
}
protected void switchCaptureBufferKey() {
if(ONE.intValue() == captureBufferKey.intValue())
captureBufferKey = TWO;
else if(TWO.intValue() == captureBufferKey.intValue())
captureBufferKey = THREE;
else
captureBufferKey = ONE;
//printBufferState("SWITCHCAPTURE");
}//End of switchWritingBufferKey() Method.
protected void switchPlayingBufferKey() {
if(ONE.intValue() == playingBufferKey.intValue())
playingBufferKey = TWO;
else if(TWO.intValue() == playingBufferKey.intValue())
playingBufferKey = THREE;
else
playingBufferKey = ONE;
}//End of switchWritingBufferKey() Method.
protected static AudioFormat getFormat() {
float sampleRate = 8000;
int sampleSizeInBits = 16;
int channels = 1;
boolean signed = true;
boolean bigEndian = true;
return new AudioFormat(sampleRate, sampleSizeInBits, channels, signed, bigEndian);
}
protected int getByfferSize() {
return bufferPool.get(ONE).size()
+ bufferPool.get(TWO).size()
+ bufferPool.get(THREE).size();
}
protected static void printBufferState(String flag) {
int a = bufferPool.get(ONE).size();
int b = bufferPool.get(TWO).size();
int c = bufferPool.get(THREE).size();
System.out.println(flag + " == TOTAL : [" + (a + b +c) + "bytes] ");
// int a,b,c;
// System.out.println(flag + "1 : [" + (a = bufferPool.get(ONE).size()) + "bytes], 2 : [" + (b = bufferPool.get(TWO).size())
// + "bytes] 3 : [" + (c = bufferPool.get(THREE).size()) + "bytes], TOTAL : [" + (a + b +c) + "bytes] ");
}
}//End of BufferManager Class.
AudioCapture.java
public class AudioCapture extends BufferManager implements Runnable {
private static final Integer RTP_HEADER_SIZE = 12;
private InetAddress ipAddress;
private DatagramSocket serverSocket;
long lStartTime = 0;
public AudioCapture(Integer port) throws UnknownHostException, SocketException {
super();
running = Boolean.TRUE;
bufferPool.put(ONE, new ByteArrayOutputStream(BUFFER_SIZE));
bufferPool.put(TWO, new ByteArrayOutputStream(BUFFER_SIZE));
bufferPool.put(THREE, new ByteArrayOutputStream(BUFFER_SIZE));
this.ipAddress = InetAddress.getByName("0.0.0.0");
serverSocket = new DatagramSocket(port, ipAddress);
}
#Override
public void run() {
System.out.println();
byte[] receiveData = new byte[1300];
DatagramPacket receivePacket = null;
lStartTime = System.currentTimeMillis();
receivePacket = new DatagramPacket(receiveData, receiveData.length);
byte[] packet = new byte[receivePacket.getLength() - RTP_HEADER_SIZE];
ByteArrayOutputStream buff = bufferPool.get(captureBufferKey);
while (running) {
if(noOfFrames <= 50) {
try {
serverSocket.receive(receivePacket);
packet = Arrays.copyOfRange(receivePacket.getData(), RTP_HEADER_SIZE, receivePacket.getLength());
if((buff.size() + packet.length) > BUFFER_SIZE) {
switchCaptureBufferKey();
buff = bufferPool.get(captureBufferKey);
}
buff.write(packet);
noOfFrames += 4;
} catch (SocketException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} // End of try-catch block.
} else {
//System.out.println("Packet Ignored, Buffer reached to its maximum limit ");
}//End of if-else block.
} // End of while loop.
}//End of run() Method.
}
AudioPlayer.java
public class AudioPlayer extends BufferManager implements Runnable {
long lStartTime = 0;
public AudioPlayer() {
super();
}
#Override
public void run() {
AudioFormat format = getFormat();
DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);
SourceDataLine line = null;
try {
line = (SourceDataLine) AudioSystem.getLine(info);
line.open(format);
line.start();
} catch (LineUnavailableException e1) {
e1.printStackTrace();
}
while (running) {
if (noOfFrames >= 24) {
ByteArrayOutputStream out = null;
try {
out = bufferPool.get(playingBufferKey);
InputStream input = new ByteArrayInputStream(out.toByteArray());
byte buffer[] = new byte[640];
int count;
while ((count = input.read(buffer, 0, buffer.length)) != -1) {
if (count > 0) {
InputStream in = new ByteArrayInputStream(buffer);
AudioInputStream ais = new AudioInputStream(in, format, buffer.length / format.getFrameSize());
byte buff[] = new byte[640];
int c = 0;
if((c = ais.read(buff)) != -1)
line.write(buff, 0, buff.length);
}
}
} catch (IOException e) {
e.printStackTrace();
}
/*byte buffer[] = new byte[1280];
try {
int count;
while ((count = ais.read(buffer, 0, buffer.length)) != -1) {
if (count > 0) {
line.write(buffer, 0, count);
}
}
} catch (IOException e) {
e.printStackTrace();
}*/
out.reset();
noOfFrames -= 4;
try {
if (getByfferSize() >= 10240) {
Thread.sleep(15);
} else if (getByfferSize() >= 5120) {
Thread.sleep(25);
} else if (getByfferSize() >= 0) {
Thread.sleep(30);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
// System.out.println("Number of frames :- " + noOfFrames);
}
}
}// End of run() method.
}// End of AudioPlayer Class class.
any help or pointer to the helpful link will be appreciable Thanks...
This answer explains a few challenges with streaming.
In a nutshell, your client needs to deal with two issues:
1) The clock (crystals) on the client and server are not perfectly in sync. The server may be a fraction of a Hz faster/slower than the client. The client continuously match the infer the clock rate of the server by examining the rate that rtp packets are delivered. The client then adjusts the playback rate via sample rate conversion. So instead of playing back at 48k, it may play back at 48000.0001 Hz.
2) Packets loss, out of order arrivals, etc. must be dealt with. If you lose packets, you need to still keep a place holder for those packets in your buffer stream otherwise your audio will skip and sound crackly and become unaligned. The simplest method would be to replace those missing packets with silence but the volume of adjacent packets should be adjusted to avoid sharp envelope changes snapping to 0.
Your design seems a bit unorthodox. I have had success using a ring buffer instead. You will have to deal with edge cases as well.
I always state that streaming media is not a trivial task.

Java output values over time

I have an audio file that I am converting into a byte array, but then you cannot tell when that byte value is actually played in the song. So I am trying to stretch it out over the length of the song.
So while the song is playing, it outputs the byte value. How is this possible?
Here is my code so far:
public class Main {
private static final String FILENAME = "assets/pf.wav";
private static double[] endResult = null;
public static void convert() throws IOException{
ByteArrayOutputStream out = new ByteArrayOutputStream();
BufferedInputStream in = new BufferedInputStream(new FileInputStream(FILENAME));
int read;
byte[] buff = new byte[1024];
while ((read = in.read(buff)) > 0)
{
out.write(buff, 0, read);
}
out.flush();
byte[] audioBytes = out.toByteArray();
endResult = calculateFFT(audioBytes);
}
public static double[] calculateFFT(byte[] signal)
{
final int mNumberOfFFTPoints =1024;
double mMaxFFTSample;
double temp;
Complex[] y;
Complex[] complexSignal = new Complex[mNumberOfFFTPoints];
double[] absSignal = new double[mNumberOfFFTPoints/2];
for(int i = 0; i < mNumberOfFFTPoints; i++){
temp = (double)((signal[2*i] & 0xFF) | (signal[2*i+1] << 8)) / 32768.0F;
complexSignal[i] = new Complex(temp,0.0);
}
y = FFT.fft(complexSignal);
mMaxFFTSample = 0.0;
int mPeakPos = 0;
for(int i = 0; i < (mNumberOfFFTPoints/2); i++)
{
absSignal[i] = Math.sqrt(Math.pow(y[i].re(), 2) + Math.pow(y[i].im(), 2));
if(absSignal[i] > mMaxFFTSample)
{
mMaxFFTSample = absSignal[i];
mPeakPos = i;
}
}
return absSignal;
}
public static void main(String[] args) throws UnsupportedAudioFileException, IOException {
File file = new File(FILENAME);
AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(file);
AudioFormat format = audioInputStream.getFormat();
long frames = audioInputStream.getFrameLength();
final double durationInSeconds = (frames+0.0) / format.getFrameRate();
try {
convert();
for(int i = 0; i < endResult.length; i++) {
System.out.println(endResult[i]);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
How can I print out the value of the byte array (endResult[i]) over time and not immediately?
Whenever you print out a value, do:
Thread.sleep(100);
To wait 100 milliseconds (0.1 seconds) before printing the next value. This is adjustable of course.

How to make sure that the file passed using java.net is as it was before transmission

I'm studying java.net and trying to transmit som file. here is the sender code
public static final FilesGetter filesGetter = new FilesGetter();
public static Socket s;
public static File[] files;
public static void main(String args[]) throws Exception{
s = new Socket("localhost", 3128);
while (true){
try{
files = filesGetter.getFilesList("/etc/dlp/templates/");
Socket s = new Socket("localhost", 3128);
args[0] = args[0]+"\n"+s.getInetAddress().getHostAddress()
+":"+s.getLocalPort();
if (files != null){
for (int i = 0; i < files.length; i++){
InputStream is = new FileInputStream(files[i]);
byte[] message = IOUtils.toByteArray(is);
s.getOutputStream().write(message);
byte buf[] = new byte[64*1024];
int r = s.getInputStream().read(buf);
String data = new String(buf, 0, r);
System.out.println(data);
}
}
} catch(Exception e){
System.out.println("init error: "+e);
}
}
}
And here is the receiver code:
public class Consumer extends Thread{
public static Socket s;
public String customerId;
int num;
public static final Filter filter = new Filter();
public MimeParser mimeParser = new MimeParser(true);
public Consumer(int num, final Socket s, final String customerId){
this.num = num;
this.s = s;
this.customerId = customerId;
setDaemon(true);
setPriority(NORM_PRIORITY);
start();
}
public static void receive(final String customerId){
try {
int i = 0;
ServerSocket server = new ServerSocket(3128, 0, InetAddress.getByName("localhost"));
System.out.println("server started");
while (true){
new Consumer(i, server.accept(), customerId);
i++;
}
} catch (Exception e){
e.printStackTrace();
}
}
public void run(){
try {
InputStream is = s.getInputStream();
OutputStream os = s.getOutputStream();
byte buf[] = new byte[64*1024];
int r = is.read(buf);
if (r < 0)
return;
ByteArrayInputStream bais = new ByteArrayInputStream(buf, 0, r);
MessageInfo mi = mimeParser.parseMessages(bais);
filter.getMessageAcceptability(mi.getPlainText(), customerId);
s.close();
} catch (Exception e){
System.out.println("init error: " + e);
}
}
}
I'm not sure of data integrity because processing of data on the server-side is not fully successful and don't know if I need to look for mistakes in the processing code(which worked well when I've been Using rabbitmq) or in client-server code. I also don't know what buffer size must be chosen.
At the sender side you can send as much as you want, 64*1024 it's OK, the send method will loop until all the data has been delivery. But at the receiver it could be that read returns before the whole file has been read, you must loop reading until the other side closes the socket.
In these cases it's better to send, in advance, an integer indicating how much data you are going to send, the receiver will loops until that much bytes are read.
For example:
int ret=0;
int offset=0;
int BUFF_LEN=64*1024;
byte[] buffer = new byte[BUFF_LEN];
while ((ret = is.read(buffer, offset, BUFF_LEN - offset)) > 0)
{
offset+=ret;
// just in case the file is bigger that the buffer size
if (offset >= BUFF_LEN) break;
}
You need to compute a checksum like SHA-1 on both the sender and the receiver's side. When they match, you can assume that there was no transmission error. Your question is really more of a protocol question.
A much simpler and more practical solution than to implement your own integrity checks would be to use the SSL protocol. That will provide you with integrity checked transmissions.

how to get UDP connection in infinite loop?

I am trying to write a program to implement the distance vector algorithm.
So I need the node to act as both the server and the client.
Basically I am using UDP protocol to send and receive messages. I am trying to listen for message from neighbouring nodes while sending the node's distance vector out every 5 seconds.
My main problem is that I want the stop listening for message so that I can broadcast my distance vector. I tried using setSoTimeout but then I get all sorts of exception that I dont know how to handle. and I am not too sure how to "reopen" the socket again to either wait for the message again or move on to broadcasting the message....
Can anybody please point me to the right direction?
My code is as follows:
import java.io.*;
import java.net.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Scanner;
public class dv_routing {
public static void main(String[] args) throws Exception {
//initialise variables to default value
int NodeID = 0;
int NodePort = 6000;
String configFile = "A.txt";
int numNbr = 0; // zero neighbour
double[] CostList = new double[10]; //Self cost list
Arrays.fill(CostList, Double.POSITIVE_INFINITY);
int[] ViaList = new int[10]; //Self cost list
Arrays.fill(ViaList, 9999);
double[] Cost = new double[10]; //Inf cost array for Nbr initialization
Arrays.fill(Cost, Double.POSITIVE_INFINITY);
Neighbour Nbr = new Neighbour(); //create Nbr
boolean ischanged = false;
//read user input
if (args.length >= 3) {
System.out.println("i'm here!");
String tmp = args[0];
char tmpchar = tmp.charAt(0);
NodeID = ((int)tmpchar - 65);
NodePort = Integer.parseInt(args[1]);
configFile = args[2];
CostList[NodeID] = 0;
System.out.println(NodeID);
System.out.println(NodePort);
System.out.println(configFile);
//poison reverse
if (args.length <= 4) {
// TODO: poison reverse
}
else
System.out.println("Incorrect Input Format! Please try again!");
}
//reading config file for neighbour data
try{
// Open the file that is the first
// command line parameter
FileInputStream fstream = new FileInputStream(configFile);
// Get the object of DataInputStream
DataInputStream in = new DataInputStream(fstream);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String strLine;
//capture the number neighbours
if ((strLine = br.readLine()) != null){
numNbr = Integer.parseInt(strLine);
System.out.println (numNbr);
}
int elementcnt = 0;
while ((strLine = br.readLine()) != null) {
//separate data
String[] temp = strLine.split(" ");
//get neighbour Node ID
char tmpchar = temp[0].trim().charAt(0);
int ID = (int)(tmpchar - 65);
//NbrIDList.add(new NbrID((int)tmpchar - 65));
//get neighbour cost
CostList[ID] = Double.parseDouble(temp[1].trim());
ViaList[ID] = ID;
//get neighbour port number
int Port = Integer.parseInt(temp[2].trim());
//create entry for neighbour
Nbr.addData(ID, Port);
Nbr.addCost(Cost);
//debugging
//System.out.println((char)(Nbr.getID(elementcnt)+65));
//System.out.println(Nbr.getPort(elementcnt));
//System.out.println(Nbr.getCost(elementcnt)[0]);
elementcnt++;
}
//Close the input stream
in.close();
}catch (Exception e){//Catch exception if any
System.err.println("Error: " + e.getMessage());
}
//set timers
long now = System.currentTimeMillis();
long end = now + 50 * 1000;
long broadcast = now + 1 * 1000;
long current = System.currentTimeMillis();
while(current < end) {
System.out.println("in first layer");
//open UDP socket for listening..
DatagramSocket nodeSocket = new DatagramSocket(NodePort);
InetAddress IPAddress = InetAddress.getByName("localhost");
byte[] receiveData = new byte[1024];
byte[] sendData = new byte[1024];
//braodcast...
String OutMsg = CostList[0]+"\t"+CostList[1]+"\t"+CostList[2]+"\t"+CostList[3]+"\t"+CostList[4]+"\t"+CostList[5]+"\t"+CostList[6]+"\t"+CostList[7]+"\t"+CostList[8]+"\t"+CostList[9];
sendData = OutMsg.getBytes();
for (int i = 0; i < numNbr; i++){
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress, Nbr.getPort(i));
nodeSocket.send(sendPacket);
}
nodeSocket.setSoTimeout(1000);
while(current < broadcast){
if (nodeSocket.isClosed()){
nodeSocket = new DatagramSocket(NodePort);
}
System.out.println("in receiving layer");
current = System.currentTimeMillis();
ischanged = false;
//get MSG
// Msg format.. "cost1"\t"cost2"\t"cost3"...
try{DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
nodeSocket.receive(receivePacket);
System.out.println("we got here");
String Msg = new String( receivePacket.getData());
System.out.println("RECEIVED: " + Msg);
int NbrPort = receivePacket.getPort();
System.out.println("From: " + NbrPort);
//process the MSG
String[] tmpstr = Msg.split("\t");
for (int i = 0; i<10; i++) {
Cost[i] = Double.parseDouble(tmpstr[i]);
}
int Idx = Nbr.indexOfPort(NbrPort);
System.out.println("From: " + NbrPort);
Nbr.updateCost(Idx, Cost);
//compare cost and update list
for (int i = 0; i<10;i++) {
double NbrNodeCost = (Nbr.getCost(Idx)[i] + CostList[Nbr.getID(Idx)]);
if (!(Double.isInfinite(NbrNodeCost)) && CostList[i] > NbrNodeCost) {
CostList[i] = NbrNodeCost;
ViaList[i] = Nbr.getID(Idx);
ischanged = true;
}
}
System.out.println("Is the list changed? " + ischanged);
System.out.println(CostList[0]+" "+CostList[1]+" "+CostList[2]+" "+CostList[3]+" "+CostList[4]+" "+CostList[5]+" "+CostList[6]+" "+CostList[7]+" "+CostList[8]+" "+CostList[9]);
System.out.println(ViaList[0]+" "+ViaList[1]+" "+ViaList[2]+" "+ViaList[3]+" "+ViaList[4]+" "+ViaList[5]+" "+ViaList[6]+" "+ViaList[7]+" "+ViaList[8]+" "+ViaList[9]);
}catch (SocketTimeoutException e) {
//System.err.println("Caught SocketException: " + e.getMessage());
System.out.println("Timeout reached!!! " + e);
nodeSocket.close();
nodeSocket = new DatagramSocket(NodePort);
current = System.currentTimeMillis();
}
catch (SocketException e1){
System.out.println("Socket closed " + e1);
}
}
//Broadcast List
System.out.println("broadcast");
broadcast = current + 1 * 1000;
current = System.currentTimeMillis();
if (ischanged) {
end = current + 10 * 1000;
}
//braodcast...
OutMsg = CostList[0]+"\t"+CostList[1]+"\t"+CostList[2]+"\t"+CostList[3]+"\t"+CostList[4]+"\t"+CostList[5]+"\t"+CostList[6]+"\t"+CostList[7]+"\t"+CostList[8]+"\t"+CostList[9];
sendData = OutMsg.getBytes();
for (int i = 0; i < numNbr; i++){
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress, Nbr.getPort(i));
nodeSocket.send(sendPacket);
}
}
//Print List
//Shortest path to node B: the next hop is C and the cost is 5
for(int i = 0; i <10; i++) {
if(ViaList[i] != 9999){
System.out.println("Shortest path to node "+(char)(i+65)+": the next hop is "+(char)(ViaList[i])+" and the cost is "+CostList[i]);
}
}
System.out.println("end");
}
}
class Neighbour {
public Neighbour(){
NbrIDList = new ArrayList<Integer>();
NbrPortList = new ArrayList<Integer>();
NbrCostList = new ArrayList<double[]>();
}
public void addData(int ID, int Port){
NbrIDList.add(ID);
NbrPortList.add(Port);
}
public void addCost(double[] Cost){
NbrCostList.add(Cost);
}
public int getID(int idx){
return (Integer) NbrIDList.get(idx);
}
public int getPort(int idx){
return (Integer) NbrPortList.get(idx);
}
public int indexOfPort(int Port){
return (Integer) NbrPortList.indexOf(Port);
}
public double[] getCost(int idx){
return (double[]) NbrCostList.get(idx);
}
public void updateCost(int idx, double[] Cost){
NbrCostList.set(idx,Cost);
}
private ArrayList<Integer> NbrIDList;
private ArrayList<Integer> NbrPortList;
private ArrayList<double[]> NbrCostList;
}
Networking is almost 99,8% threading. To solve your problem, you can create one thread to receiving messages and second one for sending message every 5 seconds.
There was a lot of questions about this:
Java: Multithreading & UDP Socket Programming
How can I implement a threaded UDP based server in Java?
java2s is also good:
Server
Client

Xuggler Encoding video of Desktop With Audio - audio has gaps

I am using Xuggler to convert images captured from the java Robot class and sound read from TargetDataLine class and encoding this into a video. I am then attempting to http stream this video data (after writing my header) to a flash client via http (Socket OutputStream) but it plays and stutters (never just playing smoothly) no matter what buffer value I use on the client side.
I am asking for help and showing my java code because I suspect it might be to do with how I am encoding the video or something about sending data via http socket which i am not getting..
ByteArrayURLHandler ba = new ByteArrayURLHandler();
final IRational FRAME_RATE = IRational.make(30);
final int SECONDS_TO_RUN_FOR = 20;
final Robot robot = new Robot();
final Toolkit toolkit = Toolkit.getDefaultToolkit();
final Rectangle screenBounds = new Rectangle(toolkit.getScreenSize());
IMediaWriter writer;
writer = ToolFactory.makeWriter(
XugglerIO.map(
XugglerIO.generateUniqueName(out, ".flv"),
out
));
writer.addListener(new MediaListenerAdapter() {
public void onAddStream(IAddStreamEvent event) {
event.getSource().getContainer().setInputBufferLength(1000);
IStreamCoder coder = event.getSource().getContainer().getStream(event.getStreamIndex()).getStreamCoder();
if (coder.getCodecType() == ICodec.Type.CODEC_TYPE_AUDIO) {
coder.setFlag(IStreamCoder.Flags.FLAG_QSCALE, false);
coder.setBitRate(32000);
System.out.println("onaddstream"+ coder.getPropertyNames().toString());
}
if (coder.getCodecType() == ICodec.Type.CODEC_TYPE_VIDEO) {
// coder.setBitRate(64000);
// coder.setBitRateTolerance(64000);
}
}
});
writer.addVideoStream(videoStreamIndex, videoStreamId, 1024, 768);
final int channelCount = 1;
int audionumber = writer.addAudioStream(audioStreamIndex, audioStreamId,1, 44100);
int bufferSize = (int)audioFormat.getSampleRate() *audioFormat.getFrameSize();//*6;///6;
byte[] audioBuf;// = new byte[bufferSize];
int i = 0;
final int audioStreamIndex = 1;
final int audioStreamId = 1;
BufferedImage screen, bgrScreen;
long startTime = System.nanoTime();
while(keepGoing)
{
audioBuf = new byte[bufferSize];
i++;
screen = robot.createScreenCapture(screenBounds);
bgrScreen = convertToType(screen, BufferedImage.TYPE_3BYTE_BGR);
long nanoTs = System.nanoTime()-startTime;
writer.encodeVideo(0, bgrScreen, nanoTs, TimeUnit.NANOSECONDS);
audioBuf = new byte[line.available()];
int nBytesRead = line.read(audioBuf, 0, audioBuf.length);
IBuffer iBuf = IBuffer.make(null, audioBuf, 0, nBytesRead);
IAudioSamples smp = IAudioSamples.make(iBuf,1,IAudioSamples.Format.FMT_S16);
if (smp == null) {
return;
}
long numSample = audioBuf.length / smp.getSampleSize();
smp.setComplete(true, numSample,(int)
audioFormat.getSampleRate(), audioFormat.getChannels(),
IAudioSamples.Format.FMT_S16, nanoTs/1000);
writer.encodeAudio(1, smp);
writer.flush();
}

Categories

Resources