/*
* myLib - https://github.com/taktod/myLib
* Copyright (c) 2014 ttProject. All rights reserved.
*
* Licensed under The MIT license.
*/
package com.ttProject.transcode.ffmpeg.worker;
import java.nio.ByteBuffer;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import org.apache.log4j.Logger;
import org.jboss.netty.buffer.ChannelBuffers;
import com.ttProject.media.Unit;
import com.ttProject.transcode.ffmpeg.FfmpegTranscodeManager;
import com.ttProject.transcode.ffmpeg.process.ProcessServer;
/**
* データを送り込みます。
* ffmpegのプロセスが受け入れ完了してからデータを送信する必要がある。
* @author taktod
*/
public class DataSendWorker implements Runnable {
/** 動作ロガー */
private final Logger logger = Logger.getLogger(DataSendWorker.class);
/** 動作サーバー */
private final ProcessServer server;
/** 転送データソース */
private final LinkedBlockingQueue<Unit> dataQueue = new LinkedBlockingQueue<Unit>();
/** 動作させるexecutor */
private ExecutorService loopExecutor = null;
private final FfmpegTranscodeManager transcodeManager;
/** 動作フラグ */
private boolean started = false;
/**
* コンストラクタ
* @param server
*/
public DataSendWorker(FfmpegTranscodeManager transcodeManager, ProcessServer server) {
this.transcodeManager = transcodeManager;
this.server = server;
}
/**
* 処理に利用するexecutorを設定
* @param executor
*/
public void setExecutor(ExecutorService executor) {
loopExecutor = executor;
}
/**
* serverから開始準備ができたらキックされる動作
*/
public synchronized void start() {
if(loopExecutor == null) {
loopExecutor = Executors.newSingleThreadExecutor();
}
loopExecutor.execute(this);
started = true;
}
/**
* 停止処理
*/
public void close() {
// たまっているデータをすべて吐き出して、終わらせる必要あり
}
/**
* データを転送します
* ここにデータをいれれば順次転送されていく・・・というのがいい。
* とりあえずロックかけて、同期処理になるようにしておく。
*/
public synchronized void send(Unit unit) throws Exception {
if(!transcodeManager.getDeunitizer().check(unit)) {
return;
}
if(!started) {
// 開始前はqueueにいれていくだけ。
dataQueue.add(unit);
}
else if(dataQueue.size() > 0) {
// queueにデータがはいっている場合も追加するだけ
dataQueue.add(unit);
}
else {
// queueにデータがなくて、開始済みの場合は、queueにいれて、executorを実行する。
dataQueue.add(unit); // いれて
loopExecutor.execute(this); // 実行
}
}
/**
* 実行処理
*/
@Override
public void run() {
try {
// 個々別にwaitかけなくても、serverがデータうけとったら、threadの動作開始すれば済むっぽい。
// dataQueueに入っているデータがなくなるまで、実行しつづける。
// どっちかというと、無限ループより、executor呼び合いの方がいいか・・・
Unit unit = dataQueue.poll(); // 即実行
// 送るbufferを作成する。
ByteBuffer buffer = transcodeManager.getDeunitizer().getBuffer(unit);
// clientにデータを送る。
if(buffer != null) {
server.sendData(ChannelBuffers.copiedBuffer(buffer));
}
if(dataQueue.size() > 0) {
// データがあったら再度実行する
loopExecutor.execute(this);
}
}
catch(Exception e) {
logger.error("想定外の例外が発生しました。", e);
}
}
}