package javaforce.media; /** FIFO buffer for video frames (images) * Uses a cyclical buffer to avoid using locks or reallocation. * * @author pquiring * * Created : Oct 24, 2013 */ import javaforce.*; public class VideoBuffer { private JFImage images[]; private int head = 0, tail = 0; private boolean headInUse, tailInUse; public VideoBuffer(int width, int height, int frames) { images = new JFImage[frames]; for(int a=0;a<frames;a++) { images[a] = new JFImage(width, height); } } //head functions /** Returns the next image to add a frame to the buffer (the head) * Returns null if buffer is full. */ public JFImage getNewFrame() { if (headInUse) freeNewFrame(); int newHead = head + 1; if (newHead == images.length) newHead = 0; if (newHead == tail) return null; //buffer full headInUse = true; return images[head]; } /** Frees the image obtained by getNewFrame() */ public void freeNewFrame() { if (!headInUse) return; headInUse = false; head++; if (head == images.length) head = 0; } //tail functions /** Returns the next image to be removed from the buffer (the tail)*/ public JFImage getNextFrame() { if (tailInUse) freeNextFrame(); if (tail == head) return null; tailInUse = true; return images[tail]; } /** Frees the image obtained by getNextFrame() */ public void freeNextFrame() { if (!tailInUse) return; tailInUse = false; tail++; if (tail == images.length) tail = 0; } public int size() { int t = tail; int h = head; if (t == h) return 0; if (h > t) return h - t; return images.length - t + h; } public void clear() { tail = head; } }