标签: android-mediacodec

如何防止MediaCodec.dequeueInputBuffer产生的java.lang.IllegalStateException

以下代码偶尔会生成 java.lang.IllegalStateException:

 int iInputBufIndex = _mcDecoder.dequeueInputBuffer(TIMEOUT_USEC);
Run Code Online (Sandbox Code Playgroud)

其中 _mcDecoder 是 MediaCodec 的一个实例。解码后的流是 H.264 视频。该代码在大多数情况下运行良好。有没有办法主动检查MediaCodec的状态来避免这个异常?

堆栈跟踪:

java.lang.IllegalStateException
    at android.media.MediaCodec.dequeueInputBuffer(Native Method)
at net.mydomain.android.MYNAMESPACE.MYCLASS.MyMethod0(Unknown Source)
at net.mydomain.android.MYNAMESPACE.MYCLASS.ProcessH264(Unknown Source)
at net.mydomain.android.MYNAMESPACE.MYCLASS.MyMethod1(Unknown Source)
at net.mydomain.android.MYNAMESPACE.MYCLASS.MyMethod2(Unknown Source)
at net.mydomain.android.MYNAMESPACE.MYCLASS.MyMethod3(Unknown Source)
at net.mydomain.android.MYNAMESPACE.MYCLASS.access$5(Unknown Source)
at net.mydomain.android.MYNAMESPACE.MYCLASS$1.run(Unknown Source)
at java.lang.Thread.run(Thread.java:841)
Run Code Online (Sandbox Code Playgroud)

android android-mediacodec

6
推荐指数
1
解决办法
6602
查看次数

使用MediaCodec和MediaMuxer录制视频,但码率和帧率不正确

我写了一个演示来使用 MediaCodec 和 MediaMuxer 录制视频。

我用我的demo录制了一段视频,用ffprobe查看视频,结果如下:

  Duration: 00:00:06.86, start: 0.000000, bitrate: 723 kb/s
Stream #0:0(eng): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 320x240, 619 kb/s, SAR 1:1 DAR 4:3, 30.02 fps, 30 tbr, 90k tbn, 180k tbc (default)
Metadata:
  creation_time   : 2015-06-05 13:19:24
  handler_name    : VideoHandle
Stream #0:1(eng): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, mono, fltp, 96 kb/s (default)
Metadata:
  creation_time   : 2015-06-05 13:19:24
  handler_name    : SoundHandle
Run Code Online (Sandbox Code Playgroud)

它包含视频和音频信息,我发现音频属性与我在源代码中设置的相同,但视频属性不正确。我的视频设置源码如下:

        MediaFormat format = MediaFormat.createVideoFormat(MIME_TYPE, mWidth, mHeight);
    format.setInteger(MediaFormat.KEY_COLOR_FORMAT,
            MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
    format.setInteger(MediaFormat.KEY_BIT_RATE, 384000); …
Run Code Online (Sandbox Code Playgroud)

android bitrate mediamuxer android-mediacodec

6
推荐指数
1
解决办法
6047
查看次数

具有 MediaCodec Surface 可靠性的 AVC 硬件编码器?

我正在开发一个 Android 应用程序,该应用程序使用 MediaCodec 使用 Surface 方法对 H.264 视频进行编码。我的目标是 Android 5.0,并且我遵循了 bigflake.com 上的所有示例和示例(我两年前开始研究这个项目,所以我经历了所有的问题和其他问题)。

在 Nexus 6(它使用 Qualcomm 硬件编码器来执行此操作)上一切正常,并且我能够以多种输出(来自 MP4 本地文件,高达 http 流)。但是,当我尝试在使用 Mediatek 芯片组的 Sony Android TV(运行 Android 5.1)上使用该应用程序时,即使从编码级别开始,一切都变得混乱起来。更具体:

  1. 基本上不可能让硬件编码器正常工作(即“OMX.MTK.VIDEO.ENCODER.AVC”)。使用最基本的设置(在 MediaCodec 级别成功),我将永远不会从中获取输出缓冲区,只有奇怪的、垃圾邮件、logcat 错误消息指出驱动程序在每次应编码帧时遇到错误,如下所示:

    01-20 05:04:30.575 1096-10598/? E/venc_omx_lib: VENC_DrvInit failed(-1)!
    01-20 05:04:30.575 1096-10598/? E/MtkOmxVenc: [ERROR] cannot set param
    01-20 05:04:30.575 1096-10598/? E/MtkOmxVenc: [ERROR] EncSettingH264Enc fail
    
    Run Code Online (Sandbox Code Playgroud)
  2. 有时,尝试将其配置为以 360 x 640 像素分辨率进行编码将成功使编码器实际编码内容,但我会注意到的第一个问题是它只会创建一个关键帧,即第一个视频帧。在那之后,不再创建任何关键帧,只有 P 帧。当然,i-frame-interval 设置为一个不错的值,并且在其他设备上没有问题。不用说,这使得创建可查找的 MP4 文件或任何类型的流媒体解决方案成为不可能。

  3. 大多数情况下,在释放编码器后,logcat 将开始无休止地发送“等待输入帧被释放...”的垃圾邮件,这基本上需要重新启动设备,因为从那时起无论如何都不会起作用。

  4. 如果它没有在简单的 release() 之后大肆破坏,没问题 - 硬件编码器确保它不能被第二次创建,并且它回退到通用的 SOFTWARE avc google 编码器。hich ofcourse 基本上是一个模型编码器,它在尝试编码大于 160p 的任何视频时只会吐出一个错误......

所以,我的问题是:有没有希望让这个 …

android android-mediacodec

6
推荐指数
0
解决办法
1539
查看次数

Android MediaCodec 将原始视频编码为 h264

我正在尝试将我的手机相机输出转换为 .h264 es 格式,但 MediaCodec 编码器在第一帧后停留在 TRY_AGAIN_LATER 输出缓冲区状态。相机预览设置为 NV21。

这是相机到编码器:

    mCamera.setPreviewCallback(new Camera.PreviewCallback() {
            private long timestamp=0;
            @Override
            public void onPreviewFrame(byte[] data, Camera camera) {
                byte[] buffer = new byte[data.length];
                encode(data);
            }
        });
Run Code Online (Sandbox Code Playgroud)

编码器初始化:

private void initCodec() {
        try {
            mBufferInfo = new MediaCodec.BufferInfo();
            mMediaCodec = MediaCodec.createEncoderByType("video/avc");
        } catch (IOException e) {
            e.printStackTrace();
        }
        MediaFormat mediaFormat = MediaFormat.createVideoFormat("video/avc",
                1920,
                1080);
        mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, 125000);
        mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, 30);
        mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT,
             MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar);
        mediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 5);
        mMediaCodec.configure(mediaFormat,
                null,
                null,
                MediaCodec.CONFIGURE_FLAG_ENCODE);
        mMediaCodec.start();
    }
