MediaCodec C++将MP4文件解码为YUV格式例子
时间: 2024-03-17 22:45:05 浏览: 164
这里有一个简单的MediaCodec C++例子,可以将MP4文件解码为YUV格式:
```c++
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <media/NdkMediaCodec.h>
#include <media/NdkMediaExtractor.h>
#include <media/NdkMediaFormat.h>
#define TIMEOUT_US 10000
int main(int argc, char **argv) {
if (argc != 3) {
fprintf(stderr, "Usage: %s <input.mp4> <output.yuv>\n", argv[0]);
return -1;
}
// 创建MediaExtractor对象
AMediaExtractor *extractor = AMediaExtractor_new();
if (!extractor) {
fprintf(stderr, "Failed to create MediaExtractor\n");
return -1;
}
// 设置数据源
if (AMediaExtractor_setDataSource(extractor, argv[1]) != AMEDIA_OK) {
fprintf(stderr, "Failed to set data source '%s'\n", argv[1]);
return -1;
}
// 获取视频轨道
AMediaFormat *format = NULL;
int trackIndex = -1;
for (int i = 0; i < AMediaExtractor_getTrackCount(extractor); i++) {
format = AMediaExtractor_getTrackFormat(extractor, i);
const char *mime;
AMediaFormat_getString(format, AMEDIAFORMAT_KEY_MIME, &mime);
if (!strncmp(mime, "video/", 6)) {
trackIndex = i;
break;
}
}
if (trackIndex == -1) {
fprintf(stderr, "No video track found\n");
return -1;
}
// 选择视频轨道
AMediaExtractor_selectTrack(extractor, trackIndex);
// 创建MediaCodec对象
AMediaCodec *decoder = AMediaCodec_createDecoderByType(AMediaFormat_toString(format));
if (!decoder) {
fprintf(stderr, "Failed to create decoder for '%s'\n", AMediaFormat_toString(format));
return -1;
}
// 配置MediaCodec对象
AMediaCodec_configure(decoder, format, NULL, NULL, 0);
// 启动MediaCodec对象
AMediaCodec_start(decoder);
// 创建输出文件
FILE *fpOut = fopen(argv[2], "wb");
if (!fpOut) {
fprintf(stderr, "Failed to create output file '%s'\n", argv[2]);
return -1;
}
// 解码视频数据
ssize_t sampleSize = 0;
uint8_t *inputBuffer = NULL;
size_t inputBufferSize = 0;
AMediaCodecBufferInfo inputBufferInfo;
memset(&inputBufferInfo, 0, sizeof(inputBufferInfo));
bool sawInputEOS = false;
bool sawOutputEOS = false;
while (!sawOutputEOS) {
// 从Extractor中获取输入数据
if (!sawInputEOS) {
int inputBufferIndex = AMediaCodec_dequeueInputBuffer(decoder, TIMEOUT_US);
if (inputBufferIndex >= 0) {
inputBuffer = AMediaCodec_getInputBuffer(decoder, inputBufferIndex, &inputBufferSize);
sampleSize = AMediaExtractor_readSampleData(extractor, inputBuffer, inputBufferSize);
if (sampleSize < 0) {
// 输入结束,发送EOS标志
AMediaCodec_queueInputBuffer(decoder, inputBufferIndex, 0, 0, 0, AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM);
sawInputEOS = true;
} else {
// 将数据提交给MediaCodec对象进行解码
AMediaCodec_queueInputBuffer(decoder, inputBufferIndex, 0, sampleSize, AMediaExtractor_getSampleTime(extractor), 0);
AMediaExtractor_advance(extractor);
}
}
}
// 从MediaCodec中获取输出数据
AMediaCodecBufferInfo outputBufferInfo;
uint8_t *outputBuffer = AMediaCodec_getOutputBuffer(decoder, &outputBufferInfo, TIMEOUT_US);
if (outputBuffer) {
// 将YUV数据保存到文件中
fwrite(outputBuffer, 1, outputBufferInfo.size, fpOut);
// 释放输出缓冲区
AMediaCodec_releaseOutputBuffer(decoder, AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED, false);
if ((outputBufferInfo.flags & AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM) != 0) {
sawOutputEOS = true;
}
} else if (outputBuffer == NULL && sawInputEOS) {
break;
}
}
// 关闭输出文件
fclose(fpOut);
// 停止并释放MediaCodec对象
AMediaCodec_stop(decoder);
AMediaCodec_delete(decoder);
// 释放MediaExtractor对象
AMediaExtractor_delete(extractor);
return 0;
}
```
请注意,此示例仅用于演示如何使用MediaCodec C++将MP4文件解码为YUV格式。实际应用中,您需要根据您的具体需求进行适当的修改和优化。
阅读全文