/* * myLib - https://github.com/taktod/myLib * Copyright (c) 2014 ttProject. All rights reserved. * * Licensed under The MIT license. */ package com.ttProject.chunk.aac; import java.util.HashSet; import java.util.Set; import org.apache.log4j.Logger; import com.ttProject.chunk.IMediaChunk; import com.ttProject.chunk.MediaChunkManager; import com.ttProject.chunk.aac.analyzer.IAacFrameAnalyzer; import com.ttProject.media.Unit; import com.ttProject.media.aac.frame.Aac; /** * aacのchunkを取り出すための動作マネージャー * 基本的にgetChunksにunitデータをいれると対応したMediaChunkが取得できる感じ * @author taktod */ public class AacChunkManager extends MediaChunkManager{ /** ロガー */ private Logger logger = Logger.getLogger(AacChunkManager.class); /** 処理中のmp3Data保持オブジェクト */ private AacDataList aacDataList = new AacDataList(); /** 解析用のオブジェクト */ private Set<IAacFrameAnalyzer> analyzers = new HashSet<IAacFrameAnalyzer>(); /** 経過frame数 */ private long passedFrame = 0; /** * aacの解析オブジェクトを登録する。 */ public void addAacFrameAnalyzer(IAacFrameAnalyzer frameAnalyzer) { frameAnalyzer.setAacDataList(aacDataList); analyzers.add(frameAnalyzer); } /** * {@inheritDoc} */ @Override public IMediaChunk getChunk(Unit unit) throws Exception { // 解析してmp3DataListにデータを追記させる。 for(IAacFrameAnalyzer analyzer : analyzers) { analyzer.analyze(unit); } // 完了したデータを確認してある場合はchunkを応答する return checkCompleteChunk(); } /** * 完了したchunkを確認。ある場合は応答します * @return * @throws Exception */ private IMediaChunk checkCompleteChunk() throws Exception { int sampleRate = aacDataList.getSampleRate(); if(sampleRate == -1) { // 解析前の場合は処理しない return null; } // 処理したいframe数 long targetFrameCount = passedFrame + (long)(getDuration() * sampleRate); if(aacDataList.getCounter() > targetFrameCount) { /** 現在処理中のchunkオブジェクト */ AacChunk chunk = new AacChunk(sampleRate); chunk.setTimestamp(aacDataList.getFirstCounter()); // データを構築する。 int frameCount = 0; do { Aac frame = aacDataList.shift(); frameCount += frame.getSampleNum(); chunk.write(frame.getBuffer()); } while(aacDataList.getFirstCounter() <= targetFrameCount); chunk.setDuration(1.0f * frameCount / sampleRate); passedFrame += frameCount; return chunk; } return null; } /** * {@inheritDoc} */ @Override public IMediaChunk getCurrentChunk() { return null; } /** * {@inheritDoc} */ @Override public IMediaChunk close() { if(aacDataList.getListCount() == 0) { return null; } // 最終のときには、中身すべて吐き出しておく。 try { int sampleRate = aacDataList.getSampleRate(); AacChunk chunk = new AacChunk(sampleRate); chunk.setTimestamp(aacDataList.getFirstCounter()); int frameCount = 0; Aac frame = null; while((frame = aacDataList.shift()) != null) { frameCount += frame.getSampleNum(); chunk.write(frame.getBuffer()); } chunk.setDuration(1.0f * frameCount / sampleRate); passedFrame += frameCount; return chunk; } catch(Exception e) { logger.warn("エラー", e); } return null; } /** * {@inheritDoc} */ @Override public String getExt() { return "aac"; } /** * {@inheritDoc} */ @Override @Deprecated public String getHeaderExt() { return "aac"; } /** * {@inheritDoc} */ @Override public long getPassedTic() { return passedFrame; } /** * 動作サンプルレートを応答します。 * @return 処理前は-1が応答されます。 */ public int getSampleRate() { return aacDataList.getSampleRate(); } }