首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >是否有可能/如何将MediaCodec解码帧直接送至MediaCodec编码器?

是否有可能/如何将MediaCodec解码帧直接送至MediaCodec编码器?
EN

Stack Overflow用户
提问于 2015-04-21 13:16:30
回答 1查看 2K关注 0票数 0

我的目标是从几个视频文件中拼接视频片段。片段由任意的开始时间和结束时间定义。最初,我想使用像mp4parser这样的库来实现它,但是它只能在同步(IFRAME)点上剪切流,而我需要更高的精度。

我的场景是从文件-> Decode ->编码-> Mux中提取编码流,将结果提取到mp4文件中。目前,一般编码工作,但结果视频是白噪音。在Nexus-S和Galaxy-S3上测试。我的代码是几个示例的组合:

  • 基于MoviePlayer.java读取先前记录的文件
  • 解码-编码: DecodeEditEncodeTest.java
  • 进入mp4的Mux视频流--这是另一个不相关的例子

我想简化示例,因为我不需要在中间处理框架。我试着把缓冲器从解码器输出输入到编码器输入,而没有Surface在中间。整个过程工作的意义上,代码运行到完成,并导致可播放的视频文件。但是,文件的内容是白噪声。

这是一段代码片段,它将帧从解码器传送到编码器。有什么不对,怎样才能让它发挥作用?

代码语言:javascript
复制
...
} else { // decoderStatus >= 0
    if (VERBOSE) Log.d(TAG, "surface decoder given buffer "
                            + decoderStatus + " (size=" + info.size + ")");
    // The ByteBuffers are null references, but we still get a nonzero
    // size for the decoded data.
    boolean doRender = (info.size != 0);
    // As soon as we call releaseOutputBuffer, the buffer will be forwarded
    // to SurfaceTexture to convert to a texture.  The API doesn't
    // guarantee that the texture will be available before the call
    // returns, so we need to wait for the onFrameAvailable callback to
    // fire.  If we don't wait, we risk rendering from the previous frame.
    //   decoder.releaseOutputBuffer(decoderStatus, doRender);
    if (doRender) {
    // This waits for the image and renders it after it arrives.
//                  if (VERBOSE) Log.d(TAG, "awaiting frame");
//                          outputSurface.awaitNewImage();
//                          outputSurface.drawImage();
//                          // Send it to the encoder.
//                              inputSurface.setPresentationTime(info.presentationTimeUs * 1000);
//                          if (VERBOSE) Log.d(TAG, "swapBuffers");
//                          inputSurface.swapBuffers();

            encoderStatus = encoder.dequeueInputBuffer(-1);

            if (encoderStatus >= 0) {
                                encoderInputBuffers[encoderStatus].clear();

                                decoderOutputBuffers[decoderStatus].position(info.offset);
                                decoderOutputBuffers[decoderStatus].limit(info.offset + info.size);

                                encoderInputBuffers[encoderStatus].put(decoderOutputBuffers[decoderStatus]);
                                encoder.queueInputBuffer(encoderStatus, 0, info.size, info.presentationTimeUs*1000, 0);
                }
            }

                        decoder.releaseOutputBuffer(decoderStatus, false);
...
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-04-21 15:44:54

使用Surface比使用ByteBuffer要好得多。它更快,也更便携。表面是缓冲区的队列,而不仅仅是像素数据的帧缓冲区;解码的视频帧是通过句柄传递的。如果您使用ByteBuffers,视频数据必须复制几次,这将减慢您的速度。

创建MediaCodec编码器,获取输入面,并将其作为输出面传递给解码器。

如果您需要使用API 16/17,则需要使用ByteBuffers。如果你搜索周围,你可以找到反工程转换器的古怪高通格式,但请记住,没有CTS测试,直到API 18,所以没有任何保证。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29773326

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档