From 752c0346ae42b30bf37fd721c6a2d6be07b3ff04 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Thu, 26 Sep 2013 01:00:18 -0400 Subject: [PATCH] WIP video. Remove WRITE_EXTERNAL_STORAGE permission. --- AndroidManifest.xml | 1 - gen/com/limelight/R.java | 4 +- src/com/limelight/nvstream/NvVideoStream.java | 150 ++++++++++++------ 3 files changed, 104 insertions(+), 51 deletions(-) diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 65e503a4..dc47bbfc 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -10,7 +10,6 @@ - ?[package:][type:]na

Must be a reference to another resource, in the form "@[+][package:]type:name" or to a theme attribute in the form "?[package:][type:]name". - @attr name com.limelight:buttonBarButtonStyle + @attr name android:buttonBarButtonStyle */ public static final int ButtonBarContainerTheme_buttonBarButtonStyle = 1; /** @@ -123,7 +123,7 @@ or to a theme attribute in the form "?[package:][type:]na

Must be a reference to another resource, in the form "@[+][package:]type:name" or to a theme attribute in the form "?[package:][type:]name". - @attr name com.limelight:buttonBarStyle + @attr name android:buttonBarStyle */ public static final int ButtonBarContainerTheme_buttonBarStyle = 0; }; diff --git a/src/com/limelight/nvstream/NvVideoStream.java b/src/com/limelight/nvstream/NvVideoStream.java index c5fe95e6..4095854f 100644 --- a/src/com/limelight/nvstream/NvVideoStream.java +++ b/src/com/limelight/nvstream/NvVideoStream.java @@ -6,11 +6,13 @@ import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.Socket; import java.net.SocketException; import java.net.UnknownHostException; import java.nio.ByteBuffer; +import java.nio.ByteOrder; import jlibrtp.DataFrame; import jlibrtp.Participant; @@ -30,7 +32,6 @@ public class NvVideoStream implements RTPAppIntf { private static final int FRAME_RATE = 60; private ByteBuffer[] decoderInputBuffers = null; private MediaCodec decoder; - private BufferedOutputStream output; private int frameIndex = 0; @@ -39,12 +40,7 @@ public class NvVideoStream implements RTPAppIntf { Socket s = new Socket(host, FIRST_FRAME_PORT); return s.getInputStream(); } - - private void openFile(String file) throws FileNotFoundException - { - output = new BufferedOutputStream(new FileOutputStream(new File(file))); - } - + public void startVideoStream(final String host, final Surface surface) { new Thread(new Runnable() { @@ -105,13 +101,80 @@ public class NvVideoStream implements RTPAppIntf { frameIndex++; } - RTPSession session = new RTPSession(rtp, rtcp); + final RTPSession session = new RTPSession(rtp, rtcp); session.addParticipant(new Participant(host, RTP_PORT, RTCP_PORT)); - session.RTPSessionRegister(NvVideoStream.this, null, null); + //session.RTPSessionRegister(NvVideoStream.this, null, null); + + // Ping thread + new Thread(new Runnable() { + @Override + public void run() { + // PING in ASCII + final byte[] pingPacket = new byte[] {0x50, 0x49, 0x4E, 0x47}; + + // RTP payload type is 127 (dynamic) + session.payloadType(127); + + // Send PING every 100 ms + for (;;) + { + session.sendData(pingPacket); + + try { + Thread.sleep(100); + } catch (InterruptedException e) { + break; + } + } + } + }).start(); + + // Receive thread + new Thread(new Runnable() { + @Override + public void run() { + byte[] packet = new byte[1500]; + + // Send PING every 100 ms + for (;;) + { + DatagramPacket dp = new DatagramPacket(packet, 0, packet.length); + + try { + rtp.receive(dp); + } catch (IOException e) { + e.printStackTrace(); + break; + } + + System.out.println("in receiveData"); + int inputIndex = decoder.dequeueInputBuffer(-1); + if (inputIndex >= 0) + { + ByteBuffer buf = decoderInputBuffers[inputIndex]; + NvVideoPacket nvVideo = new NvVideoPacket(dp.getData()); + + buf.clear(); + buf.put(nvVideo.data); + + System.out.println(nvVideo); + if (nvVideo.length == 0xc803) { + decoder.queueInputBuffer(inputIndex, + 0, nvVideo.length, + 0, 0); + frameIndex++; + } else { + decoder.queueInputBuffer(inputIndex, + 0, 0, + 0, 0); + } + } + } + } + }).start(); for (;;) { - System.out.println("in background infinite loop"); BufferInfo info = new BufferInfo(); System.out.println("dequeuing outputbuffer"); int outIndex = decoder.dequeueOutputBuffer(info, -1); @@ -144,44 +207,6 @@ public class NvVideoStream implements RTPAppIntf { @Override public void receiveData(DataFrame frame, Participant participant) { - System.out.println("in receiveData"); - int inputIndex = decoder.dequeueInputBuffer(-1); - if (inputIndex >= 0) - { - ByteBuffer buf = decoderInputBuffers[inputIndex]; - - buf.clear(); - - buf.put(frame.getConcatenatedData()); - - if (buf.position() != 1024) - { - System.out.println("Data length: "+buf.position()); - System.out.println(buf.get()+" "+buf.get()+" "+buf.get()); - } - - byte[] nvHeader = new byte[32]; - byte[] oldBuffer = buf.array(); - byte[] newBuffer = new byte[oldBuffer.length - nvHeader.length]; - System.out.println("removing crap from buffer"); - for (int i = 0; i < oldBuffer.length; i++) { - if (i < nvHeader.length) { - nvHeader[i] = oldBuffer[i]; - } else { - newBuffer[i - nvHeader.length] = oldBuffer[i]; - } - } - System.out.println("nvHeader: " + nvHeader.length + "oldBuffer: " + oldBuffer.length + - "newBuffer: " + newBuffer.length); - buf.clear(); - buf.put(newBuffer); - if (oldBuffer.length == 0xc803) { - decoder.queueInputBuffer(inputIndex, - 0, buf.position(), - 0, 0); - frameIndex++; - } - } } @Override @@ -199,4 +224,33 @@ public class NvVideoStream implements RTPAppIntf { private static long computePresentationTime(int frameIndex) { return 132 + frameIndex * 1000000 / FRAME_RATE; } + + class NvVideoPacket { + byte[] preamble; + short length; + byte[] extra; + byte[] data; + + public NvVideoPacket(byte[] payload) + { + ByteBuffer bb = ByteBuffer.wrap(payload).order(ByteOrder.LITTLE_ENDIAN); + + preamble = new byte[12+16]; + extra = new byte[38]; + + bb.get(preamble); + length = bb.getShort(); + bb.get(extra); + data = new byte[length]; + + if (bb.remaining() + length <= payload.length) + bb.get(data); + } + + public String toString() + { + return "";//String.format("Length: %d | %02x %02x %02x %02x %02x %02x %02x %02x", + //length, data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7]); + } + } }