/* * myLib - https://github.com/taktod/myLib * Copyright (c) 2014 ttProject. All rights reserved. * * Licensed under The MIT license. */ package com.ttProject.container.mpegts; import java.nio.ByteBuffer; import org.apache.log4j.Logger; import com.ttProject.nio.channels.IReadChannel; import com.ttProject.unit.extra.BitConnector; import com.ttProject.unit.extra.BitLoader; import com.ttProject.unit.extra.bit.Bit1; import com.ttProject.unit.extra.bit.Bit12; import com.ttProject.unit.extra.bit.Bit13; import com.ttProject.unit.extra.bit.Bit16; import com.ttProject.unit.extra.bit.Bit2; import com.ttProject.unit.extra.bit.Bit4; import com.ttProject.unit.extra.bit.Bit5; import com.ttProject.unit.extra.bit.Bit8; import com.ttProject.util.BufferUtil; /** * programPacket * @author taktod * * TODO for program packet, if the crc32 is same, no need to write. * this will help to reduce the media size. */ public abstract class ProgramPacket extends MpegtsPacket { /** logger */ @SuppressWarnings("unused") private Logger logger = Logger.getLogger(ProgramPacket.class); private Bit8 pointerField = null; // 0000 0000 private Bit8 tableId = null; // packet fixed value private Bit1 sectionSyntaxIndicator = null; // 1 private Bit1 reservedFutureUse1 = null; // 0 private Bit2 reserved1 = null; // 11 private Bit12 sectionLength = null; // 12bit private Bit16 programNumber = null; // 16bit private Bit2 reserved2 = null; // 11 private Bit5 versionNumber = null; // 00000 private Bit1 currentNextOrder = null; // 1 private Bit8 sectionNumber = null; // 00000000 private Bit8 lastSectionNumber = null; // 00000000 /** original data */ private ByteBuffer buffer = null; private boolean isLoaded = false; /** * constructor * @param syncByte * @param transportErrorIndicator * @param payloadUnitStartIndicator * @param transportPriority * @param pid * @param scramblingControl * @param adaptationFieldExist * @param payloadFieldExist * @param continuityCounter */ public ProgramPacket(Bit8 syncByte, Bit1 transportErrorIndicator, Bit1 payloadUnitStartIndicator, Bit1 transportPriority, Bit13 pid, Bit2 scramblingControl, Bit1 adaptationFieldExist, Bit1 payloadFieldExist, Bit4 continuityCounter) { super(syncByte, transportErrorIndicator, payloadUnitStartIndicator, transportPriority, pid, scramblingControl, adaptationFieldExist, payloadFieldExist, continuityCounter); } /** * {@inheritDoc} */ @Override public void minimumLoad(IReadChannel channel) throws Exception { super.minimumLoad(channel); int bufferLength = 180; // last 4byte(crc32) is not consider here.(lastly, we add crc32.) if(isAdaptationFieldExist()) { bufferLength -= (1 + getAdaptationField().getLength()); } buffer = BufferUtil.safeRead(channel, bufferLength); } /** * {@inheritDoc} */ @Override public void load(IReadChannel channel) throws Exception { BitLoader loader = new BitLoader(channel); pointerField = new Bit8(); tableId = new Bit8(); sectionSyntaxIndicator = new Bit1(); reservedFutureUse1 = new Bit1(); reserved1 = new Bit2(); sectionLength = new Bit12(); programNumber = new Bit16(); reserved2 = new Bit2(); versionNumber = new Bit5(); currentNextOrder = new Bit1(); sectionNumber = new Bit8(); lastSectionNumber = new Bit8(); loader.load(pointerField, tableId, sectionSyntaxIndicator, reservedFutureUse1, reserved1, sectionLength, programNumber, reserved2, versionNumber, currentNextOrder, sectionNumber, lastSectionNumber); if(isAdaptationFieldExist()) { super.setSize(8 + getAdaptationField().getLength() + 1 + sectionLength.get()); } else { super.setSize(8 + sectionLength.get()); } isLoaded = true; } /** * set sectionLength * @param length */ protected void setSectionLength(int length) { // sectionLength will be changed later, need to set. sectionLength.set(length); super.setSize(8 + sectionLength.get()); } /** * ref sectionLength * @return */ protected int getSectionLength() { return sectionLength.get(); } /** * ref buffer * @return */ protected ByteBuffer getBuffer() { return buffer; } /** * loaded? * @return */ public boolean isLoaded() { return isLoaded; } /** * {@inheritDoc} */ @Override protected ByteBuffer getHeaderBuffer() { BitConnector connector = new BitConnector(); return BufferUtil.connect( super.getHeaderBuffer(), connector.connect( pointerField, tableId, sectionSyntaxIndicator, reservedFutureUse1, reserved1, sectionLength, programNumber, reserved2, versionNumber, currentNextOrder, sectionNumber, lastSectionNumber ) ); } /** * ref the crc. * @return */ public abstract int getCrc(); /** * calculate crc * @param buffer * @return */ protected int calculateCrc(ByteBuffer buffer) { // TODO this calcuration will be work but not correct. // in the case of adaptation Field is exist on the top, won't work. Crc32 crc32 = new Crc32(); ByteBuffer tmpBuffer = buffer.duplicate(); tmpBuffer.position(5); // consider no adaptation field. while(tmpBuffer.remaining() > 0) { crc32.update(tmpBuffer.get()); } return (int)crc32.getValue(); } }