/*
* myLib - https://github.com/taktod/myLib
* Copyright (c) 2014 ttProject. All rights reserved.
*
* Licensed under The MIT license.
*/
package com.ttProject.media.mpegts;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
import com.ttProject.media.IAnalyzer;
import com.ttProject.media.Unit;
import com.ttProject.media.extra.Bit;
import com.ttProject.media.extra.Bit1;
import com.ttProject.media.extra.Bit2;
import com.ttProject.media.extra.Bit4;
import com.ttProject.media.extra.Bit5;
import com.ttProject.media.extra.Bit8;
import com.ttProject.media.extra.BitLoader;
import com.ttProject.media.mpegts.field.AdaptationField;
import com.ttProject.nio.channels.IReadChannel;
/**
* パケットデータのベース
* @author taktod
*/
public abstract class Packet extends Unit {
// 実データ(readModeではいっているものとします。)
// packetがかならずbufferをもっているとすると、ちょっと扱いにくいので、bufferがきたら読み込みを実行することとした方がよさそう。
private final byte syncByte = 0x47;
private Bit1 transportErrorIndicator; // 0
private Bit1 payloadUnitStartIndicator;
private Bit1 transportPriority; // 0
private short pid; // 13bit
private Bit2 scramblingControl; // 0
private Bit1 adaptationFieldExist;
private Bit1 payloadFieldExist; // 1
private Bit4 continuityCounter;
/** 内包しているadaptationFieldの情報 */
private AdaptationField adaptationField;
/**
* コンストラクタ
* @param position
*/
public Packet(int position) {
// 大きさは188バイト固定
super(position, 188);
}
/**
* 解析動作
*/
@Override
public void analyze(IReadChannel ch, IAnalyzer<?> analyzer)
throws Exception {
}
public boolean isPayloadUnitStart() {
return payloadUnitStartIndicator.get() != 0x00;
}
protected void setPayloadUnitStartIndicator(int flg) {
payloadUnitStartIndicator = new Bit1(flg);
}
public void setAdaptationFieldExist(int flg) {
adaptationFieldExist = new Bit1(flg);
}
public boolean isAdaptationFieldExist() {
return adaptationFieldExist.get() != 0x00;
}
public short getPid() {
return pid;
}
protected void setContinuityCounter(int counter) {
continuityCounter = new Bit4(counter);
}
/**
* header部の解析を実施しておく
* @throws Exception
*/
protected void analyzeHeader(IReadChannel channel) throws Exception {
// headerを解析しておきます。
Bit8 syncByte = new Bit8();
transportErrorIndicator = new Bit1();
payloadUnitStartIndicator = new Bit1();
transportPriority = new Bit1();
Bit5 pid_1 = new Bit5();
Bit8 pid_2 = new Bit8();
scramblingControl = new Bit2();
adaptationFieldExist = new Bit1();
payloadFieldExist = new Bit1();
continuityCounter = new Bit4();
BitLoader bitLoader = new BitLoader(channel);
bitLoader.load(syncByte, transportErrorIndicator, payloadUnitStartIndicator, transportPriority,
pid_1, pid_2, scramblingControl, adaptationFieldExist, payloadFieldExist, continuityCounter);
if(syncByte.get() != this.syncByte) {
throw new Exception("syncByteがおかしいです。");
}
pid = (short)((pid_1.get() << 8) + pid_2.get());
adaptationField = new AdaptationField();
if(adaptationFieldExist.get() != 0x00) {
// adaptationFieldがある場合
adaptationField.analyze(channel);
}
}
public AdaptationField getAdaptationField() {
return adaptationField;
}
public void setAdaptationField(AdaptationField field) {
adaptationField = field;
}
/**
* デフォルトの設定をつくっておく。
*/
public abstract void setupDefault() throws Exception;
public abstract ByteBuffer getBuffer() throws Exception;
public List<Bit> getBits() {
List<Bit> list = new ArrayList<Bit>();
list.add(new Bit8(syncByte));
list.add(transportErrorIndicator);
list.add(payloadUnitStartIndicator);
list.add(transportPriority);
list.add(new Bit5(pid >>> 8));
list.add(new Bit8(pid));
list.add(scramblingControl);
list.add(adaptationFieldExist);
list.add(payloadFieldExist);
list.add(continuityCounter);
if(adaptationFieldExist.get() != 0x00) {
list.addAll(adaptationField.getBits());
}
return list;
}
@Override
public String toString() {
StringBuilder data = new StringBuilder();
data.append(" ");
data.append("packet:");
data.append(" tei:").append(transportErrorIndicator);
data.append(" pusi:").append(payloadUnitStartIndicator);
data.append(" tp:").append(transportPriority);
data.append(" pid:").append(Integer.toHexString(pid));
data.append(" sc:").append(scramblingControl);
data.append(" afe:").append(adaptationFieldExist);
data.append(" pfe:").append(payloadFieldExist);
data.append(" cc:").append(continuityCounter);
if(adaptationField != null) {
data.append("\n");
data.append(adaptationField);
}
data.append("\n");
return data.toString();
}
}