Android 拾取视频、解码、更改其fps、使用mediacodec编码和保存
要从设备中拾取视频并对其进行解码,以更改其帧速率,然后对其进行编码并保存到设备。如何使用MediaCodec实现这一点?查阅了很多文档,但找不到方法。我有下面的解码代码。这对我有什么好处吗。如果是,如何使用该解码数据将其与更改的fps一起保存Android 拾取视频、解码、更改其fps、使用mediacodec编码和保存,android,video,encoding,decoding,android-mediacodec,Android,Video,Encoding,Decoding,Android Mediacodec,要从设备中拾取视频并对其进行解码,以更改其帧速率,然后对其进行编码并保存到设备。如何使用MediaCodec实现这一点?查阅了很多文档,但找不到方法。我有下面的解码代码。这对我有什么好处吗。如果是,如何使用该解码数据将其与更改的fps一起保存 MediaFormat mediaFormat = MediaFormat.createVideoFormat("video/avc", 1080, 720); mediaFormat.setInteger(MediaFormat
MediaFormat mediaFormat = MediaFormat.createVideoFormat("video/avc", 1080, 720);
mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, 2500000);
mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, 20);
try {
decoder = MediaCodec.createDecoderByType("video/avc");
} catch (IOException e) {
Log.d("Error", "Fail to create MediaCodec: " + e.toString());
}
///Commenting for testing...
/*
// Pass the decoded data to the surface to display
decoder.configure(mediaFormat, null, null, 0);
//decoder.configure(mediaFormat, null, null, 0);
decoder.start();
*/
///Commenting for testing...
// new BufferInfo();
ByteBuffer[] inputBuffers = decoder.getInputBuffers();
ByteBuffer[] outputBuffers = decoder.getOutputBuffers();
if (null == inputBuffers) {
Log.d("Error", "null == inputBuffers");
}
if (null == outputBuffers) {
Log.d("Error", "null == outbputBuffers 111");
}
FileInputStream file = null;
try {
file = new FileInputStream(data.getData().getPath().toString());
} catch (FileNotFoundException e) {
Log.d("Error", "open file error: " + e.toString());
return;
}
int read_size = -1;
int mCount = 0;
for (; ; ) {
byte[] h264 = null;
try {
byte[] length_bytes = new byte[4];
read_size = file.read(length_bytes);
if (read_size < 0) {
Log.d("Error", "read_size<0 pos1");
break;
}
int byteCount = bytesToInt(length_bytes, 0);
//Changed to .length
//int byteCount=length_bytes.length;
Log.d("Error", "byteCount: " + byteCount);
h264 = new byte[byteCount];
read_size = file.read(h264, 0, byteCount);
// Log.d("Error", "read_size: " + read_size);
if (read_size < 0) {
Log.d("Error", "read_size<0 pos2");
break;
}
// Log.d("Error", "pos: " + file.)
} catch (IOException e) {
Log.d("Error", "read_size 2: " + read_size);
Log.d("Error", "e.toStrinig(): " + e.toString());
break;
}
int inputBufferIndex = decoder.dequeueInputBuffer(-1);
if (inputBufferIndex >= 0) {
ByteBuffer inputBuffer = inputBuffers[inputBufferIndex];
inputBuffer.clear();
inputBuffer.put(h264);
// long sample_time = ;
decoder.queueInputBuffer(inputBufferIndex, 0, h264.length, mCount * 1000000 / 20, 0);
++mCount;
} else {
Log.d("Error", "dequeueInputBuffer error");
}
ByteBuffer outputBuffer = null;
MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
int outputBufferIndex = decoder.dequeueOutputBuffer(bufferInfo, 0);
while (outputBufferIndex >= 0) {
outputBuffer = outputBuffers[outputBufferIndex];
decoder.releaseOutputBuffer(outputBufferIndex, true);
outputBufferIndex = decoder.dequeueOutputBuffer(bufferInfo, 0);
}
// Pass the decoded data to the surface to display
decoder.configure(mediaFormat,mPreview.getHolder().getSurface() , null, 0);
//decoder.configure(mediaFormat, null, null, 0);
decoder.start();
if (outputBufferIndex >= 0) {
decoder.releaseOutputBuffer(outputBufferIndex, false);
} else if (outputBufferIndex == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
outputBuffers = decoder.getOutputBuffers();
Log.d("Error", "outputBufferIndex == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED");
} else if (outputBufferIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
// Subsequent data will conform to new format.
Log.d("Error", "outputBufferIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED");
}
try {
Thread.sleep(1000/20);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public int bytesToInt(byte[] src, int offset) {
int value;
value = (int) ((src[offset] & 0xFF)
| ((src[offset+1] & 0xFF)<<8)
| ((src[offset+2] & 0xFF)<<16)
| ((src[offset+3] & 0xFF)<<24));
return value;
}
MediaFormat=MediaFormat.createVideoFormat(“视频/avc”,1080720);
mediaFormat.setInteger(mediaFormat.KEY\u比特率,2500000);
mediaFormat.setInteger(mediaFormat.KEY\u FRAME\u RATE,20);
试一试{
解码器=MediaCodec.createDecoderByType(“视频/avc”);
}捕获(IOE异常){
Log.d(“错误”,“无法创建MediaCodec:+e.toString());
}
///测试评论。。。
/*
//将解码后的数据传递到曲面以进行显示
解码器。配置(mediaFormat,null,null,0);
//解码器。配置(mediaFormat,null,null,0);
decoder.start();
*/
///测试评论。。。
//新的BufferInfo();
ByteBuffer[]inputBuffers=解码器。getInputBuffers();
ByteBuffer[]outputBuffers=解码器。getOutputBuffers();
if(null==inputBuffers){
d(“错误”,“null==inputBuffers”);
}
if(null==输出缓冲区){
d(“错误”,“null==outbputBuffers 111”);
}
FileInputStream文件=null;
试一试{
file=newfileinputstream(data.getData().getPath().toString());
}catch(filenotfounde异常){
Log.d(“错误”,“打开文件错误:+e.toString());
回来
}
int read_size=-1;
int mCount=0;
对于(;;){
字节[]h264=null;
试一试{
字节[]长度_字节=新字节[4];
读取大小=file.read(长度为字节);
如果(读取大小<0){
Log.d(“Error”,“read_size您可以看一看,这是使用表面(解码器的输出表面->编码器的输入表面)进行解码和重新编码的一个很好的起点
请特别注意这个方法
private void editVideoData(VideoChunks inputData, MediaCodec decoder,
OutputSurface outputSurface, InputSurface inputSurface, MediaCodec encoder,
VideoChunks outputData)
您必须遵循的工作流程与以下类似:
- 提取视频曲目(MediaExtractor)
- 馈送解码器输入缓冲区
- 将解码的帧渲染到曲面
- 渲染时,编码器将获得帧(您也必须设置时间戳)
- 使用MediaMuxer将编码器帧与音频曲目进行多路复用
额外链接:一些示例
(非常有趣)解码、重采样、编码、保存。这至少是4个问题。如果每篇文章只有一个问题,堆栈溢出效果最好,否则志愿者给出对社区有价值的答案太多了。如果我们把这4个问题作为4个问题来问,我们会得到不同类型的答案。我正在寻找这4个问题的完整解决方案.Stackoverflow不是一个代码编写服务。它是一个帮助您编写代码的资源。这里没有人会为您提供完整的解决方案。如果您无法回答,请不要为我的问题操心。我只是在我的问题中包含了我需要的不同步骤,而不是问一个广泛的问题,例如,如何更改本地视频usin的FPS在stackoverflow上有几个像这样的广泛的问题,我已经看到了完整的解决方案。所以请不要太麻烦。。。。。。。。