Ashish Sharma
Ashish Sharma

Reputation: 1144

Unable to create java InputStream from javaCV FrameRecorder Class

I am using JavaCV to capture the video from my web camera using FrameRecorder.

I am working to create a library utility class that would provide the webCam video as an 'avi' video InputStream, here I am unable to do so as the FrameRecorder does not provide any such facility, all it takes is a file name and persists the video on the filesystem. What should I do to generate a java InputStream from FrameRecorder?

Following is the sample code for reference :

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();

I am open to any other alternatives too ...

thanks in advance

Ashish

Upvotes: 0

Views: 1504

Answers (2)

brunocodutra
brunocodutra

Reputation: 2349

Why do you want to use a FrameRecorder if your goal is not to create a video file?

The most practical solution I can think of, would be to simply extend InputStream using a FrameGrabber as backend. Since JavaCV doesn't seem to provide that out of the box, then I'm afraid you'd have to do it yourself.

As described on the documentation for InputStream, subclasses of InputStream must only implement public abstract int read(), however keep in mind it will also most probably be necessary to overwrite other methods too.

A good bet would be to implement public int read(byte[] b).

For reference, a very simple inefficient and unsafe implementation follows.

Warning not tested!

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;
}

Upvotes: 1

Diego C Nascimento
Diego C Nascimento

Reputation: 2801

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

Seems that the method that is called for writing the frame data is the following:

/**
* 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);

As its native method, your bet will be to redirect the native lib output other than a file, or using the image data returned to "build" your AVI.

You can use a memory mapped file, but in that case you want continuous capture of video, I don't think it would be a good idea.

Upvotes: 1

Related Questions