java 来自java android的图像序列的视频编码

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14337091/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 15:54:48  来源:igfitidea点击:

Video encode from sequence of images from java android

javaandroidimagevideo-encodingandroid-image

提问by captaindroid

I would like to encode video from sequence of images with java only in my current android project. I mean without any use of external tools such as NDK.
Also is there any availability of java libraries for encoding video from sequence of images ?

我想仅在我当前的 android 项目中使用 java 对图像序列中的视频进行编码。我的意思是不使用任何外部工具,例如 NDK。
是否还有用于从图像序列编码视频的 Java 库?

回答by Stanislav Vitvitskyy

You can use a pure java library called JCodec ( http://jcodec.org). It contains a primitive yet working H.264 ( AVC ) encoder and a fully functioning MP4 ( ISO BMF ) muxer.
Here's a CORRECTEDcode sample that uses low-level API:

您可以使用名为 JCodec ( http://jcodec.org)的纯 Java 库。它包含一个原始但有效的 H.264 (AVC) 编码器和一个功能齐全的 MP4 (ISO BMF) 多路复用器。
这是一个使用低级 API的更正代码示例:

public void imageToMP4(BufferedImage bi) {
    // A transform to convert RGB to YUV colorspace
    RgbToYuv420 transform = new RgbToYuv420(0, 0);

    // A JCodec native picture that would hold source image in YUV colorspace
    Picture toEncode = Picture.create(bi.getWidth(), bi.getHeight(), ColorSpace.YUV420);

    // Perform conversion
    transform.transform(AWTUtil.fromBufferedImage(bi), yuv);

    // Create MP4 muxer
    MP4Muxer muxer = new MP4Muxer(sink, Brand.MP4);

    // Add a video track
    CompressedTrack outTrack = muxer.addTrackForCompressed(TrackType.VIDEO, 25);

    // Create H.264 encoder
    H264Encoder encoder = new H264Encoder(rc);

    // Allocate a buffer that would hold an encoded frame
    ByteBuffer _out = ByteBuffer.allocate(ine.getWidth() * ine.getHeight() * 6);

    // Allocate storage for SPS/PPS, they need to be stored separately in a special place of MP4 file
    List<ByteBuffer> spsList = new ArrayList<ByteBuffer>();
    List<ByteBuffer> ppsList = new ArrayList<ByteBuffer>();

    // Encode image into H.264 frame, the result is stored in '_out' buffer
    ByteBuffer result = encoder.encodeFrame(_out, toEncode);

    // Based on the frame above form correct MP4 packet
    H264Utils.encodeMOVPacket(result, spsList, ppsList);

    // Add packet to video track
    outTrack.addFrame(new MP4Packet(result, 0, 25, 1, 0, true, null, 0, 0));

    // Push saved SPS/PPS to a special storage in MP4
    outTrack.addSampleEntry(H264Utils.createMOVSampleEntry(spsList, ppsList));

    // Write MP4 header and finalize recording
    muxer.writeHeader();

}

You can download JCodec library from a project web site or via Maven, for this add the below snippet to your pom.xml:

您可以从项目网站或通过 Maven 下载 JCodec 库,为此将以下代码段添加到您的 pom.xml:

<dependency>
    <groupId>org.jcodec</groupId>
    <artifactId>jcodec</artifactId>
    <version>0.1.3</version>
</dependency>

[UPDATE 1]Android users can use something like below to convert Android Bitmap object to JCodec native format:

[更新 1]Android 用户可以使用类似下面的方法将 Android Bitmap 对象转换为 JCodec 原生格式:

public static Picture fromBitmap(Bitmap src) {
    Picture dst = Picture.create((int)src.getWidth(), (int)src.getHeight(), RGB);
    fromBitmap(src, dst);
    return dst;
}

public static void fromBitmap(Bitmap src, Picture dst) {
    int[] dstData = dst.getPlaneData(0);
    int[] packed = new int[src.getWidth() * src.getHeight()];

    src.getPixels(packed, 0, src.getWidth(), 0, 0, src.getWidth(), src.getHeight());

    for (int i = 0, srcOff = 0, dstOff = 0; i < src.getHeight(); i++) {
        for (int j = 0; j < src.getWidth(); j++, srcOff++, dstOff += 3) {
            int rgb = packed[srcOff];
            dstData[dstOff]     = (rgb >> 16) & 0xff;
            dstData[dstOff + 1] = (rgb >> 8) & 0xff;
            dstData[dstOff + 2] = rgb & 0xff;
        }
    }
}