无法从javaCV FrameRecorder类创建java InputStream

时间:2013-09-09 12:43:58

标签: java opencv ffmpeg javacv

我正在使用JavaCV使用FrameRecorder从我的网络摄像头捕获视频。

我正在创建一个库实用程序类,它将webCam视频作为'avi'视频InputStream提供,在这里我无法这样做,因为FrameRecorder没有提供任何这样的工具,所需要的只是一个文件名并将视频保留在文件系统上。 如何从FrameRecorder生成java InputStream?

以下是供参考的示例代码:

FrameGrabber frameGrabber = FrameGrabber.createDefault(1);
frameGrabber.start();
IplImage grabbedImage = frameGrabber.grab();
int width = grabbedImage.width();
int height = grabbedImage.height();

FrameRecorder frameRecorder = new FFmpegFrameRecorder("c:\\output.avi", width, height);
frameRecorder.setAudioChannels(frameGrabber.getAudioChannels());
frameRecorder.start();        

int i = 0;
while ((grabbedImage = frameGrabber.grab()) != null && i <= 500) {
    frameRecorder.record(grabbedImage);
    i++;
}

frameRecorder.stop();
frameGrabber.stop();

我也对任何其他选择开放......

提前致谢

与Ashish

2 个答案:

答案 0 :(得分:1)

根据http://code.google.com/p/javacv/source/browse/src/main/java/com/googlecode/javacv/cpp/avformat.java

似乎写入帧数据的方法如下:

/**
* Write a packet to an output media file.
*
* The packet shall contain one audio or video frame.
* The packet must be correctly interleaved according to the container
* specification, if not then av_interleaved_write_frame must be used.
*
* @param s media file handle
* @param pkt The packet, which contains the stream_index, buf/buf_size,
* dts/pts, ...
* This can be NULL (at any time, not just at the end), in
* order to immediately flush data buffered within the muxer,
* for muxers that buffer up data internally before writing it
* to the output.
* @return < 0 on error, = 0 if OK, 1 if flushed and there is no more data to flush
*/
public static native int av_write_frame(AVFormatContext s, AVPacket pkt);

作为其原生方法,您的赌注是重定向除文件之外的本机lib输出, 或使用返回的图像数据“构建”您的AVI。

您可以使用内存映射文件,但在这种情况下,您希望连续捕获视频,我认为这不是一个好主意。

答案 1 :(得分:1)

如果您的目标不是创建视频文件,为什么要使用FrameRecorder

我能想到的最实用的解决方案是使用InputStream作为后端简单地扩展FrameGrabber。由于JavaCV似乎没有开箱即用,所以我担心你必须自己做。

正如documentation for InputStream所述,InputStream的子类只能实现public abstract int read(),但请记住,也很可能也需要覆盖其他方法。

一个好的选择是实施public int read(byte[] b)

作为参考,下面是一个非常简单的低效和不安全的实现。

警告未经过测试

public int read(byte[] data) throws IOException, BufferUnderflowException, Exception {

    IplImage grabbedImage = frameGrabber.grab();
    if(grabbedImage == null)
        throw <some IOException here>
    grabbedImage.getByteBuffer().get(data);
    return data.length;
}