gpt4 book ai didi

java - 如何使用 JCodec 将一系列图像转换为视频?

转载 作者:行者123 更新时间:2023-11-30 09:09:04 26 4
gpt4 key购买 nike

我正在尝试使用 JCodec 将一系列图像转换为 Java SE 桌面应用程序内的视频。我尝试过的几种方法都导致了 Windows Media Player 无法播放的视频。

我不清楚这是编解码器问题(有疑问)还是我没有正确创建视频。当我尝试在 Windows Media Player 中播放视频时,我得到:

Windows Media Player cannot play the file. The Player might not support the file type or might not support the codec that was used to compress the file.

这是我最近使用的拼凑示例。我真的不了解视频格式的内部结构,所以我什至不完全确定某些代码在做什么。

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;

import javax.imageio.ImageIO;

import org.jcodec.codecs.h264.H264Encoder;
import org.jcodec.codecs.h264.H264Utils;
import org.jcodec.common.NIOUtils;
import org.jcodec.common.SeekableByteChannel;
import org.jcodec.common.model.ColorSpace;
import org.jcodec.common.model.Picture;
import org.jcodec.containers.mp4.Brand;
import org.jcodec.containers.mp4.MP4Packet;
import org.jcodec.containers.mp4.TrackType;
import org.jcodec.containers.mp4.muxer.FramesMP4MuxerTrack;
import org.jcodec.containers.mp4.muxer.MP4Muxer;
import org.jcodec.scale.AWTUtil;
import org.jcodec.scale.RgbToYuv420;

public class CreateVideo {
private SeekableByteChannel ch;
private Picture toEncode;
private RgbToYuv420 transform;
private H264Encoder encoder;
private ArrayList<ByteBuffer> spsList;
private ArrayList<ByteBuffer> ppsList;
private FramesMP4MuxerTrack outTrack;
private ByteBuffer _out;
private int frameNo;
private MP4Muxer muxer;

public CreateVideo(File out) throws IOException {
ch = NIOUtils.writableFileChannel(out);

// Transform to convert between RGB and YUV
transform = new RgbToYuv420(0, 0);

// Muxer that will store the encoded frames
muxer = new MP4Muxer(ch, Brand.MP4);

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

// Allocate a buffer big enough to hold output frames
_out = ByteBuffer.allocate(1920 * 1080 * 6);

// Create an instance of encoder
encoder = new H264Encoder();

// Encoder extra data ( SPS, PPS ) to be stored in a special place of
// MP4
spsList = new ArrayList<ByteBuffer>();
ppsList = new ArrayList<ByteBuffer>();

}

public void encodeImage(BufferedImage bi) throws IOException {
if (toEncode == null) {
toEncode = Picture.create(bi.getWidth(), bi.getHeight(), ColorSpace.YUV420);
}

// Perform conversion
for (int i = 0; i < 3; i++) {
Arrays.fill(toEncode.getData()[i], 0);
}
transform.transform(AWTUtil.fromBufferedImage(bi), toEncode);

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

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

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

frameNo++;
}

public void finish() throws IOException {
// Push saved SPS/PPS to a special storage in MP4
outTrack.addSampleEntry(H264Utils.createMOVSampleEntry(spsList, ppsList));

// Write MP4 header and finalize recording
muxer.writeHeader();
NIOUtils.closeQuietly(ch);
}

public static void main(String[] args) throws IOException {
CreateVideo encoder = new CreateVideo(new File("C:\\video\\video.mp4"));
for (int i = 10; i < 34; i++) {
String filename = String.format("C:\\video\\%02d.png", i);
BufferedImage bi = ImageIO.read(new File(filename));
encoder.encodeImage(bi);
}
encoder.finish();
}
}

如果有更简单的编解码器/容器,我不会依赖 H264 或 MP4。唯一的要求是它应该在没有安装额外软件的基准 Windows 7 机器上播放。

最佳答案

我在使用 jcodec 的 RgbToYuv420() 转换时遇到了很多问题。
我使用自己的函数将 RGB BufferedImage 转换为 Yuv420。
我遇到的一个问题是 RgbToYuv420 平均计算的 upix 和 vpix值,这导致我的 mp4 中的颜色都不稳定。

// make a YUV420J out of BufferedImage pixels
private Picture makeFrame(BufferedImage bi, ColorSpace cs)
{
DataBuffer imgdata = bi.getRaster().getDataBuffer();
int[] ypix = new int[imgdata.getSize()];
int[] upix = new int[ imgdata.getSize() >> 2 ];
int[] vpix = new int[ imgdata.getSize() >> 2 ];
int ipx = 0, uvoff = 0;

for (int h = 0; h < bi.getHeight(); h++) {
for (int w = 0; w < bi.getWidth(); w++) {
int elem = imgdata.getElem(ipx);
int r = 0x0ff & (elem >>> 16);
int g = 0x0ff & (elem >>> 8);
int b = 0x0ff & elem;
ypix[ipx] = ((66 * r + 129 * g + 25 * b) >> 8) + 16;
if ((0 != w % 2) && (0 != h % 2)) {
upix[uvoff] = (( -38 * r + -74 * g + 112 * b) >> 8) + 128;
vpix[uvoff] = (( 112 * r + -94 * g + -18 * b) >> 8) + 128;
uvoff++;
}
ipx++;
}
}
int[][] pix = { ypix, upix, vpix, null };
// old API
// return new Picture(bi.getWidth(), bi.getHeight(), pix, ColorSpace.YUV420J);
return Picture.createPicture(bi.getWidth(), bi.getHeight(), pix, ColorSpace.YUV420J);
}

关于java - 如何使用 JCodec 将一系列图像转换为视频?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23220486/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com