标签: mediacodec

使用MediaCodec和MediaMuxer的图像到视频

我有一堆本地图像保存为jpeg文件.我的图像是使用CameraPreview捕获的,而PreviewFormat是默认值:NV21.我想从固定数量的图像生成一个小视频.

我不打算使用FFMpeg因为它需要NDK并且会引入兼容性问题.

MediaCodec和MediaMuxer似乎很有效,但网上没有一个可行的解决方案.

有一些参考资料导致我目前的解决方案.

1. EncodeAndMuxTest:http://bigflake.com/mediacodec/EncodeAndMuxTest.java.txt

这个是由法登写的.它非常适合我的需要,除了他使用的是createInputSurface而不是queueInputBuffer.

2. 将位图数组转换为YUV(YCbCr NV21)

我按照这个答案进行转换./sf/answers/1198188981/

3. 使用MediaCodec将一系列图像保存为视频

这个问题看起来与我的很相似,但我不打扰使用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 MIME_TYPE = "video/avc";

private static final int FRAME_RATE = 10;
// 10 seconds between I-frames
private static final int IFRAME_INTERVAL = 10;

private static final int NUM_FRAMES …
Run Code Online (Sandbox Code Playgroud)

android mediacodec

17
推荐指数
1
解决办法
1万
查看次数

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

我正在尝试将MediaCodec一系列图像(保存为文件中的字节数组)保存到视频文件中.我已经测试了这些图像SurfaceView(在系列中播放),我可以看到它们很好.我看了很多使用的例子MediaCodec,这是我理解的(如果我错了请纠正我):

从MediaCodec对象获取InputBuffers - >用你的帧的图像数据填充它 - >将输入缓冲区排队 - >获取编码输出缓冲区 - >将其写入文件 - >增加显示时间并重复

但是,我已经对此进行了很多测试,最终我遇到了两种情况之一:

  • 我试图模仿的所有示例项目都queueInputBuffer在第二次调用时导致Media服务器死机.
  • 我尝试codec.flush()在最后调用(在将输出缓冲区保存到文件之后,虽然我看到的所有示例都没有这样做)并且媒体服务器没有死,但是,我无法使用任何媒体播放器打开输出视频文件,所以出了点问题.

这是我的代码:

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.CONFIGURE_FLAG_ENCODE);

        codec.start();

        ByteBuffer[] inputBuffers = codec.getInputBuffers();
        ByteBuffer[] outputBuffers = codec.getOutputBuffers();
        boolean sawInputEOS = false;
        int inputBufferIndex=-1,outputBufferIndex=-1;
        BufferInfo info=null;

                    //loop …
Run Code Online (Sandbox Code Playgroud)

video android mediacodec

16
推荐指数
1
解决办法
1万
查看次数

MediaExtractor,带有原始/资产文件的MediaMetadataRetriever

我尝试在raw/assets文件夹中读取视频文件,我尝试了以下方法,但没有一个工作.我正在测试API 16.每种方法,我尝试使用和不使用mp4扩展.我真的很感激有人可以帮助我

所有方法都不会崩溃,MediaMetadataRetriever可以设置数据源,但不能获取宽度,高度和截图.VideoExtractor总是回来

06-04 16:44:10.519: E/FileSource(8695): Failed to open file FILE_PATH. (No such file or directory)
06-04 16:44:10.519: E/DecodeActivity(8695): Can't find video info!
Run Code Online (Sandbox Code Playgroud)

方法1:android.resource

String filePath = "android.resource://" + this.activity.getPackageName() + "/raw/green_backhand_slice";
videoExtractor.setDataSource(activity.getApplicationContext(), Uri.parse(filePath), null);
metaRetriever.setDataSource(act.getApplication(), Uri.parse(filePath));
Run Code Online (Sandbox Code Playgroud)

方法2:android_asset

this.filePath = "file:///android_asset/green_backhand_slice";
videoExtractor.setDataSource(activity.getApplicationContext(), Uri.parse(this.filePath), null);
metaRetriever.setDataSource(act.getApplication(), Uri.parse(filePath));
Run Code Online (Sandbox Code Playgroud)

方法3:资产文件描述符

AssetFileDescriptor assetFD = null;
try {
    assetFD = getAssets().openFd("green_backhand_slice.mp4");
} catch (IOException e) {
    e.printStackTrace();
}

metaRetriever.setDataSource(assetFD.getFileDescriptor());
Run Code Online (Sandbox Code Playgroud)

android mediacodec mediametadataretriever

16
推荐指数
1
解决办法
4893
查看次数

如何使用MediaCodec Android压缩mp4视频?

