本文解决的问题
本文主要使用MediaCodec
硬编码器对Android
设备采集的音视频编码
- 封装音视频基础编码器
- 封装音频编码器
- 封装视频编码器
- 使用新封装的视频编码器改造示例2
- 使用Camera进行视频录制(YUV420SP)并保存为视频流(H.264)
- 使用AudioRecord进行音频录制(PCM)并保存为音频流(AAC)
- 使用MediaMuxer混合器合并视频和音频为一路流(H.264)(待完成)
一、封装音视频基础编码器
- 定义编码接口类
ICodec
:
interface ICodec {
//入队
fun putBuf(data: ByteArray, offset: Int, size: Int)
//处理数据
fun dealWith(data: ByteArray)
//停止线程
fun stopWorld()
}
复制代码
- 定义编码任务线程
BaseCodec
:
音视频逐帧编码,编码是一项耗时任务,所以需要定义一队列来存储需要编码的数据帧.
BaseCodec
为抽象类并且实现了ICodec接口,在任务启动时不停的从队列中取出数据,dealWith方法进行处理
abstract class BaseCodec : Thread(), ICodec {
val inBlockingQueue = ArrayBlockingQueue<ByteArray>(30)
override fun putBuf(data: ByteArray, offset: Int, size: Int) {
val byteArray = ByteArray(size)
System.arraycopy(data, offset, byteArray, 0, size)
inBlockingQueue.put(byteArray)
}
var threadRunning = true;
override fun run() {
try {
BaseCodecLoop1@ while (threadRunning) {
val item = inBlockingQueue.take()
dealWith(item)
}
} catch (e: Exception) {
e.printStackTrace()
}
}
override fun dealWith(data: ByteArray) {}
override fun stopWorld() {
inBlockingQueue.clear()
threadRunning = false;
interrupt()
join(1000)
}
}
const val SAMPLE_RATE_IN_HZ = 44100 //采样率44.1KHz
const val CHANNEL = AudioFormat.CHANNEL_IN_MONO //单声道,立体声:CHANNEL_IN_STEREO
const val AUDIO_FORMAT = AudioFormat.ENCODING_PCM_16BIT //每个采样点16bit
const val DEST_BIT_RATE = 128000 //编码码率
复制代码
- 封装
MediaCodec
音视频编码基础类BaseMediaCodec
:
该类包含
- 初始化对应mime类型的MediaCodec
/**
* mime类型对应的格式
* video/avc: h.264
* video/hevc: h.265
* audio/mp4a-latm: aac
*/
复制代码
- 数据入队
- 发送结束标记
- 数据解码出队线程
CodecListener
编码结束回传结果的接口- stopWorld释放接口
二、封装音频编码器
- 初始化:默认初始化
audio/m