package cn.org.hentai.jtt1078.test;
|
|
import cn.org.hentai.jtt1078.server.Jtt1078Decoder;
|
import cn.org.hentai.jtt1078.util.Packet;
|
|
import java.io.FileOutputStream;
|
import java.io.InputStream;
|
import java.net.ServerSocket;
|
import java.net.Socket;
|
import java.util.LinkedList;
|
|
/**
|
* Created by houcheng on 2019-12-10.
|
*/
|
public class VideoServer
|
{
|
public static void main(String[] args) throws Exception
|
{
|
System.out.println("started...");
|
|
String command = ("ffmpeg -f h264 -i /opt/test/xxoo.Video -f sln -ar 8000 -ac 1 -i /opt/test/xxoo.Audio -vcodec copy -acodec aac -map 0:v:0 -map 1:a:0 -probesize 512 -analyzeduration 100 -f flv rtmp://localhost/live/fuck");
|
Process process = Runtime.getRuntime().exec(command);
|
new Reader(process.getErrorStream()).start();
|
|
Thread.sleep(2000);
|
|
ServerSocket server = new ServerSocket(1078, 100);
|
Socket conn = server.accept();
|
System.out.println("Connected from: " + conn.getRemoteSocketAddress());
|
InputStream input = conn.getInputStream();
|
|
Publisher videoPublisher = new VideoPublisher();
|
Publisher audioPublisher = new AudioPublisher();
|
|
videoPublisher.start();
|
audioPublisher.start();
|
|
int len = -1;
|
byte[] block = new byte[1024];
|
Jtt1078Decoder decoder = new Jtt1078Decoder();
|
while (true)
|
{
|
len = input.read(block);
|
if (len == -1) break;
|
decoder.write(block, 0, len);
|
|
while (true)
|
{
|
Packet p = decoder.decode();
|
if (p == null) break;
|
|
int lengthOffset = 28;
|
int dataType = (p.seek(15).nextByte() >> 4) & 0x0f;
|
// 透传数据类型:0100,没有后面的时间以及Last I Frame Interval和Last Frame Interval字段
|
if (dataType == 0x04) lengthOffset = 28 - 8 - 2 - 2;
|
else if (dataType == 0x03) lengthOffset = 28 - 4;
|
|
// FFMpegManager.getInstance().feed(publisherId, packet.seek(lengthOffset + 2).nextBytes());
|
if (dataType == 0x00 || dataType == 0x01 || dataType == 0x02)
|
{
|
videoPublisher.publish(p.seek(lengthOffset + 2).nextBytes());
|
}
|
else
|
{
|
audioPublisher.publish(p.seek(lengthOffset + 2).nextBytes());
|
}
|
}
|
}
|
|
System.in.read();
|
}
|
|
|
|
static class Reader extends Thread
|
{
|
InputStream stdout = null;
|
public Reader(InputStream is)
|
{
|
this.stdout = is;
|
}
|
|
public void run()
|
{
|
int len = -1;
|
byte[] block = new byte[512];
|
try
|
{
|
while ((len = stdout.read(block)) > -1)
|
{
|
System.out.print(new String(block, 0, len));
|
}
|
}
|
catch(Exception ex)
|
{
|
ex.printStackTrace();
|
}
|
}
|
}
|
|
static class Publisher extends Thread
|
{
|
Object lock = new Object();
|
LinkedList<byte[]> messages = new LinkedList();
|
|
public void publish(byte[] msg)
|
{
|
synchronized (lock)
|
{
|
messages.add(msg);
|
lock.notify();
|
}
|
}
|
|
public byte[] peek()
|
{
|
byte[] msg = null;
|
synchronized (lock)
|
{
|
while (messages.size() == 0) try { lock.wait(); } catch(Exception e) { }
|
msg = messages.removeFirst();
|
}
|
return msg;
|
}
|
|
public FileOutputStream open(String fname)
|
{
|
try
|
{
|
return new FileOutputStream(fname);
|
}
|
catch(Exception ex)
|
{
|
throw new RuntimeException(ex);
|
}
|
}
|
}
|
|
static class VideoPublisher extends Publisher
|
{
|
public void run()
|
{
|
FileOutputStream fos = open("/opt/test/xxoo.Video");
|
while (!this.isInterrupted())
|
{
|
try
|
{
|
byte[] msg = peek();
|
fos.write(msg);
|
fos.flush();
|
}
|
catch(Exception ex)
|
{
|
ex.printStackTrace();
|
break;
|
}
|
}
|
}
|
}
|
|
static class AudioPublisher extends Publisher
|
{
|
public void run()
|
{
|
FileOutputStream fos = open("/opt/test/xxoo.Audio");
|
while (!this.isInterrupted())
|
{
|
try
|
{
|
byte[] msg = peek();
|
fos.write(msg);
|
fos.flush();
|
}
|
catch(Exception ex)
|
{
|
ex.printStackTrace();
|
break;
|
}
|
}
|
}
|
}
|
}
|