You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

130 lines
3.8 KiB
Java

2 years ago
package org.easydarwin.push;
import android.content.Context;
import android.util.Log;
import org.easydarwin.muxer.EasyMuxer;
import org.easydarwin.sw.JNIUtil;
import org.easydarwin.sw.X264Encoder;
import java.util.concurrent.ArrayBlockingQueue;
/**
* Created by apple on 2017/5/13.
*/
public class SWConsumer extends Thread implements VideoConsumer {
private static final String TAG = "SWConsumer";
private int mHeight;
private int mWidth;
private X264Encoder x264;
private final Pusher mPusher;
private volatile boolean mVideoStarted;
public SWConsumer(Context context, Pusher pusher){
mPusher = pusher;
}
@Override
public void onVideoStart(int width, int height) {
this.mWidth = width;
this.mHeight = height;
x264 = new X264Encoder();
int bitrate = (int) (mWidth*mHeight*20*2*0.07f);
x264.create(width, height, 20, bitrate/500);
mVideoStarted = true;
start();
}
class TimedBuffer {
byte[] buffer;
long time;
public TimedBuffer(byte[] data) {
buffer = data;
time = System.currentTimeMillis();
}
}
private ArrayBlockingQueue<TimedBuffer> yuvs = new ArrayBlockingQueue<TimedBuffer>(2);
private ArrayBlockingQueue<byte[]> yuv_caches = new ArrayBlockingQueue<byte[]>(10);
@Override
public void run(){
byte[]h264 = new byte[mWidth*mHeight*3/2];
byte[] keyFrm = new byte[1];
int []outLen = new int[1];
do {
try {
int r = 0;
TimedBuffer tb = yuvs.take();
byte[] data = tb.buffer;
long begin = System.currentTimeMillis();
r = x264.encode(data, 0, h264, 0, outLen, keyFrm);
if (r > 0) {
Log.i(TAG, String.format("encode spend:%d ms. keyFrm:%d", System.currentTimeMillis() - begin, keyFrm[0]));
// newBuf = new byte[outLen[0]];
// System.arraycopy(h264, 0, newBuf, 0, newBuf.length);
}
keyFrm[0] = 0;
yuv_caches.offer(data);
mPusher.push(h264, 0, outLen[0], tb.time, 1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}while (mVideoStarted);
}
final int millisPerframe = 1000/20;
long lastPush = 0;
@Override
public int onVideo(byte[] data, int format) {
try {
if (lastPush == 0) {
lastPush = System.currentTimeMillis();
}
long time = System.currentTimeMillis() - lastPush;
if (time >= 0) {
time = millisPerframe - time;
if (time > 0) Thread.sleep(time / 2);
}
byte[] buffer = yuv_caches.poll();
if (buffer == null || buffer.length != data.length) {
buffer = new byte[data.length];
}
System.arraycopy(data, 0, buffer, 0, data.length);
JNIUtil.yuvConvert(buffer, mWidth, mHeight, 4);
yuvs.offer(new TimedBuffer(buffer));
if (time > 0) Thread.sleep(time / 2);
lastPush = System.currentTimeMillis();
}catch (InterruptedException ex){
ex.printStackTrace();
}
return 0;
}
@Override
public void onVideoStop() {
do {
mVideoStarted = false;
try {
interrupt();
join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}while (isAlive());
if (x264 != null) {
x264.close();
}
x264 = null;
}
@Override
public void setMuxer(EasyMuxer muxer) {
}
}