我正在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) 我想使用 NDK 和 opengl 在后台(无 UI)中分析视频。我想解码视频并在纹理(内存)上渲染。我们怎么做?
我尝试使用 AMediaCodec 直接在纹理上渲染。但问题是它需要 ANativeWindow(在 AMediaCodec_configure 中),我无法从 opengl 纹理(使用 glGenTextures 创建)创建它。任何人都可以请建议吗?
我正在尝试在设备之间流式传输视频。我想尽可能支持旧设备。所以我从MediaRecorderGingerbread (API 10) 的课程开始,但它有问题。所以现在,我要转向 Jelly Bean (API 16) 和MediaCodec.
我正在向 Camera 中的编解码器提供数据PreviewCallback。我必须使用相同的分辨率进行预览和编解码器。但是在我们的一些测试设备上,预览分辨率和编解码器及其分辨率之间没有交集。
那么,如何在这些设备上捕捉视频呢?我知道有 createInputSurfacein MediaCodec,但它需要 API 18,我将不得不削减超过 35%的设备,这是不可接受的。
那么如何解决呢?
寻找最佳分辨率的代码:
CamcorderProfile bestProfile() {
final int[] profiles;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
profiles = new int[]{CamcorderProfile.QUALITY_HIGH, CamcorderProfile.QUALITY_2160P, CamcorderProfile.QUALITY_1080P, CamcorderProfile.QUALITY_720P, CamcorderProfile.QUALITY_480P, CamcorderProfile.QUALITY_CIF, CamcorderProfile.QUALITY_QCIF, CamcorderProfile.QUALITY_LOW};
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
profiles = new int[]{CamcorderProfile.QUALITY_HIGH, CamcorderProfile.QUALITY_1080P, CamcorderProfile.QUALITY_720P, CamcorderProfile.QUALITY_480P, CamcorderProfile.QUALITY_CIF, CamcorderProfile.QUALITY_QCIF, CamcorderProfile.QUALITY_LOW};
} else {
profiles = new int[]{CamcorderProfile.QUALITY_HIGH, CamcorderProfile.QUALITY_LOW};
}
for (final …Run Code Online (Sandbox Code Playgroud) 我正在尝试从一系列位图创建电影。我想以 API 19 为目标,但也可以利用 API 21(如果它在设备上可用)。
我一直在阅读 bigflake CTS 测试,尤其是这里的EncodeAndMux 和 EncodeDecodeTest
我想使用 MediaCodec 和 MediaMuxer 类,而不是 FFMpeg 或 Jcodec 等。
如果您能指出我哪里出错以及如何解决,我将不胜感激。我是 Android 新手,为此苦苦挣扎了好几天!我正在三星 Galaxy Note 3 上进行测试
更新:我能够访问 EOS,但在尝试释放编码器时出现编解码器错误。
这是更新后的代码:
public void createMovie(View view) {
Log.v(TAG,"CREATING MOVIE");
//1. Prepare the encoder and the GPUImageView
try {
prepareEncoder();
presentationTime = 0;
int j = 0;
for (int i = firstImageIndex; i <= lastImageIndex; i++) {
Log.v(TAG, "inLoop: " + i);
//1
durationInNanosec = (long) ((float) durations.get(j) * 100000); …Run Code Online (Sandbox Code Playgroud) 最近我在 Android 5.0.2 (API 21) 上遇到了一个奇怪的问题。我的应用程序使用 SurfaceTexture 来显示视频。播放机制主要基于google/grafika 的 CameraCaptureAvtivity,但视频源是解码 .mp4 电影文件而不是相机。该应用程序运行良好,直到我在带有 Android 5.0.2 的 Galaxy S6 上运行它(在那之前我成功使用了 4.4.2 和 4.4.4 的设备)。问题是,每次我尝试从 SurfaceTexture 接收时间戳时getTimestamp(),该方法都会返回 0,但播放没问题。在时间戳正确之前我提到的其他设备上。
有人可以告诉我这是否可能是Android错误?有什么办法可以解决吗?
我使用的解码音频MediaExtractor,MediaCodec和AudioTrack。我配置AudioTrack使用MediaFormat由归国MediaCodec.getOutputFormat()接收后MediaCodec.INFO_OUTPUT_FORMAT_CHANGED从MediaCodec。在某些设备上,这会导致音频加速,而MediaFormat返回的则MediaExtractor正常工作。(在其他设备上,情况正好相反。)
以下是一些细节:
MediaFormat,因为我无法访问这些设备,但我假设它返回单声道的立体声,或 22050 Hz 的 44100 Hz,而不实际重新采样文件。任何帮助,将不胜感激。谢谢!
我目前有两个单独的媒体提取器和编解码器,用于将每个单独的样本分解为ByteBuffers。然后我将每个样本存储到两个short数组中。然后我调用我的混合函数,它将两个样本合并为一个short[],如果我short[]用AudioTrack它来播放,结果会很好,两种声音都可以根据需要同时播放。
但是,我真正想做的是使用MediaMuxer将我的新short[]文件转换回 mp4 音频文件并将其存储到设备以供以后播放。有人可以帮我弄清楚我做错了什么吗?
这是我拥有的一些代码......正如你所看到的,我注释掉了AudioTrack,这就是我试图将short[]背面变成 的地方,ByteBuffer所以我可以使用媒体复用器来创建音频文件。这给我的结果是一个新的音频文件,它是存储在我设备上的正确名称和总长度……但是当我尝试播放它时……它在几分之一秒内从头跳到尾,实际上并没有播放和音频。
songOutPath = Environment.getExternalStorageDirectory()+"/My Folder/song.raw";
muxer = new MediaMuxer(songOutPath, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
mTrackIndex = muxer.addTrack(format);
muxer.start();
mMuxerStarted = true;
MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
final long timeoutUs = 5000;
boolean sawInputEOS = false;
boolean sawOutputEOS = false;
int noOutputCounter = 0;
MediaCodec.BufferInfo info2 = new MediaCodec.BufferInfo();
final long timeoutUs2 = 5000;
boolean sawInputEOS2 = false;
boolean sawOutputEOS2 …Run Code Online (Sandbox Code Playgroud) 我需要使用 GLSurfaceView 播放视频流。我试图获取输出并渲染它们。但是颜色不对。
我将输出缓冲区转储到文件并用 yuv 查看器打开它,颜色也不正确。所以我怀疑我使用错误的方式来获取输出缓冲区?这是代码:
mediaCodec = MediaCodec.createDecoderByType("video/avc");
MediaFormat mediaFormat = MediaFormat.createVideoFormat("video/avc", width, height);
mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, 500000);
mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, 15);
mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420PackedSemiPlanar);
mediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 5);
mediaCodec.configure(mediaFormat, null, null, 0);
mediaCodec.start();
ByteBuffer[] inputBuffers = mediaCodec.getInputBuffers();
int inputBufferIndex = mediaCodec.dequeueInputBuffer(-1);
if (inputBufferIndex >= 0) {
ByteBuffer inputBuffer = inputBuffers[inputBufferIndex];
inputBuffer.clear();
inputBuffer.put(avFrame.frmData);
mediaCodec.queueInputBuffer(inputBufferIndex, 0, avFrame.frmData.length, 0L, 0);
}
MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
ByteBuffer[] outputBuffers = mediaCodec.getOutputBuffers();
int outputBufferIndex = mediaCodec.dequeueOutputBuffer(bufferInfo, 0);
byte[] outData = new byte[bufferInfo.size];
while (outputBufferIndex >= 0) {
ByteBuffer outputBuffer = …Run Code Online (Sandbox Code Playgroud) 我使用 MediaMuxer 混合音频和无线电数据,数据来自两个编码器,流程正确,我得到输出并播放。但是 MediaMuxer 在 writeSampleData 时可能会因为错误而失败:
E/MPEG4Writer: timestampUs 21932611 < lastTimestampUs 22055361 for Video track
10-14 14:23:41.580 20089-20230/org.cocos2dx.simplegame E/AndroidRuntime: FATAL EXCEPTION: MediaMuxer
10-14 14:23:41.580 20089-20230/org.cocos2dx.simplegame E/AndroidRuntime: Process: org.cocos2dx.simplegame, PID: 20089
10-14 14:23:41.580 20089-20230/org.cocos2dx.simplegame E/AndroidRuntime: java.lang.IllegalStateException: writeSampleData returned an error
10-14 14:23:41.580 20089-20230/org.cocos2dx.simplegame E/AndroidRuntime: at android.media.MediaMuxer.nativeWriteSampleData(Native Method)
10-14 14:23:41.580 20089-20230/org.cocos2dx.simplegame E/AndroidRuntime: at android.media.MediaMuxer.writeSampleData(MediaMuxer.java:334)
10-14 14:23:41.580 20089-20230/org.cocos2dx.simplegame E/AndroidRuntime: at com.duapps.durecorder.muxer.DuMediaMuxer.handleMessage(DuMediaMuxer.java:53)
10-14 14:23:41.580 20089-20230/org.cocos2dx.simplegame E/AndroidRuntime: at android.os.Handler.dispatchMessage(Handler.java:102)
10-14 14:23:41.580 20089-20230/org.cocos2dx.simplegame E/AndroidRuntime: at android.os.Looper.loop(Looper.java:136)
10-14 14:23:41.580 20089-20230/org.cocos2dx.simplegame E/AndroidRuntime: at android.os.HandlerThread.run(HandlerThread.java:61)
Run Code Online (Sandbox Code Playgroud)
我看到MPEG4Writer,错误的根本原因是视频的时间戳,它让MediaMuxer运行到IllegalState。经过大量测试后,我知道视频和音频时间戳都可能出现错误,并且当我更改音频采样率时,重复率会发生变化。
当我只录制音频或广播时,错误不会再次发生。
有人可以给我一些建议吗?
android ×10
mediamuxer ×4
audio ×3
video ×2
android-ndk ×1
audiotrack ×1
grafika ×1
java ×1
mp3 ×1
mp4 ×1
yuv ×1