Android 拾取视频、解码、更改其fps、使用mediacodec编码和保存

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

要从设备中拾取视频并对其进行解码,以更改其帧速率,然后对其进行编码并保存到设备。如何使用MediaCodec实现这一点?查阅了很多文档,但找不到方法。我有下面的解码代码。这对我有什么好处吗。如果是,如何使用该解码数据将其与更改的fps一起保存

 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上有几个像这样的广泛的问题,我已经看到了完整的解决方案。所以请不要太麻烦。。。。。。。。