0

我正在使用 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();

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

提前致谢

阿什什

4

2 回答 2

1

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

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

文档中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;
}
于 2013-09-17T22:11:12.003 回答
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。

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

于 2013-09-17T17:55:21.810 回答