标签: mediacodec

Android Camera onPreviewFrame帧率不一致

我正在尝试通过Camera的PreviewCall返回(onPreviewFrame)使用MediaCodec对每秒30帧的视频进行编码.我编码的视频总是播放得非常快(这是不可取的).所以,我试图通过设置一个int frameCount变量来检查进入我相机预览的帧数,以记住它的计数.我期待的是每秒30帧,因为我将相机的预览设置为30 fps预览(如下所示).我回来的结果是不一样的.我调用onPreviewFrame回调10秒钟,我得到的帧数量只有大约100帧.这很糟糕,因为我期待300帧.我的相机参数设置正确吗?这是Android的Camera预览回拨的限制吗?如果这是对Android相机预览回调的限制,那么还有其他相机回调能够以每秒30帧的速度返回相机的图像数据(nv21,yuv,yv12)吗?

感谢您阅读并花时间去帮忙.我将不胜感激任何评论和意见.

以下是使用Camera的onPreviewFrame编码视频的示例:

http://www.youtube.com/watch?v=I1Eg2bvrHLM&feature=youtu.be

                Camera.Parameters parameters = mCamera.getParameters();
                parameters.setPreviewFormat(ImageFormat.NV21);
                parameters.setPictureSize(previewWidth,previewHeight);
                parameters.setPreviewSize(previewWidth, previewHeight);
//              parameters.setPreviewFpsRange(30000,30000);

                parameters.setPreviewFrameRate(30);
                mCamera.setParameters(parameters);

                mCamera.setPreviewCallback(previewCallback);
                mCamera.setPreviewDisplay(holder);
Run Code Online (Sandbox Code Playgroud)

android android-camera mediacodec

8
推荐指数
1
解决办法
7387
查看次数

native_window_api_connect返回错误:参数无效(-22)

我正在使用MediaCodec API编写视频播放器应用程序.我必须在视频解码开始前显示空白屏幕.所以我使用以下代码显示空白屏幕.

Canvas c=null;
            c = surfaceView.getHolder().lockCanvas();
            c.drawColor(Color.BLACK);
            surfaceView.getHolder().unlockCanvasAndPost(c);
Run Code Online (Sandbox Code Playgroud)

此视频解码将开始.但在配置时

videoDecoder.configure(format, surfaceView.getHolder().getSurface(), null, 0);
Run Code Online (Sandbox Code Playgroud)

它给出了以下错误

02-03 03:52:37.542: E/MediaCodec(9655): native_window_api_connect returned an error: Invalid argument (-22)
02-03 03:52:37.542: E/Video Decoder Configuration(9655): java.lang.IllegalStateException
Run Code Online (Sandbox Code Playgroud)

所以我的应用程序因该错误而崩溃.没有那个空白屏幕代码解码器工作正常.我该如何解决这个问题?

android android-mediaplayer mediacodec

8
推荐指数
1
解决办法
3680
查看次数

在Android上解码h264 ByteStream

我想在Android中解码并显示原始的h264视频字节流,因此我目前正在使用这些MediaCodec/Format类.我从服务器通过Udp获取帧数据.但是,遗憾的是,目前没有显示任何内容.

这是我到目前为止所拥有的.

初始化MediaCodec类:

codec = MediaCodec.createDecoderByType("video/avc");

MediaFormat format = new MediaFormat();
format.setString(MediaFormat.KEY_MIME, "video/avc");
format.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, 100000);
format.setInteger(MediaFormat.KEY_WIDTH, 800);
format.setInteger(MediaFormat.KEY_HEIGHT, 600);
format.setInteger("max-width", 800);
format.setInteger("max-height", 600);
format.setInteger("push-blank-buffers-on-shutdown", 1);

codec.configure(format, surface, null, 0);
Run Code Online (Sandbox Code Playgroud)

解码器的用法:

int inIndex = codec.dequeueInputBuffer(10000);
if(inIndex >= 0)
{
                ByteBuffer inputBuffer = codecInputBuffers[inIndex];
                inputBuffer.clear();
                inputBuffer.put(frameData);
                codec.queueInputBuffer(inIndex, 0, frameSize, 33, 0);
}

int outIndex = codec.dequeueOutputBuffer(null, 10000);

