package lzf.video.edit.decoder;
import android.media.MediaCodec;
import android.media.MediaExtractor;
import android.media.MediaFormat;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
/**
* Android SDK 支持的编码器
* @author Darcy
* @version android.os.Build.VERSION.SDK_INT >= 16
*/
public class AndroidAudioDecoder extends AudioDecoder{
private static final String TAG = "AndroidAudioDecoder";
AndroidAudioDecoder(String encodefile) {
super(encodefile);
}
@Override
public RawAudioInfo decodeToFile(String outFile) throws IOException{
long beginTime = System.currentTimeMillis();
final String encodeFile = mEncodeFile;
MediaExtractor extractor = new MediaExtractor();
extractor.setDataSource(encodeFile);
MediaFormat mediaFormat = null;
for (int i = 0; i < extractor.getTrackCount(); i++) {
MediaFormat format = extractor.getTrackFormat(i);
String mime = format.getString(MediaFormat.KEY_MIME);
if (mime.startsWith("audio/")) {
extractor.selectTrack(i);
mediaFormat = format;
break;
}
}
if(mediaFormat == null){
extractor.release();
return null;
}
RawAudioInfo rawAudioInfo = new RawAudioInfo();
rawAudioInfo.channel = mediaFormat.getInteger(MediaFormat.KEY_CHANNEL_COUNT);
rawAudioInfo.sampleRate = mediaFormat.getInteger(MediaFormat.KEY_SAMPLE_RATE);
rawAudioInfo.tempRawFile = outFile;
FileOutputStream fosDecoder = new FileOutputStream(rawAudioInfo.tempRawFile);
String mediaMime = mediaFormat.getString(MediaFormat.KEY_MIME);
MediaCodec codec = MediaCodec.createDecoderByType(mediaMime);
codec.configure(mediaFormat, null, null, 0);
codec.start();
ByteBuffer[] codecInputBuffers = codec.getInputBuffers();
ByteBuffer[] codecOutputBuffers = codec.getOutputBuffers();
final double audioDurationUs = mediaFormat.getLong(MediaFormat.KEY_DURATION);
final long kTimeOutUs = 5000;
MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
boolean sawInputEOS = false;
boolean sawOutputEOS = false;
int totalRawSize = 0;
try{
while (!sawOutputEOS) {
if (!sawInputEOS) {
int inputBufIndex = codec.dequeueInputBuffer(kTimeOutUs);
if (inputBufIndex >= 0) {
ByteBuffer dstBuf = codecInputBuffers[inputBufIndex];
int sampleSize = extractor.readSampleData(dstBuf, 0);
if (sampleSize < 0) {
sawInputEOS = true;
codec.queueInputBuffer(inputBufIndex,0,0,0,MediaCodec.BUFFER_FLAG_END_OF_STREAM );
} else {
long presentationTimeUs = extractor.getSampleTime();
codec.queueInputBuffer(inputBufIndex,0,sampleSize,presentationTimeUs,0);
extractor.advance();
}
}
}
int res = codec.dequeueOutputBuffer(info, kTimeOutUs);
if (res >= 0) {
int outputBufIndex = res;
// Simply ignore codec config buffers.
if ((info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG)!= 0) {
codec.releaseOutputBuffer(outputBufIndex, false);
continue;
}
if(info.size != 0){
ByteBuffer outBuf = codecOutputBuffers[outputBufIndex];
outBuf.position(info.offset);
outBuf.limit(info.offset + info.size);
byte[] data = new byte[info.size];
outBuf.get(data);
totalRawSize += data.length;
fosDecoder.write(data);
if(mOnAudioDecoderListener != null)
mOnAudioDecoderListener.onDecode(data, info.presentationTimeUs / audioDurationUs);
}
codec.releaseOutputBuffer(outputBufIndex, false);
if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
sawOutputEOS = true;
}
} else if (res == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
codecOutputBuffers = codec.getOutputBuffers();
} else if (res == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
MediaFormat oformat = codec.getOutputFormat();
}
}
rawAudioInfo.size = totalRawSize;
if(mOnAudioDecoderListener != null)
mOnAudioDecoderListener.onDecode(null, 1);
return rawAudioInfo;
}finally{
fosDecoder.close();
codec.stop();
codec.release();
extractor.release();
}
}
}