/*
* JAVE - A Java Audio/Video Encoder (based on FFMPEG)
*
* Copyright (C) 2008-2009 Carlo Pelliccia (www.sauronsoftware.it)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package it.sauronsoftware.jave;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.StringTokenizer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Main class of the package. Instances can encode audio and video streams.
*
* @author Carlo Pelliccia
*/
public class Encoder {
/**
* This regexp is used to parse the ffmpeg output about the supported
* formats.
*/
private static final Pattern FORMAT_PATTERN = Pattern
.compile("^\\s*([D ])([E ])\\s+([\\w,]+)\\s+.+$");
/**
* This regexp is used to parse the ffmpeg output about the included
* encoders/decoders.
*/
private static final Pattern ENCODER_DECODER_PATTERN = Pattern.compile(
"^\\s*([D ])([E ])([AVS]).{3}\\s+(.+)$", Pattern.CASE_INSENSITIVE);
/**
* This regexp is used to parse the ffmpeg output about the ongoing encoding
* process.
*/
private static final Pattern PROGRESS_INFO_PATTERN = Pattern.compile(
"\\s*(\\w+)\\s*=\\s*(\\S+)\\s*", Pattern.CASE_INSENSITIVE);
/**
* This regexp is used to parse the ffmpeg output about the size of a video
* stream.
*/
private static final Pattern SIZE_PATTERN = Pattern.compile(
"(\\d+)x(\\d+)", Pattern.CASE_INSENSITIVE);
/**
* This regexp is used to parse the ffmpeg output about the frame rate value
* of a video stream.
*/
private static final Pattern FRAME_RATE_PATTERN = Pattern.compile(
"([\\d.]+)\\s+(?:fps|tb\\(r\\))", Pattern.CASE_INSENSITIVE);
/**
* This regexp is used to parse the ffmpeg output about the bit rate value
* of a stream.
*/
private static final Pattern BIT_RATE_PATTERN = Pattern.compile(
"(\\d+)\\s+kb/s", Pattern.CASE_INSENSITIVE);
/**
* This regexp is used to parse the ffmpeg output about the sampling rate of
* an audio stream.
*/
private static final Pattern SAMPLING_RATE_PATTERN = Pattern.compile(
"(\\d+)\\s+Hz", Pattern.CASE_INSENSITIVE);
/**
* This regexp is used to parse the ffmpeg output about the channels number
* of an audio stream.
*/
private static final Pattern CHANNELS_PATTERN = Pattern.compile(
"(mono|stereo)", Pattern.CASE_INSENSITIVE);
/**
* This regexp is used to parse the ffmpeg output about the success of an
* encoding operation.
*/
private static final Pattern SUCCESS_PATTERN = Pattern.compile(
"^\\s*video\\:\\S+\\s+audio\\:\\S+\\s+global headers\\:\\S+.*$",
Pattern.CASE_INSENSITIVE);
/**
* The locator of the ffmpeg executable used by this encoder.
*/
private FFMPEGLocator locator;
/**
* It builds an encoder using a {@link DefaultFFMPEGLocator} instance to
* locate the ffmpeg executable to use.
*/
public Encoder() {
this.locator = new DefaultFFMPEGLocator();
}
/**
* It builds an encoder with a custom {@link FFMPEGLocator}.
*
* @param locator
* The locator picking up the ffmpeg executable used by the
* encoder.
*/
public Encoder(FFMPEGLocator locator) {
this.locator = locator;
}
/**
* Returns a list with the names of all the audio decoders bundled with the
* ffmpeg distribution in use. An audio stream can be decoded only if a
* decoder for its format is available.
*
* @return A list with the names of all the included audio decoders.
* @throws EncoderException
* If a problem occurs calling the underlying ffmpeg executable.
*/
public String[] getAudioDecoders() throws EncoderException {
ArrayList res = new ArrayList();
FFMPEGExecutor ffmpeg = locator.createExecutor();
ffmpeg.addArgument("-formats");
try {
ffmpeg.execute();
RBufferedReader reader = null;
reader = new RBufferedReader(new InputStreamReader(ffmpeg
.getInputStream()));
String line;
boolean evaluate = false;
while ((line = reader.readLine()) != null) {
if (line.trim().length() == 0) {
continue;
}
if (evaluate) {
Matcher matcher = ENCODER_DECODER_PATTERN.matcher(line);
if (matcher.matches()) {
String decoderFlag = matcher.group(1);
String audioVideoFlag = matcher.group(3);
if ("D".equals(decoderFlag)
&& "A".equals(audioVideoFlag)) {
String name = matcher.group(4);
res.add(name);
}
} else {
break;
}
} else if (line.trim().equals("Codecs:")) {
evaluate = true;
}
}
} catch (IOException e) {
throw new EncoderException(e);
} finally {
ffmpeg.destroy();
}
int size = res.size();
String[] ret = new String[size];
for (int i = 0; i < size; i++) {
ret[i] = (String) res.get(i);
}
return ret;
}
/**
* Returns a list with the names of all the audio encoders bundled with the
* ffmpeg distribution in use. An audio stream can be encoded using one of
* these encoders.
*
* @return A list with the names of all the included audio encoders.
* @throws EncoderException
* If a problem occurs calling the underlying ffmpeg executable.
*/
public String[] getAudioEncoders() throws EncoderException {
ArrayList res = new ArrayList();
FFMPEGExecutor ffmpeg = locator.createExecutor();
ffmpeg.addArgument("-formats");
try {
ffmpeg.execute();
RBufferedReader reader = null;
reader = new RBufferedReader(new InputStreamReader(ffmpeg
.getInputStream()));
String line;
boolean evaluate = false;
while ((line = reader.readLine()) != null) {
if (line.trim().length() == 0) {
continue;
}
if (evaluate) {
Matcher matcher = ENCODER_DECODER_PATTERN.matcher(line);
if (matcher.matches()) {
String encoderFlag = matcher.group(2);
String audioVideoFlag = matcher.group(3);
if ("E".equals(encoderFlag)
&& "A".equals(audioVideoFlag)) {
String name = matcher.group(4);
res.add(name);
}
} else {
break;
}
} else if (line.trim().equals("Codecs:")) {
evaluate = true;
}
}
} catch (IOException e) {
throw new EncoderException(e);
} finally {
ffmpeg.destroy();
}
int size = res.size();
String[] ret = new String[size];
for (int i = 0; i < size; i++) {
ret[i] = (String) res.get(i);
}
return ret;
}
/**
* Returns a list with the names of all the video decoders bundled with the
* ffmpeg distribution in use. A video stream can be decoded only if a
* decoder for its format is available.
*
* @return A list with the names of all the included video decoders.
* @throws EncoderException
* If a problem occurs calling the underlying ffmpeg executable.
*/
public String[] getVideoDecoders() throws EncoderException {
ArrayList res = new ArrayList();
FFMPEGExecutor ffmpeg = locator.createExecutor();
ffmpeg.addArgument("-formats");
try {
ffmpeg.execute();
RBufferedReader reader = null;
reader = new RBufferedReader(new InputStreamReader(ffmpeg
.getInputStream()));
String line;
boolean evaluate = false;
- 1
- 2
- 3
- 4
前往页