title: Record and play h.264 video in memory using Jcodec
body: <p>I am working on a project that requires h.264 video to be written to memory and then read from memory. In other words, using a byte array rather than a File. The only java encoder library that I can find is JCodec.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  I am using version 0.2.0 of JCodec's SequenceEncoder8Bit and FrameGrab8Bit classes to read and write to a byte array. The error that I am currently getting is</p>
  
  <pre><code>    java.io.IOException: Could not find movie meta information box
      at org.jcodec.containers.mp4.demuxer.MP4Demuxer.findMovieBox(MP4Demuxer.java:56)
      at org.jcodec.containers.mp4.demuxer.MP4Demuxer.&lt;init&gt;(MP4Demuxer.java:46)
      at ....
  </code></pre>
  
  <p>My code example is as follows:</p>
  
  <pre><code>import java.awt.image.BufferedImage;
  import java.io.IOException;
  import java.nio.ByteBuffer;
  import java.util.Arrays;
  
  import org.jcodec.api.FrameGrab8Bit;
  import org.jcodec.api.JCodecException;
  import org.jcodec.api.SequenceEncoder8Bit;
  import org.jcodec.common.io.ByteBufferSeekableByteChannel;
  import org.jcodec.common.io.SeekableByteChannel;
  import org.jcodec.common.model.Picture8Bit;
  import org.jcodec.common.model.Rational;
  import org.jcodec.scale.AWTUtil;
  import org.opencv.core.Mat;
  
  public class Sequence8BitTest {
  
  private static boolean _isDone = false;
  
  public static void main(String[] args) {
      byte[] data = writeVideo();
      readVideo(data);
  }
  
  private static void encodeVideo(SequenceEncoder8Bit encoder, ByteBuffer buffer, int videoSize){
      try{//Close Encoder
          encoder.finish();
          buffer = ByteBuffer.wrap(Arrays.copyOf(buffer.array(), videoSize));
      }catch(IOException e){
          e.printStackTrace();
      }
  }
  
  private static BufferedImage matToBufferedImage(Mat in) throws IOException {
      byte[] data = new byte[in.width() * in.height() * (int)in.elemSize()];
      int type;
      BufferedImage out;
  
      in.get(0, 0, data);
  
      if(in.channels() == 1){
          type = BufferedImage.TYPE_BYTE_GRAY;
      }
      else{
          type = BufferedImage.TYPE_3BYTE_BGR;
      }
  
      out = new BufferedImage(in.width(), in.height(), type);
      out.getRaster().setDataElements(0, 0, in.width(), in.height(), data);
  
      return out;
  }
  
  private static BufferedImage readImage(FrameGrab8Bit grabber) {
      Picture8Bit pic = null;
  
      try {
          pic = grabber.getNativeFrame();
      } catch (IOException e) {
          e.printStackTrace();
          return null;
      }
  
      return AWTUtil.toBufferedImage8Bit(pic);
  
  }
  
  private static void readVideo(byte[] data){
      FrameGrab8Bit grabber = null;
      BufferedImage img;
      ByteBuffer buffer;
      SeekableByteChannel channel;
  
      buffer = ByteBuffer.wrap(data);
      channel = new ByteBufferSeekableByteChannel(buffer);
  
      try {
          grabber = FrameGrab8Bit.createFrameGrab8Bit(channel);
  
          while((img = readImage(grabber)) != null){
              //display Image
          }
  
          channel.close();
  
      } catch (IOException | JCodecException e) {
          e.printStackTrace();
          System.exit(-1);
      }
  }
  
  private static void writeImage(Mat mat, SequenceEncoder8Bit encoder){
      try{//Mat -&gt; BufferedImage -&gt; Picture8Bit
          BufferedImage img = matToBufferedImage(mat);
          Picture8Bit pic = AWTUtil.fromBufferedImageRGB8Bit(img);//this is the 
          encoder.encodeNativeFrame(pic);                        //only constructor that won't crash
      }catch(Exception e){
          e.printStackTrace();
      }
  }
  
  public static byte[] writeVideo(){
      int fps = 25;
      int videoSize = 300_000;//allocated for buffer --&gt; think max size
      ByteBuffer buffer = ByteBuffer.allocate(videoSize);
      Mat mat = new Mat();
      SeekableByteChannel channel = new ByteBufferSeekableByteChannel(buffer);
      SequenceEncoder8Bit enc = null;
  
      try {// new SequenceEncoder..
          enc = new SequenceEncoder8Bit(channel, new Rational(fps, 1));
          enc.getEncoder().setKeyInterval(fps);
  
          while(!_isDone){//Here, grabbing mat frames from camera using JavaCV
              writeImage(mat, enc);
          }   
          encodeVideo(enc, buffer, (int)channel.position());
      } catch (IOException e1) {
          e1.printStackTrace();
      }
  
      return buffer.array();
  }   
  
  }
  </code></pre>
  
  <p>I looked into the code base and the call to SequenceEncoder8Bit.finish() does write a header to the buffer. Not sure why I can't get the metadata. Anyone out their familiar with this stuff?</p>