Not logged in.  Login/Logout/Register | List snippets | | Create snippet | Upload image | Upload data

229
LINES

< > BotCompany Repo | #1034384 // JavaCPP ffpmeg Decode H264 Demo [Windows, testing]

JavaX source code (desktop) [tags: use-pretranspiled] - run with: x30.jar

Download Jar. Uses 18364K of libraries. Click here for Pure Java version (5259L/30K).

1  
!7
2  
3  
// argument: mkv file to read
4  
// output: png files
5  
6  
// from https://github.com/vzhn/ffmpeg-java-samples/blob/master/src/main/java/DemuxAndDecodeH264.java
7  
8  
lib 1400558 // javacpp ffmpeg examples for Win x64
9  
10  
p { DemuxAndDecodeH264.main(args); }
11  
12  
import org.bytedeco.javacpp.*;
13  
14  
import javax.imageio.ImageIO;
15  
import java.awt.image.BufferedImage;
16  
import java.awt.image.DataBufferByte;
17  
import java.io.File;
18  
import java.io.IOException;
19  
import java.time.Duration;
20  
import java.time.temporal.ChronoUnit;
21  
22  
import static org.bytedeco.javacpp.avcodec.*;
23  
import static org.bytedeco.javacpp.avformat.*;
24  
import static org.bytedeco.javacpp.avutil.*;
25  
import org.bytedeco.javacpp.presets.avutil;
26  
27  
/**
28  
* Read and decode h264 video from matroska (MKV) container
29  
*/
30  
sclass DemuxAndDecodeH264 {
31  
    /** Matroska format context */
32  
    private AVFormatContext avfmtCtx;
33  
34  
    /** Matroska video stream information  */
35  
    private AVStream videoStream;
36  
37  
    /** matroska packet */
38  
    private AVPacket avpacket;
39  
40  
    /** H264 Decoder ID */
41  
    private AVCodec codec;
42  
43  
    /** H264 Decoder context */
44  
    private AVCodecContext codecContext;
45  
46  
    /** yuv420 frame */
47  
    private AVFrame yuv420Frame;
48  
49  
    /** RGB frame */
50  
    private AVFrame rgbFrame;
51  
52  
    /** java RGB frame */
53  
    private BufferedImage img;
54  
55  
    /** yuv420 to rgb converter */
56  
    private swscale.SwsContext sws_ctx;
57  
58  
    /** number of frame */
59  
    private int nframe;
60  
    
61  
    int maxFrames = 10;
62  
63  
    /* 1/1000 of second */
64  
    private AVRational tb1000;
65  
66  
    private DemuxAndDecodeH264() {
67  
        tb1000 = new AVRational();
68  
        tb1000.num(1);
69  
        tb1000.den(1000);
70  
    }
71  
72  
    public static void main(String... argv) throws IOException {
73  
        new DemuxAndDecodeH264().start(argv);
74  
    }
75  
76  
    private void start(String[] argv) throws IOException {
77  
        av_log_set_level(AV_LOG_VERBOSE);
78  
79  
        openInput(argv[0]);
80  
        findVideoStream();
81  
        initDecoder();
82  
        initRgbFrame();
83  
        initYuv420Frame();
84  
        getSwsContext();
85  
86  
        avpacket = new avcodec.AVPacket();
87  
        while ((av_read_frame(avfmtCtx, avpacket)) >= 0 && !done()) {
88  
            if (avpacket.stream_index() == videoStream.index()) {
89  
                processAVPacket(avpacket);
90  
            }
91  
            av_packet_unref(avpacket);
92  
        }
93  
        // now process delayed frames
94  
        if (!done()) processAVPacket(null);
95  
        free();
96  
    }
97  
98  
    private AVFormatContext openInput(String file) throws IOException {
99  
        avfmtCtx = new AVFormatContext(null);
100  
        BytePointer filePointer = new BytePointer(file);
101  
        int r = avformat.avformat_open_input(avfmtCtx, filePointer, null, null);
102  
        filePointer.deallocate();
103  
        if (r < 0) {
104  
            avfmtCtx.close();
105  
            throw new IOException("avformat_open_input error: " + r);
106  
        }
107  
        return avfmtCtx;
108  
    }
109  
110  
    private void findVideoStream() throws IOException {
111  
        int r = avformat_find_stream_info(avfmtCtx, (PointerPointer) null);
112  
        if (r < 0) {
113  
            avformat_close_input(avfmtCtx);
114  
            avfmtCtx.close();
115  
            throw new IOException("error: " + r);
116  
        }
117  
118  
        PointerPointer<AVCodec> decoderRet = new PointerPointer<>(1);
119  
        int videoStreamNumber = av_find_best_stream(avfmtCtx, AVMEDIA_TYPE_VIDEO, -1, -1, decoderRet, 0);
120  
        if (videoStreamNumber < 0) {
121  
            throw new IOException("failed to find video stream");
122  
        }
123  
124  
        if (decoderRet.get(AVCodec.class).id() != AV_CODEC_ID_H264) {
125  
            throw new IOException("failed to find h264 stream");
126  
        }
127  
        decoderRet.deallocate();
128  
        videoStream =  avfmtCtx.streams(videoStreamNumber);
129  
    }
130  
131  
    private void initDecoder() {
132  
        codec = avcodec_find_decoder(AV_CODEC_ID_H264);
133  
        codecContext = avcodec_alloc_context3(codec);
134  
        if((codec.capabilities() & avcodec.AV_CODEC_CAP_TRUNCATED) != 0) {
135  
            codecContext.flags(codecContext.flags() | avcodec.AV_CODEC_CAP_TRUNCATED);
136  
        }
137  
        avcodec_parameters_to_context(codecContext, videoStream.codecpar());
138  
        if(avcodec_open2(codecContext, codec, (PointerPointer) null) < 0) {
139  
            throw new RuntimeException("Error: could not open codec.\n");
140  
        }
141  
    }
142  
143  
    private void initYuv420Frame() {
144  
        yuv420Frame = av_frame_alloc();
145  
        if (yuv420Frame == null) {
146  
            throw new RuntimeException("Could not allocate video frame\n");
147  
        }
148  
    }
149  
150  
    private void initRgbFrame() {
151  
        rgbFrame = av_frame_alloc();
152  
        rgbFrame.format(AV_PIX_FMT_BGR24);
153  
        rgbFrame.width(codecContext.width());
154  
        rgbFrame.height(codecContext.height());
155  
        int ret = av_image_alloc(rgbFrame.data(),
156  
                rgbFrame.linesize(),
157  
                rgbFrame.width(),
158  
                rgbFrame.height(),
159  
                rgbFrame.format(),
160  
                1);
161  
        if (ret < 0) {
162  
            throw new RuntimeException("could not allocate buffer!");
163  
        }
164  
        img = new BufferedImage(rgbFrame.width(), rgbFrame.height(), BufferedImage.TYPE_3BYTE_BGR);
165  
    }
166  
167  
    private void getSwsContext() {
168  
        sws_ctx = swscale.sws_getContext(
169  
                codecContext.width(), codecContext.height(), codecContext.pix_fmt(),
170  
                rgbFrame.width(), rgbFrame.height(), rgbFrame.format(),
171  
                0, null, null, (DoublePointer) null);
172  
    }
173  
174  
    private void processAVPacket(AVPacket avpacket) throws IOException {
175  
        int ret = avcodec.avcodec_send_packet(codecContext, avpacket);
176  
        if (ret < 0) {
177  
            throw new RuntimeException("Error sending a packet for decoding\n");
178  
        }
179  
        receiveFrames();
180  
    }
181  
    
182  
    bool done() { ret nframe >= maxFrames; }
183  
184  
    private void receiveFrames() throws IOException {
185  
        int ret = 0;
186  
        while (ret >= 0 && !done()) {
187  
            ret = avcodec.avcodec_receive_frame(codecContext, yuv420Frame);
188  
            if (ret == avutil.AVERROR_EAGAIN()
189  
              || ret == org.bytedeco.javacpp.avutil.AVERROR_EOF()) {
190  
                continue;
191  
            } else
192  
            if (ret < 0) {
193  
                throw new RuntimeException("error during decoding");
194  
            }
195  
            swscale.sws_scale(sws_ctx, yuv420Frame.data(), yuv420Frame.linesize(), 0,
196  
                    yuv420Frame.height(), rgbFrame.data(), rgbFrame.linesize());
197  
198  
            rgbFrame.best_effort_timestamp(yuv420Frame.best_effort_timestamp());
199  
            processFrame(rgbFrame);
200  
        }
201  
    }
202  
203  
    private void processFrame(AVFrame rgbFrame) throws IOException {
204  
        DataBufferByte buffer = (DataBufferByte) img.getRaster().getDataBuffer();
205  
        rgbFrame.data(0).get(buffer.getData());
206  
207  
        long ptsMillis = av_rescale_q(rgbFrame.best_effort_timestamp(), videoStream.time_base(), tb1000);
208  
        Duration d = Duration.of(ptsMillis, ChronoUnit.MILLIS);
209  
210  
        String name = String.format("img_%05d_%02d-%02d-%02d-%03d.png", ++nframe,
211  
                d.toHoursPart(),
212  
                d.toMinutesPart(),
213  
                d.toSecondsPart(),
214  
                d.toMillisPart());
215  
        ImageIO.write(img, "png", new File(name));
216  
    }
217  
218  
    private void free() {
219  
        av_packet_unref(avpacket);
220  
        avcodec.avcodec_close(codecContext);
221  
        avcodec.avcodec_free_context(codecContext);
222  
223  
        swscale.sws_freeContext(sws_ctx);
224  
        av_frame_free(rgbFrame);
225  
        av_frame_free(yuv420Frame);
226  
        avformat.avformat_close_input(avfmtCtx);
227  
        avformat.avformat_free_context(avfmtCtx);
228  
    }
229  
}

Author comment

Began life as a copy of #1033824

download  show line numbers  debug dex  old transpilations   

Travelled to 5 computer(s): bhatertpkbcr, iveijnkanddl, mqqgnosmbjvj, tpturoigtvwk, xeobevbjagfg

No comments. add comment

Snippet ID: #1034384
Snippet name: JavaCPP ffpmeg Decode H264 Demo [Windows, testing]
Eternal ID of this version: #1034384/1
Text MD5: cbd5c8778e34bc04484027d6db2a654b
Transpilation MD5: b6272f93e4662f52d9dca1584af54ac2
Author: stefan
Category: javax / gazelle v
Type: JavaX source code (desktop)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2022-02-04 21:53:11
Source code size: 7715 bytes / 229 lines
Pitched / IR pitched: No / No
Views / Downloads: 193 / 807
Referenced in: [show references]