I am referring to this excellent example of how to encode the preview frames of the camera directly into an mp4 file: http://bigflake.com/mediacodec/CameraToMpegTest.java.txt
I have adopted the code in the way that I also would like to render the preview image on the screen. Therefore I got something like a GLTextureView with its own EGLContext. This Context is then used as shared EGLContext when I create the EGLContext for the encoder rendering:
mEGLContext = EGL14.eglCreateContext(mEGLDisplay, configs[0], sharedContext == null ? …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用 OpenGL ES 2 上下文在 Android 上使用 MediaCodec 录制视频。
为此,我想使用以下方法使用可记录表面:
private static final int EGL_RECORDABLE_ANDROID = 0x3142;
Run Code Online (Sandbox Code Playgroud)
创建一个新的上下文。实际上,我正在我的第一个上下文中在纹理中渲染一个场景。我想在新的上下文中呈现它以将数据发送到 MediaCodec。
我正在尝试使用Recording 补丁执行与本突破教程相同的操作
我在我的游戏中实现了 InputSurface 和 GameRecorder,但我只记录了一个空场景。
我的主要问题是,上下文不共享相同的 OpenGL 对象,我不知道这样做的最佳解决方案。
我如何发送最终图像渲染或整个场景以在同一线程中渲染以避免线程问题,以正确记录表面?
问题很简单,但我没有任何线索可以解决它:
我编写了一行代码来在我的 Nexus 4 (Android 4.4.2) 上创建一个 AAC 编码器
MediaCodec codec = MediaCodec.createEncoderByType("audio/mp4a-latm");
Run Code Online (Sandbox Code Playgroud)
“codec”中保存的返回值不为空,但在Logcat中出现红色错误信息:
03-20 15:25:08.985: E/OMXMaster(24517): A component of name 'OMX.qcom.audio.decoder.aac' already exists, ignoring this one.
Run Code Online (Sandbox Code Playgroud)
我也试过另一行:
MediaCodec codec = MediaCodec.createByCodecName("OMX.google.aac.encoder");
Run Code Online (Sandbox Code Playgroud)
并得到相同的错误结果。
在使用 MediaCodec 之前,我是否错过了任何初始化步骤?我在官方文档中没有找到任何关于此的信息。
有没有人遇到过这个问题?
实际上我正在尝试将 PCM 编码为 AAC 文件。我已经阅读了@hubeir这篇文章。看来他已经做到了。我做了同样的事情:(1)设置媒体编解码器并输入 PCM 数据以获得编码帧。为此,我从cts 中读取了代码。每个编码的帧长度约为 371-379。(2)将adts标题添加到框架中,然后保存到文件。我一点一点地检查了头部,它是正确的。但该文件仍然无法播放。所以我想也许错误日志是问题所在。
以下是我的全部代码,供参考:
MediaCodec codec = MediaCodec.createByCodecName("OMX.google.aac.encoder");
MediaFormat format = new MediaFormat();
format.setString(MediaFormat.KEY_MIME, "audio/mp4a-latm");
format.setInteger(MediaFormat.KEY_AAC_PROFILE,
MediaCodecInfo.CodecProfileLevel.AACObjectELD);
format.setInteger(MediaFormat.KEY_SAMPLE_RATE, nSamplerate);
format.setInteger(MediaFormat.KEY_BIT_RATE, 128000);
format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, nChannels);
codec.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
codec.start();
ByteBuffer[] inputBuffers = codec.getInputBuffers();
ByteBuffer[] …Run Code Online (Sandbox Code Playgroud) 我是 Android 新手。我不知道如何在 android 中压缩视频。
请给我建议选项?
我开始为应用程序解码/编码视频,似乎BigFlake 的网站是工作视频代码的权威参考。我已将ExtractMpegFramesTest_egl14.java复制到我的项目中,并将其修改为使用不同的文件路径,但仅此而已。它从我复制到设备中的预先录制的视频中正确提取帧。然而,当尝试将它与从设备相机录制的视频一起使用时,我得到的帧只是水平线:
在测试了不同录制的视频后,我意识到问题来自旋转视频。该设备的摄像头对来自帧缓冲区的帧进行编码,然后在视频上添加旋转标签。这可以从对象中提取MediaFormat:
int rotation = format.getInteger("rotation-degrees");
Run Code Online (Sandbox Code Playgroud)
不幸的是,交换已保存图像的宽度/高度不会改变任何内容,图像仍然会损坏。必须对保存代码执行哪些操作才能正确处理旋转帧?
我目前正在尝试在 Android 上开发一个视频播放器,但在颜色格式方面遇到了困难。
上下文:我通过MediaExtractor/MediaCodec的标准组合提取和解码视频。因为我需要提取的帧可用作 OpenGLES 纹理 (RGB),所以我设置了解码器 ( MediaCodec ),以便它通过 SurfaceTexture提供外部 GLES 纹理 ( GL_TEXTURE_EXTERNAL_OES )。我知道我的硬件解码器输出的数据是NV12 ( YUV420SemiPlanar ) 格式,我需要通过渲染将其转换为 RGB(使用片段着色器进行转换)。
MediaCodec ---> GLES 外部纹理 (NV12) [1] ---> 渲染 ---> GLES 纹理 (RGB)
我遇到的困难是:如何访问 GLES 外部纹理 ( [1] ) 中包含的特定 Y、U 和 V 值。我不知道 GLES 纹理内存是如何设置的,也不知道如何访问它(“texture()”和“texelFetch()”GLSL 函数除外)。
我正在努力用另一个文件中的音乐替换我的视频的音轨。所以我修改了标准ExtractDecodeEditEncodeTest代码(来自 bigflake),以便MediaExtractor从所说的“另一个文件”创建音频。但是,当我尝试将 EOS 缓冲区发送到音频解码器时,发生了一件奇怪的事情:
this.audioDecoder.queueInputBuffer(decoderInputBufferIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
这使我获得了android.media.MediaCodec$CodecException: Error 0xfffffff3.
当我在 try-catch-finally 循环中捕获它时,它显然是一个android.media.MediaCodec.error_neg_13(代码:-13)。然而,视频仍然看起来不错,替换了音轨。
据我搜索,这个错误没有任何内容,甚至在日志中也没有。有谁知道是什么导致了它以及我如何防止它发生?
我正在尝试直接从android 设备的相机流式传输视频捕获。到目前为止,我已经能够从 android 相机的onPreviewFrame (byte[] data, Camera camera) 函数捕获每一帧,对数据进行编码,然后成功解码数据并显示到表面。我使用 android 的MediaCodec进行编码和解码。但是视频的颜色和方向不正确 [旋转 90 度]。搜索了一段时间后,我发现了这个 YV12toYUV420PackedSemiPlanar 函数 - 如果我在将原始相机数据传递给编码器之前在原始相机数据上使用这个函数,颜色显示正确,但它仍然旋转了 90 度。
public static byte[] YV12toYUV420PackedSemiPlanar(final byte[] input, final int width, final int height) {
final int frameSize = width * height;
final int qFrameSize = frameSize/4;
byte[] output = new byte[input.length];
System.arraycopy(input, 0, output, 0, frameSize);
for (int i = 0; i < (qFrameSize); i++)
{
byte b …Run Code Online (Sandbox Code Playgroud) android video-encoding video-streaming h.264 android-mediacodec
我有一个视频效果应用程序,我使用 OpenGL 绘制到帧缓冲区对象,然后将生成的纹理绘制到显示器,然后是 MediaCodec 输入表面(如果应用程序正在编码)。
我最初在同步模式下为 API 18 编写了编码器(基于大片示例)。我最近将它切换到 API 21 和异步模式。
它可以很好地录制视频,我相信我已经正确设置了所有内容。然而,对 eglSwapBuffers 的调用似乎会导致帧速率显着下降。
如果我删除所有其他 OpenGL 调用,它会运行得更好,但我渲染的东西并不那么昂贵(它可以每帧渲染好多次)。更改编码器设置(即从 640x360 @ 2Mbps 到 1920x1080 @ 16Mbps)几乎没有区别。
唯一使它运行得更快的是删除对 eglSwapBuffers 的调用(它将缓冲区数据发送到编码器)。
我的理解是输出缓冲区不会像以前那样阻塞异步模式下的调用。我错了吗?是否有调用渲染器的首选方法,或异步在单独线程上渲染的方法?
任何关于从哪里开始的帮助或想法将不胜感激,谢谢!
我正在尝试使用 Android 实现流畅的视频清理VideoView。的seekTo方法MediaPlayer并不完全是我想要的。它并不完全寻求我传入的毫秒数,它实际上是从/跳转到最近的位置,而不是我想要的确切位置。框架也显示出很大的差距。不是毫秒的确切帧。
我四处寻找,发现SEEK_CLOSEST_SYNC只能寻找最近的同步帧而不是 EXACT。这取决于视频的生成方式。我怎样才能实现平滑擦洗并寻求准确位置即使视频暂停或播放。是否可以通过 AndroidVideoView或MediaPlayer类或我应该改变方法?