001package net.bramp.ffmpeg.nut;
002
003import com.google.common.base.MoreObjects;
004import java.io.IOException;
005import org.slf4j.Logger;
006import org.slf4j.LoggerFactory;
007
008public class Packet {
009
010  static final Logger LOG = LoggerFactory.getLogger(Packet.class);
011
012  public enum Startcode {
013    MAIN(0x7A561F5F04ADL + (((long) ('N' << 8) + 'M') << 48)),
014    STREAM(0x11405BF2F9DBL + (((long) ('N' << 8) + 'S') << 48)),
015    SYNCPOINT(0xE4ADEECA4569L + (((long) ('N' << 8) + 'K') << 48)),
016    INDEX(0xDD672F23E64EL + (((long) ('N' << 8) + 'X') << 48)),
017    INFO(0xAB68B596BA78L + (((long) ('N' << 8) + 'I') << 48));
018
019    private final long startcode;
020
021    Startcode(long startcode) {
022      this.startcode = startcode;
023    }
024
025    public long value() {
026      return startcode;
027    }
028
029    public boolean equalsCode(long startcode) {
030      return this.startcode == startcode;
031    }
032
033    /**
034     * Returns the Startcode enum for this code.
035     *
036     * @param startcode The numeric code for this Startcode.
037     * @return The Startcode
038     */
039    public static Startcode of(long startcode) {
040      for (Startcode c : Startcode.values()) {
041        if (c.equalsCode(startcode)) {
042          return c;
043        }
044      }
045      return null;
046    }
047
048    public static boolean isPossibleStartcode(long startcode) {
049      return (startcode & 0xFFL) == 'N';
050    }
051
052    public static String toString(long startcode) {
053      Startcode c = of(startcode);
054      if (c != null) {
055        return c.name();
056      }
057      return String.format("%X", startcode);
058    }
059  }
060
061  public final PacketHeader header = new PacketHeader();
062  public final PacketFooter footer = new PacketFooter();
063
064  protected void readBody(NutDataInputStream in) throws IOException {
065    // Default implementation does nothing
066  }
067
068  public void read(NutDataInputStream in, long startcode) throws IOException {
069    header.read(in, startcode);
070    readBody(in);
071    seekToPacketFooter(in);
072    footer.read(in);
073  }
074
075  public void seekToPacketFooter(NutDataInputStream in) throws IOException {
076    long current = in.offset();
077    if (current > header.end) {
078      throw new IOException("Can not seek backwards at:" + current + " end:" + header.end);
079    }
080    // TODO Fix this to not cast longs to ints
081    in.skipBytes((int) (header.end - current));
082  }
083
084  @Override
085  public String toString() {
086    return MoreObjects.toStringHelper(this).add("header", header).add("footer", footer).toString();
087  }
088}