MediaCodec 解码视频文件
程序员文章站
2022-03-05 09:59:38
...
首先初始化解码器: 其中包括视频解码器 和 音频解码器
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
extractor = new MediaExtractor();
audioExtractor = new MediaExtractor();
try {
extractor.setDataSource(path);
audioExtractor.setDataSource(path);
for (int i = 0; i < extractor.getTrackCount(); i++) {
MediaFormat format = extractor.getTrackFormat(i);
String mime = format.getString(MediaFormat.KEY_MIME);
Log.i(TAG, "mime: " + mime);
if (mime.startsWith("video/")) {
extractor.selectTrack(i);
decoder = MediaCodec.createDecoderByType(mime);
decoder.configure(format, surfaceHolder.getSurface(), null, 0);
//format.setInteger(MediaFormat.KEY_FRAME_RATE, 30);//帧率
//format.setInteger(MediaFormat.KEY_BIT_RATE, 17648);//设置比特率
decoder.start();
Log.i(TAG, "createDecoder mime: " + mime);
//break;
} else if (mime.startsWith("audio/")) {
audioExtractor.selectTrack(i);
audioDecoder = MediaCodec.createDecoderByType(mime);
//采样率
format.setInteger(MediaFormat.KEY_SAMPLE_RATE, 8000);
//声道个数
format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 1);
//比特率
format.setInteger(MediaFormat.KEY_BIT_RATE, 0);
format.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectLC);
//ByteBuffer key(暂时不了解该参数的含义,但必须设置)
audioDecoder.configure(format, null, null, 0);
audioDecoder.start();
}
}
if (audioDecoder!=null){
audio = new AudioDecodecPlay();
audio.start();
}
if (decoder != null) {
DecodecPlay play = new DecodecPlay();
play.start();
Log.i(TAG, "initDecoder: 找不到解码器");
return false;
}
} catch (IOException e) {
e.printStackTrace();
}
} else {
Log.i(TAG, "initDecoder: failed");
return false;
}
初始化解码器就可以开始解码了:
视频解码线程
private class DecodecPlay extends Thread {
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
@Override
public void run() {
ByteBuffer[] inputBuffers = decoder.getInputBuffers();
ByteBuffer[] outputBuffers = decoder.getOutputBuffers();
MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
boolean first = false;
long startMs=0;
boolean isEndOfStream = false;
while (!Thread.interrupted()) {
if (!isEndOfStream) {
int dequeueIndex = decoder.dequeueInputBuffer(1000);
Log.i(TAG, "dequeueIndex: " + dequeueIndex);
if (dequeueIndex > 0) {
ByteBuffer inputBuffer = inputBuffers[dequeueIndex];
int sampleSize = extractor.readSampleData(inputBuffer, 0);
if (sampleSize<0){
Log.e(TAG, "input buffer end of stream");
decoder.queueInputBuffer(dequeueIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
isEndOfStream = true;
}else {
Log.i(TAG, "time: "+extractor.getSampleTime());
decoder.queueInputBuffer(dequeueIndex, 0, sampleSize, extractor.getSampleTime(), 0);
extractor.advance();
}
}
}
int outputIndex = decoder.dequeueOutputBuffer(info, 10000);
switch (outputIndex){
case MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED:
Log.i(TAG, "--缓冲区已经更改");
outputBuffers = decoder.getOutputBuffers();
break;
case MediaCodec.INFO_OUTPUT_FORMAT_CHANGED:
Log.i(TAG, "--格式以及更改-----> "+decoder.getOutputFormat().getString(MediaFormat.KEY_MIME));
break;
case MediaCodec.INFO_TRY_AGAIN_LATER:
Log.i(TAG, "dequeueOutputBuffer indicates that the call timed out.");
break;
default:
Log.i(TAG, "run: outputIndex01"+outputIndex);
if (!first){
startMs = System.currentTimeMillis();
first=true;
}
Log.i(TAG, "info.presentationTimeUs: "+info.presentationTimeUs/1000+"::::"+(System.currentTimeMillis() - startMs));
long sleepTime = (info.presentationTimeUs / 1000) - (System.currentTimeMillis() - startMs);
if (sleepTime>0){
try {
sleep(sleepTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
decoder.releaseOutputBuffer(outputIndex, true);
break;
}
if((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0){
Log.d(TAG, "Output buffer BUFFER_FLAG_END_OF_STREAM");
finish();
break;
}
}
decoder.stop();
decoder.release();
extractor.release();
}
}
音频解码线程:
private class AudioDecodecPlay extends Thread {
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
@Override
public void run() {
boolean first=false;
ByteBuffer[] inputBuffers = audioDecoder.getInputBuffers();
ByteBuffer[] outputBuffers = audioDecoder.getOutputBuffers();
MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
boolean isEndOfStream = false;
long startMs = 0;
while (!Thread.interrupted()) {
if (!isEndOfStream) {
int dequeueIndex = audioDecoder.dequeueInputBuffer(1000);
Log.i(TAG, "dequeueIndex: " + dequeueIndex);
if (dequeueIndex > 0) {
ByteBuffer inputBuffer = inputBuffers[dequeueIndex];
int sampleSize = audioExtractor.readSampleData(inputBuffer, 0);
if (sampleSize<0){
Log.e(TAG, "input buffer end of stream");
audioDecoder.queueInputBuffer(dequeueIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
isEndOfStream = true;
}else {
audioDecoder.queueInputBuffer(dequeueIndex, 0, sampleSize, audioExtractor.getSampleTime(), 0);
audioExtractor.advance();
}
}
}
int outputIndex = audioDecoder.dequeueOutputBuffer(info, 10000);
switch (outputIndex){
case MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED:
Log.i(TAG, "--缓冲区已经更改");
outputBuffers = audioDecoder.getOutputBuffers();
break;
case MediaCodec.INFO_OUTPUT_FORMAT_CHANGED:
Log.i(TAG, "--格式以及更改-----> "+decoder.getOutputFormat().getString(MediaFormat.KEY_MIME));
break;
case MediaCodec.INFO_TRY_AGAIN_LATER:
Log.i(TAG, "dequeueOutputBuffer indicates that the call timed out.");
break;
default:
Log.i(TAG, "run: outputIndex02"+outputIndex);
if (!first){
startMs = System.currentTimeMillis();
first=true;
}
Log.i(TAG, "info.presentationTimeUs: "+info.presentationTimeUs/1000+"::::"+(System.currentTimeMillis() - startMs));
long sleepTime = (info.presentationTimeUs / 1000) - (System.currentTimeMillis() - startMs);
if (sleepTime>0){
try {
sleep(sleepTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
ByteBuffer buffer = outputBuffers[outputIndex];
byte[] data = new byte[buffer.remaining()];
buffer.get(data);
mPlayer.write(data,0,data.length);
audioDecoder.releaseOutputBuffer(outputIndex, false);
break;
}
if((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0){
Log.d(TAG, "Output buffer BUFFER_FLAG_END_OF_STREAM");
break;
}
}
audioDecoder.stop();
audioDecoder.release();
audioExtractor.release();
}
}
关键代码就这么多!!!
解码后的音频可以使用AudioTrack播放
mPlayer = new AudioTrack(AudioManager.STREAM_MUSIC,
sampleRateInHz, channelConfig, audioFormat,2880,
AudioTrack.MODE_STREAM);
mPlayer.play();
上一篇: 算法:91. 解码方法
下一篇: python3 歌词文件krc转lrc