如何使用Android MediaCodec编码相机数据(YUV420sp)

2024-01-28

感谢您的关注! 我想使用Android MediaCodec API对从Camera获取的视频帧进行编码, 不幸的是,我没有成功做到这一点!我对 MediaCodec API 还不太熟悉。 以下是我的代码,我需要你的帮助来弄清楚我应该做什么。

1、相机设置:

Parameters parameters = mCamera.getParameters();
parameters.setPreviewFormat(ImageFormat.NV21);
parameters.setPreviewSize(320, 240);
mCamera.setParameters(parameters);

2、设置编码器:

private void initCodec() {
    try {
        fos = new FileOutputStream(mVideoFile, false);
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    }
    mMediaCodec = MediaCodec.createEncoderByType("video/avc");
    MediaFormat mediaFormat = MediaFormat.createVideoFormat("video/avc",
            320,
            240);
    mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, 125000);
    mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, 15);
    mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT,
            MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar);
    mediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 5);
    mMediaCodec.configure(mediaFormat,
            null,
            null,
            MediaCodec.CONFIGURE_FLAG_ENCODE);
    mMediaCodec.start();
    inputBuffers = mMediaCodec.getInputBuffers();
    outputBuffers = mMediaCodec.getOutputBuffers();
}

private void encode(byte[] data) {
    int inputBufferIndex = mMediaCodec.dequeueInputBuffer(0);
    if (inputBufferIndex >= 0) {
        ByteBuffer inputBuffer = inputBuffers[inputBufferIndex];
        inputBuffer.clear();
        inputBuffer.put(data);
        mMediaCodec.queueInputBuffer(inputBufferIndex, 0, data.length, 0, 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];
            System.out.println("buffer info-->" + bufferInfo.offset + "--"
                    + bufferInfo.size + "--" + bufferInfo.flags + "--"
                    + bufferInfo.presentationTimeUs);
            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(TAG, "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);
}

我猜问题出现在编码器方法中,该方法将在相机预览回调中使用,例如

initCodec();

//mCamera.setPreviewCallback(new MyPreviewCallback());
mCamera.setPreviewCallback(new PreviewCallback() {
    @Override
    public void onPreviewFrame(byte[] data, Camera camera) {
        encode(data);
    }
});

我只是不知道如何使用 MediaCodec API 正确执行此操作。您能给我一些建议或相关链接吗?

谢谢你!


我已经解决了这个问题,如下:

private synchronized void encode(byte[] data)
{
    inputBuffers = mMediaCodec.getInputBuffers();// here changes
    outputBuffers = mMediaCodec.getOutputBuffers();

    int inputBufferIndex = mMediaCodec.dequeueInputBuffer(-1);
    Log.i(TAG, "inputBufferIndex-->" + inputBufferIndex);
    //......

接下来,您会发现您编码的视频颜色不正确,有关更多信息,请访问这里MediaCodec 和相机:色彩空间不匹配 https://stackoverflow.com/questions/13703596/mediacodec-and-camera-colorspaces-dont-match

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用Android MediaCodec编码相机数据(YUV420sp) 的相关文章

随机推荐

  • PHP 从视频中提取音频

    我需要一种从某些视频中提取音频的方法 用 PHP 我有来自 YouTube 的视频流 所以我真的很喜欢它 如果它是动态流 而不是我必须将其保存到临时目录并在那里处理它 尽管这是可以接受的 谢谢 Isaac Waller编辑 更具体地说 我有
  • 将动画翻译到 Android 中的正确位置

    我在我的应用程序中为图像创建了动画 图像从屏幕中间开始直到左上角 现在我需要确保图像放置在所有设备中的正确位置 左上角 目前 对于不同的设备 它被放置在左上角的不同位置 我该如何解决它 我的代码如下
  • 修改flexdashboard的shinyauthr

    我已经构建了一个使用运行时闪亮的交互式 Flexdashboard 我想创建一个用户身份验证登录模块 页面 我偶然发现保罗 坎贝尔 Paul Campbell 的闪亮作者包 https paul rbind io 2018 11 04 in
  • 对 Java 8 可选* 值的操作。

    Java 8 有许多可选类 例如OptionalDouble OptionalInt OptionalLong 有没有一种使用同类可选值的好方法 也就是说 我希望能够做到 OptionalDouble d1 OptionalDouble o
  • 列出有关 SQL Server 中所有数据库文件的信息

    是否可以列出 SQL Server 上所有数据库的文件 MDF LDF 信息 我想获得一个列表 显示哪个数据库正在使用本地磁盘上的哪些文件 我尝试过的 exec sp databases所有数据库 select from sys datab
  • 如何去除图像中的小颗粒背景噪声?

    我正在尝试从我拥有的图像中消除渐变背景噪音 我尝试了很多方法cv2没有成功 首先将图像转换为灰度 使其失去一些可能有助于找到轮廓的梯度 有人知道处理这种背景的方法吗 我什至尝试从角落取样并应用某种内核过滤器 消除梯度的一种方法是使用cv2
  • 如何导航到同级路线?

    假设我有这个路由器配置 export const EmployeeRoutes path sales component SalesComponent path contacts component ContactsComponent 并已
  • 开发 Eclipse RCP 应用程序

    这是我第一次使用 Eclipse 3 8 开发 RCP 应用程序 我的问题可能看起来很奇怪 但对我来说确实很困惑 我可以在哪里放置应用程序的代码 如果我为我的应用程序创建所需的类 我可以在哪里使用它们的对象 在里面Application j
  • 将一系列图像从 java 应用程序传输到 ffmpeg 子进程

    我正在寻找一种将一系列图像 jpeg 从java应用程序流式传输到FFMpeg STDIN管道的方法 FFMpeg 应该处理这些图像并创建一个视频文件作为输出 FFMpeg 作为 java 应用程序的子进程执行 使用以下命令 ffmpeg
  • 使用 PHP/MySQL 日期查询向 Google 可视化页面提交表单

    我使用从 PHP MySQL 提取的数据在谷歌可视化上创建饼图 该图表看起来不错 但我想添加一个日历 日期选择器 以使饼图动态化 我的日期范围选择器似乎正在工作 它从我的数据库中提取正确的数据 选择日期 提交查询后 它返回此字符串 over
  • 如何知道节点是 Virtual TreeView 中的根节点?

    我正在使用虚拟树视图 有没有可靠的方法来知道节点是否是根节点 我尝试使用 if not Assigned Node Parent then Output This is root else Output This is not root 但
  • 在表格布局中显示动态行的问题:Android

    我想以表格布局显示数据 数据数量是动态的 所以我需要在表中实现动态行 为此 我想在一行中显示 4 个 TextView Problem 目前 我能够在表中和四个 TextView 中显示数据 但我希望所有四个 EditText 之间有一些空
  • 在不使用排序功能的情况下按某个元素对嵌套列表进行排序。

    如果我有一个像这样的嵌套列表 L James 1 2 Alan 1 1 Henry 1 5 如何在不使用排序或排序函数的情况下根据每个子列表中的最后一个数字从最高到最低对它进行排序 Output final Henry 1 5 James
  • SAS 替换所有列中的字符

    我有一个 SAS 数据集 必须导出到 csv 文件 我有以下两个相互矛盾的要求 我必须使用分号作为 csv 文件中的分隔符 一些字符变量是从公式中手动输入的字符串 因此它们可能包含分号 我对上述问题的解决方案是转义分号或用逗号替换它 我怎样
  • OpenCV Mat 对象 - 获取数据长度

    在 OpenCV 中 我可以使用 C 中的 VideoCapture 捕获帧 但是 当我尝试从帧中获取数据并计算长度时 它只返回 0 下面是我的示例代码 VideoCapture cap 0 for Mat frame cap gt gt
  • Codeigniter:执行 $this->db->last_query();执行查询?

    查询执行是否发生在get where 以下 codeigniter 活动记录语句的子句 this gt db gt select q this gt db gt get where Contacts array id gt contact
  • 在 JavaScript 正则表达式中使用 {1}+ 所有格量词时出现正则表达式错误

    由于我同时学习 Javascript 和 Express js 因此我在发出 get 请求时尝试使用正则表达式 为了熟悉正则表达式 我使用了这个chart http docs oracle com javase tutorial essen
  • 如何使用信号更新另一个模型字段来更新模型字段?

    我正在尝试添加所有total值在Transaction模型并将它们放入Sale模型的第一个实例 pk 1 gross total场地 这是我的代码 模型 py class Sale models Model gross total mode
  • 为什么应用程序有时会在killProcess 上重新启动?

    通常 通过调用以下命令退出我的应用程序 android os Process killProcess android os Process myPid 表现良好 没有发生任何事故 但每隔一段时间 应用程序就会再次重新启动 退出后 相关日志片
  • 如何使用Android MediaCodec编码相机数据(YUV420sp)

    感谢您的关注 我想使用Android MediaCodec API对从Camera获取的视频帧进行编码 不幸的是 我没有成功做到这一点 我对 MediaCodec API 还不太熟悉 以下是我的代码 我需要你的帮助来弄清楚我应该做什么 1