标签: android-mediacodec

MediaCodec和MediaExtractor的理解

我想对音频文件进行一些处理而不播放它们,只是数学。我怀疑我的做法是否正确,并且有几个问题。我读了一些示例,但大多数都是关于视频流的,根本没有处理原始数据。

  1. 我准备了一个 mp3 文件,它有 2 个相同的通道,即它是立体声的,但左右声道相同。解码后,我期望获得具有相同数字对的缓冲区,因为 PCM-16 交替存储通道样本,例如 { L R L R L R...},对吗?例如:

    { 105 105 601 601 -243 -243 -484 -484...}。

    但我得到了一对接近但不相等的数字:

    { -308 -264 -1628 -1667 -2568 -2550 -4396 -4389}

    mp3 算法是否对相同的值进行不同的编码?为什么?

  2. 我想处理 1024 个样本包中的数据。如果没有足够的样本用于另一个包,我想保存其余的直到下一批原始数据(参见mExcess代码)。是否能保证订单得以保留?

  3. 我曾经将“样本”理解为音频数据的每个值。这里我看到了MediaExtractor::readSampleDataMediaExtractor::advance方法。第一个返回约 2000 个值,在第二个的描述中表示“前进到下一个样本”。这只是命名的重叠吗?我看到了几个示例,其中这些方法在循环中成对调用。我的用法正确吗?

这是我的代码:

