/*
* myLib - https://github.com/taktod/myLib
* Copyright (c) 2014 ttProject. All rights reserved.
*
* Licensed under The MIT license.
*/
package com.ttProject.container.mpegts.type;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
import org.apache.log4j.Logger;
import com.ttProject.container.mpegts.ProgramPacket;
import com.ttProject.container.mpegts.field.PmtElementaryField;
import com.ttProject.nio.channels.ByteReadChannel;
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.Bit2;
import com.ttProject.unit.extra.bit.Bit3;
import com.ttProject.unit.extra.bit.Bit32;
import com.ttProject.unit.extra.bit.Bit4;
import com.ttProject.unit.extra.bit.Bit8;
import com.ttProject.util.BufferUtil;
/**
* Pmt
* marioの
* 47500010
* 0002B0170001C10000
* E100F000
* 1BE100F000(h264)
* 0FE101F000(aac)
* 2F44B99B(CRC32)
*
* rtypeDelta aacのみになったやつ
* 47500010
* 0002B0120001C10000
* E100F000
* 0FE100F000(aac)
* B69BC0D9(CRC32)
*
*
* vlcが出力したデータ
* 474042309500FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
* [ ]ここまでは普通
* []adaptationfieldで埋めてある。
* 0002B01E0001E30000(programPacketで共通化している部分)
* []tableId 2
* [ ]sectionLength
* [ ]programNumber 1
* [] version numberが0x11になってる。
* [ ] lastSectionNumberが0ではない
* E044F000
* [ ] pcrPidが0x44
* [ ]ふつう
* 81E044F00C 050441432D330A0400000000(1トラック分しかないじゃんw)
* 81ED7715(crc32)
*
* 0002B01E0001E30000E044F00081E044F00C050441432D330A040000000081ED7715
* 0002B01E0001E30000E044F00081E044F00C050441432D330A040000000081ED7715
* 0002B01E0001E30000E044F00081E044F00C050441432D330A040000000081ED7715
*
* 途中から長さがかわってた。始めは1Bのデータ(h264のデータが追加されてますね。)
* 0002B0290001E50000E045F00081E044F00C050441432D330A04000000001BE045F0060A040000000097DACB3E
* 0002B0290001E50000
* E045F000
* 81E044F00C 05 04 41432D33 0A 04 00000000
* [1B]E045F006 0A 04 00000000
* 97DACB3E
* @author taktod
*/
public class Pmt extends ProgramPacket {
/** logger */
@SuppressWarnings("unused")
private Logger logger = Logger.getLogger(Pmt.class);
private Bit3 reserved1 = null;
private Bit13 pcrPid = null;
private Bit4 reserved2 = null;
private Bit12 programInfoLength = null;
private List<PmtElementaryField> fields = new ArrayList<PmtElementaryField>();
private Bit32 crc32 = new Bit32();
/**
* constructor
* @param syncByte
* @param transportErrorIndicator
* @param payloadUnitStartIndicator
* @param transportPriority
* @param pid
* @param scramblingControl
* @param adaptationFieldExist
* @param payloadFieldExist
* @param continuityCounter
*/
public Pmt(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);
super.update();
}
/**
* constructor
* @param pmtPid
*/
public Pmt(int pmtPid) {
this(new Bit8(0x47), new Bit1(), new Bit1(1), new Bit1(),
new Bit13(pmtPid), new Bit2(), new Bit1(), new Bit1(1),
new Bit4()
);
try {
super.load(new ByteReadChannel(new byte[]{
0x00, 0x02, (byte)0xB0, 0x0D, 0x00, 0x01, (byte)0xC1, 0x00, 0x00
}));
}
catch(Exception e) {
}
reserved1 = new Bit3(0x07);
pcrPid = new Bit13(0x0100);
reserved2 = new Bit4(0x0F);
programInfoLength = new Bit12();
super.update();
}
@Override
public void minimumLoad(IReadChannel channel) throws Exception {
super.minimumLoad(channel);
BitLoader loader = new BitLoader(channel);
loader.load(crc32);
super.update();
}
@Override
public void load(IReadChannel channel) throws Exception {
if(isLoaded()) {
return;
}
IReadChannel holdChannel = new ByteReadChannel(getBuffer());
super.load(holdChannel);
BitLoader loader = new BitLoader(holdChannel);
reserved1 = new Bit3();
pcrPid = new Bit13();
reserved2 = new Bit4();
programInfoLength = new Bit12();
loader.load(reserved1, pcrPid, reserved2, programInfoLength);
int size = getSectionLength() - 5 - 4 - 4;
while(size > 0) {
PmtElementaryField elementaryField = new PmtElementaryField();
elementaryField.load(holdChannel);
size -= elementaryField.getSize();
fields.add(elementaryField);
}
super.update();
}
@Override
protected void requestUpdate() throws Exception {
BitConnector connector = new BitConnector();
connector.feed(reserved1, pcrPid, reserved2, programInfoLength);
for(PmtElementaryField elementaryField : fields) {
connector.feed(elementaryField.getBits());
}
// connect with header
ByteBuffer tmpBuffer = BufferUtil.connect(
getHeaderBuffer(),
connector.connect()
);
int crc32 = calculateCrc(tmpBuffer);
this.crc32.set(crc32);
ByteBuffer buffer = ByteBuffer.allocate(188);
buffer.put(tmpBuffer);
buffer.putInt(crc32);
// fill to make 188 byte.
while(buffer.position() < 188) {
buffer.put((byte)0xFF);
}
buffer.flip();
super.setData(buffer);
}
public int getPcrPid() {
return pcrPid.get();
}
public void setPcrPid(int pid) {
pcrPid.set(pid);
}
public boolean isPesPid(int pid) {
for(PmtElementaryField field : fields) {
if(field.getPid() == pid) {
return true;
}
}
return false;
}
public void addNewField(PmtElementaryField field) {
if(!fields.contains(field)) {
fields.add(field);
short length = 0;
length += 5;
length += 4;
for(PmtElementaryField elementaryField : fields) {
length += (short) elementaryField.getSize();
}
length += 4;
setSectionLength(length);
}
}
public List<PmtElementaryField> getFields() {
return new ArrayList<PmtElementaryField>(fields);
}
/**
* {@inheritDoc}
*/
@Override
public int getCrc() {
return crc32.get();
}
}