switch(outIndex)
{
  case MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED:
    codecOutputBuffers = codec.getOutputBuffers();
    System.out.println("OB Changed");
    break;
  case MediaCodec.INFO_OUTPUT_FORMAT_CHANGED:
        System.out.println("OF Changed");
        break;
  case MediaCodec.INFO_TRY_AGAIN_LATER:
    System.out.println("l8r");
    break;
  default:
    ByteBuffer buffer = …
Run Code Online (Sandbox Code Playgroud)

java video android decode mediacodec

8
推荐指数
1
解决办法
7871
查看次数

视频使用OnAudioFilterRead数据编码错误

我正在尝试使用OnAudioFilterRead函数将Unity游戏音频录制到mp4文件.

function OnAudioFilterRead(var data:float[], var channels:int)
Run Code Online (Sandbox Code Playgroud)

我的解决方案概述.
步骤1.将从Unity获取的数据样本转换为bytes []

private void Convert2Bytes(float[] samples) {
    Int16[] intData = new Int16[samples.Length];
    //converting in 2 float[] steps to Int16[], //then Int16[] to Byte[]

    Byte[] bytesData = new Byte[samples.Length * 2];
    //bytesData array is twice the size of
    //dataSource array because a float converted in Int16 is 2 bytes.

    float rescaleFactor = 32767; //to convert float to Int16

    for (int i = 0; i<samples.Length; i++) {
        intData[i] = (short) ((samples[i] * gain) * rescaleFactor); …
Run Code Online (Sandbox Code Playgroud)

mp4 android unity-game-engine h.264 mediacodec

8
推荐指数
0
解决办法
355
查看次数

带声音的Android视频循环缓冲区

我正在使用Google的开源示例:Grafika.我正在使用它的ContinuousCaptureActivity.java此活动中演示了CircularBuffer的实现,但生成的视频文件中没有包含音频.

我想在此活动中添加音频录制功能,并将录制的音频以相同的CircularBuffered时尚添加到视频中.

为实现这一目标,我探索了MediaCodec库,该库已在4.3+版本中推出.我还使用MediaMuxer捕获视频和音频流,并将它们混合到一个视频中.

但是,我不确定如何在ContinuousCaptureActivity.java课堂上实现录音功能.任何帮助都非常感谢.

audio video android mediacodec grafika

8
推荐指数
0
解决办法
1022
查看次数

使用MediaCodec截断视频

我使用Android MediaCodec库来转码视频文件(主要是在这里更改分辨率示例代码)

我想要实现的另一件事是截断视频 - 仅开始15秒.逻辑是检查videoExtractor.getSampleTime()它是否大于15秒,我只是写一个EOS解码器缓冲区.

但我得到一个例外 Caused by: android.media.MediaCodec$CodecException: Error 0xfffffff3

这是我的代码:

        while ((!videoEncoderDone) || (!audioEncoderDone)) {
        while (!videoExtractorDone
                && (encoderOutputVideoFormat == null || muxing)) {
            int decoderInputBufferIndex = videoDecoder.dequeueInputBuffer(TIMEOUT_USEC);
            if (decoderInputBufferIndex == MediaCodec.INFO_TRY_AGAIN_LATER)
                break;

            ByteBuffer decoderInputBuffer = videoDecoderInputBuffers[decoderInputBufferIndex];
            int size = videoExtractor.readSampleData(decoderInputBuffer, 0);
            long presentationTime = videoExtractor.getSampleTime();

            if (size >= 0) {
                videoDecoder.queueInputBuffer(
                        decoderInputBufferIndex,
                        0,
                        size,
                        presentationTime,
                        videoExtractor.getSampleFlags());
            }
            videoExtractorDone = !videoExtractor.advance();

            if (!videoExtractorDone && videoExtractor.getSampleTime() > mVideoDurationLimit * 1000000) { …
Run Code Online (Sandbox Code Playgroud)

android mediacodec

8
推荐指数
1
解决办法
639
查看次数

了解Android相机SurfaceTexture和MediaCodec Surface的用法

我正在尝试了解Android中的图形内存使用/流,特别是关于使用编码来自相机的帧的方面MediaCodec。为了做到这一点,我必须了解许多我不清楚的图形,OpenGL和Android术语/概念。我已经阅读了Android图形体系结构材料,一系列SO问题和大量资源,但我仍然感到困惑,主要是因为在不同的上下文中术语似乎具有不同的含义。

我已经从fadden的站点这里查看了CameraToMpegTest 。我的具体问题是如何MediaCodec::createInputSurface()与结合使用Camera::setPreviewTexture()。似乎先创建了OpenGL纹理,然后将其用于创建一个Android SurfaceTexture,然后可以将其传递给setPreviewTexture()。我的具体问题:

  1. 关于setPreviewTexture()帧从相机转到哪个内存缓冲区,调用实际上会做什么?
  2. 根据我的理解,OpenGL纹理是GPU可以访问的大量内存。在Android上,必须使用带有正确用法标记的gralloc进行分配。Android的说明中SurfaceTexture提到它允许您“将图像流式传输到给定的OpenGL纹理”:https : //developer.android.com/reference/android/graphics/Sur​​faceTexture.html#SurfaceTexture(int)SurfaceTexture在OpenGL纹理之上做什么?
  3. MediaCodec::createInputSurface()返回一个Android Surface。据我了解,Android Surface代表缓冲区队列的生产方,因此它可能是多个缓冲区。该API参考提到,“表面必须用硬件加速API来呈现,如OpenGL ES”。如何帧从相机获取捕捉SurfaceTexture到这Surface是输入到编码器?我看到CameraToMpegTest的创建EGLSurface使用这种Surface莫名其妙但不知道很多关于EGL我没有得到这个部分。
  4. 有人可以澄清“渲染”的用法吗?我看到诸如“渲染到表面”,“渲染到屏幕”之类的东西似乎可能意味着不同的含义。

编辑:mstorsjo的答复的后续行动:

  1. 我挖成的代码,SurfaceTextureCameraClient::setPreviewTarget()CameraService一些尝试和了解的内部运作Camera::setPreviewTexture()更好,有更多的问题。对于我最初理解内存分配的问题,似乎要SurfaceTexture创建一个BufferQueue并将其CameraService传递IGraphicBufferProducer给平台摄像机HAL实现。然后,摄像机HAL可以适当地设置gralloc使用标志(例如GRALLOC_USAGE_SW_READ_RARELY | GRALLOC_USAGE_SW_WRITE_NEVER | GRALLOC_USAGE_HW_TEXTURE),还可以从中退出缓冲区BufferQueue。因此,摄像机捕获帧的缓冲区是由gralloc分配的缓冲区,这些缓冲区带有一些特殊的使用标志,例如GRALLOC_USAGE_HW_TEXTURE。我在具有统一内存架构的ARM平台上工作,因此GPU和CPU可以访问相同的内存,因此,这会对您产生什么样的影响?GRALLOC_USAGE_HW_TEXTURE 标志有关于如何分配缓冲区的?
  2. 的OpenGL(ES)部分SurfaceTexture似乎主要是作为的一部分实现的GLConsumer,而魔术似乎在中 …

android opengl-es android-camera egl mediacodec

8
推荐指数
1
解决办法
2288
查看次数

如何检查Android MediaCodec是否支持恒定质量模式

我有一个屏幕录制应用程序,它使用MediaCodec编码器对视频帧进行编码.这是我检索视频编码器的一种方法:

videoCodec = MediaCodec.createEncoderByType(MediaFormat.MIMETYPE_VIDEO_AVC);
Run Code Online (Sandbox Code Playgroud)

然后我尝试确定此编码器支持的最佳比特率模式,我的优先顺序是"恒定质量"模式,可变比特率模式,恒定比特率模式.这是我尝试这样做的方式:

MediaCodecInfo.CodecCapabilities capabilities = videoCodec.getCodecInfo().getCapabilitiesForType(MediaFormat.MIMETYPE_VIDEO_AVC);
MediaCodecInfo.EncoderCapabilities encoderCapabilities = capabilities.getEncoderCapabilities();

if (encoderCapabilities.isBitrateModeSupported(MediaCodecInfo.EncoderCapabilities.BITRATE_MODE_CQ)) {
    Timber.i("Setting bitrate mode to constant quality");
    videoFormat.setInteger(MediaFormat.KEY_BITRATE_MODE, MediaCodecInfo.EncoderCapabilities.BITRATE_MODE_CQ);
} else if (encoderCapabilities.isBitrateModeSupported(MediaCodecInfo.EncoderCapabilities.BITRATE_MODE_VBR)) {
    Timber.w("Setting bitrate mode to variable bitrate");
    videoFormat.setInteger(MediaFormat.KEY_BITRATE_MODE, MediaCodecInfo.EncoderCapabilities.BITRATE_MODE_VBR);
} else if (encoderCapabilities.isBitrateModeSupported(MediaCodecInfo.EncoderCapabilities.BITRATE_MODE_CBR)) {
    Timber.w("Setting bitrate mode to constant bitrate");
    videoFormat.setInteger(MediaFormat.KEY_BITRATE_MODE, MediaCodecInfo.EncoderCapabilities.BITRATE_MODE_CBR);
}
Run Code Online (Sandbox Code Playgroud)

在我的三星Galaxy S7上运行它最终选择VBR模式,即据说不支持恒定质量模式.但是,如果我只是将BITRATE_MODE设置为恒定质量,它不仅可以工作,而且实际上可以产生比VBR模式更高质量的视频.

因此,如果此编码器显然支持恒定质量模式,为什么我会从isBitrateModeSupported()获得误报?我在这里错过了什么吗?

android video-capture video-encoding mediacodec

8
推荐指数
1
解决办法
814
查看次数

解码音频文件并重新编码为所需的PCM格式:44,100 kHz,2通道,16位

我想将音频文件解码为原始PCM数据,以将其流式传输到本地网络中的播放设备.我使用了引入API级别16 的新MediaExtractorMediaCodec类.该器件要求PCM数据为44,100 kHz,有2个通道和16位样本大小.只要输入文件大致符合这些要求,这就可以正常工作.但是,无论何时我正在解码使用的文件 - 例如 - 32,000 kHz的采样率并且可能只有一个通道,那么我无法从MediaCodec类获得所需的输出.

因为似乎无法指定MediaCodec类的输出格式.所以我决定实例化另一个MediaCodec对象,将原始数据重新编码为我想要的格式.根据Android 4.1 支持的媒体格式列表,Android支持编码到PCM/Wave.但是我无法创建编码为PCM/Wave的MediaCodec对象.我尝试将各种MIME类型传递给MediaCodec.createEncoderByType(type); 但我总是以IOException失败:

java.io.IOException: Failed to allocate component instance
at android.media.MediaCodec.native_setup(Native Method)
at android.media.MediaCodec.<init>(MediaCodec.java:210)
at android.media.MediaCodec.createEncoderByType(MediaCodec.java:194)
[..]
Run Code Online (Sandbox Code Playgroud)

有没有人能够成功创建编码为PCM/Wave的MediaCodec实例并且可以为我提供一个工作示例?

audio android pcm mediacodec mediaextractor

7
推荐指数
1
解决办法
4218
查看次数

Android提取解码编码Mux音频

我正在尝试调整ExtractDecodeEditEncodeMuxTest.java中的代码,以便从通过Cordova的device.capture.captureVideo录制的mp4中提取音频和视频,解码音频,编辑解码的音频样本,编码音频,并将音频复用回来用视频再次保存为mp4.

我的第一次尝试只是提取,解码,编码和复用音频而不尝试编辑任何音频样本 - 如果我能做到这一点,我相当确定我可以根据需要编辑解码的样本.我不需要编辑视频,因此我假设我可以简单地使用MediaExtractor来提取和复用视频轨道.

但是,我遇到的问题是我似乎无法正确地获得音频解码/编码过程.不断发生的事情是,复用器从提取的视频轨道和提取的 - >解码 - >编码的音频轨道创建mp4,但是当视频播放正常时,音频以短暂的噪声开始,然后看起来像是最后一个几秒钟的音频数据正常播放(但在视频的开头),然后静音播放视频的其余部分.

一些相关领域:

private MediaFormat audioFormat;
private MediaFormat videoFormat;
private int videoTrackIndex = -1;
private int audioTrackIndex = -1;
private static final int MAX_BUFFER_SIZE = 256 * 1024;

// parameters for the audio encoder
private static final String OUTPUT_AUDIO_MIME_TYPE = "audio/mp4a-latm"; // Advanced Audio Coding
private static final int OUTPUT_AUDIO_CHANNEL_COUNT = 2; // Must match the input stream. not using this, getting from input format
private static final int OUTPUT_AUDIO_BIT_RATE = …
Run Code Online (Sandbox Code Playgroud)

audio android multiplexing mediacodec mediamuxer

7
推荐指数
1
解决办法
2103
查看次数