mirror of
https://github.com/moonlight-stream/moonlight-android.git
synced 2025-07-20 03:23:07 +00:00
Refactor AV code
This commit is contained in:
parent
9b91543c2d
commit
d3b9387c37
@ -5,14 +5,102 @@ import java.net.DatagramPacket;
|
|||||||
import java.net.DatagramSocket;
|
import java.net.DatagramSocket;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.net.SocketException;
|
import java.net.SocketException;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
|
|
||||||
|
import jlibrtp.Participant;
|
||||||
|
import jlibrtp.RTPSession;
|
||||||
|
|
||||||
|
import com.limelight.nvstream.av.AvBufferDescriptor;
|
||||||
|
import com.limelight.nvstream.av.AvBufferPool;
|
||||||
|
import com.limelight.nvstream.av.AvRtpPacket;
|
||||||
|
|
||||||
|
import android.media.MediaCodec;
|
||||||
|
import android.media.MediaFormat;
|
||||||
import android.net.rtp.AudioGroup;
|
import android.net.rtp.AudioGroup;
|
||||||
import android.net.rtp.AudioStream;
|
import android.net.rtp.AudioStream;
|
||||||
|
import android.view.Surface;
|
||||||
|
|
||||||
public class NvAudioStream {
|
public class NvAudioStream {
|
||||||
private AudioGroup group;
|
public static final int RTP_PORT = 48000;
|
||||||
private AudioStream stream;
|
public static final int RTCP_PORT = 47999;
|
||||||
|
|
||||||
public static final int PORT = 48000;
|
private LinkedBlockingQueue<AvRtpPacket> packets = new LinkedBlockingQueue<AvRtpPacket>();
|
||||||
|
|
||||||
|
private RTPSession session;
|
||||||
|
private DatagramSocket rtp;
|
||||||
|
|
||||||
|
private AvBufferPool pool = new AvBufferPool(1500);
|
||||||
|
|
||||||
|
public void setupRtpSession(String host) throws SocketException
|
||||||
|
{
|
||||||
|
DatagramSocket rtcp;
|
||||||
|
|
||||||
|
rtp = new DatagramSocket(RTP_PORT);
|
||||||
|
rtcp = new DatagramSocket(RTCP_PORT);
|
||||||
|
|
||||||
|
session = new RTPSession(rtp, rtcp);
|
||||||
|
session.addParticipant(new Participant(host, RTP_PORT, RTCP_PORT));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void startReceiveThread()
|
||||||
|
{
|
||||||
|
// Receive thread
|
||||||
|
new Thread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
DatagramPacket packet = new DatagramPacket(pool.allocate(), 1500);
|
||||||
|
AvBufferDescriptor desc = new AvBufferDescriptor(null, 0, 0);
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
rtp.receive(packet);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
desc.length = packet.getLength();
|
||||||
|
desc.offset = packet.getOffset();
|
||||||
|
desc.data = packet.getData();
|
||||||
|
|
||||||
|
// Give the packet to the depacketizer thread
|
||||||
|
packets.add(new AvRtpPacket(desc));
|
||||||
|
|
||||||
|
// Get a new buffer from the buffer pool
|
||||||
|
packet.setData(pool.allocate(), 0, 1500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void startUdpPingThread()
|
||||||
|
{
|
||||||
|
// 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();
|
||||||
|
}
|
||||||
|
|
||||||
/*public void startStream(String host) throws SocketException, UnknownHostException
|
/*public void startStream(String host) throws SocketException, UnknownHostException
|
||||||
{
|
{
|
||||||
@ -33,63 +121,4 @@ public class NvAudioStream {
|
|||||||
System.out.println("Joined");
|
System.out.println("Joined");
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
public void start(final String host)
|
|
||||||
{
|
|
||||||
new Thread(new Runnable() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
final DatagramSocket ds;
|
|
||||||
try {
|
|
||||||
ds = new DatagramSocket(PORT);
|
|
||||||
} catch (SocketException e1) {
|
|
||||||
// TODO Auto-generated catch block
|
|
||||||
e1.printStackTrace();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
new Thread(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
byte[] ping = new byte[]{0x50, 0x49, 0x4e, 0x47};
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
DatagramPacket dgp = new DatagramPacket(ping, 0, ping.length);
|
|
||||||
dgp.setSocketAddress(new InetSocketAddress(host, PORT));
|
|
||||||
try {
|
|
||||||
ds.send(dgp);
|
|
||||||
} catch (IOException e1) {
|
|
||||||
// TODO Auto-generated catch block
|
|
||||||
e1.printStackTrace();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
Thread.sleep(1000);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}).start();
|
|
||||||
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
|
|
||||||
DatagramPacket dp = new DatagramPacket(new byte[1500], 1500);
|
|
||||||
|
|
||||||
try {
|
|
||||||
ds.receive(dp);
|
|
||||||
} catch (IOException e) {
|
|
||||||
// TODO Auto-generated catch block
|
|
||||||
e.printStackTrace();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
//System.out.println("Got UDP 48000: "+dp.getLength());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}).start();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -13,9 +13,8 @@ import java.util.concurrent.LinkedBlockingQueue;
|
|||||||
import com.limelight.nvstream.av.AvBufferDescriptor;
|
import com.limelight.nvstream.av.AvBufferDescriptor;
|
||||||
import com.limelight.nvstream.av.AvBufferPool;
|
import com.limelight.nvstream.av.AvBufferPool;
|
||||||
import com.limelight.nvstream.av.AvDecodeUnit;
|
import com.limelight.nvstream.av.AvDecodeUnit;
|
||||||
import com.limelight.nvstream.av.AvPacket;
|
|
||||||
import com.limelight.nvstream.av.AvDepacketizer;
|
|
||||||
import com.limelight.nvstream.av.AvRtpPacket;
|
import com.limelight.nvstream.av.AvRtpPacket;
|
||||||
|
import com.limelight.nvstream.av.video.AvVideoDepacketizer;
|
||||||
|
|
||||||
import jlibrtp.Participant;
|
import jlibrtp.Participant;
|
||||||
import jlibrtp.RTPSession;
|
import jlibrtp.RTPSession;
|
||||||
@ -30,8 +29,8 @@ public class NvVideoStream {
|
|||||||
public static final int RTCP_PORT = 47999;
|
public static final int RTCP_PORT = 47999;
|
||||||
public static final int FIRST_FRAME_PORT = 47996;
|
public static final int FIRST_FRAME_PORT = 47996;
|
||||||
|
|
||||||
private ByteBuffer[] videoDecoderInputBuffers, audioDecoderInputBuffers;
|
private ByteBuffer[] videoDecoderInputBuffers;
|
||||||
private MediaCodec videoDecoder, audioDecoder;
|
private MediaCodec videoDecoder;
|
||||||
|
|
||||||
private LinkedBlockingQueue<AvRtpPacket> packets = new LinkedBlockingQueue<AvRtpPacket>();
|
private LinkedBlockingQueue<AvRtpPacket> packets = new LinkedBlockingQueue<AvRtpPacket>();
|
||||||
|
|
||||||
@ -40,7 +39,7 @@ public class NvVideoStream {
|
|||||||
|
|
||||||
private AvBufferPool pool = new AvBufferPool(1500);
|
private AvBufferPool pool = new AvBufferPool(1500);
|
||||||
|
|
||||||
private AvDepacketizer depacketizer = new AvDepacketizer();
|
private AvVideoDepacketizer depacketizer = new AvVideoDepacketizer();
|
||||||
|
|
||||||
private InputStream openFirstFrameInputStream(String host) throws UnknownHostException, IOException
|
private InputStream openFirstFrameInputStream(String host) throws UnknownHostException, IOException
|
||||||
{
|
{
|
||||||
@ -94,19 +93,13 @@ public class NvVideoStream {
|
|||||||
videoDecoder = MediaCodec.createDecoderByType("video/avc");
|
videoDecoder = MediaCodec.createDecoderByType("video/avc");
|
||||||
MediaFormat videoFormat = MediaFormat.createVideoFormat("video/avc", 1280, 720);
|
MediaFormat videoFormat = MediaFormat.createVideoFormat("video/avc", 1280, 720);
|
||||||
|
|
||||||
audioDecoder = MediaCodec.createDecoderByType("audio/mp4a-latm");
|
|
||||||
MediaFormat audioFormat = MediaFormat.createAudioFormat("audio/mp4a-latm", 48000, 2);
|
|
||||||
|
|
||||||
videoDecoder.configure(videoFormat, surface, null, 0);
|
videoDecoder.configure(videoFormat, surface, null, 0);
|
||||||
audioDecoder.configure(audioFormat, null, null, 0);
|
|
||||||
|
|
||||||
videoDecoder.setVideoScalingMode(MediaCodec.VIDEO_SCALING_MODE_SCALE_TO_FIT);
|
videoDecoder.setVideoScalingMode(MediaCodec.VIDEO_SCALING_MODE_SCALE_TO_FIT);
|
||||||
|
|
||||||
videoDecoder.start();
|
videoDecoder.start();
|
||||||
audioDecoder.start();
|
|
||||||
|
|
||||||
videoDecoderInputBuffers = videoDecoder.getInputBuffers();
|
videoDecoderInputBuffers = videoDecoder.getInputBuffers();
|
||||||
audioDecoderInputBuffers = audioDecoder.getInputBuffers();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void startVideoStream(final String host, final Surface surface)
|
public void startVideoStream(final String host, final Surface surface)
|
||||||
@ -139,9 +132,6 @@ public class NvVideoStream {
|
|||||||
// Start decoding the data we're receiving
|
// Start decoding the data we're receiving
|
||||||
startDecoderThread();
|
startDecoderThread();
|
||||||
|
|
||||||
// Start playing back audio data
|
|
||||||
startAudioPlaybackThread();
|
|
||||||
|
|
||||||
// Read the first frame to start the UDP video stream
|
// Read the first frame to start the UDP video stream
|
||||||
try {
|
try {
|
||||||
readFirstFrame(host);
|
readFirstFrame(host);
|
||||||
@ -201,32 +191,6 @@ public class NvVideoStream {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AvDecodeUnit.TYPE_AAC:
|
|
||||||
{
|
|
||||||
int inputIndex = audioDecoder.dequeueInputBuffer(0);
|
|
||||||
if (inputIndex == -4)
|
|
||||||
{
|
|
||||||
ByteBuffer buf = audioDecoderInputBuffers[inputIndex];
|
|
||||||
|
|
||||||
// Clear old input data
|
|
||||||
buf.clear();
|
|
||||||
|
|
||||||
// Copy data from our buffer list into the input buffer
|
|
||||||
for (AvBufferDescriptor desc : du.getBufferList())
|
|
||||||
{
|
|
||||||
buf.put(desc.data, desc.offset, desc.length);
|
|
||||||
|
|
||||||
// Release the buffer back to the buffer pool
|
|
||||||
pool.free(desc.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
audioDecoder.queueInputBuffer(inputIndex,
|
|
||||||
0, du.getDataLength(),
|
|
||||||
0, du.getFlags());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
System.out.println("Unknown decode unit type");
|
System.out.println("Unknown decode unit type");
|
||||||
@ -322,40 +286,6 @@ public class NvVideoStream {
|
|||||||
}).start();
|
}).start();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startAudioPlaybackThread()
|
|
||||||
{
|
|
||||||
new Thread(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
BufferInfo info = new BufferInfo();
|
|
||||||
System.out.println("Waiting for audio");
|
|
||||||
int outIndex = audioDecoder.dequeueOutputBuffer(info, -1);
|
|
||||||
System.out.println("Got audio");
|
|
||||||
switch (outIndex) {
|
|
||||||
case MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED:
|
|
||||||
System.out.println("Output buffers changed");
|
|
||||||
break;
|
|
||||||
case MediaCodec.INFO_OUTPUT_FORMAT_CHANGED:
|
|
||||||
System.out.println("Output format changed");
|
|
||||||
System.out.println("New output Format: " + videoDecoder.getOutputFormat());
|
|
||||||
break;
|
|
||||||
case MediaCodec.INFO_TRY_AGAIN_LATER:
|
|
||||||
System.out.println("Try again later");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (outIndex >= 0) {
|
|
||||||
audioDecoder.releaseOutputBuffer(outIndex, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}).start();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void outputDisplayLoop()
|
private void outputDisplayLoop()
|
||||||
{
|
{
|
||||||
for (;;)
|
for (;;)
|
||||||
|
@ -5,7 +5,7 @@ import java.util.List;
|
|||||||
public class AvDecodeUnit {
|
public class AvDecodeUnit {
|
||||||
public static final int TYPE_UNKNOWN = 0;
|
public static final int TYPE_UNKNOWN = 0;
|
||||||
public static final int TYPE_H264 = 1;
|
public static final int TYPE_H264 = 1;
|
||||||
public static final int TYPE_AAC = 2;
|
public static final int TYPE_OPUS = 2;
|
||||||
|
|
||||||
private int type;
|
private int type;
|
||||||
private List<AvBufferDescriptor> bufferList;
|
private List<AvBufferDescriptor> bufferList;
|
||||||
|
@ -4,6 +4,7 @@ import java.nio.ByteBuffer;
|
|||||||
|
|
||||||
public class AvRtpPacket {
|
public class AvRtpPacket {
|
||||||
|
|
||||||
|
private byte packetType;
|
||||||
private short seqNum;
|
private short seqNum;
|
||||||
private AvBufferDescriptor buffer;
|
private AvBufferDescriptor buffer;
|
||||||
|
|
||||||
@ -13,13 +14,21 @@ public class AvRtpPacket {
|
|||||||
|
|
||||||
ByteBuffer bb = ByteBuffer.wrap(buffer.data, buffer.offset, buffer.length);
|
ByteBuffer bb = ByteBuffer.wrap(buffer.data, buffer.offset, buffer.length);
|
||||||
|
|
||||||
// Discard the first couple of bytes
|
// Discard the first byte
|
||||||
bb.getShort();
|
bb.position(bb.position()+1);
|
||||||
|
|
||||||
|
// Get the packet type
|
||||||
|
packetType = bb.get();
|
||||||
|
|
||||||
// Get the sequence number
|
// Get the sequence number
|
||||||
seqNum = bb.getShort();
|
seqNum = bb.getShort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public byte getPacketType()
|
||||||
|
{
|
||||||
|
return packetType;
|
||||||
|
}
|
||||||
|
|
||||||
public short getSequenceNumber()
|
public short getSequenceNumber()
|
||||||
{
|
{
|
||||||
return seqNum;
|
return seqNum;
|
||||||
|
@ -1,17 +1,19 @@
|
|||||||
package com.limelight.nvstream.av;
|
package com.limelight.nvstream.av.video;
|
||||||
|
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.concurrent.LinkedBlockingQueue;
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
|
|
||||||
|
import com.limelight.nvstream.av.AvBufferDescriptor;
|
||||||
|
import com.limelight.nvstream.av.AvDecodeUnit;
|
||||||
|
import com.limelight.nvstream.av.AvRtpPacket;
|
||||||
|
|
||||||
import android.media.MediaCodec;
|
import android.media.MediaCodec;
|
||||||
|
|
||||||
public class AvDepacketizer {
|
public class AvVideoDepacketizer {
|
||||||
|
|
||||||
// Current NAL state
|
// Current NAL state
|
||||||
private LinkedList<AvBufferDescriptor> avcNalDataChain = null;
|
private LinkedList<AvBufferDescriptor> avcNalDataChain = null;
|
||||||
private int avcNalDataLength = 0;
|
private int avcNalDataLength = 0;
|
||||||
private LinkedList<AvBufferDescriptor> aacNalDataChain = null;
|
|
||||||
private int aacNalDataLength = 0;
|
|
||||||
private int currentlyDecoding;
|
private int currentlyDecoding;
|
||||||
|
|
||||||
// Sequencing state
|
// Sequencing state
|
||||||
@ -19,28 +21,6 @@ public class AvDepacketizer {
|
|||||||
|
|
||||||
private LinkedBlockingQueue<AvDecodeUnit> decodedUnits = new LinkedBlockingQueue<AvDecodeUnit>();
|
private LinkedBlockingQueue<AvDecodeUnit> decodedUnits = new LinkedBlockingQueue<AvDecodeUnit>();
|
||||||
|
|
||||||
private void reassembleAacNal()
|
|
||||||
{
|
|
||||||
// This is the start of a new AAC NAL
|
|
||||||
if (aacNalDataChain != null && aacNalDataLength != 0)
|
|
||||||
{
|
|
||||||
System.out.println("Assembling AAC NAL: "+aacNalDataLength);
|
|
||||||
|
|
||||||
/*AvBufferDescriptor header = aacNalDataChain.getFirst();
|
|
||||||
for (int i = 0; i < header.length; i++)
|
|
||||||
System.out.printf("%02x ", header.data[header.offset+i]);
|
|
||||||
System.out.println();*/
|
|
||||||
|
|
||||||
// Construct the AAC decode unit
|
|
||||||
AvDecodeUnit du = new AvDecodeUnit(AvDecodeUnit.TYPE_AAC, aacNalDataChain, aacNalDataLength, 0);
|
|
||||||
decodedUnits.add(du);
|
|
||||||
|
|
||||||
// Clear old state
|
|
||||||
aacNalDataChain = null;
|
|
||||||
aacNalDataLength = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void reassembleAvcNal()
|
private void reassembleAvcNal()
|
||||||
{
|
{
|
||||||
// This is the start of a new NAL
|
// This is the start of a new NAL
|
||||||
@ -103,7 +83,7 @@ public class AvDepacketizer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addInputData(AvPacket packet)
|
public void addInputData(AvVideoPacket packet)
|
||||||
{
|
{
|
||||||
AvBufferDescriptor location = packet.getNewPayloadDescriptor();
|
AvBufferDescriptor location = packet.getNewPayloadDescriptor();
|
||||||
|
|
||||||
@ -132,18 +112,6 @@ public class AvDepacketizer {
|
|||||||
avcNalDataLength = 0;
|
avcNalDataLength = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (NAL.isAacStartSequence(specialSeq))
|
|
||||||
{
|
|
||||||
// We're decoding AAC now
|
|
||||||
currentlyDecoding = AvDecodeUnit.TYPE_AAC;
|
|
||||||
|
|
||||||
// Reassemble any pending AAC NAL
|
|
||||||
reassembleAacNal();
|
|
||||||
|
|
||||||
// Setup state for the new NAL
|
|
||||||
aacNalDataChain = new LinkedList<AvBufferDescriptor>();
|
|
||||||
aacNalDataLength = 0;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Not either sequence we want
|
// Not either sequence we want
|
||||||
@ -181,12 +149,6 @@ public class AvDepacketizer {
|
|||||||
avcNalDataChain.add(data);
|
avcNalDataChain.add(data);
|
||||||
avcNalDataLength += location.offset-start;
|
avcNalDataLength += location.offset-start;
|
||||||
}
|
}
|
||||||
else if (currentlyDecoding == AvDecodeUnit.TYPE_AAC && aacNalDataChain != null)
|
|
||||||
{
|
|
||||||
// Add a buffer descriptor describing the NAL data in this packet
|
|
||||||
aacNalDataChain.add(data);
|
|
||||||
aacNalDataLength += location.offset-start;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -205,15 +167,13 @@ public class AvDepacketizer {
|
|||||||
currentlyDecoding = AvDecodeUnit.TYPE_UNKNOWN;
|
currentlyDecoding = AvDecodeUnit.TYPE_UNKNOWN;
|
||||||
avcNalDataChain = null;
|
avcNalDataChain = null;
|
||||||
avcNalDataLength = 0;
|
avcNalDataLength = 0;
|
||||||
aacNalDataChain = null;
|
|
||||||
aacNalDataLength = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
lastSequenceNumber = seq;
|
lastSequenceNumber = seq;
|
||||||
|
|
||||||
// Pass the payload to the non-sequencing parser
|
// Pass the payload to the non-sequencing parser
|
||||||
AvBufferDescriptor rtpPayload = packet.getNewPayloadDescriptor();
|
AvBufferDescriptor rtpPayload = packet.getNewPayloadDescriptor();
|
||||||
addInputData(new AvPacket(rtpPayload));
|
addInputData(new AvVideoPacket(rtpPayload));
|
||||||
}
|
}
|
||||||
|
|
||||||
public AvDecodeUnit getNextDecodeUnit() throws InterruptedException
|
public AvDecodeUnit getNextDecodeUnit() throws InterruptedException
|
||||||
@ -235,7 +195,7 @@ class NAL {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// This assumes that the buffer passed in is already a special sequence
|
// This assumes that the buffer passed in is already a special sequence
|
||||||
public static boolean isAacStartSequence(AvBufferDescriptor specialSeq)
|
public static boolean isUnknownStartSequence(AvBufferDescriptor specialSeq)
|
||||||
{
|
{
|
||||||
if (specialSeq.length != 3)
|
if (specialSeq.length != 3)
|
||||||
return false;
|
return false;
|
@ -1,9 +1,11 @@
|
|||||||
package com.limelight.nvstream.av;
|
package com.limelight.nvstream.av.video;
|
||||||
|
|
||||||
public class AvPacket {
|
import com.limelight.nvstream.av.AvBufferDescriptor;
|
||||||
|
|
||||||
|
public class AvVideoPacket {
|
||||||
private AvBufferDescriptor buffer;
|
private AvBufferDescriptor buffer;
|
||||||
|
|
||||||
public AvPacket(AvBufferDescriptor rtpPayload)
|
public AvVideoPacket(AvBufferDescriptor rtpPayload)
|
||||||
{
|
{
|
||||||
buffer = new AvBufferDescriptor(rtpPayload);
|
buffer = new AvBufferDescriptor(rtpPayload);
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user