INFO_OUTPUT_BUFFERS_CHANGED和INFO_FORMAT_CHANGED去呗
时间: 2023-08-01 20:10:55 浏览: 261
INFO_OUTPUT_BUFFERS_CHANGED和INFO_FORMAT_CHANGED都是常量,通常用于音频编解码器回调函数中,表示音频编解码器的状态发生了变化。
INFO_OUTPUT_BUFFERS_CHANGED表示输出缓冲区已经发生了变化,通常在输出缓冲区的大小或数量发生变化时触发,需要重新获取输出缓冲区的指针。
INFO_FORMAT_CHANGED表示音频格式已经发生了变化,通常在音频编解码器初始化时触发,需要重新配置音频编解码器的参数,如采样率、声道数等。
两者的区别在于触发事件的原因不同,INFO_OUTPUT_BUFFERS_CHANGED主要是处理输出缓冲区的变化,而INFO_FORMAT_CHANGED主要是处理编解码器参数的变化。在回调函数中,需要根据不同的事件类型做出相应的处理,以保证音频数据的正常处理和输出。
相关问题
INFO_OUTPUT_BUFFERS_CHANGED通过getOutputBuffers取出来的数据应该如何编码成MP4代码例子
下面是一个使用MediaCodec和MediaMuxer将H.264编码数据编码成MP4文件的代码示例:
```java
private MediaCodec mEncoder;
private MediaMuxer mMuxer;
private int mTrackIndex;
private boolean mMuxerStarted;
// 初始化编码器和复用器
private void initEncoder() throws IOException {
MediaFormat format = MediaFormat.createVideoFormat("video/avc", mWidth, mHeight);
format.setInteger(MediaFormat.KEY_BIT_RATE, mBitRate);
format.setInteger(MediaFormat.KEY_FRAME_RATE, mFrameRate);
format.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, mIFrameInterval);
mEncoder = MediaCodec.createEncoderByType("video/avc");
mEncoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
Surface surface = mEncoder.createInputSurface();
mEncoder.start();
mMuxer = new MediaMuxer(mOutputFile.getAbsolutePath(), MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
mTrackIndex = -1;
mMuxerStarted = false;
}
// 编码数据
private void encodeData() {
while (mEncoding) {
int index = mEncoder.dequeueOutputBuffer(mBufferInfo, TIMEOUT_US);
if (index == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
// 编解码器输出缓冲区状态已更改
continue;
}
if (index == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
// 编解码器输出格式已更改,添加轨道到复用器
MediaFormat format = mEncoder.getOutputFormat();
mTrackIndex = mMuxer.addTrack(format);
mMuxer.start();
mMuxerStarted = true;
continue;
}
if (index < 0) {
// 没有可用输出缓冲区
continue;
}
ByteBuffer outputBuffer = mEncoder.getOutputBuffer(index);
if (outputBuffer == null) {
mEncoder.releaseOutputBuffer(index, false);
continue;
}
if ((mBufferInfo.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0) {
// 编码器配置数据,忽略
mBufferInfo.size = 0;
}
if (mBufferInfo.size != 0) {
outputBuffer.position(mBufferInfo.offset);
outputBuffer.limit(mBufferInfo.offset + mBufferInfo.size);
if (mMuxerStarted) {
mMuxer.writeSampleData(mTrackIndex, outputBuffer, mBufferInfo);
}
}
mEncoder.releaseOutputBuffer(index, false);
if ((mBufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
break;
}
}
if (mMuxerStarted) {
mMuxer.stop();
mMuxer.release();
mMuxerStarted = false;
}
mEncoder.stop();
mEncoder.release();
}
```
在上面的代码中,initEncoder方法用于初始化编码器和复用器,encodeData方法用于编码数据。在encodeData方法中,我们先使用dequeueOutputBuffer方法获取输出缓冲区的索引。如果输出缓冲区的索引大于等于0,则使用getOutputBuffer方法获取输出缓冲区,并从中读取实际的编码数据。然后,将读取的数据写入到MP4文件中。如果返回的输出缓冲区索引大于等于0,使用releaseOutputBuffer方法释放输出缓冲区。最后,如果已经写入了编码数据,则使用MediaMuxer将数据写入到MP4文件中。
在native层中,使用AMediaCodec 和 AMediaMuxer 编码生成MP4文件的demo
好的,我可以为您提供一个简单的使用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裸流数据输入到标准输入中。
阅读全文