在native层中,使用AMediaCodec 和 AMediaMuxer 编码生成MP4文件的demo
时间: 2024-03-17 08:42:37 浏览: 78
好的,我可以为您提供一个简单的使用AMediaCodec和AMediaMuxer编码生成MP4文件的示例代码。示例代码如下:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <media/NdkMediaCodec.h>
#include <media/NdkMediaFormat.h>
#include <media/NdkMediaMuxer.h>
#define MAX_SAMPLE_SIZE (1024 * 1024)
#define TIMEOUT_USEC 10000
int main(int argc, char **argv) {
const char *path = "/sdcard/output.mp4";
int fd = open(path, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
if (fd < 0) {
printf("open file failed\n");
return -1;
}
AMediaMuxer *muxer = AMediaMuxer_new(fd, AMEDIAMUXER_OUTPUT_FORMAT_MPEG_4);
if (!muxer) {
printf("create muxer failed\n");
return -1;
}
AMediaFormat *format = AMediaFormat_new();
AMediaFormat_setString(format, AMEDIAFORMAT_KEY_MIME, "video/avc");
AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_WIDTH, 1280);
AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_HEIGHT, 720);
AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_BIT_RATE, 2000000);
AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_FRAME_RATE, 30);
AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_I_FRAME_INTERVAL, 1);
AMediaCodec *encoder = AMediaCodec_createEncoderByType("video/avc");
if (!encoder) {
printf("create encoder failed\n");
return -1;
}
AMediaCodec_configure(encoder, format, NULL, NULL, AMEDIACODEC_CONFIGURE_FLAG_ENCODE);
AMediaCodec_start(encoder);
uint8_t *input_data = NULL;
AMediaCodecBufferInfo input_info;
uint8_t *output_data = NULL;
AMediaCodecBufferInfo output_info;
bool input_done = false;
bool output_done = false;
int64_t time_us = 0;
while (!output_done) {
if (!input_done) {
int input_index = AMediaCodec_dequeueInputBuffer(encoder, TIMEOUT_USEC);
if (input_index >= 0) {
input_data = AMediaCodec_getInputBuffer(encoder, input_index, NULL);
ssize_t sample_size = read(STDIN_FILENO, input_data, MAX_SAMPLE_SIZE);
if (sample_size < 0) {
printf("read data failed\n");
break;
}
input_done = (sample_size == 0);
if (input_done) {
AMediaCodec_queueInputBuffer(encoder, input_index, 0, 0, time_us, AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM);
} else {
AMediaCodec_queueInputBuffer(encoder, input_index, 0, sample_size, time_us, 0);
}
time_us += 1000000 / 30;
}
}
ssize_t output_index = AMediaCodec_dequeueOutputBuffer(encoder, &output_info, TIMEOUT_USEC);
if (output_index == AMEDIACODEC_INFO_TRY_AGAIN_LATER) {
continue;
} else if (output_index == AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED) {
AMediaFormat *output_format = NULL;
output_format = AMediaCodec_getOutputFormat(encoder);
AMediaMuxer_addTrack(muxer, output_format);
AMediaMuxer_start(muxer);
} else if (output_index == AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED) {
// do nothing
} else if (output_index < 0) {
printf("unexpected result from encoder\n");
break;
} else {
output_data = AMediaCodec_getOutputBuffer(encoder, output_index, NULL);
AMediaMuxer_writeSampleData(muxer, 0, output_data, &output_info);
AMediaCodec_releaseOutputBuffer(encoder, output_index, false);
output_done = (output_info.flags & AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM) != 0;
}
}
AMediaCodec_stop(encoder);
AMediaCodec_delete(encoder);
AMediaFormat_delete(format);
AMediaMuxer_stop(muxer);
AMediaMuxer_delete(muxer);
close(fd);
return 0;
}
```
这个示例代码将从标准输入中读取h264裸流,并使用AMediaCodec和AMediaMuxer进行编码和封装成MP4文件。您可以将其编译成可执行文件并在Android设备上运行。注意,在运行前请确保您已经打开了摄像头权限并且已经有h264裸流数据输入到标准输入中。
阅读全文