/*
* myLib - https://github.com/taktod/myLib
* Copyright (c) 2014 ttProject. All rights reserved.
*
* Licensed under The MIT license.
*/
package com.ttProject.media.flv1;
import com.ttProject.media.extra.Bit1;
import com.ttProject.media.extra.Bit2;
import com.ttProject.media.extra.Bit3;
import com.ttProject.media.extra.Bit5;
import com.ttProject.media.extra.Bit8;
import com.ttProject.media.extra.BitLoader;
import com.ttProject.media.flv1.frame.DisposableInterFrame;
import com.ttProject.media.flv1.frame.InterFrame;
import com.ttProject.media.flv1.frame.IntraFrame;
import com.ttProject.nio.channels.IReadChannel;
/**
* flvの内容解析を実施する。
* @author taktod
*/
public class FrameAnalyzer implements IFrameAnalyzer {
@Override
public Frame analyze(IReadChannel ch) throws Exception {
BitLoader bitLoader = new BitLoader(ch);
Bit8 pictureStartCode1 = new Bit8();
Bit8 pictureStartCode2 = new Bit8();
Bit1 pictureStartCode3 = new Bit1();
Bit5 version = new Bit5();
Bit8 temporalReference = new Bit8();
Bit3 pictureSize = new Bit3();
bitLoader.load(pictureStartCode1, pictureStartCode2, pictureStartCode3,
version, temporalReference, pictureSize);
if(pictureStartCode1.get() != 0 ||
pictureStartCode2.get() != 0 ||
pictureStartCode3.get() != 1) {
throw new Exception("開始タグが想定外です。");
}
int width = 0;
int height = 0;
Bit8 width1 = null;
Bit8 width2 = null;
Bit8 height1 = null;
Bit8 height2 = null;
switch(pictureSize.get()) {
case 0: // custom1
width1 = new Bit8();
height1 = new Bit8();
bitLoader.load(width1, height1);
width = width1.get();
height = height1.get();
break;
case 1: // custom2
width1 = new Bit8();
width2 = new Bit8();
height1 = new Bit8();
height2 = new Bit8();
bitLoader.load(width1, width2, height1, height2);
width = ((width1.get() << 8) | width2.get());
height = ((height1.get() << 8) | height2.get());
break;
case 2: // CIF
width = 352;
height = 288;
break;
case 3: // QCIF
width = 176;
height = 144;
break;
case 4: // SQCIF
width = 128;
height = 96;
break;
case 5: // 320x240
width = 320;
height = 240;
break;
case 6: // 160x120
width = 160;
height = 120;
break;
case 7: // reserved
throw new Exception("pictureSizeがreservedになっていました。");
}
Bit2 pictureType = new Bit2();
Bit1 deblockingFlag = new Bit1();
Bit5 quantizer = new Bit5();
Bit1 extraInformationFlag = new Bit1();
bitLoader.load(pictureType, deblockingFlag, quantizer, extraInformationFlag);
Bit8 extraInformation = null;
if(extraInformationFlag.get() == 1) {
extraInformation = new Bit8();
bitLoader.load(extraInformation);
}
switch(pictureType.get()) {
case 0: // intraFrame
return new IntraFrame(pictureStartCode1, pictureStartCode2, pictureStartCode3, version, temporalReference, pictureSize, width, height, pictureType, deblockingFlag, quantizer, extraInformationFlag, extraInformation);
case 1: // interFrame
return new InterFrame(pictureStartCode1, pictureStartCode2, pictureStartCode3, version, temporalReference, pictureSize, width, height, pictureType, deblockingFlag, quantizer, extraInformationFlag, extraInformation);
case 2: // disposableInterFrame
return new DisposableInterFrame(pictureStartCode1, pictureStartCode2, pictureStartCode3, version, temporalReference, pictureSize, width, height, pictureType, deblockingFlag, quantizer, extraInformationFlag, extraInformation);
case 3: // reserved
default:
throw new Exception("知らないフレームタイプです");
}
}
}