Articles of mediacodec

如何使用MediaCodec Android压缩mp4video?

在我的Android应用程序中,我想通过更改其分辨率,比特率来压缩mp4video。 我不想使用FFmpeg(因为我不想使用NDK),所以我决定使用MediaCodec API。 以下是我的逻辑步骤: 使用MediaExtractor提取video文件,然后解码数据。 使用我的新分辨率,比特率和编码数据创建新的编码器。 使用MediaMuxer创建新的mp4文件。 我的问题是:我不知道如何设置解码器输出和编码器输入之间的连接。 我可以将video解码为Surface或从曲面编码新video。 但我不明白如何连接它们。 我读了这些链接: Android MediaCodec: 使用新的MediaCodec库和Bigflake的示例减少mp4video大小 , Android上的video压缩 : https ://android.googlesource.com/platform/cts/+/jb-mr2-release/tests /tests/media/src/android/media/cts/DecodeEditEncodeTest.java 任何人都可以给我一个明确的解释我必须做什么吗?

如何将Camera预览传递给MediaCodec.createInputSurface()创建的Surface?

理想情况下,我想完成两个目标: 通过Surface将Camera预览数据传递给MediaCodec编码器。 我可以使用MediaCodec.createInputSurface()创建Surface但Camera.setPreviewDisplay()采用SurfaceHolder ,而不是Surface 。 除了将Camera预览数据传递给编码器之外,我还想在屏幕上显示预览(这样用户实际上可以看到他们编码的内容)。 如果没有涉及编码器,那么我将使用SurfaceView ,但这似乎不适用于这种情况,因为SurfaceView创建了自己的Surface ,我想我需要使用MediaCodec创建的那个。 我在网上搜索了很多解决方案,但没find。 bigflake.com上的一些例子似乎是朝着正确方向迈出的一步,但他们采取了一种方法,增加了一堆我想避免的EGL / SurfaceTexture开销。 我希望有一个更简单的例子或解决方案,我可以让Camera和MediaCodec更直接地说话而不涉及EGL或纹理。

使用MediaMuxer无法混合音频文件和video文件?

我正在开发一个记录屏幕video和音频的Android应用程序。 我录制了这两个文件:mp3音频文件和mp4video文件(没有声音)。 现在我想混合它们并创建一个新的mp4video文件(带声音)。 从Android 4.3开始,Google建议使用MediaMuxer类来混合流音频和video。 我多次尝试都没有成功。 从Google解决我的MediaMuxer API问题的解决方案? 任何帮助将不胜感激。

使用MediaCodec将一系列图像保存为video

