
org.jcodec.player.app.PlayerApplet Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jcodec Show documentation
Show all versions of jcodec Show documentation
Pure Java implementation of video/audio codecs and formats
package org.jcodec.player.app;
import static java.lang.Math.round;
import static org.apache.commons.lang.StringUtils.capitaliseAllWords;
import java.awt.BorderLayout;
import java.awt.Color;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.JApplet;
import netscape.javascript.JSObject;
import org.apache.commons.io.FileUtils;
import org.jcodec.common.model.ChannelLabel;
import org.jcodec.common.model.RationalLarge;
import org.jcodec.common.model.TapeTimecode;
import org.jcodec.common.tools.Debug;
import org.jcodec.player.Player;
import org.jcodec.player.Player.Listener;
import org.jcodec.player.Player.Status;
import org.jcodec.player.Stepper;
import org.jcodec.player.filters.JCodecVideoSource;
import org.jcodec.player.filters.JSoundAudioOut;
import org.jcodec.player.filters.MediaInfo;
import org.jcodec.player.filters.MediaInfo.AudioInfo;
import org.jcodec.player.filters.MediaInfo.VideoInfo;
import org.jcodec.player.filters.audio.AudioMixer;
import org.jcodec.player.filters.audio.AudioMixer.Pin;
import org.jcodec.player.filters.audio.AudioSource;
import org.jcodec.player.filters.audio.JCodecAudioSource;
import org.jcodec.player.filters.http.HttpMedia;
import org.jcodec.player.filters.http.HttpPacketSource;
import org.jcodec.player.ui.SwingVO;
/**
* This class is part of JCodec ( www.jcodec.org ) This software is distributed
* under FreeBSD License
*
* Media player applet for JCodec streaming
*
* @author The JCodec project
*
*/
public class PlayerApplet extends JApplet {
/**
*
*/
private static final long serialVersionUID = -6134123851724553559L;
private Player player;
private JCodecVideoSource video;
private SwingVO vo;
public JSObject onStatus1;
public JSObject onStatus2;
public JSObject onStateChanged;
private Timer timer = new Timer(true);
private AudioMixer audio;
private TimerTask status2Task;
private Stepper stepper;
public class Status1 {
public double time;
public int frame;
public int[] tapeTimecode;
public Status1(double time, int frame, int[] tapeTimecode) {
this.time = time;
this.frame = frame;
this.tapeTimecode = tapeTimecode;
}
};
public class Status2 {
public double duration;
public int nFrames;
public int[][] cache;
public int[][] audio;
public Status2(double duration, int nFrames, int[][] cache, int[][] audio) {
this.duration = duration;
this.nFrames = nFrames;
this.cache = cache;
this.audio = audio;
}
};
public void open(final String src) {
Debug.println("Opening source: " + src);
try {
if (player != null) {
Debug.println("Destroying old player.");
player.destroy();
video.close();
audio.close();
status2Task.cancel();
status2Task = null;
}
HttpMedia http = AccessController.doPrivileged(new PrivilegedAction() {
public HttpMedia run() {
try {
File cacheWhere = determineCacheLocation();
FileUtils.forceMkdir(cacheWhere);
return new HttpMedia(new URL(src), cacheWhere);
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("Could not open HTTP source: '" + src + "'");
}
}
});
Debug.println("Initialized packet source");
Debug.println("Creating player");
final HttpPacketSource videoTrack = http.getVideoTrack();
video = new JCodecVideoSource(videoTrack);
audio = audio(http);
player = new Player(video, audio, vo, new JSoundAudioOut());
player.addListener(new Listener() {
public void timeChanged(RationalLarge pts, int frameNo, TapeTimecode tt) {
if (onStatus1 == null)
return;
onStatus1.call(
"call",
new Object[] {
null,
new Status1((double) pts.getNum() / pts.getDen(), frameNo, tt != null ? new int[] {
tt.getHour(), tt.getMinute(), tt.getSecond(), tt.getFrame(),
tt.isDropFrame() ? 1 : 0 } : null) });
}
public void statusChanged(Status status) {
if (onStateChanged != null)
onStateChanged.call("call", new Object[] { null, status.toString() });
}
});
status2Task = new TimerTask() {
public void run() {
if (onStatus2 == null)
return;
try {
VideoInfo videoInfo = player.getVideoSource().getMediaInfo();
onStatus2.call("call", new Object[] {
null,
new Status2((double) videoInfo.getDuration() / videoInfo.getTimescale(),
(int) videoInfo.getNFrames(), videoTrack.getCached(), enabledChannels()) });
} catch (IOException e) {
e.printStackTrace();
}
}
};
timer.scheduleAtFixedRate(status2Task, 0, 1000);
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("Could not open source", e);
}
}
private AudioMixer audio(HttpMedia http) throws IOException {
List audioTracks = http.getAudioTracks();
AudioSource[] audios = new AudioSource[audioTracks.size()];
for (int i = 0; i < audioTracks.size(); i++) {
audios[i] = new JCodecAudioSource(audioTracks.get(i));
}
return new AudioMixer(2, audios);
}
public class AudioTrack {
public AudioTrack(String name, String[] channels) {
this.name = name;
this.channels = channels;
}
public String name;
public String[] channels;
}
public AudioTrack[] getAudioConfig() {
try {
Pin[] pins = audio.getPins();
AudioTrack[] ats = new AudioTrack[pins.length];
for (int i = 0; i < pins.length; i++) {
AudioInfo ai = pins[i].getSource().getAudioInfo();
ats[i] = new AudioTrack(ai.getName(), channels(ai.getLabels()));
}
return ats;
} catch (IOException e) {
e.printStackTrace();
}
return new AudioTrack[0];
}
private String[] channels(ChannelLabel[] labels) {
String[] strs = new String[labels.length];
for (int i = 0; i < labels.length; i++) {
strs[i] = labels[i] != null ? capitaliseAllWords(labels[i].toString().toLowerCase().replace("_", " "))
: "N/A";
}
return strs;
}
public void toggleChannel(int trackId, int channelId) {
audio.getPins()[trackId].toggle(channelId);
}
public void muteChannel(int trackId, int channelId) {
audio.getPins()[trackId].mute(channelId);
}
public void unmuteChannel(int trackId, int channelId) {
audio.getPins()[trackId].unmute(channelId);
}
private int[][] enabledChannels() {
Pin[] pins = audio.getPins();
int[][] result = new int[pins.length][];
for (int i = 0; i < pins.length; i++) {
result[i] = pins[i].getSoloChannels();
}
return result;
}
@Override
public void init() {
this.setBackground(Color.BLACK);
vo = new SwingVO();
add(vo, BorderLayout.CENTER);
validate();
String src = this.getParameter("src");
if (src != null) {
open(src);
if ("true".equalsIgnoreCase(this.getParameter("play"))) {
player.play();
}
}
}
@Override
public void stop() {
Debug.println("Stopping player");
if (player == null)
return;
player.destroy();
try {
video.close();
audio.close();
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("Could not destroy player", e);
}
}
public void play() {
if (player == null)
throw new IllegalArgumentException("player is not initialized");
Debug.println("Starting playback.");
if (stepper != null) {
player.seek(stepper.getPos());
stepper = null;
}
player.play();
}
public void pause() {
if (player == null)
throw new IllegalArgumentException("player is not initialized");
player.pause();
}
public void togglePause() {
if (player == null)
throw new IllegalArgumentException("player is not initialized");
if (player.getStatus() == Player.Status.PAUSED) {
if (stepper != null) {
player.seek(stepper.getPos());
stepper = null;
}
player.play();
} else
player.pause();
}
public void seekRel(int sec) {
if (player == null)
throw new IllegalArgumentException("player is not initialized");
RationalLarge pos = player.getPos();
try {
player.seek(new RationalLarge(pos.getNum() + pos.getDen() * sec, pos.getDen()));
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("Could not relative seek", e);
}
}
public void seek(double sec) {
if (player == null)
throw new IllegalArgumentException("player is not initialized");
try {
player.seek(new RationalLarge(round(sec * 1000000), 1000000));
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("Could not seek", e);
}
}
public void stepForward() {
if (player.getStatus() != Player.Status.PAUSED) {
player.pause();
return;
}
try {
if (stepper == null) {
stepper = new Stepper(video, audio, vo, new JSoundAudioOut());
stepper.setListeners(player.getListeners());
stepper.gotoFrame(player.getFrameNo());
}
stepper.next();
} catch (Exception e) {
throw new RuntimeException("Could not step", e);
}
}
public void stepBackward() {
// if (player.getStatus() != Player.Status.PAUSED) {
// player.pause();
// return;
// }
// try {
// if (stepper == null) {
// stepper = new Stepper(video, audio, vo, new JSoundAudioOut());
// stepper.setListeners(player.getListeners());
// stepper.gotoFrame(player.getFrameNo());
// }
// stepper.prev();
// } catch (Exception e) {
// throw new RuntimeException("Could not step", e);
// }
}
private File determineCacheLocation() {
String os = System.getProperty("os.name");
String home = System.getProperty("user.home");
if (os.startsWith("Mac")) {
return new File(home, "Library/JCodec");
} else if (os.startsWith("Windows")) {
return new File(home, "Application Data/JCodec");
} else {
return new File(home, ".jcodec");
}
}
public double getTime() {
RationalLarge t = player.getPos();
return ((double) t.getNum()) / t.getDen();
}
public MediaInfo[] getMediaInfo() throws IOException {
ArrayList info = new ArrayList();
info.add(sourceInfo(video.getMediaInfo()));
Pin[] pins = audio.getPins();
for (Pin pin : pins) {
info.add(sourceInfo(pin.getSource().getAudioInfo()));
}
return info.toArray(new MediaInfo[0]);
}
private MediaInfo sourceInfo(MediaInfo mediaInfo) {
MediaInfo result = mediaInfo;
while (result.getTranscodedFrom() != null)
result = result.getTranscodedFrom();
return result;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy