/*
* myLib - https://github.com/taktod/myLib
* Copyright (c) 2014 ttProject. All rights reserved.
*
* Licensed under GNU GENERAL PUBLIC LICENSE Version 3.
*/
package com.ttProject.xuggle.frame;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.ttProject.frame.AudioFrame;
import com.ttProject.frame.IAnalyzer;
import com.ttProject.frame.IFrame;
import com.ttProject.frame.VideoFrame;
import com.ttProject.frame.aac.AacFrameAnalyzer;
import com.ttProject.frame.extra.AudioMultiFrame;
import com.ttProject.frame.extra.VideoMultiFrame;
import com.ttProject.frame.h264.NalAnalyzer;
import com.ttProject.nio.channels.ByteReadChannel;
import com.ttProject.nio.channels.IReadChannel;
import com.xuggle.xuggler.ICodec.Type;
import com.xuggle.xuggler.IPacket;
import com.xuggle.xuggler.IStreamCoder;
/**
* IPacket -> frame変換クラス
* @author taktod
*/
public class Depacketizer {
/** ロガー */
@SuppressWarnings("unused")
private Logger logger = LoggerFactory.getLogger(Depacketizer.class);
private IAnalyzer analyzer = null;
// どうやってやろう?
public IFrame getFrame(IStreamCoder encoder, IPacket packet) throws Exception {
IReadChannel channel = new ByteReadChannel(packet.getData().getByteArray(0, packet.getSize()));
try {
if(encoder.getCodecType() == Type.CODEC_TYPE_AUDIO) {
// logger.info("audioframe解析はじめ:" + (packet.getPts() * packet.getTimeBase().getDouble()));
switch(encoder.getCodecID()) {
case CODEC_ID_AAC:
if(analyzer == null || !(analyzer instanceof AacFrameAnalyzer)) {
analyzer = new AacFrameAnalyzer();
}
// AACの
break;
default:
throw new Exception("処理不能なコーデックでした:" + encoder.getCodecID());
}
AudioFrame result = null;
AudioFrame frame = null;
while((frame = (AudioFrame)analyzer.analyze(channel)) != null) {
// ここでframeにtimestampをつけないとだめっぽい
frame.setPts(packet.getPts());
frame.setTimebase(packet.getTimeBase().getDenominator());
if(result == null) {
result = frame;
}
else {
AudioMultiFrame multiFrame = null;
if(result instanceof AudioMultiFrame) {
multiFrame = (AudioMultiFrame) result;
}
else {
multiFrame = new AudioMultiFrame();
multiFrame.addFrame(result);
}
multiFrame.addFrame(frame);
result = multiFrame;
}
}
return result;
}
else if(encoder.getCodecType() == Type.CODEC_TYPE_VIDEO) {
// logger.info("videoframe解析はじめ:" + (packet.getPts() * packet.getTimeBase().getDouble()));
switch(encoder.getCodecID()) {
case CODEC_ID_H264:
// h264のNal解析を走らせる必要がある。
if(analyzer == null || !(analyzer instanceof NalAnalyzer)) {
analyzer = new NalAnalyzer();
}
break;
default:
throw new Exception("処理不能なコーデックでした:" + encoder.getCodecID());
}
VideoFrame result = null; // sliceかsliceIDRのみ応答すればよし
VideoFrame frame = null;
while((frame = (VideoFrame)analyzer.analyze(channel)) != null) {
// ここでframeにtimestampをつけないとだめっぽい
frame.setPts(packet.getPts());
frame.setTimebase(packet.getTimeBase().getDenominator());
if(result == null) {
result = frame;
}
else {
VideoMultiFrame multiFrame = null;
if(result instanceof VideoMultiFrame) {
multiFrame = (VideoMultiFrame)result;
}
else {
multiFrame = new VideoMultiFrame();
multiFrame.addFrame(result);
}
multiFrame.addFrame(frame);
result = multiFrame;
}
}
return result;
}
}
finally{
channel.close();
}
return null;
}
}