Download Jar. Uses 16081K of libraries. Click here for Pure Java version (319L/3K).
1 | !7 |
2 | |
3 | // from https://github.com/vzhn/ffmpeg-java-samples/blob/master/src/main/java/EncodeAndMuxH264.java |
4 | |
5 | /*lib 1400538 |
6 | lib 1400539 |
7 | lib 1400540 |
8 | lib 1400541 |
9 | lib 1400542 |
10 | lib 1400543*/ |
11 | lib 1400544 // javacpp ffmpeg examples for linux x64 |
12 | |
13 | p { EncodeAndMuxH264.main(args); } |
14 | |
15 | import org.apache.commons.cli.CommandLine; |
16 | import org.apache.commons.cli.DefaultParser; |
17 | import org.apache.commons.cli.Option; |
18 | import org.apache.commons.cli.Options; |
19 | import org.apache.commons.cli.HelpFormatter; |
20 | import org.apache.commons.cli.ParseException; |
21 | import org.bytedeco.javacpp.*; |
22 | |
23 | import java.awt.*; |
24 | import java.awt.image.BufferedImage; |
25 | import java.awt.image.DataBufferByte; |
26 | |
27 | import static org.bytedeco.javacpp.avcodec.*; |
28 | import static org.bytedeco.javacpp.avformat.*; |
29 | import static org.bytedeco.javacpp.avutil.*; |
30 | import static org.bytedeco.javacpp.swscale.sws_getContext; |
31 | |
32 | sclass EncodeAndMuxH264 { |
33 | private final static String DEFAULT_FPS = "30"; |
34 | private static final String DEFAULT_BITRATE = "400000"; |
35 | private static final String DEFAULT_WIDTH = "640"; |
36 | private static final String DEFAULT_HEIGHT = "320"; |
37 | private static final String DEFAULT_GOP = "60"; |
38 | private static final String DEFAULT_MAX_B_FRAMES = "12"; |
39 | private static final String DEFAULT_N_FRAMES = "300"; |
40 | private static final String DEFAULT_PROFILE = "baseline"; |
41 | private static final String DEFAULT_FILE = "out.mkv"; |
42 | |
43 | private AVFrame frame; |
44 | private AVFrame rgbFrame; |
45 | private swscale.SwsContext swsContext; |
46 | private BufferedImage image; |
47 | private AVCodecContext cc; |
48 | private int fps; |
49 | private int bitrate; |
50 | private int width; |
51 | private int height; |
52 | private int gopSize; |
53 | private int maxBFrames; |
54 | private int nFrames; |
55 | private String profile; |
56 | private AVCodec codec; |
57 | private AVFormatContext oc; |
58 | private AVOutputFormat fmt; |
59 | private String ofile; |
60 | private AVRational streamTimebase; |
61 | private AVRational codecTimebase; |
62 | private AVPacket pkt; |
63 | |
64 | private EncodeAndMuxH264() {} |
65 | |
66 | public static void main(String... argv) throws ParseException { |
67 | Options options = new Options(); |
68 | options.addOption("help", false, "show help and exit"); |
69 | options.addOption("fps", true, "fps"); |
70 | options.addOption("bitrate", true, "bitrate"); |
71 | options.addOption("width", true, "width"); |
72 | options.addOption("height", true, "height"); |
73 | options.addOption("gop", true, "gop"); |
74 | options.addOption("max_b_frames", true, "max_b_frames"); |
75 | options.addOption("n_frames", true, "number of frames"); |
76 | options.addOption("profile", true, "h264 profile"); |
77 | options.addOption("file", true, "output file name"); |
78 | CommandLine cmd = new DefaultParser().parse(options, argv); |
79 | if (cmd.hasOption("help")) { |
80 | HelpFormatter helpFormatter = new HelpFormatter(); |
81 | helpFormatter.printHelp("EncodeAndMuxH264 [options]", options); |
82 | } else { |
83 | System.out.println("options:"); |
84 | EncodeAndMuxH264 instance = new EncodeAndMuxH264(); |
85 | instance.fps = Integer.parseInt(getOption(cmd, "fps", DEFAULT_FPS)); |
86 | instance.bitrate = Integer.parseInt(getOption(cmd, "bitrate", DEFAULT_BITRATE)); |
87 | instance.width = Integer.parseInt(getOption(cmd,"width", DEFAULT_WIDTH)); |
88 | instance.height = Integer.parseInt(getOption(cmd,"height", DEFAULT_HEIGHT)); |
89 | instance.gopSize = Integer.parseInt(getOption(cmd,"gop", DEFAULT_GOP)); |
90 | instance.maxBFrames = Integer.parseInt(getOption(cmd,"max_b_frames", DEFAULT_MAX_B_FRAMES)); |
91 | instance.nFrames = Integer.parseInt(getOption(cmd,"n_frames", DEFAULT_N_FRAMES)); |
92 | instance.profile = getOption(cmd,"profile", DEFAULT_PROFILE); |
93 | instance.ofile = getOption(cmd,"file", DEFAULT_FILE); |
94 | |
95 | instance.start(); |
96 | } |
97 | } |
98 | |
99 | private static String getOption(CommandLine cmd, String key, String defaultValue) { |
100 | String v = cmd.getOptionValue(key, defaultValue); |
101 | System.out.println("\t" + key + " = \"" + v + "\""); |
102 | return v; |
103 | } |
104 | |
105 | private void start() { |
106 | allocCodecContext(); |
107 | |
108 | AVPacket pkt = av_packet_alloc(); |
109 | |
110 | allocFrame(cc); |
111 | allocRgbFrame(cc); |
112 | allocSwsContext(); |
113 | allocOutputContext(); |
114 | |
115 | encodeVideo(pkt); |
116 | writeDelayedFrames(); |
117 | |
118 | av_write_trailer(oc); |
119 | free(cc, oc); |
120 | } |
121 | |
122 | private void writeDelayedFrames() { |
123 | sendFrame(null); |
124 | } |
125 | |
126 | private void encodeVideo(AVPacket pkt) { |
127 | for (int i = 0; i < nFrames; i++) { |
128 | frame.pts(avutil.av_rescale_q(i, codecTimebase, streamTimebase)); |
129 | |
130 | drawFrame(i); |
131 | sendFrame(frame); |
132 | } |
133 | } |
134 | |
135 | private void sendFrame(AVFrame o) { |
136 | int r = avcodec.avcodec_send_frame(cc, o); |
137 | if (r == 0) { |
138 | receivePacket(); |
139 | } else { |
140 | throw new RuntimeException("error: " + r); |
141 | } |
142 | } |
143 | |
144 | private void drawFrame(int n) { |
145 | Graphics gc = image.getGraphics(); |
146 | gc.clearRect(0, 0, image.getWidth(), image.getHeight()); |
147 | gc.setFont(gc.getFont().deriveFont(50f)); |
148 | gc.drawString(String.format("pts: %d", n), 200, 200); |
149 | gc.dispose(); |
150 | |
151 | DataBufferByte dataBufferByte = (DataBufferByte) image.getRaster().getDataBuffer(); |
152 | rgbFrame.data(0).put(dataBufferByte.getData()); |
153 | |
154 | swscale.sws_scale( |
155 | swsContext, rgbFrame.data(), rgbFrame.linesize(), 0, |
156 | frame.height(), frame.data(), frame.linesize() |
157 | ); |
158 | } |
159 | |
160 | private void allocOutputContext() { |
161 | oc = new AVFormatContext(); |
162 | pkt = new AVPacket(); |
163 | int r = avformat_alloc_output_context2(oc, null, null, ofile); |
164 | if (r < 0) { |
165 | throw new RuntimeException("could not allocate output context"); |
166 | } |
167 | fmt = oc.oformat(); |
168 | AVStream st = avformat_new_stream(oc, codec); |
169 | avcodec_parameters_from_context(st.codecpar(), cc); |
170 | st.time_base(cc.time_base()); |
171 | |
172 | av_dump_format(oc, 0, ofile, 1); |
173 | |
174 | /* open the output file, if needed */ |
175 | PointerPointer pp = new PointerPointer(1); |
176 | try { |
177 | if (avio_open(pp, new BytePointer(ofile), AVIO_FLAG_WRITE) <0){ |
178 | throw new RuntimeException("Could not open " + fmt); |
179 | } |
180 | oc.pb(new AVIOContext(pp.get())); |
181 | } finally { |
182 | pp.deallocate(); |
183 | } |
184 | |
185 | /* Write the stream header, if any. */ |
186 | if (avformat_write_header(oc, (AVDictionary) null) < 0) { |
187 | throw new RuntimeException("Error occurred when opening output file\n"); |
188 | } |
189 | |
190 | streamTimebase = st.time_base(); |
191 | } |
192 | |
193 | private void allocCodecContext() { |
194 | codecTimebase = new avutil.AVRational(); |
195 | codecTimebase.num(1); |
196 | codecTimebase.den(fps); |
197 | codec = avcodec_find_encoder(AV_CODEC_ID_H264); |
198 | cc = avcodec_alloc_context3(codec); |
199 | |
200 | cc.bit_rate(bitrate); |
201 | cc.width(width); |
202 | cc.height(height); |
203 | cc.time_base(codecTimebase); |
204 | cc.gop_size(gopSize); |
205 | cc.max_b_frames(maxBFrames); |
206 | if (profile != null && !"".equals(profile)) { |
207 | av_opt_set(cc.priv_data(), "profile", profile, 0); |
208 | } |
209 | |
210 | cc.pix_fmt(avutil.AV_PIX_FMT_YUV420P); |
211 | cc.flags(cc.flags() | AV_CODEC_FLAG_GLOBAL_HEADER); |
212 | if (avcodec_open2(cc, codec, (AVDictionary) null) < 0) { |
213 | throw new RuntimeException("could not open codec"); |
214 | } |
215 | } |
216 | |
217 | private void free(AVCodecContext cc, AVFormatContext oc) { |
218 | avcodec_close(cc); |
219 | avcodec_free_context(cc); |
220 | av_free(rgbFrame.data(0)); |
221 | av_free(frame.data(0)); |
222 | av_free(rgbFrame); |
223 | av_free(frame); |
224 | |
225 | avio_close(oc.pb()); |
226 | av_free(oc); |
227 | } |
228 | |
229 | private void allocSwsContext() { |
230 | swsContext = sws_getContext(rgbFrame.width(), rgbFrame.height(), rgbFrame.format(), |
231 | frame.width(), frame.height(), frame.format(), swscale.SWS_BICUBIC, |
232 | null, null, (DoublePointer) null); |
233 | |
234 | if (swsContext.isNull()) { |
235 | throw new RuntimeException("Could not init sws context!"); |
236 | } |
237 | } |
238 | |
239 | private void allocRgbFrame(AVCodecContext cc) { |
240 | image = new BufferedImage(cc.width(), cc.height(), BufferedImage.TYPE_3BYTE_BGR); |
241 | |
242 | rgbFrame = av_frame_alloc(); |
243 | rgbFrame.format(AV_PIX_FMT_BGR24); |
244 | rgbFrame.width(cc.width()); |
245 | rgbFrame.height(cc.height()); |
246 | int ret = av_frame_get_buffer(rgbFrame, 32); |
247 | if (ret < 0) { |
248 | throw new RuntimeException("Could not allocate the video frame data"); |
249 | } |
250 | } |
251 | |
252 | private void allocFrame(AVCodecContext cc) { |
253 | frame = av_frame_alloc(); |
254 | frame.format(cc.pix_fmt()); |
255 | frame.width(cc.width()); |
256 | frame.height(cc.height()); |
257 | int ret = av_frame_get_buffer(frame, 32); |
258 | if (ret < 0) { |
259 | throw new RuntimeException("Could not allocate the video frame data"); |
260 | } |
261 | } |
262 | |
263 | private void receivePacket() { |
264 | int r; |
265 | while ((r = avcodec.avcodec_receive_packet(cc, pkt)) == 0) { |
266 | r = av_interleaved_write_frame(oc, pkt); |
267 | av_packet_unref(pkt); |
268 | if (r != 0) { |
269 | throw new RuntimeException("Error while writing video frame\n"); |
270 | } |
271 | } |
272 | |
273 | if (r != AVERROR_EAGAIN() && r != AVERROR_EOF()) { |
274 | throw new RuntimeException("error"); |
275 | } |
276 | } |
277 | } |
Began life as a copy of #1033821
download show line numbers debug dex old transpilations
Travelled to 3 computer(s): bhatertpkbcr, mowyntqkapby, mqqgnosmbjvj
No comments. add comment
Snippet ID: | #1033823 |
Snippet name: | JavaCPP ffpmeg Encode H264 Demo [OK on Linux x64] |
Eternal ID of this version: | #1033823/4 |
Text MD5: | ca049d66e323f8146d8a17ec126aa839 |
Transpilation MD5: | c5d08aceccbd18027d08e4fe5bcec436 |
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-01-06 19:17:12 |
Source code size: | 9795 bytes / 277 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 251 / 1012 |
Version history: | 3 change(s) |
Referenced in: | [show references] |