/*
* myLib - https://github.com/taktod/myLib
* Copyright (c) 2014 ttProject. All rights reserved.
*
* Licensed under The MIT license.
*/
package com.ttProject.convertprocess;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.Map;
import org.apache.log4j.Logger;
import com.ttProject.convertprocess.frame.ShareFrameData;
import com.ttProject.convertprocess.server.ProcessServer;
import com.ttProject.frame.CodecType;
import com.ttProject.frame.IAudioFrame;
import com.ttProject.frame.IFrame;
import com.ttProject.frame.IVideoFrame;
import com.ttProject.frame.extra.AudioMultiFrame;
import com.ttProject.frame.extra.VideoMultiFrame;
/**
* プロセスにデータを送り出すマネージャー
* 旧FfmpegConvertManagerに相当
* @author taktod
*/
public class ProcessManager {
/** ロガー */
private static final Logger logger = Logger.getLogger(ProcessManager.class);
/** 対象プロセス */
private final Map<String, ProcessHandler> handlers = new HashMap<String, ProcessHandler>();
/** 動作pid */
private static final String pid;
/** 動作ポート番号 */
private int portNumber;
/** 動作サーバー */
private ProcessServer server;
/**
* 静的初期化
*/
static {
RuntimeMXBean bean = ManagementFactory.getRuntimeMXBean();
pid = bean.getName().split("@")[0];
}
/**
* コンストラクタ
* @throws Exception
*/
public ProcessManager() throws Exception {
ProcessServer processServer = null;
int portNumber = Integer.parseInt(pid) % 1000 + 1000;
for(;portNumber < 65535;portNumber += 1000) {
try {
processServer = new ProcessServer(portNumber);
break;
}
catch(Exception e) {
;
}
}
if(portNumber > 65535) {
logger.fatal("ローカルサーバー用のprocessServerのポート番号が決定できませんでした。");
throw new RuntimeException("ローカルサーバー用の動作ポート番号が決まらない");
}
server = processServer;
this.portNumber = portNumber;
}
/**
* 動作プロセスを取得する
* @param name
* @return
*/
public ProcessHandler getProcessHandler(String name) {
ProcessHandler handler = handlers.get(name);
if(handler == null) {
handler = new ProcessHandler(portNumber);
handlers.put(name, handler);
}
return handler;
}
/**
* 動作を開始する
*/
public void start() {
for(ProcessHandler handler : handlers.values()) {
try {
handler.executeProcess();
}
catch(Exception e) {
logger.error("プロセス起動で問題発生", e);
}
}
}
/**
* フレームを子プロセスに送信する
* @param frame
*/
public void pushFrame(IFrame frame, int id) throws Exception {
if(frame instanceof AudioMultiFrame) {
AudioMultiFrame multiFrame = (AudioMultiFrame)frame;
for(IAudioFrame audioFrame : multiFrame.getFrameList()) {
pushFrame(audioFrame, id);
}
return;
}
else if(frame instanceof VideoMultiFrame) {
VideoMultiFrame multiFrame = (VideoMultiFrame)frame;
for(IVideoFrame videoFrame : multiFrame.getFrameList()) {
pushFrame(videoFrame, id);
}
return;
}
if(frame == null) {
// frameがnullの場合はほっとく。
return;
}
// codecCheckerを利用して、どのcodecTypeであるか調べる
CodecType codecType = frame.getCodecType();
// shareFrameDataを作り出しておく
ShareFrameData shareFrameData = new ShareFrameData(codecType, frame, id);
// 送るデータをセットしておく。
ByteBuffer buffer = null;
switch(codecType) {
case H264:
buffer = frame.getPackBuffer();
break;
default:
buffer = frame.getData();
break;
}
if(buffer == null) {
return;
}
shareFrameData.setFrameData(buffer);
// 相手に送付する。
server.sendData(shareFrameData.getShareData());
}
/**
* 終了処理
*/
public void close() {
for(ProcessHandler handler : handlers.values()) {
handler.close();
}
if(server != null) {
server.closeServer();
}
}
}