/*
* myLib - https://github.com/taktod/myLib
* Copyright (c) 2014 ttProject. All rights reserved.
*
* Licensed under The MIT license.
*/
package com.ttProject.container.mkv;
import org.apache.log4j.Logger;
import com.ttProject.container.NullContainer;
import com.ttProject.container.mkv.type.Audio;
import com.ttProject.container.mkv.type.BitDepth;
import com.ttProject.container.mkv.type.Block;
import com.ttProject.container.mkv.type.BlockDuration;
import com.ttProject.container.mkv.type.BlockGroup;
import com.ttProject.container.mkv.type.CRC32;
import com.ttProject.container.mkv.type.Channels;
import com.ttProject.container.mkv.type.Cluster;
import com.ttProject.container.mkv.type.CodecDecodeAll;
import com.ttProject.container.mkv.type.CodecID;
import com.ttProject.container.mkv.type.CodecName;
import com.ttProject.container.mkv.type.CodecPrivate;
import com.ttProject.container.mkv.type.ContentCompAlgo;
import com.ttProject.container.mkv.type.ContentCompSettings;
import com.ttProject.container.mkv.type.ContentCompression;
import com.ttProject.container.mkv.type.ContentEncoding;
import com.ttProject.container.mkv.type.ContentEncodings;
import com.ttProject.container.mkv.type.CueClusterPosition;
import com.ttProject.container.mkv.type.CuePoint;
import com.ttProject.container.mkv.type.CueRelativePosition;
import com.ttProject.container.mkv.type.CueTime;
import com.ttProject.container.mkv.type.CueTrack;
import com.ttProject.container.mkv.type.CueTrackPositions;
import com.ttProject.container.mkv.type.Cues;
import com.ttProject.container.mkv.type.DateUTC;
import com.ttProject.container.mkv.type.DefaultDuration;
import com.ttProject.container.mkv.type.DisplayHeight;
import com.ttProject.container.mkv.type.DisplayUnit;
import com.ttProject.container.mkv.type.DisplayWidth;
import com.ttProject.container.mkv.type.DocType;
import com.ttProject.container.mkv.type.DocTypeReadVersion;
import com.ttProject.container.mkv.type.DocTypeVersion;
import com.ttProject.container.mkv.type.Duration;
import com.ttProject.container.mkv.type.EBML;
import com.ttProject.container.mkv.type.EBMLMaxIDLength;
import com.ttProject.container.mkv.type.EBMLMaxSizeLength;
import com.ttProject.container.mkv.type.EBMLReadVersion;
import com.ttProject.container.mkv.type.EBMLVersion;
import com.ttProject.container.mkv.type.FlagDefault;
import com.ttProject.container.mkv.type.FlagEnabled;
import com.ttProject.container.mkv.type.FlagForced;
import com.ttProject.container.mkv.type.FlagInterlaced;
import com.ttProject.container.mkv.type.FlagLacing;
import com.ttProject.container.mkv.type.Info;
import com.ttProject.container.mkv.type.Language;
import com.ttProject.container.mkv.type.MaxBlockAdditionID;
import com.ttProject.container.mkv.type.MinCache;
import com.ttProject.container.mkv.type.MuxingApp;
import com.ttProject.container.mkv.type.PixelHeight;
import com.ttProject.container.mkv.type.PixelWidth;
import com.ttProject.container.mkv.type.Position;
import com.ttProject.container.mkv.type.PrevSize;
import com.ttProject.container.mkv.type.ReferenceBlock;
import com.ttProject.container.mkv.type.SamplingFrequency;
import com.ttProject.container.mkv.type.Seek;
import com.ttProject.container.mkv.type.SeekHead;
import com.ttProject.container.mkv.type.SeekID;
import com.ttProject.container.mkv.type.SeekPosition;
import com.ttProject.container.mkv.type.Segment;
import com.ttProject.container.mkv.type.SegmentUID;
import com.ttProject.container.mkv.type.SimpleBlock;
import com.ttProject.container.mkv.type.SimpleTag;
import com.ttProject.container.mkv.type.Tag;
import com.ttProject.container.mkv.type.TagLanguage;
import com.ttProject.container.mkv.type.TagName;
import com.ttProject.container.mkv.type.TagString;
import com.ttProject.container.mkv.type.TagTrackUID;
import com.ttProject.container.mkv.type.Tags;
import com.ttProject.container.mkv.type.Targets;
import com.ttProject.container.mkv.type.Timecode;
import com.ttProject.container.mkv.type.TimecodeScale;
import com.ttProject.container.mkv.type.Title;
import com.ttProject.container.mkv.type.TrackEntry;
import com.ttProject.container.mkv.type.TrackNumber;
import com.ttProject.container.mkv.type.TrackTimecodeScale;
import com.ttProject.container.mkv.type.TrackType;
import com.ttProject.container.mkv.type.TrackUID;
import com.ttProject.container.mkv.type.Tracks;
import com.ttProject.container.mkv.type.Video;
import com.ttProject.container.mkv.type.Void;
import com.ttProject.container.mkv.type.WritingApp;
import com.ttProject.nio.channels.IReadChannel;
import com.ttProject.unit.ISelector;
import com.ttProject.unit.IUnit;
import com.ttProject.unit.extra.BitLoader;
import com.ttProject.unit.extra.EbmlValue;
import com.ttProject.unit.extra.bit.Bit1;
/**
* mkvTagSelector
* @author taktod
*/
public class MkvTagSelector implements ISelector {
/** logger */
@SuppressWarnings("unused")
private Logger logger = Logger.getLogger(MkvTagSelector.class);
/**
* {@inheritDoc}
*/
@Override
public IUnit select(IReadChannel channel) throws Exception {
if(channel.position() == channel.size()) {
// no more.
return null;
}
// TODO cause of test4 on mkv sample. need to skip in the case of tag size is more than 4bytes.
BitLoader loader = new BitLoader(channel);
EbmlValue tag = new EbmlValue();
Bit1 bit1 = null;
int zeroCount = 0;
do {
bit1 = new Bit1();
loader.load(bit1);
zeroCount ++;
}while(tag.addBit1(bit1));
if(zeroCount > 4) {
for(int i = 0;i < 8 - zeroCount;i ++) {
bit1 = new Bit1();
loader.load(bit1);
}
return NullContainer.getInstance();
}
loader.load(tag.getDataBit());
EbmlValue size = new EbmlValue();
loader.load(size);
MkvTag mkvTag = null;
switch(Type.getType(tag.getEbmlValue())) {
case EBML:
mkvTag = new EBML(size);
break;
case EBMLVersion:
mkvTag = new EBMLVersion(size);
break;
case EBMLReadVersion:
mkvTag = new EBMLReadVersion(size);
break;
case EBMLMaxIDLength:
mkvTag = new EBMLMaxIDLength(size);
break;
case EBMLMaxSizeLength:
mkvTag = new EBMLMaxSizeLength(size);
break;
case DocType:
mkvTag = new DocType(size);
break;
case DocTypeVersion:
mkvTag = new DocTypeVersion(size);
break;
case DocTypeReadVersion:
mkvTag = new DocTypeReadVersion(size);
break;
case Segment:
mkvTag = new Segment(size);
break;
case SeekHead:
mkvTag = new SeekHead(size);
break;
case Seek:
mkvTag = new Seek(size);
break;
case SeekID:
mkvTag = new SeekID(size);
break;
case SeekPosition:
mkvTag = new SeekPosition(size);
break;
case Void:
mkvTag = new Void(size);
break;
case Info:
mkvTag = new Info(size);
break;
case TimecodeScale:
mkvTag = new TimecodeScale(size);
break;
case MuxingApp:
mkvTag = new MuxingApp(size);
break;
case WritingApp:
mkvTag = new WritingApp(size);
break;
case SegmentUID:
mkvTag = new SegmentUID(size);
break;
case Duration:
mkvTag = new Duration(size);
break;
case Tracks:
mkvTag = new Tracks(size);
break;
case TrackEntry:
mkvTag = new TrackEntry(size);
break;
case TrackNumber:
mkvTag = new TrackNumber(size);
break;
case TrackUID:
mkvTag = new TrackUID(size);
break;
case FlagLacing:
mkvTag = new FlagLacing(size);
break;
case Language:
mkvTag = new Language(size);
break;
case CodecID:
mkvTag = new CodecID(size);
break;
case TrackType:
mkvTag = new TrackType(size);
break;
case DefaultDuration:
mkvTag = new DefaultDuration(size);
break;
case Video:
mkvTag = new Video(size);
break;
case PixelWidth:
mkvTag = new PixelWidth(size);
break;
case PixelHeight:
mkvTag = new PixelHeight(size);
break;
case CodecPrivate:
mkvTag = new CodecPrivate(size);
break;
case Audio:
mkvTag = new Audio(size);
break;
case Channels:
mkvTag = new Channels(size);
break;
case SamplingFrequency:
mkvTag = new SamplingFrequency(size);
break;
case BitDepth:
mkvTag = new BitDepth(size);
break;
case Tags:
mkvTag = new Tags(size);
break;
case Tag:
mkvTag = new Tag(size);
break;
case Targets:
mkvTag = new Targets(size);
break;
case SimpleTag:
mkvTag = new SimpleTag(size);
break;
case TagName:
mkvTag = new TagName(size);
break;
case TagString:
mkvTag = new TagString(size);
break;
case Cluster:
mkvTag = new Cluster(size);
break;
case Timecode:
mkvTag = new Timecode(size);
break;
case SimpleBlock:
mkvTag = new SimpleBlock(size);
break;
case Cues:
mkvTag = new Cues(size);
break;
case CuePoint:
mkvTag = new CuePoint(size);
break;
case CueTime:
mkvTag = new CueTime(size);
break;
case CueTrackPositions:
mkvTag = new CueTrackPositions(size);
break;
case CueTrack:
mkvTag = new CueTrack(size);
break;
case CueClusterPosition:
mkvTag = new CueClusterPosition(size);
break;
case TagLanguage:
mkvTag = new TagLanguage(size);
break;
case Title:
mkvTag = new Title(size);
break;
case FlagDefault:
mkvTag = new FlagDefault(size);
break;
case DisplayWidth:
mkvTag = new DisplayWidth(size);
break;
case DisplayHeight:
mkvTag = new DisplayHeight(size);
break;
case DateUTC:
mkvTag = new DateUTC(size);
break;
case MinCache:
mkvTag = new MinCache(size);
break;
case ContentEncodings:
mkvTag = new ContentEncodings(size);
break;
case ContentEncoding:
mkvTag = new ContentEncoding(size);
break;
case ContentCompression:
mkvTag = new ContentCompression(size);
break;
case ContentCompAlgo:
mkvTag = new ContentCompAlgo(size);
break;
case ContentCompSettings:
mkvTag = new ContentCompSettings(size);
break;
case FlagEnabled:
mkvTag = new FlagEnabled(size);
break;
case FlagForced:
mkvTag = new FlagForced(size);
break;
case TrackTimecodeScale: // deprecated
mkvTag = new TrackTimecodeScale(size);
break;
case MaxBlockAdditionID:
mkvTag = new MaxBlockAdditionID(size);
break;
case CodecDecodeAll:
mkvTag = new CodecDecodeAll(size);
break;
case FlagInterlaced:
mkvTag = new FlagInterlaced(size);
break;
case BlockGroup:
mkvTag = new BlockGroup(size);
break;
case Block:
mkvTag = new Block(size);
break;
case ReferenceBlock:
mkvTag = new ReferenceBlock(size);
break;
case BlockDuration:
mkvTag = new BlockDuration(size);
break;
case CRC32:
mkvTag = new CRC32(size);
break;
case Position:
mkvTag = new Position(size);
break;
case PrevSize:
mkvTag = new PrevSize(size);
break;
case TagTrackUID:
mkvTag = new TagTrackUID(size);
break;
case CodecName:
mkvTag = new CodecName(size);
break;
case CueRelativePosition:
mkvTag = new CueRelativePosition(size);
break;
case DisplayUnit:
mkvTag = new DisplayUnit(size);
break;
default:
throw new Exception("undefined mkvTagType.:" + Type.getType(tag.getEbmlValue()));
}
mkvTag.minimumLoad(channel);
return mkvTag;
}
}