/*
* myLib - https://github.com/taktod/myLib
* Copyright (c) 2014 ttProject. All rights reserved.
*
* Licensed under The MIT license.
*/
package com.ttProject.container.flv;
import org.apache.log4j.Logger;
import com.ttProject.container.flv.type.AudioTag;
import com.ttProject.container.flv.type.MetaTag;
import com.ttProject.container.flv.type.VideoTag;
import com.ttProject.frame.AudioAnalyzer;
import com.ttProject.frame.VideoAnalyzer;
import com.ttProject.frame.aac.AacDsiFrameAnalyzer;
import com.ttProject.frame.adpcmswf.AdpcmswfFrameAnalyzer;
import com.ttProject.frame.flv1.Flv1FrameAnalyzer;
import com.ttProject.frame.h264.DataNalAnalyzer;
import com.ttProject.frame.mp3.Mp3FrameAnalyzer;
import com.ttProject.frame.nellymoser.NellymoserFrameAnalyzer;
import com.ttProject.frame.pcmalaw.PcmalawFrameAnalyzer;
import com.ttProject.frame.pcmmulaw.PcmmulawFrameAnalyzer;
import com.ttProject.frame.speex.SpeexFrameAnalyzer;
import com.ttProject.frame.speex.SpeexFrameSelector;
import com.ttProject.frame.speex.type.CommentFrame;
import com.ttProject.frame.speex.type.HeaderFrame;
import com.ttProject.frame.vp6.Vp6FrameAnalyzer;
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.bit.Bit16;
import com.ttProject.unit.extra.bit.Bit24;
import com.ttProject.unit.extra.bit.Bit8;
/**
* flvTagSelector
* @author taktod
*/
public class FlvTagSelector implements ISelector {
/** logger */
@SuppressWarnings("unused")
private Logger logger = Logger.getLogger(FlvTagSelector.class);
/** videoFrameAnalyzer */
private VideoAnalyzer videoFrameAnalyzer = null;
/** audioFrameAnalyzer */
private AudioAnalyzer audioFrameAnalyzer = null;
/**
* {@inheritDoc}
*/
@Override
public IUnit select(IReadChannel channel) throws Exception {
if(channel.position() == channel.size()) {
// no more.
return null;
}
// first 8 bit decide the data type.
Bit8 firstByte = new Bit8();
BitLoader loader = new BitLoader(channel);
loader.load(firstByte);
IUnit unit;
if(firstByte.get() == 'F') {
// header
Bit16 restSignature = new Bit16();
loader.load(restSignature);
Bit24 signature = new Bit24(firstByte.get() << 16 | restSignature.get());
unit = new FlvHeaderTag(signature);
unit.minimumLoad(channel);
return unit;
}
else {
switch(firstByte.get()) {
case 0x12:
MetaTag metaTag = new MetaTag(firstByte);
metaTag.minimumLoad(channel);
return metaTag;
case 0x09:
VideoTag videoTag = new VideoTag(firstByte);
videoTag.minimumLoad(channel);
switch(videoTag.getCodec()) {
case JPEG:
// JPEG for flv is not used anymore.
break;
case FLV1:
if(videoFrameAnalyzer == null || !(videoFrameAnalyzer instanceof Flv1FrameAnalyzer)) {
videoFrameAnalyzer = new Flv1FrameAnalyzer();
}
break;
case SCREEN:
break;
case ON2VP6:
if(videoFrameAnalyzer == null || !(videoFrameAnalyzer instanceof Vp6FrameAnalyzer)) {
videoFrameAnalyzer = new Vp6FrameAnalyzer();
}
break;
case ON2VP6_ALPHA:
if(videoFrameAnalyzer == null || !(videoFrameAnalyzer instanceof Vp6FrameAnalyzer)) {
videoFrameAnalyzer = new Vp6FrameAnalyzer();
}
break;
case SCREEN_V2:
break;
case H264:
if(videoFrameAnalyzer == null || !(videoFrameAnalyzer instanceof DataNalAnalyzer)) {
videoFrameAnalyzer = new DataNalAnalyzer();
}
break;
default:
break;
}
videoTag.setFrameAnalyzer(videoFrameAnalyzer);
return videoTag;
case 0x08:
AudioTag audioTag = new AudioTag(firstByte);
audioTag.minimumLoad(channel);
switch(audioTag.getCodec()) {
case PCM:
break;
case ADPCM:
if(audioFrameAnalyzer == null || !(audioFrameAnalyzer instanceof AdpcmswfFrameAnalyzer)) {
audioFrameAnalyzer = new AdpcmswfFrameAnalyzer();
}
break;
case MP3:
if(audioFrameAnalyzer == null || !(audioFrameAnalyzer instanceof Mp3FrameAnalyzer)) {
audioFrameAnalyzer = new Mp3FrameAnalyzer();
}
break;
case LPCM:
break;
case NELLY_16:
case NELLY_8:
case NELLY:
if(audioFrameAnalyzer == null || !(audioFrameAnalyzer instanceof NellymoserFrameAnalyzer)) {
audioFrameAnalyzer = new NellymoserFrameAnalyzer();
}
break;
case G711_A:
if(audioFrameAnalyzer == null || !(audioFrameAnalyzer instanceof PcmalawFrameAnalyzer)) {
audioFrameAnalyzer = new PcmalawFrameAnalyzer();
}
break;
case G711_U:
if(audioFrameAnalyzer == null || !(audioFrameAnalyzer instanceof PcmmulawFrameAnalyzer)) {
audioFrameAnalyzer = new PcmmulawFrameAnalyzer();
}
break;
case RESERVED:
break;
case AAC:
if(audioFrameAnalyzer == null || !(audioFrameAnalyzer instanceof AacDsiFrameAnalyzer)) {
audioFrameAnalyzer = new AacDsiFrameAnalyzer();
}
break;
case SPEEX:
if(audioFrameAnalyzer == null || !(audioFrameAnalyzer instanceof SpeexFrameAnalyzer)) {
audioFrameAnalyzer = new SpeexFrameAnalyzer();
SpeexFrameSelector speexFrameSelector = (SpeexFrameSelector)audioFrameAnalyzer.getSelector();
// headerFrameとcommentFrameを設定しておく。
HeaderFrame headerFrame = new HeaderFrame();
headerFrame.fillWithFlvDefault();
speexFrameSelector.setHeaderFrame(headerFrame);
speexFrameSelector.setCommentFrame(new CommentFrame());
}
break;
case MP3_8:
if(audioFrameAnalyzer == null || !(audioFrameAnalyzer instanceof Mp3FrameAnalyzer)) {
audioFrameAnalyzer = new Mp3FrameAnalyzer();
}
break;
case DEVICE_SPECIFIC:
break;
default:
break;
}
audioTag.setFrameAnalyzer(audioFrameAnalyzer);
return audioTag;
default:
throw new Exception("unexpected tag.");
}
}
}
}