以下代码偶尔会生成 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) 我写了一个演示来使用 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 应用程序,该应用程序使用 MediaCodec 使用 Surface 方法对 H.264 视频进行编码。我的目标是 Android 5.0,并且我遵循了 bigflake.com 上的所有示例和示例(我两年前开始研究这个项目,所以我经历了所有的问题和其他问题)。
在 Nexus 6(它使用 Qualcomm 硬件编码器来执行此操作)上一切正常,并且我能够以多种输出(来自 MP4 本地文件,高达 http 流)。但是,当我尝试在使用 Mediatek 芯片组的 Sony Android TV(运行 Android 5.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)有时,尝试将其配置为以 360 x 640 像素分辨率进行编码将成功使编码器实际编码内容,但我会注意到的第一个问题是它只会创建一个关键帧,即第一个视频帧。在那之后,不再创建任何关键帧,只有 P 帧。当然,i-frame-interval 设置为一个不错的值,并且在其他设备上没有问题。不用说,这使得创建可查找的 MP4 文件或任何类型的流媒体解决方案成为不可能。
大多数情况下,在释放编码器后,logcat 将开始无休止地发送“等待输入帧被释放...”的垃圾邮件,这基本上需要重新启动设备,因为从那时起无论如何都不会起作用。
如果它没有在简单的 release() 之后大肆破坏,没问题 - 硬件编码器确保它不能被第二次创建,并且它回退到通用的 SOFTWARE avc google 编码器。hich ofcourse 基本上是一个模型编码器,它在尝试编码大于 160p 的任何视频时只会吐出一个错误......
所以,我的问题是:有没有希望让这个 …
我正在尝试将我的手机相机输出转换为 .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) 我正在尝试从 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) 我对使用 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) 我正在NV21对来自相机预览的帧进行编码。由于某种原因,在其他设备上运行良好的模式Sony Xperia Z1在Android 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 4.3 中提供的 和 来录制音频和视频AudioRecord。MediaCodec但是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) “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?(一个提供表面来接收解码器输出,一个重新缩放并渲染到编码器输入表面。)
我想使用 NDK 和 opengl 在后台(无 UI)中分析视频。我想解码视频并在纹理(内存)上渲染。我们怎么做?
我尝试使用 AMediaCodec 直接在纹理上渲染。但问题是它需要 ANativeWindow(在 AMediaCodec_configure 中),我无法从 opengl 纹理(使用 glGenTextures 创建)创建它。任何人都可以请建议吗?
android ×10
mediamuxer ×3
audio ×2
encoding ×2
video ×2
android-ndk ×1
bitrate ×1
h.264 ×1
vulkan ×1
yuv ×1