我正在尝试使用MediaCodec将一系列图像(保存为文件中的字节数组)保存到video文件中。 我已经在SurfaceView上测试了这些图像(在系列中播放),我可以看到它们很好。 我看了很多使用MediaCodec例子,这就是我的理解(如果我错了请纠正我): 从MediaCodec对象获取InputBuffers – >用你的帧的图像数据填充它 – >将输入缓冲区排队 – >获取编码输出缓冲区 – >将其写入文件 – >增加显示时间并重复 但是,我已经对此进行了大量测试,最终我遇到了两种情况之一: 我试图模仿的所有示例项目都在第二次调用queueInputBuffer时导致Media服务器queueInputBuffer 。 我尝试在最后调用codec.flush() (在将输出缓冲区保存到文件之后,虽然我看到的所有示例都没有这样做)并且媒体服务器没有死,但是,我无法打开输出video文件任何媒体播放器,都有问题。 这是我的代码: MediaCodec codec = MediaCodec.createEncoderByType(MIMETYPE); MediaFormat mediaFormat = null; if(CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_720P)){ mediaFormat = MediaFormat.createVideoFormat(MIMETYPE, 1280 , 720); } else { mediaFormat = MediaFormat.createVideoFormat(MIMETYPE, 720, 480); } mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, 700000); mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, 10); mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar); mediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 5); codec.configure(mediaFormat, null, null, […]

使用MediaCodec和MediaMuxer的图像到video

我有一堆本地图像保存为jpeg文件。 我的图像是使用CameraPreview捕获的,PreviewFormat是默认值:NV21。 我想从固定数量的图像生成一个小video。 我不打算使用FFMpeg因为它需要NDK并且会引入兼容性问题。 MediaCodec和MediaMuxer看起来很有效,但网上没有一个可行的解决方案。 有一些参考资料导致我目前的解决方案。 1. EncodeAndMuxTest : http : //bigflake.com/mediacodec/EncodeAndMuxTest.java.txt 这个是由法登写的。 它非常适合我的需要,除了他使用的是createInputSurface而不是queueInputBuffer。 2. 将位图数组转换为YUV(YCbCr NV21) 我按照这个答案进行转换。 https://stackoverflow.com/a/17116985/3047840 3. 使用MediaCodec将一系列图像保存为video 这个问题看起来与我的很相似,但我不打扰使用MediaMuxer。 我的代码如下: public class EncodeAndMux extends Activity { private static final String TAG = “EncodeAndMuxTest”; private static final boolean VERBOSE = false; private static final File OUTPUT_DIR = Environment .getExternalStorageDirectory(); private static final String […]

PCM – > AAC(编码器) – > PCM(解码器)实时正确优化

我正在努力实施 AudioRecord (MIC) -> PCM -> AAC Encoder AAC -> PCM Decode -> AudioTrack?? (SPEAKER) 使用Android 4.1+(API16)上的MediaCodec 。 首先,我成功(但不确定正确优化)实现了PCM -> AAC Encoder MediaCodec PCM -> AAC Encoder ,如下所示 private boolean setEncoder(int rate) { encoder = MediaCodec.createEncoderByType(“audio/mp4a-latm”); MediaFormat format = new MediaFormat(); format.setString(MediaFormat.KEY_MIME, “audio/mp4a-latm”); format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 1); format.setInteger(MediaFormat.KEY_SAMPLE_RATE, 44100); format.setInteger(MediaFormat.KEY_BIT_RATE, 64 * 1024);//AAC-HE 64kbps format.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectHE); encoder.configure(format, […]

如何使用Android MediaCodec生成AAC ADTS基本流

我要做的是:使用Android的MediaCodec将原始PCM音频样本编码为原始AAC文件。 我遇到的问题:当我使用FFMPEG将生成的原始AAC文件打包到M4A容器中时,FFMPEG抱怨文件中缺少编解码器参数。 细节: 由于我找不到生成输出AAC文件的音频编码器的任何MediaCodec示例代码,我尝试将video编码器修改为音频编码器。 原始代码在这里: source_code 我配置了这样的音频编码器: mEncoderFormat = MediaFormat.createAudioFormat(“audio/mp4a-latm”, (int)mAudioSampleRate, 2); // redundant? mEncoderFormat.setString(MediaFormat.KEY_MIME, “audio/mp4a-latm”); mEncoderFormat.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectELD); mEncoderFormat.setInteger(MediaFormat.KEY_SAMPLE_RATE, kSampleRates); mEncoderFormat.setInteger(MediaFormat.KEY_BIT_RATE, kBitRates); mEncoderFormat.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 2); testEncoderWithFormat(“audio/mp4a-latm”, mEncoderFormat); try { codec.configure( mEncoderFormat, null /* surface */, null /* crypto */, MediaCodec.CONFIGURE_FLAG_ENCODE); } catch (IllegalStateException e) { Log.e(TAG, “codec ‘” + componentName + “‘ failed configuration.”); return; } […]

MediaCodec getInputImage在某些设备上返回null

我想通过将颜色格式设置为COLOR_FormatYUV420Flexible来使用MediaCodec进行编码。 我的输入缓冲区是yuv420p。当我像这样输入缓冲区时: int inputBufferIndex = mEncoder.dequeueInputBuffer(-1); mCurrentBufferIndex = inputBufferIndex; if (inputBufferIndex >= 0) { ByteBuffer inputBuffer = inputBuffers[inputBufferIndex]; //if(VERBOSE) Log.i(TAG,”pos:”+inputBuffer.position()+”\tlimit:”+inputBuffer.limit()); inputBuffer.clear(); return inputBuffer; } 但有些设备颜色错误。 所以我试试这个: int inputBufferIndex = mEncoder.dequeueInputBuffer(-1); mCurrentBufferIndex = inputBufferIndex; if (inputBufferIndex >= 0) { Image img = mEncoder.getInputImage(inputBufferIndex); if(img==null) return null; //mCurrentInputPlanes = img.getPlanes(); ByteBuffer buffers[]={img.getPlanes()[0].getBuffer(), img.getPlanes()[1].getBuffer(), img.getPlanes()[2].getBuffer()}; 我将缓冲区填充到YUV通道。它可以在某些设备上运行。 但是当调用getInputImage时,moto X […]

SurfaceTexture的onFrameAvailable()方法总是调用得太迟了

我正在尝试使用以下MediaExtractor示例: http://bigflake.com/mediacodec/ – ExtractMpegFramesTest.java(需要4.1,API 16) 我遇到的问题是outputSurface.awaitNewImage(); 似乎总是抛出RuntimeException(“帧等待超时”),每当mFrameSyncObject.wait(TIMEOUT_MS)调用超时时抛出它。 无论我将TIMEOUT_MS设置为什么, onFrameAvailable()总是在超时发生后立即被调用。 我尝试了50毫秒和30000毫秒,它是相同的。 似乎在线程繁忙时无法完成onFrameAvailable()调用,并且一旦超时发生并结束线程代码执行,它就可以解析onFrameAvailable()调用。 有没有人设法让这个例子工作,或者知道MediaExtractor应该如何使用GL纹理? 编辑:在使用API​​ 4.4和4.1.1的设备上尝试此操作,两者都发生了同样的情况。 编辑2: 得益于fadden 4.4。 问题是th.join();方法名为th.join(); 它阻止了主线程并阻止了onFrameAvailable()调用的处理。 有一次我评论了th.join(); 它适用于4.4。 我想也许ExtractMpegFramesWrapper.runTest()本身应该在另一个线程上运行,所以主线程没有被阻止。 在调用codec.configure() ,4.1.2上还有一个小问题,它给出了错误: A/ACodec(2566): frameworks/av/media/libstagefright/ACodec.cpp:1041 CHECK(def.nBufferSize >= size) failed. A/libc(2566): Fatal signal 11 (SIGSEGV) at 0xdeadbaad (code=1), thread 2625 (CodecLooper) 通过在通话前添加以下内容我解决了这个问题: format.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, 0); 然而,我现在在4.1.1(Galaxy S2 GT-I9100)和4.1.2(三星Galaxy Tab GT-P3110)上的问题是它们都始终将info.size设置为0以用于所有帧。 这是日志输出: loop input buffer not available […]

Android MediaCodec AAC编码器

我使用Android SDK提供的MediaCodec类,因为API级别16与OMX.SEC.aac.enc编码器一起将音频编码为文件。 我从AudioRecord类中获取音频输入。 我的AudioRecord类的实例配置如下: bufferSize = AudioRecord.getMinBufferSize(44100, AudioFormat.CHANNEL_IN_STEREO, AudioFormat.ENCODING_PCM_16BIT); recorder = new AudioRecord(MediaRecorder.AudioSource.MIC, 44100, AudioFormat.CHANNEL_IN_STEREO, AudioFormat.ENCODING_DEFAULT, bufferSize); 我能够从AudioRecord实例播放原始数据,因此问题不在那里。 我将AudioRecord实例的输出写入ByteBuffer实例,并将其传递给编码器的可用输入缓冲区。 编码器的输出写入SD卡上的文件。 这些是我的MediaCodec实例的配置参数: codec = MediaCodec.createEncoderByType(“audio/mp4a-latm”); MediaFormat format = new MediaFormat(); format.setString(MediaFormat.KEY_MIME, “audio/mp4a-latm”); format.setInteger(MediaFormat.KEY_BIT_RATE, 64 * 1024); format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 2); format.setInteger(MediaFormat.KEY_SAMPLE_RATE, 44100); format.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectHE); codec.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE); VLC告诉我,我的aac文件中没有流。 命令FFMPEG -i @filename@给出了以下错误: 处理输入时发现无效数据 。 我测试过的所有媒体播放器都无法播放我的文件。 为什么我无法播放我的文件? 我在LogCat没有收到OpenMAX错误,并且编码时应用程序不会崩溃。 我写了一个video编码器,它的工作原理与之相同。 […]