public static void foo(String filepath) throws IOException {
    final int SAMPLES_PER_CHUNK = 1024;

    MediaExtractor mediaExtractor = new MediaExtractor();
    mediaExtractor.setDataSource(filepath);
    MediaFormat mediaFormat = mediaExtractor.getTrackFormat(0);
    mediaExtractor.release();

    MediaCodecList mediaCodecList = new …
Run Code Online (Sandbox Code Playgroud)

java audio android android-mediacodec

5
推荐指数
1
解决办法
1333
查看次数

使用 FFMPEG 从 Lottie JSON 文件制作视频并与原始视频叠加时出现问题

使用 FFMPEG 视频处理库和 MediaCodec 处理 Lottie 动画有一些独特的概念。在这方面,我想从 Lottie 动画制作视频并将该视频叠加在其他原始视频上。

但问题是我无法从 Lottie 动画制作具有透明背景的视频。因此,我使用 MediaCodec 和 MediaMuxer 从 Lottie 动画制作了简单的视频,它从 Lottie Drawable 中一帧一帧地将其附加到视频(Lottie Video)。这是有关此概念的链接 - https://engineering.21buttons.com/how-to-generate-videos-using-lottie-in-android-2db6ecceb2a

然后我使用 FFmpeg 库将此视频叠加到原始视频上。这里 FFmpeg 执行两个任务,首先它在 Lottie Video 中制作透明背景,其次它将这个 Lottie Video 覆盖在原始视频之上。

这里实际的问题就出来了,FFmpeg 在处理 25 秒的视频时需要超过 8 到 9 分钟,所以我想找到这个问题的解决方案,因为我的时间限制只有 1 到 2 分钟。任何人都有解决方案或实现此概念的新IDE,那么请告诉我,我将不胜感激。

这个概念的图形表示

android ffmpeg mediamuxer android-mediacodec lottie

5
推荐指数
1
解决办法
3184
查看次数

Android MediaCodec 启动失败

我正在尝试使用 MediaCodec 从我拥有的一组位图生成 mp4 文件。
经过大量编码和测试后,我注意到互联网上不存在任何示例,也没有在 Android Studio 模拟器上进行任何工作,但它们确实可以在我的两部真实手机(android 7 和 9)中工作...所以我一直只进行测试真正的手机。

经过大量编码和测试后,我得到了一个有效的编码(适用于我的两部手机,但适用于 Android 模拟器)并部署到生产中。

我的网站已经上线几个月了,大约有 150 个日常用户,但其中大约 30% 的用户遇到了我在 Android 模拟器上注意到的同样的崩溃问题。所以这不是模拟器的限制。

E/ACodec:[OMX.google.h264.encoder] configureCodec 返回错误 -38 signalError(omxError 0x80001001,internalError -2147483648) E/MediaCodec:编解码器报告错误 0x80001001,actionCode 0,而处于状态 3 E/MediaCodec:配置失败错误 0x80001001,正在重置...

private static MediaCodecInfo selectCodec(String mimeType) {
        int numCodecs = MediaCodecList.getCodecCount();
        for (int i = 0; i < numCodecs; i++) {
            MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(i);
            if (!codecInfo.isEncoder()) {
                continue;
            }
            String[] types = codecInfo.getSupportedTypes();
            for (String type : types) {
                if (type.equalsIgnoreCase(mimeType)) {
                    return codecInfo;
                } …
Run Code Online (Sandbox Code Playgroud)

encoding android android-mediacodec

5
推荐指数
0
解决办法
2516
查看次数

编码时视频加密

我正在开发使用 MediaCodec 录制视频并使用 MediaMuxer 将其转换为 Mp4(h.264+aac) 的应用程序。我想对该 mp4 进行加密,但我无法找到在录制时加密视频的方法。因此,目前我必须在创建视频后对视频进行加密。由于解码时使用 MediaCrypto 还有其他方法吗?

media encryption android android-mediacodec

5
推荐指数
1
解决办法
321
查看次数

如何在 MediaCodec 编码器和 CameraX 之间共享 Surface

CameraX我想从(预览用例)获取图像并使用 .h.264 视频将它们编码为 h.264 视频MediaCodec。我怎样才能做到这一点?我正在尝试的是,通过使用.in来使用Surface返回的值。我从该设置中继承了一个类,并配置我的编码器和覆盖以从. 这预计会起作用吗?我真的可以共享这样的 Surface 并期望 CameraX 写入此 Surface 并填充我的编码器的输入吗?MediaCodec.createInputSurface()Preview.Builder()Preview.setSurfaceProvider()Preview.SurfaceProvideronSurfaceRequested()SurfacecreateInputSurface()

是否有更有效的方法来对实时 CameraX 源进行编码?

注意:我使用的是 KOTLIN

android kotlin-android-extensions android-mediacodec android-camerax

5
推荐指数
1
解决办法
1389
查看次数

如何使用 MediaRecorder 记录现有表面(不是 PercientSurface)

我正在尝试记录我无权访问的摄像机流。我只能访问自定义 SurfaceView,它从相机预览中获取图像并渲染图像。

我想将表面\相机视频保存到文件中。我正在使用 SDK 进行流式传输 (Amazon Chime),但我无权访问相机组件来添加用于录制的持久表面。

虽然我确实可以访问每个新图像“VideoRenderer.I420Frame”,但不确定如何将其积累到视频中。

我想到的另一种方法是使用“MediaRecorder”中的表面,但是当我使用这个表面(此视图)时,我得到了这个异常:

java.lang.IllegalArgumentException:不是 PercientSurface

我可以以某种方式创建一个 PersistentSurface 并将当前表面复制到新表面中,同时获取新图像吗?或者以其他方式解决这个问题?

这个类目前看起来像这样:

class RecordingVideoRenderView : SurfaceViewRenderer, VideoRenderView {

private var recording: Boolean = false
private val logger = ConsoleLogger(LogLevel.DEBUG)
private val TAG = "RecordingVideoRenderView"
private lateinit var recorder: MediaRecorder

constructor(context: Context) : super(context)

constructor(context: Context, attrs: AttributeSet) : super(context, attrs)

override fun renderFrame(frame: Any) {
    this.renderFrame(frame as VideoRenderer.I420Frame)
}

override fun initialize(initParams: Any?) {
    this.init((initParams as EglBase).eglBaseContext, null)
}

override fun finalize() {
    this.release()
}

fun startRecording() …
Run Code Online (Sandbox Code Playgroud)

android surface mediarecorder kotlin android-mediacodec

5
推荐指数
0
解决办法
1853
查看次数

RTP 的 AMR 解码

我正在接收一些 RTP 流,我只知道每个数据包的 AMR-WB 八位字节对齐 100 毫秒。某些第 3 方可以接收相同的流及其“可听”,因此这是正确的。现在我正在接收这些数据并尝试解码,但没有运气......

在里面:

val sampleRate = 16000
val mc = MediaCodec.createDecoderByType(MediaFormat.MIMETYPE_AUDIO_AMR_WB)
val mf = MediaFormat.createAudioFormat(MediaFormat.MIMETYPE_AUDIO_AMR_WB, sampleRate, 1)
mf.setInteger(MediaFormat.KEY_SAMPLE_RATE, sampleRate) // is it needed?
mc.configure(mf, null, null, 0)
mc.start()
Run Code Online (Sandbox Code Playgroud)

分别解码每个数据包:

private fun decode(decoder: MediaCodec, mediaFormat: MediaFormat, rtpPacket: RtpPacket): ByteArray {
    var outputBuffer: ByteBuffer
    var outputBufferIndex: Int

    val inputBuffers: Array<ByteBuffer> = decoder.inputBuffers
    var outputBuffers: Array<ByteBuffer> = decoder.outputBuffers

    // input
    val inputBufferIndex = decoder.dequeueInputBuffer(-1L)
    if (inputBufferIndex >= 0) {
        val inputBuffer = inputBuffers[inputBufferIndex]
        inputBuffer.clear()
        inputBuffer.put(rtpPacket.payload)
        // …
Run Code Online (Sandbox Code Playgroud)

android android-mediacodec

5
推荐指数
1
解决办法
401
查看次数

MediaCodec 编码忽略我的 BUFFER_FLAG_SYNC_FRAME 标志

在我的 Android 应用程序中,我使用 MediaCodec 以 webm (vp8) 格式编码一些媒体。编码按预期工作。但是,我需要确保偶尔创建一个同步帧。这是我所做的:

encoder.queueInputBuffer(..., MediaCodec.BUFFER_FLAG_SYNC_FRAME);
Run Code Online (Sandbox Code Playgroud)

在代码的后面,我检查同步帧:

encoder.dequeueOutputBuffer(bufferInfo, 0);
boolean isSyncFrame = (bufferInfo.flags & MediaCodec.BUFFER_FLAG_SYNC_FRAME);
Run Code Online (Sandbox Code Playgroud)

问题是 isSyncFrame 永远不会得到真正的值。

我想知道我是否在编码配置中犯了错误。可能有更好的方法告诉编码器偶尔创建一个同步帧。

我希望这不是 MediaCodec 中的错误。预先感谢您的帮助。

android android-mediacodec

4
推荐指数
1
解决办法
2620
查看次数

MediaCodec 编码的视频底部有绿条,色度搞砸了

我从Grafika开始了一个项目并对其进行了修改。我有一个框架(与原始框架没有太大区别),它可以从 中捕获预览Camera并同时以不同的分辨率将其连续编码为视频。

MediaCodec(用于编码)配置为使用COLOR_FormatSurface,以便我们能够渲染到getInputSurface()使用 GLES查询的 Surface 。

媒体格式设置为 MIME 类型 video/avc

对于大多数手机,此设置非常有效。

但对于一些手机,编码视频的色度值略微倾斜,底部有一个绿色条。

目前编码器表面的分辨率为 640x360。选择渲染到表面的 EGLConfig 支持 32 位 RGBA 格式。

预览是完美的所有手机。

所以我假设应用程序端或操作系统框架端的编码器参数有问题。

它发生在 Android 4.4 上。- 不确定,是否可以在 5.* 上重现。

![绿条图像] 2

encoding android opengl-es grafika android-mediacodec

4
推荐指数
1
解决办法
1732
查看次数

如何从 MP4 中逐帧获取?(媒体编解码器)

实际上我正在使用 OpenGL,我想将我所有的纹理都放在 MP4 中以压缩它们。

然后我需要从我的 Android 上的 MP4 中获取它

我需要以某种方式解码 MP4 并根据请求逐帧获取。

我找到了这个 MediaCodec

https://developer.android.com/reference/android/media/MediaCodec

和这个 MediaMetadataRetriever

https://developer.android.com/reference/android/media/MediaMetadataRetriever

但是我没有看到如何逐帧请求的方法......

如果有人用过MP4,请给我一个去哪里的方法。

PS我正在使用本机方式(JNI),所以怎么做都无所谓..Java或本机,但我需要找到方法。

编辑1

我制作了某种电影(只有一个 3d 模型),所以我每 32 毫秒更改一次几何和纹理。因此,在我看来,将 mp4 用于 tex 似乎是合理的,因为每个新帧(32 毫秒)都与原始帧非常相似......

现在我为一个模型使用 400 帧。对于几何,我使用 .mtr,对于 tex,我使用 .pkm(因为它针对 android 进行了优化),所以我有大约 350 个 .mtr 文件(因为有些文件包含子索引)和 400 个 .pkm 文件......

这就是为什么我要为 tex 使用 mp4 的原因。因为一个 mp4 比 400 .pkm 小得多

编辑2

请看一下 Edit1

实际上,我需要知道的只是可以MP4按帧读取的Android API ?也许某种getNextFrame()方法?

像这样的东西

MP4Player player = new MP4Player(PATH_TO_MY_MP4_FILE);

void readMP4(){
   Bitmap b;

   while(player.hasNext()){ …
Run Code Online (Sandbox Code Playgroud)

mp4 android opengl-es android-mediacodec

4
推荐指数
1
解决办法
6293
查看次数