Run Code Online (Sandbox Code Playgroud)

和编码器本身:

private synchronized void encode(byte[] data) { …
Run Code Online (Sandbox Code Playgroud)

encoding android h.264 android-mediacodec

6
推荐指数
0
解决办法
4670
查看次数

Android MediaCodec dequeueInputBuffer 总是返回 -1

我正在尝试从 AudioRecord 对象中获取原始数据,并使用 MediaMuxer 和 MediaCodec 将其保存在文件中。

我启动编解码器,启动多路复用器,将数据加载到输入缓冲区中,但没有这样的运气。

从调试调查中,我发现问题发生在对dequeueInputBuffer(). 看起来前几块数据成功了,但最终dequeueInputBuffer()只是-1不断返回。

有什么明显的东西我失踪了吗?这似乎是我正在填满输入缓冲区,但编解码器永远不会释放它们。

相关代码片段:

int numChunks = input.length / CHUNKSIZE;
mAudioEncoder.start();
    for (int chunk = 0; chunk <= numChunks; chunk++) {
        byte[] passMe = new byte[CHUNKSIZE];
        int inputBufferIndex = -1;
        Log.d("offerAudioEncoder","printing chunk #" + chunk + "of " + numChunks);
        //Copy the data into the chunk array
        if (chunk < input.length / CHUNKSIZE)
            for (int i = 0; i < CHUNKSIZE; i++)
                passMe[i] = input[chunk * …
Run Code Online (Sandbox Code Playgroud)

audio encoding android mediamuxer android-mediacodec

6
推荐指数
1
解决办法
1758
查看次数

如何将 Android MediaCodec Surface 连接到 Vulkan

我对使用 Android MediaCodec 进行解码并将 YUV 通过 Surface 馈送到 OpenGL 纹理有很好的理解。我想用 Vulkan 做类似的事情。但是我没有成功找到任何文档或示例代码。

我的问题是:我将如何连接以下管道?

MediaCodec Video Decoder ? Surface ? texture ? Vulkan
Run Code Online (Sandbox Code Playgroud)

细节

OpenGL 比较

为了进行比较,在 OpenGL 的情况下,Android Surface 的构造和使用方式如下

 textureId = glGenTextures( &textureId )
 surface = new Surface( new SurfaceTexture( textureId ) )
 mediaCodec.configure( surface )
Run Code Online (Sandbox Code Playgroud)

android vulkan android-mediacodec

6
推荐指数
1
解决办法
1835
查看次数

在 Xperia Z1 上使用 MediaCodec 编码相机预览帧时视频质量不一致

我正在NV21对来自相机预览的帧进行编码。由于某种原因,在其他设备上运行良好的模式Sony Xperia Z1Android 4.3. 它发送回质量不正确(低)的编码帧。

MediaCodec的格式是COLOR_FormatYUV420SemiPlanar(NV12我通过交换 U 和 V 分量NV21来转换NV12)。发送回给我的输出缓冲区的大小非常小,与我使用的分辨率 ( ) 和比特率 ( )MediaCodec不对应。最初的几帧质量很好,但随后质量显着下降:1280x7201000000

int encoderStatus = mMediaCodec.dequeueOutputBuffer(mBufferInfo, TIMEOUT_USEC);
// a few encoderStatus checks skipped
ByteBuffer encodedData = outputBuffers[encoderStatus];
Log.i(Constants.TAG, "Buffer size " + mBufferInfo.size);
Run Code Online (Sandbox Code Playgroud)

Xperia Z1 上的日志如下:

Buffer size 26
Buffer size 52172
Buffer size 23650
Buffer size 14394
Buffer size 3591
Buffer size 1849
Buffer size 3908

... …
Run Code Online (Sandbox Code Playgroud)

android android-mediacodec

5
推荐指数
1
解决办法
3716
查看次数

在 Android 上使用 MediaMuxer 录制音频和视频

我正在尝试使用 Android 4.3 中提供的 和 来录制音频和视频AudioRecordMediaCodec但是MediaMuxer,有时音频编码器线程会停止并且不再进行编码。结果是,mp4 文件损坏,因为复用器未接收任何编码的音频帧。在我的三星 Galaxy Note 3 上,它可以正常工作 99%,但在我的索尼 Xperia Z1 上,编码线程总是卡住。我真的不知道是什么原因,也许有人可以帮助我优化我的代码:

录音机.java

package com.cmdd.horicam;

import java.nio.ByteBuffer;

import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaCodec;
import android.media.MediaCodecInfo;
import android.media.MediaFormat;
import android.media.MediaRecorder;
import android.os.Looper;
import android.util.Log;

public class AudioRecorder implements Runnable {
    public static final String TAG = "AudioRecorder";
    public static final boolean VERBOSE = false;

    public MovieMuxerAudioHandler mAudioHandler;

     // audio format settings
    public static final String MIME_TYPE_AUDIO = "audio/mp4a-latm";
    public static final int …
Run Code Online (Sandbox Code Playgroud)

audio video android mediamuxer android-mediacodec

5
推荐指数
1
解决办法
8129
查看次数

为什么MediaCodec的解码器不输出统一的YUV格式(如YUV420P)?

“MediaCodec 解码器可以使用上述格式之一或专有格式在 ByteBuffers 中生成数据。例如,基于 Qualcomm SoC 的设备通常使用 OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar32m (#2141391876 / 0x7FA30C04)。”

这使得处理输出缓冲区变得困难甚至无法处理。为什么不使用统一的YUV格式?为什么有这么多YUV颜色格式?

@fadden,我发现可以解码到 Surface 并获取 RGB 缓冲区(如http://bigflake.com/mediacodec/ExtractMpegFramesTest.java.txt),我可以将 RGB 缓冲区传输为 YUV 格式然后对其进行编码吗?

而且,fadden,我尝试使用 API 18+ 并遇到了一些问题。我参考了 ContinuousCaptureActivity 和 ExtractMpegFramesTest 代码。在ContinuousCaptureActivity中:

    mEglCore = new EglCore(null, EglCore.FLAG_RECORDABLE);
    mDisplaySurface = new WindowSurface(mEglCore, holder.getSurface(), false);
    mDisplaySurface.makeCurrent();

    mFullFrameBlit = new FullFrameRect(
            new Texture2dProgram(Texture2dProgram.ProgramType.TEXTURE_EXT));
    mTextureId = mFullFrameBlit.createTextureObject();
    mCameraTexture = new SurfaceTexture(mTextureId);
    mCameraTexture.setOnFrameAvailableListener(this);
    mCamera.setPreviewTexture(mCameraTexture);
Run Code Online (Sandbox Code Playgroud)

FullFrameRect 创建一个 SurfaceTexture 并将其设置为相机预览纹理。

但是在 ExtractMpegFramesTest 中,使用了 CodecOutputSurface 并且它还创建了一个纹理。我怎样才能一起使用 CodecOutputSurface 和 FullFrameRect?(一个提供表面来接收解码器输出,一个重新缩放并渲染到编码器输入表面。)

android yuv android-mediacodec

5
推荐指数
1
解决办法
3090
查看次数

如何使用 NDK 创建 ANativeWindow?

我想使用 NDK 和 opengl 在后台(无 UI)中分析视频。我想解码视频并在纹理(内存)上渲染。我们怎么做?

我尝试使用 AMediaCodec 直接在纹理上渲染。但问题是它需要 ANativeWindow(在 AMediaCodec_configure 中),我无法从 opengl 纹理(使用 glGenTextures 创建)创建它。任何人都可以请建议吗?

video android android-ndk android-mediacodec

5
推荐指数
0
解决办法
1612
查看次数