音视频开发路线:
Android 音视频开发入门指南_Jhuster的专栏的技术博客_51CTO博客_android 音视频开发入门
demo地址:
GitHub - wygsqsj/videoPath: 音视频学习路线demo
MediaCodec异步方式上一节使用同步方式使用MediaCodec总感觉比较麻烦,我们java中使用大量的回调来实现监听者模式,MediaCodec在sdk 19版本后也通过回调来告知使用者,input或者output已经准备好的情况,具体的api就是为MediaCodec设置CallBack,并实现其中的四个方法:
decodeCodec.setCallback(new MediaCodec.Callback() {
@Override
public void onInputBufferAvailable(@NonNull MediaCodec codec, int index) {
Log.i(LOG_TAG, "input数据已准备好,当前index:" + index);
}
@Override
public void onOutputBufferAvailable(@NonNull MediaCodec codec, int index, @NonNull MediaCodec.BufferInfo info) {
Log.i(LOG_TAG, "outPut数据已准备好,当前index:" + index);
}
@Override
public void onError(@NonNull MediaCodec codec, @NonNull MediaCodec.CodecException e) {
Log.i(LOG_TAG, "编解码出错 onError" + e.toString());
}
@Override
public void onOutputFormatChanged(@NonNull MediaCodec codec, @NonNull MediaFormat format) {
Log.i(LOG_TAG, "format发生更改,onOutputFormatChanged" + format.toString());
}
});
注意点:
- 先设置callBack,再设置config
- callBack回调发生再主线程,需要自己手动切换
具体的使用流程跟上一节其实是一样的,就是while循环中手动获取现在改为回调通知了,切换线程我是通过在子线程中构建Handler,收到回调之后再通过Handler把消息发出去,回调的信息通过一个队列去记录一下,具体的代码如下:
package com.wish.videopath.demo5;
import android.content.Context;
import android.media.MediaCodec;
import android.media.MediaExtractor;
import android.media.MediaFormat;
import android.os.Build;
import android.os.Environment;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import com.wish.videopath.R;
import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Queue;
import java.util.concurrent.linkedBlockingQueue;
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import static com.wish.videopath.MainActivity.LOG_TAG;
public class DecodeAACAsyn extends Thread {
private Context context;
private MediaFormat audioFormat;
private File pcmFile;
private FileOutputStream fos = null;
private MediaCodec decodeCodec = null;
private Queue mOutDataQueue = new linkedBlockingQueue<>();
private Queue mInputDataQueue = new linkedBlockingQueue<>();
private MediaExtractor audioExtractor = new MediaExtractor();
private Handler mHandler;
private Runnable outRunnable = () -> {
try {
Log.e(LOG_TAG, "outRunnable,当前线程: " + Thread.currentThread().getName());
byte[] pcmData = mOutDataQueue.poll();
if (pcmData == null) {
return;
}
Log.e(LOG_TAG, "Handler回调收到,当前数据大小:" + pcmData.length);
//装车
fos.write(pcmData);//数据写入文件中
fos.flush();
} catch (Exception e) {
e.printStackTrace();
}
};
private Runnable inputRunnable = () -> {
try {
Log.e(LOG_TAG, "inputRunnable,当前线程: " + Thread.currentThread().getName());
Integer index = mInputDataQueue.poll();
if (index == null) {
return;
}
ByteBuffer buffer;
if (Build.VE



