/*
 * Copyright (C) 2007-2009 KenD00
 * 
 * This file is part of DumpHD.
 * 
 * DumpHD is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package dumphd.util;

/**
 * Represents an Aligned Unit found on BluRays. Contains 32 MPEG Transport Packets, each with a 4 byte TP_extra_header.
 * This class is used as a mask over the byte array containing the data, the data gets not copied.
 * 
 * @author KenD00
 */
public class TSAlignedUnit {

   /**
    * Length of an TS Aligned Unit in bytes
    */
   public final static int UNIT_LENGTH = 6144;
   /**
    * Length of an TS Pack in bytes
    */
   public final static int PACKET_LENGTH = 192;


   /**
    * The underlying byte array this object uses
    */
   private byte[] unit = null;
   /**
    * The offset of the Aligned Unit inside the underlying byte array
    */
   private int unitOffset = 0;



   public TSAlignedUnit() {
      // Nothing
   }


   public void parse(byte[] unit, int offset) throws TSParserException {
      if (offset + TSAlignedUnit.UNIT_LENGTH <= unit.length) {
         this.unit = unit;
         this.unitOffset = offset;
      } else throw new TSParserException("Aligned Unit data too small");
   }

   /**
    * Returns the encryption state of this Aligned Unit.
    * 
    * @return If true, this Aligned Unit is encrypted, otherwise not
    */
   public boolean isEncrypted() {
      return (ByteArray.getUByte(unit, unitOffset) >>> 6 != 0);
   }

   /**
    * Sets the encryption state of this Aligned Unit.
    * The encryption state must not be changed if the Aligned Unit is encrypted, it must be decrypted first.
    * 
    * @param encrypted If true, the Aligned Unit is marked as encrypted, otherwise as unencrypted
    */
   public void setEncrypted(boolean encrypted) {
      for (int i = unitOffset; i < unitOffset + TSAlignedUnit.UNIT_LENGTH; i += TSAlignedUnit.PACKET_LENGTH) {
         unit[i] = (byte)(unit[i] & 0x3F);
         if (encrypted) {
            unit[i] = (byte)(unit[i] | 0xC0);
         }
      }
   }

}