在我的Android应用程序中,我想通过更改其分辨率,比特率来压缩mp4视频.我不想使用FFmpeg(因为我不想使用NDK),所以我决定使用MediaCodec API.

以下是我的逻辑步骤:

  1. 使用MediaExtractor提取视频文件,然后解码数据.
  2. 使用我的新分辨率,比特率和编码数据创建新的编码器.
  3. 使用MediaMuxer创建新的mp4文件.

我的问题是:我不知道如何设置解码器输出和编码器输入之间的连接.我可以将视频解码为Surface或从曲面编码新视频.但我不明白如何连接它们.

我读了这些链接:Android MediaCodec:使用新的MediaCodec库和Bigflake的示例减少mp4视频大小,Android上的视频压缩:https://android.googlesource.com/platform/cts/+/jb-mr2-release/tests /tests/media/src/android/media/cts/DecodeEditEncodeTest.java

谁能给我一个明确的解释我要做什么?

compression mp4 android mediacodec

16
推荐指数
1
解决办法
1万
查看次数

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

理想情况下,我想完成两个目标:

  1. 通过Camera预览将预览数据传递给MediaCodec编码器Surface.我可以创建Surface使用MediaCodec.createInputSurface()但是Camera.setPreviewDisplay()需要a SurfaceHolder,而不是a Surface.
  2. 除了将Camera预览数据传递给编码器之外,我还想在屏幕上显示预览(这样用户实际上可以看到他们编码的内容).如果编码器没有参与,那么我会使用a SurfaceView,但这似乎不适用于这种情况,因为SurfaceView创建了自己的编码器Surface,我认为我需要使用创建的编码器MediaCodec.

我在网上搜索了很多解决方案,但没有找到解决方案.bigflake.com上的一些例子似乎是朝着正确方向迈出的一步,但他们采取了一种方法,增加了一堆我想避免的EGL/SurfaceTexture开销.我希望有一个简单的例子或解决方案,我能得到Camera并且MediaCodec不涉及EGL或纹理更直接交谈.

camera android encoder surfaceview mediacodec

15
推荐指数
1
解决办法
5429
查看次数

在Android上使用AudioRecord和MediaCodec编码AAC音频

我正在尝试使用Android AudioRecord和MediaCodec编码aac音频.我创建了一个非常类似的编码器类(使用Android MediaCodec从相机编码H.264).通过这个类,我创建了一个AudioRecord实例,并告诉它将其byte []数据读出到AudioEncoder(audioEncoder.offerEncoder(Data)).

 while(isRecording) 
 {
  audioRecord.read(Data, 0, Data.length);
  audioEncoder.offerEncoder(Data);
 }
Run Code Online (Sandbox Code Playgroud)

这是我的AudioRecord设置

    int audioSource = MediaRecorder.AudioSource.MIC;
    int sampleRateInHz = 44100;
    int channelConfig = AudioFormat.CHANNEL_IN_MONO;
    int audioFormat = AudioFormat.ENCODING_PCM_16BIT;
    int bufferSizeInBytes = AudioRecord.getMinBufferSize(sampleRateInHz, channelConfig, audioFormat);
Run Code Online (Sandbox Code Playgroud)

我成功收集了一些byte []数组数据并将其写入本地文件.不幸的是,该文件无法播放.我做了一些在线搜索,发现了一个相关的帖子(如何使用Android MediaCodec生成AAC ADTS基本流).因此,遇到类似问题的其他人说主要问题是"MediaCodec编码器生成原始AAC流.原始AAC流需要转换为可播放格式,例如ADTS流".所以我尝试添加ADTS标头.然而,在我添加了ADTS头之后(我在下面的代码中注释掉了),我的AudioEncoder甚至都不会写输出音频文件.有什么我想念的吗?我的设置是否正确?

欢迎任何建议,意见和意见,非常感谢.多谢你们!

import android.media.MediaCodec;
import android.media.MediaCodecInfo;
import android.media.MediaFormat;
import android.os.Environment;
import android.util.Log;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;

public class AudioEncoder {

    private MediaCodec mediaCodec;
    private BufferedOutputStream outputStream;
    private String mediaType = "audio/mp4a-latm";

