这是一个很长的问题,但我必须解释我正在经历的问题才能正确地解决问题.希望我能找到像@fadden或@mstorsjo这样的人来看看这个问题.
有关此问题的最新更新,请参阅编辑3.
我目前正在快速精确地寻求使用MediaCodec.我目前要逐帧跳过的是,我首先得到总帧数:
mediaInfo.totalFrames = videoTrack.getSamples().size();
Run Code Online (Sandbox Code Playgroud)
然后我得到视频文件的长度:
mediaInfo.durationUs = videoTrack.getDuration() * 1000 *1000 / timeScale;
//then calling:
public long getDuration() {
if (mMediaInfo != null) {
return (int) mMediaInfo.durationUs / 1000; // to millisecond
}
return -1;
}
Run Code Online (Sandbox Code Playgroud)
现在,当我想要获得下一帧时,我会调用以下内容:
mNextFrame.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
int frames = Integer.parseInt(String.valueOf(getTotalFrames));
int intervals = Integer.parseInt(String.valueOf(mPlayer.getDuration() / frames));
if (mPlayer.isPlaying()) {
mPlayer.pause();
mPlayer.seekTo(mPlayer.getCurrentPosition() + intervals);
} else {
mPlayer.seekTo(mPlayer.getCurrentPosition() + intervals);
}
}
}); …Run Code Online (Sandbox Code Playgroud) 有没有办法使用标准Android API 获取MPEG-4视频文件的个人资料代码?
示例配置文件的代码如下:baseline,main,high等.
我不想ffmpeg在Android应用程序中包含二进制文件以获取此信息.
我在MediaCodecInfo.CodecProfileLevel类中找到了配置文件列表的引用.任何人都可以确认这是否是我应该使用的那个?
以下是从MX Player应用程序中
获取的视频信息的示例屏幕截图
ffmpeg二进制文件,所以我可以肯定地说他们使用它来提取profile-code. android mpeg-4 android-mediaplayer mediaextractor android-mediacodec
我正在尝试使用MediaCodec在onImageAvailable回调中记录ImageReader中的原始帧,但无法编写正常工作的代码.大多数示例都使用Camera 1 API或MediaRecorder.我的目标是捕获单个帧处理它并从中创建一个mp4
原始的YUV帧
@Override
public void onImageAvailable(ImageReader reader) {
Image i = reader.acquireLatestImage();
processImage(i);
i.close();
Log.d("hehe", "onImageAvailable");
}
};
Run Code Online (Sandbox Code Playgroud)
MediaCodec
MediaCodec codec = MediaCodec.createByCodecName(name);
MediaFormat mOutputFormat; // member variable
codec.setCallback(new MediaCodec.Callback() {
@Override
void onInputBufferAvailable(MediaCodec mc, int inputBufferId) {
ByteBuffer inputBuffer = codec.getInputBuffer(inputBufferId);
// fill inputBuffer with valid data
…
codec.queueInputBuffer(inputBufferId, …);
}
@Override
void onOutputBufferAvailable(MediaCodec mc, int outputBufferId, …) {
ByteBuffer outputBuffer = codec.getOutputBuffer(outputBufferId);
MediaFormat bufferFormat = codec.getOutputFormat(outputBufferId); // option A
// bufferFormat is equivalent to mOutputFormat
// …Run Code Online (Sandbox Code Playgroud) 这是我的第一篇文章,所以请耐心等待。
我正在尝试将原始 h264 视频播放到 Android 应用程序中的 Surface 对象上。我在 HTC 上使用 android 5.0.1。在阅读了 android 文档后,我发现我需要使用 MediaCodec 对象来解码原始字节,然后将它们释放到 Surface。我已经倾注了大量其他问题和文档,但还没有找到我看似非常简单的问题的答案。这是我的代码片段:
@Override
public void surfaceCreated(SurfaceHolder surfHolder) {
try {
String codecType = "video/avc";
MediaFormat mf = MediaFormat.createVideoFormat(codecType, 45 ,45);
mc = MediaCodec.createByCodecName(codecType);
mc.configure(mf, surfHolder.getSurface(), null, 0);
mc.setCallback(vcb);
mc.start();
}
catch (Exception e) {
e.printStackTrace();
}
}
Run Code Online (Sandbox Code Playgroud)
但是,当它尝试按名称创建编解码器时遇到了问题,并且出现此错误:
08-26 18:09:02.054 9132-9132/com.james.firstclient I/InputMethodManager? [startInputInner] EditorInfo { packageName=com.james.firstclient, inputType=0x20001, imeOptions=0x48000005, privateImeOptions=null }, windowGainingFocus=android.view.ViewRootImpl$W@37cf53de, mServedView=android.widget.EditText{2a8889bf VFED..CL .F....I. 48,177-1032,290 #7f080001 app:id/hostText}, mServedInputConnectionWrapper=android.view.inputmethod.InputMethodManager$ControlledInputConnectionWrapper@3ed5088c
08-26 18:09:03.964 9132-9292/com.james.firstclient D/libc? [NET] android_getaddrinfofornet+,hn 12(0x3139322e313638),sn(),hints(known),family …Run Code Online (Sandbox Code Playgroud) 以下代码偶尔会生成 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) android ×10
encoding ×2
h.264 ×2
mediacodec ×2
mediamuxer ×2
audio ×1
bitrate ×1
mpeg-4 ×1
vulkan ×1