我正在使用android v21设备将数据流式传输到javafx应用程序。它的工作正常,但我有大约2秒的延迟。
到目前为止,基本交通是这样的>>
我到台式机和打包器的数据流比我的帧速率快得多,并且通常只是在等待。在其他任何地方都没有数据的积累,因此我假设我的任何代码都不会延迟。
我通过将相机中的yuv写入纹理并定时确定android设备将帧编码为h264的时间,然后直到发送它的时间,测试了我的android设备。所以16 + 6 = 22ms
我觉得问题出在Javacv ffmpeg framegrabber。我正在研究此api,以了解发生这种情况的原因。
我主要担心的是,framegrabber花费了很多时间才能启动...大约4秒钟。
[开始后,我可以清楚地看到我插入了多少帧,抓取了多少帧,并且总是滞后一些较大的数字,例如40到200。
而且Framegrabber.grab()也会阻塞,并且每隔100毫秒运行一次以匹配我的帧速率,无论我告诉它运行多快,这样我就永远追赶不上。
您有什么建议吗?
我开始认为javacv不是一个可行的解决方案,因为似乎很多人都在解决此延迟问题。如果您有其他建议,请提出建议。
我的ffmpeg framgrabber
public RapidDecoder(final InputStream inputStream, final ImageView view) { System.out.println(TAG + " starting"); grabber = new FFmpegFrameGrabber(inputStream, 0); converter = new Java2DFrameConverter(); mView = view; emptyBuffer = new Runnable() { @Override public void run() { System.out.println(TAG + " emptybuffer thread running"); try { grabber.setFrameRate(12); grabber.setVideoBitrate(10000); //grabber.setOption("g", "2"); // grabber.setOption("bufsize", "10000"); //grabber.setOption("af", "delay 20"); //grabber.setNumBuffers(0); //grabber.setOption("flush_packets", "1"); //grabber.setOption("probsize", "32"); //grabber.setOption("analyzeduration", "0"); grabber.setOption("preset", "ultrafast"); grabber.setOption("fflags", "nobuffer"); //grabber.setVideoOption("nobuffer", "1"); //grabber.setOption("fflags", "discardcorrupt"); //grabber.setOption("framedrop", "\\"); //grabber.setOption("flags","low_delay"); grabber.setOption("strict","experimental"); //grabber.setOption("avioflags", "direct"); //grabber.setOption("filter:v", "fps=fps=30"); grabber.setVideoOption("tune", "zerolatency"); //grabber.setFrameNumber(60); grabber.start(); }catch (Exception e) { System.out.println(TAG + e); } while (true) { try{ grabFrame(); Thread.sleep(1); }catch (Exception e) { System.out.println(TAG + " emptybuffer " + e); } } } }; display = new Runnable() { @Override public void run() { System.out.println(TAG + " display thread running "); while(true) { try{ displayImage(); Thread.sleep(10); }catch (Exception e) { System.out.println(TAG + " display " + e); } } } }; } public void generateVideo() { System.out.println(TAG + " genvid "); new Thread(emptyBuffer).start(); new Thread(display).start(); } public synchronized void grabFrame() throws FrameGrabber.Exception { //frame = grabber.grabFrame(); frame = grabber.grab(); //System.out.println("grab"); } public synchronized void displayImage() { bufferedImage = converter.convert(frame); frame = null; if (bufferedImage == null) return; mView.setImage(SwingFXUtils.toFXImage(bufferedImage, null)); //System.out.println("display"); }
在这里您可以看到我用图像绘制纹理并发送到h264编码器
@ Overridepublic void onTextureFrameCaptured(int width,int height,int texId,float [] tranformMatrix,int rotation,long timestamp){//Log.d(TAG,“ onTextureFrameCaptured:->”);
VideoRenderer.I420Frame frame = new VideoRenderer.I420Frame(width, height, rotation, texId, tranformMatrix, 0,timestamp); avccEncoder.renderFrame(frame); videoView.renderFrame(frame); surfaceTextureHelper.returnTextureFrame(); }
在这里您可以看到webrtc编码发生
@Override
public void renderFrame(VideoRenderer.I420Frame i420Frame) {
start = System.nanoTime();
bufferque++;
mediaCodecHandler.post(new Runnable() {
@Override
public void run() {
videoEncoder.encodeTexture(false, i420Frame.textureId, i420Frame.samplingMatrix, TimeUnit.NANOSECONDS.toMicros(i420Frame.timestamp));
}
});
}
/**
* Called to retrieve an encoded frame
*/
@Override
public void onEncodedFrame(MediaCodecVideoEncoder.OutputBufferInfo frame, MediaCodec.BufferInfo bufferInfo) {
b = new byte[frame.buffer().remaining()];
frame.buffer().get(b);
synchronized (lock)
{
encodedBuffer.add(b);
lock.notifyAll();
if(encodedBuffer.size() > 1)
{
Log.e(TAG, "drainEncoder: too big: " + encodedBuffer.size(),null );
}
}
duration = System.nanoTime() - start;
bufferque--;
calcAverage();
if (bufferque > 0)
{
Log.d(TAG, "onEncodedFrame: bufferque size: " + bufferque);
}
}
我正在使用android v21设备将数据流式传输到javafx应用程序。它的工作正常,但我有大约2秒的延迟。截至目前,基本交通方式如下:android webrtc / ...
我在几天之内解决了这个问题,然后在上面编辑了我的问题,但让我为可能需要它们的人提供详细信息。