MediaCodec C++将MP4文件解码为YUV格式完整代码
时间: 2024-03-17 22:47:49 浏览: 233
以下是使用 MediaCodec C++ 解码 MP4 文件为 YUV 格式的完整代码示例:
```c++
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <android/native_window_jni.h>
#include <android/log.h>
#include <media/NdkMediaCodec.h>
#include <media/NdkMediaExtractor.h>
#include <media/NdkMediaFormat.h>
#define LOG_TAG "MediaCodecTest"
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
void decode(const char *filepath) {
// 初始化 MediaExtractor
AMediaExtractor *extractor = AMediaExtractor_new();
if (!extractor) {
LOGE("Failed to create extractor.");
return;
}
// 设置需要解码的文件路径
media_status_t status = AMediaExtractor_setDataSource(extractor, filepath);
if (status != AMEDIA_OK) {
LOGE("Failed to set data source. status: %d", status);
AMediaExtractor_delete(extractor);
return;
}
// 找到第一个视频轨道
int trackCount = AMediaExtractor_getTrackCount(extractor);
AMediaFormat *format = NULL;
int videoTrackIndex = -1;
for (int i = 0; i < trackCount; ++i) {
format = AMediaExtractor_getTrackFormat(extractor, i);
const char *mime;
AMediaFormat_getString(format, AMEDIAFORMAT_KEY_MIME, &mime);
if (!strncmp(mime, "video/", 6)) {
videoTrackIndex = i;
break;
}
AMediaFormat_delete(format);
}
if (videoTrackIndex == -1) {
LOGE("No video track found.");
AMediaExtractor_delete(extractor);
return;
}
// 初始化 MediaCodec
AMediaCodec *codec = AMediaCodec_createDecoderByType(mime);
if (!codec) {
LOGE("Failed to create codec.");
AMediaExtractor_delete(extractor);
AMediaFormat_delete(format);
return;
}
status = AMediaCodec_configure(codec, format, NULL, NULL, 0);
if (status != AMEDIA_OK) {
LOGE("Failed to configure codec. status: %d", status);
AMediaCodec_delete(codec);
AMediaExtractor_delete(extractor);
AMediaFormat_delete(format);
return;
}
status = AMediaCodec_start(codec);
if (status != AMEDIA_OK) {
LOGE("Failed to start codec. status: %d", status);
AMediaCodec_stop(codec);
AMediaCodec_delete(codec);
AMediaExtractor_delete(extractor);
AMediaFormat_delete(format);
return;
}
// 获取输出缓冲区
AMediaCodecBufferInfo bufferInfo;
ssize_t outputBufferIndex = AMediaCodec_dequeueOutputBuffer(codec, &bufferInfo, 0);
while (outputBufferIndex >= 0) {
// 获取输出缓冲区的数据
size_t bufferSize = bufferInfo.size;
uint8_t *bufferData = AMediaCodec_getOutputBuffer(codec, outputBufferIndex, &bufferSize);
if (bufferData) {
// 处理 YUV 数据
// ...
// 渲染 YUV 数据到 Surface
ANativeWindow *window = ANativeWindow_fromSurface(env, surface);
ANativeWindow_lock(window, &buffer, NULL);
memcpy(buffer.bits, bufferData, bufferSize);
ANativeWindow_unlockAndPost(window);
ANativeWindow_release(window);
// 释放输出缓冲区
AMediaCodec_releaseOutputBuffer(codec, outputBufferIndex, false);
}
outputBufferIndex = AMediaCodec_dequeueOutputBuffer(codec, &bufferInfo, 0);
}
// 释放资源
AMediaExtractor_delete(extractor);
AMediaCodec_stop(codec);
AMediaCodec_delete(codec);
AMediaFormat_delete(format);
}
int main(int argc, char *argv[]) {
if (argc != 2) {
printf("Usage: %s <mp4 file path>\n", argv[0]);
return -1;
}
decode(argv[1]);
return 0;
}
```
请注意,此代码示例仅用于参考。在实际开发中,需要根据具体的需求进行修改和优化。
阅读全文