native层,yuv420 通过AMediaCodec编码成h264,并通过AMediaMuxer封装成mp4的demo
时间: 2024-03-12 15:48:43 浏览: 71
以下是一个简单的示例代码,演示了如何使用 `AMediaCodec` 编码 YUV420 数据为 H264 格式,并使用 `AMediaMuxer` 将其封装为 MP4 格式。
```c++
#include <media/NdkMediaCodec.h>
#include <media/NdkMediaFormat.h>
#include <media/NdkMediaMuxer.h>
const int kWidth = 640;
const int kHeight = 480;
const int kFrameRate = 30;
const int kBitRate = 1024 * 1024;
const int kIFrameInterval = 5;
const char* kMimeType = "video/avc";
const int kTimeoutUs = 10000;
// 读取 YUV 数据的回调函数,这里假设 YUV 数据已经准备好了
void readYuvData(uint8_t* buffer, size_t size) {
// TODO: 从 YUV 数据源读取数据
}
int main(int argc, char** argv) {
// 创建编码器格式
AMediaFormat* encoderFormat = AMediaFormat_new();
AMediaFormat_setString(encoderFormat, AMEDIAFORMAT_KEY_MIME, kMimeType);
AMediaFormat_setInt32(encoderFormat, AMEDIAFORMAT_KEY_WIDTH, kWidth);
AMediaFormat_setInt32(encoderFormat, AMEDIAFORMAT_KEY_HEIGHT, kHeight);
AMediaFormat_setInt32(encoderFormat, AMEDIAFORMAT_KEY_BIT_RATE, kBitRate);
AMediaFormat_setInt32(encoderFormat, AMEDIAFORMAT_KEY_FRAME_RATE, kFrameRate);
AMediaFormat_setInt32(encoderFormat, AMEDIAFORMAT_KEY_I_FRAME_INTERVAL, kIFrameInterval);
// 创建编码器
AMediaCodec* encoder = AMediaCodec_createEncoderByType(kMimeType);
AMediaCodec_configure(encoder, encoderFormat, NULL, NULL, AMEDIACODEC_CONFIGURE_FLAG_ENCODE);
// 获取编码器输入缓冲区
AMediaCodecBufferInfo inputBufferInfo;
int inputBufferIndex = AMediaCodec_dequeueInputBuffer(encoder, kTimeoutUs);
uint8_t* inputBuffer = AMediaCodec_getInputBuffer(encoder, inputBufferIndex, NULL);
// 读取 YUV 数据
readYuvData(inputBuffer, size);
// 将 YUV 数据送入编码器
AMediaCodec_queueInputBuffer(encoder, inputBufferIndex, 0, size, timestamp, 0);
// 获取编码器输出缓冲区
AMediaCodecBufferInfo outputBufferInfo;
int outputBufferIndex = AMediaCodec_dequeueOutputBuffer(encoder, &outputBufferInfo, kTimeoutUs);
uint8_t* outputBuffer = AMediaCodec_getOutputBuffer(encoder, outputBufferIndex, NULL);
// 获取编码后的数据
size_t encodedSize = outputBufferInfo.size;
uint8_t* encodedData = outputBuffer + outputBufferInfo.offset;
// 创建封装器
AMediaMuxer* muxer = AMediaMuxer_new("/sdcard/output.mp4", AMEDIAMUXER_OUTPUT_FORMAT_MPEG_4);
// 添加视频轨道
AMediaFormat* videoFormat = AMediaFormat_new();
AMediaFormat_setString(videoFormat, AMEDIAFORMAT_KEY_MIME, kMimeType);
AMediaFormat_setInt32(videoFormat, AMEDIAFORMAT_KEY_WIDTH, kWidth);
AMediaFormat_setInt32(videoFormat, AMEDIAFORMAT_KEY_HEIGHT, kHeight);
AMediaFormat_setInt32(videoFormat, AMEDIAFORMAT_KEY_FRAME_RATE, kFrameRate);
int videoTrackIndex = AMediaMuxer_addTrack(muxer, videoFormat);
AMediaMuxer_start(muxer);
// 将编码后的数据写入封装器
AMediaMuxer_writeSampleData(muxer, videoTrackIndex, encodedData, &outputBufferInfo);
// 释放资源
AMediaCodec_stop(encoder);
AMediaCodec_delete(encoder);
AMediaFormat_delete(encoderFormat);
AMediaFormat_delete(videoFormat);
AMediaMuxer_stop(muxer);
AMediaMuxer_delete(muxer);
return 0;
}
```
需要注意的是,这只是一个简单的示例代码,实际使用时还需要进行一些参数的调整和错误处理等。此外,还需要对 YUV 数据源的读取进行实现。
阅读全文