    public AudioEncoder() …
Run Code Online (Sandbox Code Playgroud)

android aac audiorecord mediacodec

15
推荐指数
2
解决办法
2万
查看次数

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

我正在开发一个记录屏幕视频和音频的Android应用程序.
我录制了这两个文件:mp3音频文件和mp4视频文件(没有声音).

现在我想混合它们并创建一个新的mp4视频文件(带声音).从Android 4.3开始,Google建议使用MediaMuxer该类来混合流音频和视频.我多次尝试都没有成功.

MediaMuxer从Google 解决我的API 问题的任何解决方案?任何帮助将不胜感激.

audio video android mediacodec

15
推荐指数
2
解决办法
8259
查看次数

使用Android的MediaCodec和MediaMuxer复用AAC音频

我正在修改一个Android Framework示例,将MediaCodec生成的基本AAC流打包成一个独立的.mp4文件.我正在使用MediaMuxer包含由MediaCodec实例生成的一个AAC轨道的单个实例.

但是,我总是在调用时始终收到错误消息mMediaMuxer.writeSampleData(trackIndex, encodedData, bufferInfo):

E/MPEG4Writer?timestampUs 0 < lastTimestampUs XXXXX for Audio track

当我将原始输入数据排队时,mCodec.queueInputBuffer(...)我提供0作为每个框架示例的时间戳值(我也尝试使用具有相同结果的单调增加的时间戳值.我已成功将原始相机帧编码为h264/mp4文件同样的方法).

查看完整的来源

最相关的片段:

private static void testEncoder(String componentName, MediaFormat format, Context c) {
    int trackIndex = 0;
    boolean mMuxerStarted = false;
    File f = FileUtils.createTempFileInRootAppStorage(c, "aac_test_" + new Date().getTime() + ".mp4");
    MediaCodec codec = MediaCodec.createByCodecName(componentName);

    try {
        codec.configure(
                format,
                null /* surface */,
                null /* crypto */,
                MediaCodec.CONFIGURE_FLAG_ENCODE);
    } catch (IllegalStateException e) {
        Log.e(TAG, "codec '" + …
Run Code Online (Sandbox Code Playgroud)

android mediacodec

14
推荐指数
1
解决办法
1万
查看次数

使用MediaCodec记录曲面

因此,在我的应用程序中,我能够使用GPUImage库向来自Camera的视频显示效果(如模糊滤镜,高斯).

基本上,我(库)将来自摄像机的输入,获得真实的原始字节的数据,将其转换为从YUV格式RGBA格式,然后应用上的影响到该图像和显示器SurfaceGLSurfaceView使用OpenGL.最后,对于用户来说,它看起来像是应用了效果的视频.

现在我想Surface使用MediaCodec API 将视频帧记录下来.

但是这个讨论说我们无法将预定义传递SurfaceMediaCodec.

我在bigflake看到了一些他正在Surface使用的样品,MediaCodec.createInputSurface()但对我来说,Surface来自于GLSurfaceView.

那么,我如何录制Surface视频的帧?

我将并行录制音频,使用FFMPEG合并该视频和音频,并作为应用效果的视频呈现给用户.

android ffmpeg opengl-es glsurfaceview mediacodec

14
推荐指数
1
解决办法
5078
查看次数

Android MediaCodec在异步模式下编码和解码

我正在尝试解码文件中的视频,并使用API Level 21及更高版本(Android OS 5.0 Lollipop)支持MediaCodec的新异步模式将其编码为不同的格式.

Big Flake,Google的Grafika等网站上以同步模式执行此操作有很多示例,并且StackOverflow上有许多答案,但它们都不支持异步模式.

我不需要在此过程中显示视频.

我相信一般的程序是用一个读取文件MediaExtractor作为MediaCodec(解码器)的输入,允许解码器的输出渲染成一个Surface也是共享输入到MediaCodec(编码器),然后最后写入编码器输出文件通过MediaMuxer.它Surface是在编码器设置期间创建的,并与解码器共享.

我可以将视频解码为a TextureView,但Surface与编码器共享而不是屏幕也没有成功.

MediaCodec.Callback()为我的两个编解码器设置了s.我认为问题在于我不知道在Encoder的回调onInputBufferAvailable()函数中该怎么做.我不知道(或知道如何)将数据从Surface编码器复制到编码器中 - 这应该自动发生(就像在解码器输出上一样codec.releaseOutputBuffer(outputBufferId, true);).然而,我认为onInputBufferAvailable需要打电话codec.queueInputBuffer才能运作.我只是不知道如何设置参数而不从像MediaExtractorDecode端使用的那样获取数据.

如果您有一个打开视频文件MediaCodec示例,对其进行解码,使用异步回调将其编码为不同的分辨率或格式,然后将其保存为文件,请分享您的示例代码.

=== 编辑 ===

下面是我在异步模式下尝试做的同步模式的一个工作示例:ExtractDecodeEditEncodeMuxTest.java:https://android.googlesource.com/platform/cts/+/jb-mr2-release/tests/tests/media /src/android/media/cts/ExtractDecodeEditEncodeMuxTest.java这个例子在我的应用程序中工作

Android MediaCodec

android video-encoding mediacodec android-5.0-lollipop android-5.1.1-lollipop

14
推荐指数
1
解决办法
9914
查看次数