Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java - h.264 video encoding

I'm trying to make a program that can encode and decode h.264 video so I can edit this video. Can anyone tell me how I do this if I want to make this program in java?

like image 225
Mahfud Harun Avatar asked Jan 24 '12 15:01

Mahfud Harun


People also ask

What is video encoding h264?

H. 264 is a well-known video compression standard for high-definition digital video. Also known as MPEG-4 Part 10 or Advanced Video Coding (MPEG-4 AVC), H. 264 is defined as a block-oriented, compensation-based video compression standard that defines multiple profiles (tools) and levels (max bitrates and resolutions).

Is H 264 codec free?

MPEG LA has allowed the free use of H. 264 technologies for streaming Internet video that is free to end users, and Cisco Systems pays royalties to MPEG LA on behalf of the users of binaries for its open source H. 264 encoder.

Is H 264 A good codec?

Nowadays, H. 264 codec is most commonly used in video streaming. This codec is an industry standard for video compression that helps creators record, compress, and distribute their online videos. It delivers good video quality at lower bitrates compared to previous standards.

Which encoder is best h264?

Zencoder encodes H. 264 content using a variety of software, but our core encoder is the excellent x264, the best H. 264 encoder available, and one of the best video encoding implementations for any codec.


2 Answers

There is a Java wrapper available for VLC: http://www.capricasoftware.co.uk/projects/vlcj/

like image 22
Bas Avatar answered Oct 07 '22 06:10

Bas


You can use JCodec ( http://jcodec.org ).

To decode a video sequence go:

int frameNumber = 10000;
FileChannelWrapper ch = null;
try {
    ch = NIOUtils.readableFileChannel(new File(path to mp4));
    FrameGrab frameGrab = new FrameGrab(ch);

    frameGrab.seek(frameNumber);
    Picture frame;
    for (int i = 0; (frame = frameGrab.getNativeFrame()) != null && i < 200; i++) {
        // Do something
    }
} finally {
    NIOUtils.closeQuietly(ch);
}

To encode a sequence:

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

    public SequenceEncoder(File out) throws IOException {
        this.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(Picture bi) throws IOException {
        if (toEncode == null) {
            toEncode = Picture.create(bi.getWidth(), bi.getHeight(), ColorSpace.YUV420);
        }

        // Perform conversion ( RGB -> YUV )
        transform.transform(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);
    }
}

And finally to convert TO and FROM Android image use:

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;
        }
    }
}

public static Bitmap toBitmap(Picture src) {
    Bitmap dst = Bitmap.create(pic.getWidth(), pic.getHeight(), ARGB_8888);
    toBitmap(src, dst);
    return dst;
}

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

    for (int i = 0, dstOff = 0, srcOff = 0; i < src.getHeight(); i++) {
        for (int j = 0; j < src.getWidth(); j++, dstOff++, srcOff += 3) {
            packed[dstOff] = (srcData[srcOff] << 16) | (srcData[srcOff + 1] << 8) | srcData[srcOff + 2];
        }
    }
    dst.setPixels(packed, 0, src.getWidth(), 0, 0, src.getWidth(), src.getHeight());
}

FINALLY on decoding you'll get YUV frame out, in order to transform it to RGB frame go:

Transform transform = ColorUtil.getTransform(pic.getColor(), ColorSpace.RGB);
Picture rgb = Picture.create(pic.getWidth(), pic.getHeight(), ColorSpace.RGB);
transform.transform(pic, rgb);

And make sure your download JAR with all deps: http://jcodec.org/downloads/jcodec-0.1.3-uberjar.jar

like image 65
Stanislav Vitvitskyy Avatar answered Oct 07 '22 07:10

Stanislav Vitvitskyy