1 | import static org.jcodec.common.Tuple._2; |
2 | import static org.jcodec.common.Tuple._3; |
3 | |
4 | import org.jcodec.common.Codec; |
5 | import org.jcodec.common.Demuxer; |
6 | import org.jcodec.common.DemuxerTrack; |
7 | import org.jcodec.common.DemuxerTrackMeta; |
8 | import org.jcodec.common.Format; |
9 | import org.jcodec.common.JCodecUtil; |
10 | import org.jcodec.common.TrackType; |
11 | import org.jcodec.common.logging.Logger; |
12 | import org.jcodec.common.model.Packet; |
13 | import org.jcodec.common.tools.MainUtils; |
14 | import org.jcodec.common.tools.MainUtils.Cmd; |
15 | import org.jcodec.common.tools.MathUtil; |
16 | import org.jcodec.samples.transcode.Transcoder.Filter; |
17 | import org.jcodec.samples.transcode.filters.DumpMvFilter; |
18 | |
19 | /** |
20 | * This class is part of JCodec ( www.jcodec.org ) This software is distributed |
21 | * under FreeBSD License |
22 | * |
23 | * Transcoder command line. |
24 | * |
25 | * @author The JCodec project |
26 | * |
27 | */ |
28 | sclass TranscodeMain { |
29 | private static final String FLAG_SEEK_FRAMES = "seek-frames"; |
30 | private static final String FLAG_MAX_FRAMES = "max-frames"; |
31 | |
32 | private static final String FLAG_OUTPUT_AUDIO_CODEC = "o:ac"; |
33 | private static final String FLAG_INPUT_AUDIO_CODEC = "i:ac"; |
34 | private static final String FLAG_OUTPUT_VIDEO_CODEC = "o:vc"; |
35 | private static final String FLAG_INPUT_VIDEO_CODEC = "i:vc"; |
36 | private static final String FLAG_OUTPUT_FORMAT = "o:f"; |
37 | private static final String FLAG_INPUT_FORMAT = "i:f"; |
38 | |
39 | private static final String FLAG_PROFILE = "profile"; |
40 | private static final String FLAG_INTERLACED = "interlaced"; |
41 | |
42 | private static final String FLAG_DUMPMV = "dumpMv"; |
43 | private static final String FLAG_DUMPMVJS = "dumpMvJs"; |
44 | |
45 | private static final String FLAG_DOWNSCALE = "downscale"; |
46 | |
47 | private static Map<String, Format> extensionToF = new HashMap<String, Format>(); |
48 | private static Map<String, Codec> extensionToC = new HashMap<String, Codec>(); |
49 | private static Map<Format, Codec> videoCodecsForF = new HashMap<Format, Codec>(); |
50 | private static Map<Format, Codec> audioCodecsForF = new HashMap<Format, Codec>(); |
51 | private static Set<Codec> supportedDecoders = new HashSet<Codec>(); |
52 | |
53 | static { |
54 | extensionToF.put("mpg", Format.MPEG_PS); |
55 | extensionToF.put("mpeg", Format.MPEG_PS); |
56 | extensionToF.put("m2p", Format.MPEG_PS); |
57 | extensionToF.put("ps", Format.MPEG_PS); |
58 | extensionToF.put("vob", Format.MPEG_PS); |
59 | extensionToF.put("evo", Format.MPEG_PS); |
60 | extensionToF.put("mod", Format.MPEG_PS); |
61 | extensionToF.put("tod", Format.MPEG_PS); |
62 | |
63 | extensionToF.put("ts", Format.MPEG_TS); |
64 | extensionToF.put("m2t", Format.MPEG_TS); |
65 | |
66 | extensionToF.put("mp4", Format.MOV); |
67 | extensionToF.put("m4a", Format.MOV); |
68 | extensionToF.put("m4v", Format.MOV); |
69 | extensionToF.put("mov", Format.MOV); |
70 | extensionToF.put("3gp", Format.MOV); |
71 | |
72 | extensionToF.put("mkv", Format.MKV); |
73 | extensionToF.put("webm", Format.MKV); |
74 | |
75 | extensionToF.put("264", Format.H264); |
76 | extensionToF.put("raw", Format.RAW); |
77 | extensionToF.put("", Format.RAW); |
78 | extensionToF.put("flv", Format.FLV); |
79 | extensionToF.put("avi", Format.AVI); |
80 | extensionToF.put("jpg", Format.IMG); |
81 | extensionToF.put("jpeg", Format.IMG); |
82 | extensionToF.put("png", Format.IMG); |
83 | |
84 | extensionToF.put("mjp", Format.MJPEG); |
85 | |
86 | extensionToF.put("ivf", Format.IVF); |
87 | extensionToF.put("y4m", Format.Y4M); |
88 | extensionToF.put("wav", Format.WAV); |
89 | |
90 | extensionToC.put("mpg", Codec.MPEG2); |
91 | extensionToC.put("mpeg", Codec.MPEG2); |
92 | extensionToC.put("m2p", Codec.MPEG2); |
93 | extensionToC.put("ps", Codec.MPEG2); |
94 | extensionToC.put("vob", Codec.MPEG2); |
95 | extensionToC.put("evo", Codec.MPEG2); |
96 | extensionToC.put("mod", Codec.MPEG2); |
97 | extensionToC.put("tod", Codec.MPEG2); |
98 | extensionToC.put("ts", Codec.MPEG2); |
99 | extensionToC.put("m2t", Codec.MPEG2); |
100 | extensionToC.put("m4a", Codec.AAC); |
101 | extensionToC.put("mkv", Codec.H264); |
102 | extensionToC.put("webm", Codec.VP8); |
103 | extensionToC.put("264", Codec.H264); |
104 | extensionToC.put("raw", Codec.RAW); |
105 | extensionToC.put("jpg", Codec.JPEG); |
106 | extensionToC.put("jpeg", Codec.JPEG); |
107 | extensionToC.put("png", Codec.PNG); |
108 | extensionToC.put("mjp", Codec.JPEG); |
109 | extensionToC.put("y4m", Codec.RAW); |
110 | |
111 | videoCodecsForF.put(Format.MPEG_PS, Codec.MPEG2); |
112 | audioCodecsForF.put(Format.MPEG_PS, Codec.MP2); |
113 | videoCodecsForF.put(Format.MOV, Codec.H264); |
114 | audioCodecsForF.put(Format.MOV, Codec.AAC); |
115 | videoCodecsForF.put(Format.MKV, Codec.VP8); |
116 | audioCodecsForF.put(Format.MKV, Codec.VORBIS); |
117 | audioCodecsForF.put(Format.WAV, Codec.PCM); |
118 | videoCodecsForF.put(Format.H264, Codec.H264); |
119 | videoCodecsForF.put(Format.RAW, Codec.RAW); |
120 | videoCodecsForF.put(Format.FLV, Codec.H264); |
121 | videoCodecsForF.put(Format.AVI, Codec.MPEG4); |
122 | videoCodecsForF.put(Format.IMG, Codec.PNG); |
123 | videoCodecsForF.put(Format.MJPEG, Codec.JPEG); |
124 | videoCodecsForF.put(Format.IVF, Codec.VP8); |
125 | videoCodecsForF.put(Format.Y4M, Codec.RAW); |
126 | |
127 | supportedDecoders.add(Codec.AAC); |
128 | supportedDecoders.add(Codec.H264); |
129 | supportedDecoders.add(Codec.JPEG); |
130 | supportedDecoders.add(Codec.MPEG2); |
131 | supportedDecoders.add(Codec.PCM); |
132 | supportedDecoders.add(Codec.PNG); |
133 | supportedDecoders.add(Codec.PRORES); |
134 | supportedDecoders.add(Codec.RAW); |
135 | supportedDecoders.add(Codec.VP8); |
136 | } |
137 | |
138 | public static void main(String[] args) throws Exception { |
139 | Cmd cmd = MainUtils.parseArguments(args); |
140 | if (args.length < 2) { |
141 | MainUtils.printHelpVarArgs(new HashMap<String, String>() { |
142 | { |
143 | |
144 | put(FLAG_INPUT_FORMAT, "Input format [default=auto]."); |
145 | put(FLAG_OUTPUT_FORMAT, "Output format [default=auto]."); |
146 | put(FLAG_INPUT_VIDEO_CODEC, "Input video codec [default=auto]."); |
147 | put(FLAG_OUTPUT_VIDEO_CODEC, "Output video codec [default=auto]."); |
148 | put(FLAG_INPUT_AUDIO_CODEC, "Input audio codec [default=auto]."); |
149 | put(FLAG_OUTPUT_AUDIO_CODEC, "Output audio codec [default=auto]."); |
150 | put(FLAG_SEEK_FRAMES, "Seek frames"); |
151 | put(FLAG_MAX_FRAMES, "Max frames"); |
152 | put(FLAG_PROFILE, "Profile to use (supported by some encoders)."); |
153 | put(FLAG_INTERLACED, "Encode output as interlaced (supported by Prores encoder)."); |
154 | put(FLAG_DUMPMV, "Dump motion vectors (supported by h.264 decoder)."); |
155 | put(FLAG_DUMPMVJS, "Dump motion vectors in form of JASON file (supported by h.264 decoder)."); |
156 | put(FLAG_DOWNSCALE, "Decode frames in downscale (supported by MPEG, Prores and Jpeg decoders)."); |
157 | } |
158 | }, "input", "output"); |
159 | return; |
160 | } |
161 | |
162 | String input = cmd.getArg(0); |
163 | String output = cmd.getArg(1); |
164 | |
165 | String inputFormatRaw = cmd.getStringFlag(FLAG_INPUT_FORMAT); |
166 | Format inputFormat; |
167 | if (inputFormatRaw == null) { |
168 | inputFormat = getFormatFromExtension(input); |
169 | if (inputFormat != Format.IMG) { |
170 | Format detectFormat = JCodecUtil.detectFormat(new File(input)); |
171 | if (detectFormat != null) |
172 | inputFormat = detectFormat; |
173 | } |
174 | } else { |
175 | inputFormat = Format.valueOf(inputFormatRaw.toUpperCase()); |
176 | } |
177 | if (inputFormat == null) { |
178 | Logger.error("Input format could not be detected"); |
179 | return; |
180 | } |
181 | |
182 | String outputFormatRaw = cmd.getStringFlag(FLAG_OUTPUT_FORMAT); |
183 | Format outputFormat; |
184 | if (outputFormatRaw == null) { |
185 | outputFormat = getFormatFromExtension(output); |
186 | } else { |
187 | outputFormat = Format.valueOf(outputFormatRaw.toUpperCase()); |
188 | } |
189 | |
190 | int videoTrackNo = -1; |
191 | String inputCodecVideoRaw = cmd.getStringFlag(FLAG_INPUT_VIDEO_CODEC); |
192 | _3<Integer, Integer, Codec> inputCodecVideo = null; |
193 | if (inputCodecVideoRaw == null) { |
194 | if (inputFormat == Format.IMG) { |
195 | inputCodecVideo = _3(0, 0, getCodecFromExtension(input)); |
196 | } else if (inputFormat.isVideo()) { |
197 | inputCodecVideo = selectSuitableTrack(input, inputFormat, TrackType.VIDEO); |
198 | } |
199 | } else { |
200 | inputCodecVideo = _3(0, 0, Codec.valueOf(inputCodecVideoRaw.toUpperCase())); |
201 | } |
202 | |
203 | String outputCodecVideoRaw = cmd.getStringFlag(FLAG_OUTPUT_VIDEO_CODEC); |
204 | Codec outputCodecVideo = null; |
205 | boolean videoCopy = false; |
206 | if (outputCodecVideoRaw == null) { |
207 | outputCodecVideo = getCodecFromExtension(output); |
208 | if (outputCodecVideo == null) |
209 | outputCodecVideo = getFirstVideoCodecForFormat(outputFormat); |
210 | } else { |
211 | if ("copy".equalsIgnoreCase(outputCodecVideoRaw)) { |
212 | videoCopy = true; |
213 | outputCodecVideo = inputCodecVideo.v2; |
214 | } else if("none".equalsIgnoreCase(outputCodecVideoRaw)) { |
215 | outputCodecVideo = null; |
216 | inputCodecVideo = null; |
217 | } else { |
218 | outputCodecVideo = Codec.valueOf(outputCodecVideoRaw.toUpperCase()); |
219 | } |
220 | } |
221 | |
222 | String inputCodecAudioRaw = cmd.getStringFlag(FLAG_INPUT_AUDIO_CODEC); |
223 | _3<Integer, Integer, Codec> inputCodecAudio = null; |
224 | if (inputCodecAudioRaw == null) { |
225 | if (inputFormat.isAudio()) { |
226 | inputCodecAudio = selectSuitableTrack(input, inputFormat, TrackType.AUDIO); |
227 | } |
228 | } else { |
229 | inputCodecAudio = _3(0, 0, Codec.valueOf(inputCodecAudioRaw.toUpperCase())); |
230 | } |
231 | |
232 | String outputCodecAudioRaw = cmd.getStringFlag(FLAG_OUTPUT_AUDIO_CODEC); |
233 | Codec outputCodecAudio = null; |
234 | boolean audioCopy = false; |
235 | if (outputCodecAudioRaw == null) { |
236 | if (outputFormat.isAudio()) |
237 | outputCodecAudio = getFirstAudioCodecForFormat(outputFormat); |
238 | } else { |
239 | if ("copy".equalsIgnoreCase(outputCodecAudioRaw)) { |
240 | audioCopy = true; |
241 | outputCodecAudio = inputCodecAudio.v2; |
242 | } else if("none".equalsIgnoreCase(outputCodecVideoRaw)) { |
243 | outputCodecAudio = null; |
244 | inputCodecAudio = null; |
245 | } else { |
246 | outputCodecAudio = Codec.valueOf(outputCodecAudioRaw.toUpperCase()); |
247 | } |
248 | } |
249 | if (inputCodecAudio == null) |
250 | outputCodecAudio = null; |
251 | |
252 | List<Filter> filters = new ArrayList<Filter>(); |
253 | if (cmd.getBooleanFlag(FLAG_DUMPMV)) |
254 | filters.add(new DumpMvFilter(false)); |
255 | else if (cmd.getBooleanFlag(FLAG_DUMPMVJS)) |
256 | filters.add(new DumpMvFilter(true)); |
257 | |
258 | Transcoder transcoder = new Transcoder(cmd.getArg(0), cmd.getArg(1), inputFormat, outputFormat, inputCodecVideo, |
259 | outputCodecVideo, inputCodecAudio, outputCodecAudio, videoCopy, audioCopy, filters); |
260 | transcoder.setSeekFrames(cmd.getIntegerFlagD(FLAG_SEEK_FRAMES, 0)); |
261 | transcoder.setMaxFrames(cmd.getIntegerFlagD(FLAG_MAX_FRAMES, Integer.MAX_VALUE)); |
262 | transcoder.setProfile(cmd.getStringFlag(FLAG_PROFILE)); |
263 | transcoder.setInterlaced(cmd.getBooleanFlagD(FLAG_INTERLACED, false)); |
264 | Integer downscale = cmd.getIntegerFlagD(FLAG_DOWNSCALE, 1); |
265 | if (downscale != null && (1 << MathUtil.log2(downscale)) != downscale) { |
266 | Logger.error( |
267 | "Only values [2, 4, 8] are supported for " + FLAG_DOWNSCALE + ", the option will have no effect."); |
268 | } else { |
269 | transcoder.setDownscale(downscale); |
270 | } |
271 | transcoder.transcode(); |
272 | } |
273 | |
274 | private static Codec getFirstAudioCodecForFormat(Format inputFormat) { |
275 | return audioCodecsForF.get(inputFormat); |
276 | } |
277 | |
278 | private static Codec getFirstVideoCodecForFormat(Format inputFormat) { |
279 | return videoCodecsForF.get(inputFormat); |
280 | } |
281 | |
282 | private static Codec detectVideoDecoder(DemuxerTrack track) throws IOException { |
283 | DemuxerTrackMeta meta = track.getMeta(); |
284 | if (meta != null) { |
285 | Codec codec = meta.getCodec(); |
286 | if (codec != null) |
287 | return codec; |
288 | } |
289 | Packet packet = track.nextFrame(); |
290 | if (packet == null) |
291 | return null; |
292 | |
293 | return JCodecUtil.detectDecoder(packet.getData()); |
294 | } |
295 | |
296 | private static _3<Integer, Integer, Codec> selectSuitableTrack(String input, Format format, TrackType targetType) |
297 | throws IOException { |
298 | _2<Integer, Demuxer> demuxerPid; |
299 | if (format == Format.MPEG_TS) { |
300 | demuxerPid = JCodecUtil.createM2TSDemuxer(new File(input), targetType); |
301 | } else { |
302 | demuxerPid = _2(0, JCodecUtil.createDemuxer(format, new File(input))); |
303 | } |
304 | if(demuxerPid == null || demuxerPid.v1 == null) |
305 | return null; |
306 | int trackNo = 0; |
307 | List<? extends DemuxerTrack> tracks = targetType == TrackType.VIDEO ? demuxerPid.v1.getVideoTracks() |
308 | : demuxerPid.v1.getAudioTracks(); |
309 | for (DemuxerTrack demuxerTrack : tracks) { |
310 | Codec codec = detectVideoDecoder(demuxerTrack); |
311 | if (supportedDecoders.contains(codec)) { |
312 | return _3(demuxerPid.v0, trackNo, codec); |
313 | } |
314 | trackNo++; |
315 | } |
316 | return null; |
317 | } |
318 | |
319 | private static Format getFormatFromExtension(String output) { |
320 | String extension = output.replaceFirst(".*\\.([^\\.]+$)", "$1"); |
321 | return extensionToF.get(extension); |
322 | } |
323 | |
324 | private static Codec getCodecFromExtension(String output) { |
325 | String extension = output.replaceFirst(".*\\.([^\\.]+$)", "$1"); |
326 | return extensionToC.get(extension); |
327 | } |
328 | |
329 | public static Set<Format> formats(Format... formats) { |
330 | return new HashSet<Format>(Arrays.asList(formats)); |
331 | } |
332 | |
333 | public static Set<Codec> codecs(Codec... codecs) { |
334 | return new HashSet<Codec>(Arrays.asList(codecs)); |
335 | } |
336 | } |
download show line numbers debug dex old transpilations
Travelled to 13 computer(s): aoiabmzegqzx, bhatertpkbcr, cbybwowwnfue, cfunsshuasjs, gwrvuhgaqvyk, ishqpsrjomds, lpdgvwnxivlt, mqqgnosmbjvj, pyentgdyhuwx, pzhvpgtvlbxg, tslmcundralx, tvejysmllsmz, vouqrxazstgt
No comments. add comment
Snippet ID: | #1006719 |
Snippet name: | class Transcode (from JCodec 0.2.0) |
Eternal ID of this version: | #1006719/1 |
Text MD5: | 6dc867e73742a9f883255c045cc1e4d7 |
Author: | stefan |
Category: | javax video |
Type: | JavaX fragment (include) |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2017-02-02 23:49:20 |
Source code size: | 14061 bytes / 336 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 604 / 605 |
Referenced in: | [show references] |