0

Java 8 here. And while I mention JCodec, that I'm open to any solution that works!


In the JCodec README they provide a decent example for how one can turn a list of BufferedImages into an MP4 on disk like so:

SeekableByteChannel out = null;
try {
    out = NIOUtils.writableFileChannel("/tmp/output.mp4");
    // for Android use: AndroidSequenceEncoder
    AWTSequenceEncoder encoder = new AWTSequenceEncoder(out, Rational.R(25, 1));
    for (...) {
        // Generate the image, for Android use Bitmap
        BufferedImage image = ...;
        // Encode the image
        encoder.encodeImage(image);
    }
    // Finalize the encoding, i.e. clear the buffers, write the header, etc.
    encoder.finish();
} finally {
    NIOUtils.closeQuietly(out);
}

Instead of writing to a file system resource on the disk (such as "/tmp/output.mp4"), I'd like to write to a (fully MP4-compliant) in-memory buffer, ideally a byte[] or something that will convert into a byte[].

Is this possible to do with JCodec (maybe something inside of NIOUtils or similar)?

hotmeatballsoup
  • 385
  • 6
  • 58
  • 136
  • 1
    You could create a `SeekableByteChannel` implementation that simply reads/writes to an internal `ByteBuffer` or `byte[]`. Or since you're using NIO, if you want to avoid writing to a SSD/HDD you can use an [in-memory file system](https://github.com/google/jimfs). Just open a `FileChannel` to a `Path` from the in-memory file system, write to it, and then read the bytes afterwards. – Slaw Sep 09 '19 at 20:28
  • Thanks @Slaw (+1), where could I open the `FileChannel` from? From inside the `SeekableByteChannel` implementation? Any chance you could provide a pseudo-code example of what you're talking about here? Thanks again! – hotmeatballsoup Sep 09 '19 at 23:34
  • Also @Slaw looks like there is a [`ByteBufferSeekableByteChannel`](https://github.com/jcodec/jcodec/blob/master/src/main/java/org/jcodec/common/io/ByteBufferSeekableByteChannel.java) that _appears_ to do what you explain...any chance you could take a look at that source code and see if it does (or explain why it doesn't)? Thanks immensely! – hotmeatballsoup Sep 09 '19 at 23:40
  • 2
    You'd open the `FileChannel` normally, via one of the `FileChannel#open` static methods. Note, however, the `Path` _must_ come from the in-memory `FileSystem`; this means you can't create the `Path` using `Paths#get` or `Path#of`. Also, I just realized that JCodec has its own `SeekableByteChannel` (for some reason) which is not the same as `java.nio.channels.SeekableByteChannel`. A `FileChannel` implements the latter, which means you'd need to use [`FileChannelWrapper`](https://github.com/jcodec/jcodec/blob/master/src/main/java/org/jcodec/common/io/FileChannelWrapper.java). – Slaw Sep 09 '19 at 23:59
  • 2
    As for `ByteBufferSeekableByteChannel`, it's very similar to what I meant except that it doesn't appear to be resizable. In other words, it can only hold a set number of bytes which is determined by the `ByteBuffer` passed in during construction. – Slaw Sep 10 '19 at 00:01
  • Is the lack of resizability a concern in your mind? If I were to initialize the `ByteBuffer` to the same size of video (in bytes), shouldn't I be able to write the video into it (without the need to resize it)? – hotmeatballsoup Sep 10 '19 at 00:09
  • 2
    If you can know for certain what the capacity of the `ByteBuffer` needs to be ahead-of-time then there's no problem. – Slaw Sep 10 '19 at 00:10
  • 1
    @Slaw I guess, it uses its own `SeekableByteChannel` because the standard `SeekableByteChannel` was introduced in Java 7. – Holger Sep 10 '19 at 09:04

0 Answers0