/* * myLib - https://github.com/taktod/myLib * Copyright (c) 2014 ttProject. All rights reserved. * * Licensed under The MIT license. */ package com.ttProject.container.riff; import java.nio.ByteBuffer; import com.ttProject.frame.Frame; import com.ttProject.frame.IAnalyzer; import com.ttProject.frame.IAudioFrame; import com.ttProject.frame.IFrame; import com.ttProject.frame.IVideoFrame; import com.ttProject.frame.NullFrame; import com.ttProject.frame.extra.AudioMultiFrame; import com.ttProject.frame.extra.VideoMultiFrame; import com.ttProject.nio.channels.ByteReadChannel; import com.ttProject.nio.channels.IReadChannel; import com.ttProject.util.BufferUtil; /** * riffFrameUnit * base for frame unit. * @author taktod */ public abstract class RiffFrameUnit extends RiffSizeUnit { /** trackId */ private final int trackId; /** format information */ private RiffFormatUnit formatUnit = null; /** frameBuffer is holded on the memory */ private ByteBuffer frameBuffer = null; /** * constructor * @param typeValue * @param type */ public RiffFrameUnit(int dataValue, Type type) { super(type); byte[] dat = new byte[2]; dat[0] = (byte)((dataValue >> 24) & 0xFF); dat[1] = (byte)((dataValue >> 16) & 0xFF); trackId = Integer.parseInt(new String(dat).intern()); } /** * ref the trackId * @return */ public int getTrackId() { return trackId; } /** * set the format unit. * should I use public for this? * cause of package, now this can be protected. * @param formatUnit */ protected void setFormatUnit(RiffFormatUnit formatUnit) { this.formatUnit = formatUnit; } @Override public void minimumLoad(IReadChannel channel) throws Exception { super.minimumLoad(channel); // load the buffer on the memory frameBuffer = BufferUtil.safeRead(channel, getSize() - 8); if(!formatUnit.isTimeReady()) { IFrame frame = getFrame(); // ref the frame and update data. if(!(frame instanceof IAudioFrame)) { throw new Exception("formatUnit doesn't have any tic information for videoFrame."); } // update with audioFrame information for tics. IAudioFrame aFrame = (IAudioFrame)frame; formatUnit.setScale(aFrame.getSampleNum()); formatUnit.setRate(aFrame.getSampleRate()); } setPts(formatUnit.getNextPts(getSize() - 8)); setTimebase(formatUnit.getTimebase()); } /** * {@inheritDoc} */ @Override @Deprecated public void load(IReadChannel channel) throws Exception { // don't use, for wav file, data obj uses extra IReadChannel on Selector. // however if we use load func, IReadChannel can be original one. } /** * get the frame * @return */ public IFrame getFrame() throws Exception { IReadChannel frameChannel = new ByteReadChannel(frameBuffer); IAnalyzer analyzer = formatUnit.getFrameAnalyzer(); IFrame frame = null; IFrame resultFrame = null; // TODO for multiFrame need to proceed the pts. // just now, share the same pts for all frame on frame unit. while((frame = analyzer.analyze(frameChannel)) != null) { if(!(frame instanceof NullFrame)) { resultFrame = processFrame(resultFrame, frame); } } resultFrame = processFrame(resultFrame, analyzer.getRemainFrame()); return resultFrame; } private IFrame processFrame(IFrame resultFrame, IFrame frame) throws Exception { if(frame == null) { return resultFrame; } Frame f = (Frame)frame; f.setPts(getPts()); f.setTimebase(getTimebase()); if(resultFrame == null) { return frame; } else if(frame instanceof IAudioFrame) { IAudioFrame aFrame = (IAudioFrame)frame; if(resultFrame instanceof AudioMultiFrame) { ((AudioMultiFrame) resultFrame).addFrame(aFrame); } else if(resultFrame instanceof IAudioFrame) { AudioMultiFrame multiFrame = new AudioMultiFrame(); multiFrame.addFrame((IAudioFrame)resultFrame); multiFrame.addFrame(aFrame); resultFrame = multiFrame; } return resultFrame; } else if(frame instanceof IVideoFrame) { IVideoFrame vFrame = (IVideoFrame)frame; if(resultFrame instanceof VideoMultiFrame) { ((VideoMultiFrame) resultFrame).addFrame(vFrame); } else if(resultFrame instanceof IVideoFrame) { VideoMultiFrame multiFrame = new VideoMultiFrame(); multiFrame.addFrame((IVideoFrame)resultFrame); multiFrame.addFrame(vFrame); resultFrame = multiFrame; } return resultFrame; } else { throw new Exception("neither Audio nor Video frame."); } } }