/* * myLib - https://github.com/taktod/myLib * Copyright (c) 2014 ttProject. All rights reserved. * * Licensed under GNU GENERAL PUBLIC LICENSE Version 3. */ package com.ttProject.transcode.xuggle.track; import com.xuggle.xuggler.IAudioResampler; import com.xuggle.xuggler.IAudioSamples; import com.xuggle.xuggler.IPacket; import com.xuggle.xuggler.IStreamCoder; /** * audio処理の細部抜き出し * @author taktod */ public class AudioTrackModule extends TrackModule { /** trackManager参照 */ private final XuggleTrackManager trackManager; /** 処理パケット(可能なら使い回します) */ private IPacket packet = null; /** リサンプル動作(必要なら実行します) */ private IAudioResampler resampler = null; /** * コンストラクタ * @param trackManager */ protected AudioTrackModule(XuggleTrackManager trackManager) { this.trackManager = trackManager; } /** * 処理の実行 * @param xuggleObject IAudioSamplesであることを期待しています。 */ @Override protected void process(Object xuggleObject) { try { // データの再確認(ひっかかることはまずないはず。) if(!(xuggleObject instanceof IAudioSamples)) { throw new Exception("データがAudioSamplesではありません。異常です。"); } IAudioSamples samples = (IAudioSamples) xuggleObject; // エンコーダー参照 IStreamCoder encoder = trackManager.getEncoder(); if(encoder == null) { throw new Exception("プロセス開始前にencoderが設定されていませんでした。"); } // データのフォーマットが一致しているか確認します。 if(samples.getSampleRate() != encoder.getSampleRate() || samples.getFormat() != encoder.getSampleFormat() || samples.getChannels() != encoder.getChannels()) { // 一致しない場合はリサンプルする必要あり // resamplerをつくってリサンプルする必要あり。 if(resampler == null || resampler.getOutputRate() != encoder.getSampleRate() || resampler.getOutputFormat() != encoder.getSampleFormat() || resampler.getOutputChannels() != encoder.getChannels()) { if(resampler != null) { // これ消さなくてもいいかも・・・xuggleがエラーになる場合はコメントアウトしておきたい。 // audioResampler.delete(); } resampler = IAudioResampler.make( encoder.getChannels(), samples.getChannels(), encoder.getSampleRate(), samples.getSampleRate(), encoder.getSampleFormat(), samples.getFormat()); } IAudioSamples spls = IAudioSamples.make(1024, encoder.getChannels()); int retval = resampler.resample(spls, samples, samples.getNumSamples()); if(retval <= 0) { throw new Exception("音声のリサンプルに失敗しました。"); } samples = spls; } // エンコード実行 int samplesConsumed = 0; while(samplesConsumed < samples.getNumSamples()) { if(packet == null) { packet = IPacket.make(); } if(!encoder.isOpen()) { if(encoder.open(null, null) < 0) { throw new Exception("エンコーダーが開けませんでした"); } } int retval = encoder.encodeAudio(packet, samples, samplesConsumed); if(retval < 0) { throw new Exception("音声変換失敗"); } samplesConsumed += retval; trackManager.applyData(packet); } } catch(Exception e) { // 例外が発生した場合は通知しておく。 trackManager.reportException(e); } } /** * オブジェクトがこのプログラムで動作可能か応答する * @return true:可能 false:不能 */ @Override protected boolean checkObject(Object xuggleObject) { if(!(xuggleObject instanceof IAudioSamples)) { // audio用の処理でなければスルー return false; } IAudioSamples samples = (IAudioSamples) xuggleObject; if(!samples.isComplete()) { // データが完成していなかったらスルー return false; } return true; } /** * 終了処理 */ @Override protected void close() { } }