/* * myLib - https://github.com/taktod/myLib * Copyright (c) 2014 ttProject. All rights reserved. * * Licensed under The MIT license. */ package com.ttProject.media.mp4.atom; import java.nio.ByteBuffer; import com.ttProject.media.mp4.Atom; import com.ttProject.media.mp4.IAtomAnalyzer; import com.ttProject.nio.CacheBuffer; import com.ttProject.nio.channels.FileReadChannel; import com.ttProject.nio.channels.IFileReadChannel; import com.ttProject.nio.channels.IReadChannel; import com.ttProject.util.BufferUtil; /** * 各チャンクが保持しているサンプル数を保持しています。 * @author taktod * */ public class Stsc extends Atom { private int count; private CacheBuffer buffer; private int nextChunkNum = 0; private int nextSampleCount = 0; private int nextDataRef = 0; private int chunkNum; private int sampleCount; private int dataRef; public Stsc(int position, int size) { super(Stsc.class.getSimpleName().toLowerCase(), position, size); } @Override public void analyze(IReadChannel ch, IAtomAnalyzer analyzer) throws Exception { ch.position(getPosition() + 8); ByteBuffer buffer = BufferUtil.safeRead(ch, 8); analyzeFirstInt(buffer.getInt()); count = buffer.getInt(); // このあとのデータは開始chunk番号 含有サンプル数 データ参照indexとなっている。(すべてint) /* * 1,3,2 4,2,1 6,1,2とある場合 * 1,3,2 * 2,3,2 * 3,3,2 * 4,2,1 * 5,2,1 * 6,1,2 * 7,1,2...となる * 一番最後のデータのあとはおわりまで同じデータがなんども繰り返される * よってstcoの値がわからないと最後がどこであるか判定できない。(ずっと同じあたいがかえってくるので注意が必要) */ } public void start(IReadChannel src, boolean copy) throws Exception { IReadChannel source; if(copy) { if(!(src instanceof IFileReadChannel)) { throw new Exception("IFileReadChannel系のreadChannelでないと、オブジェクトのcloneは作成不能です"); } source = FileReadChannel.openFileReadChannel(((IFileReadChannel)src).getUri()); } else { source = src; } source.position(getPosition() + 16); buffer = new CacheBuffer(source, getSize() - 16); } public int nextChunk() throws Exception { chunkNum ++; if(nextChunkNum > chunkNum) { return nextChunkNum; // 一番最後のchunkNumがいくつあるかわからないので、処理しようがなくなってしまう。 } else if(chunkNum == nextChunkNum) { sampleCount = nextSampleCount; dataRef = nextDataRef; } // 最終の部分だけ、考慮しないとだめ、次のデータはないのに、しばらくデータを読み込みつづける必要がでてくる。 if(buffer.remaining() == 0) { // データがなくなったらあとはずっとchunkNumを応答しておく。 return chunkNum; } // 次のデータを読み取る nextChunkNum = buffer.getInt(); nextSampleCount = buffer.getInt(); nextDataRef = buffer.getInt(); // すでにchunkNumとnextChunkNumが一致する場合(例えばはじめのアクセスでは発生する) if(chunkNum == nextChunkNum) { sampleCount = nextSampleCount; dataRef = nextDataRef; } return nextChunkNum; } public int getChunkNum() { return chunkNum; } public int getSampleCount() { return sampleCount; } public int getDataRef() { return dataRef; } public int getCount() { return count; } @Override public String toString() { return super.toString(" "); } }