java - android - 设置 mediacodec 的呈现时间

标签 java android encode android-mediacodec mediamuxer

我使用下面的代码将原始数据编码为 h264 以创建视频,它的编码非常好,但视频播放速度太快。看来演示时间有问题。当记录开始时,我设置“tstart”的值,并为每一帧计算当前时间与 tstart 的差异,并将其传递给 queueinputbuffer,但没有任何改变。哪一部分有问题?我知道在 android 4.3 中我可以将表面传递给 mediacodec 但我想支持 android 4.1。提前致谢。

 public void onPreviewFrame(final byte[] bytes, Camera camera) {
                    if (recording == true) {
                        long time = System.nanoTime();
                        time -= tstart;
                        if(mThread.isAlive()&&recording == true) {
                            encode(bytes, time );

                        }

                    }
 }

private synchronized void encode(byte[] dataInput,long time)
{
    byte[] data=new byte[dataInput.length];
    NV21toYUV420Planar(dataInput,data,640,480);

    inputBuffers = mMediaCodec.getInputBuffers();// here changes
    outputBuffers = mMediaCodec.getOutputBuffers();

    int inputBufferIndex = mMediaCodec.dequeueInputBuffer(-1);

    if (inputBufferIndex >= 0) {
        ByteBuffer inputBuffer = inputBuffers[inputBufferIndex];
        inputBuffer.clear();
        inputBuffer.put(data);
        time/=1000;
        mMediaCodec.queueInputBuffer(inputBufferIndex, 0, data.length, time, 0);

    } else {
        return;
    }

    MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
    int outputBufferIndex = mMediaCodec.dequeueOutputBuffer(bufferInfo, 0);
    Log.i("tag", "outputBufferIndex-->" + outputBufferIndex);
    do {
        if (outputBufferIndex >= 0) {
            ByteBuffer outBuffer = outputBuffers[outputBufferIndex];
            byte[] outData = new byte[bufferInfo.size];
            outBuffer.get(outData);
            try {
                if (bufferInfo.offset != 0) {
                    fos.write(outData, bufferInfo.offset, outData.length
                            - bufferInfo.offset);
                } else {
                    fos.write(outData, 0, outData.length);
                }
                fos.flush();
                Log.i("camera", "out data -- > " + outData.length);
                mMediaCodec.releaseOutputBuffer(outputBufferIndex, false);
                outputBufferIndex = mMediaCodec.dequeueOutputBuffer(bufferInfo,
                        0);
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else if (outputBufferIndex == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
            outputBuffers = mMediaCodec.getOutputBuffers();
        } else if (outputBufferIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
            MediaFormat format = mMediaCodec.getOutputFormat();
        }
    } while (outputBufferIndex >= 0);
}

最佳答案

您的问题是您没有将输出帧写入实际存储任何时间戳的容器中。您正在编写一个纯 H264 文件,其中仅包含原始编码帧,没有索引,没有时间戳,没有音频,没有其他任何东西。

为了获得文件的正确时间戳,您需要使用 MediaMuxer(出现在 4.3 中)或类似的第三方库(例如 libavformat 或类似的)将编码数据包写入文件。输出数据包的时间戳在 bufferInfo.presentationTime 中,在 if (outputBufferIndex >= 0) { 子句中,你根本不用它——你是基本上丢弃了时间戳。

关于java - android - 设置 mediacodec 的呈现时间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36114808/

相关文章:

objective-c - 如何在 `NSCoder` 中编码 UIImage

java - 以下代码中的同步有什么问题

java - GWT - 您是否忘记继承所需的模块?

java - 获得除法后的小数值

python编码十六进制用00填充每个字符

powershell - 用 UTF-8 编码一个字符串

java - 查找数组中连续的重复整数

java - 检索插入顺序中的 LinkedHashSet 元素并将它们保存到局部变量中

java - 将文件复制到 Assets 文件夹

java - 如何在按钮中容纳长文本?