Android 使用c++MediaCodec 解码例子
时间: 2024-04-02 22:34:34 浏览: 139
Android使用MediaCodeC与OpenGL硬解码 录制mp4音视频实现源码
5星 · 资源好评率100%
以下是使用C++ MediaCodec 进行视频解码的示例代码:
```c++
#include <jni.h>
#include <android/log.h>
#include <android/native_window_jni.h>
#include <media/NdkMediaCodec.h>
#include <media/NdkMediaExtractor.h>
#define LOG_TAG "MediaCodec"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
extern "C" JNIEXPORT void JNICALL
Java_com_example_mediadecoder_MainActivity_decode(JNIEnv *env, jobject thiz, jstring filePath, jobject surface) {
const char *path = env->GetStringUTFChars(filePath, nullptr);
AMediaExtractor *extractor = AMediaExtractor_new();
AMediaCodec *codec = nullptr;
int32_t trackIndex = -1;
bool sawInputEOS = false;
bool sawOutputEOS = false;
// 设置文件路径
media_status_t result = AMediaExtractor_setDataSource(extractor, path);
if (result != AMEDIA_OK) {
LOGE("AMediaExtractor_setDataSource error: %d", result);
goto end;
}
// 查找视频轨道
int32_t numTracks = AMediaExtractor_getTrackCount(extractor);
for (int32_t i = 0; i < numTracks; ++i) {
AMediaFormat *format = AMediaExtractor_getTrackFormat(extractor, i);
const char *mime = nullptr;
AMediaFormat_getString(format, AMEDIAFORMAT_KEY_MIME, &mime);
if (mime && !strncmp(mime, "video/", 6)) {
trackIndex = i;
break;
}
AMediaFormat_delete(format);
}
if (trackIndex == -1) {
LOGE("No video track found in %s", path);
goto end;
}
// 获取视频格式
AMediaFormat *format = AMediaExtractor_getTrackFormat(extractor, trackIndex);
int32_t width = 0, height = 0;
AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_WIDTH, &width);
AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_HEIGHT, &height);
LOGI("Video size: %dx%d", width, height);
// 创建 MediaCodec 解码器
codec = AMediaCodec_createDecoderByType("video/avc");
result = AMediaCodec_configure(codec, format, ANativeWindow_fromSurface(env, surface), nullptr, 0);
if (result != AMEDIA_OK) {
LOGE("AMediaCodec_configure error: %d", result);
goto end;
}
// 启动解码器
result = AMediaCodec_start(codec);
if (result != AMEDIA_OK) {
LOGE("AMediaCodec_start error: %d", result);
goto end;
}
// 解码视频帧
AMediaCodecBufferInfo bufferInfo;
int64_t presentationTimeUs;
size_t bufIdx;
while (!sawOutputEOS) {
if (!sawInputEOS) {
bufIdx = AMediaExtractor_getSampleTrackIndex(extractor);
if (bufIdx == trackIndex) {
result = AMediaExtractor_readSampleData(extractor, AMediaCodec_getInputBuffer(codec, bufIdx), 0);
if (result == AMEDIA_OK) {
presentationTimeUs = AMediaExtractor_getSampleTime(extractor);
AMediaCodec_queueInputBuffer(codec, bufIdx, 0, AMediaExtractor_getSampleSize(extractor), presentationTimeUs,
AMediaExtractor_getSampleFlags(extractor));
AMediaExtractor_advance(extractor);
} else if (result == AMEDIA_ERROR_END_OF_STREAM) {
sawInputEOS = true;
AMediaCodec_queueInputBuffer(codec, bufIdx, 0, 0, 0, AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM);
} else {
LOGE("AMediaExtractor_readSampleData error: %d", result);
goto end;
}
}
}
result = AMediaCodec_dequeueOutputBuffer(codec, &bufferInfo, 5000);
if (result == AMEDIA_OK) {
if (bufferInfo.flags & AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM) {
sawOutputEOS = true;
}
AMediaCodec_releaseOutputBuffer(codec, result, true);
} else if (result == AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED) {
AMediaFormat *newFormat = nullptr;
newFormat = AMediaCodec_getOutputFormat(codec);
AMediaFormat_getInt32(newFormat, AMEDIAFORMAT_KEY_WIDTH, &width);
AMediaFormat_getInt32(newFormat, AMEDIAFORMAT_KEY_HEIGHT, &height);
LOGI("Video output format changed to %dx%d", width, height);
AMediaFormat_delete(newFormat);
} else if (result == AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED) {
LOGI("AMediaCodec_dequeueOutputBuffer returned AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED");
} else {
LOGE("AMediaCodec_dequeueOutputBuffer error: %d", result);
goto end;
}
}
end:
if (codec) {
AMediaCodec_stop(codec);
AMediaCodec_delete(codec);
}
if (extractor) {
AMediaExtractor_delete(extractor);
}
env->ReleaseStringUTFChars(filePath, path);
}
```
在此示例代码中,我们使用 `AMediaExtractor` 获取视频文件中的视频轨道,并使用 `AMediaCodec` 进行解码。注意,此代码仅支持解码 H.264 编码视频。
阅读全文