-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathPlayer.java
264 lines (217 loc) · 8.32 KB
/
Player.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
import java.io.*;
import java.text.DecimalFormat;
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.Timer;
public class Player {
// GUI
//----
JFrame f = new JFrame("MJJPEG Player");
JButton playButton = new JButton("Play");
JButton pauseButton = new JButton("Pause");
JButton tearButton = new JButton("Close");
JPanel mainPanel = new JPanel();
JPanel buttonPanel = new JPanel();
JLabel statLabel1 = new JLabel();
JLabel statLabel2 = new JLabel();
JLabel statLabel3 = new JLabel();
JLabel iconLabel = new JLabel();
ImageIcon icon;
Timer timer; //timer used to play frames
//Video constants:
//------------------
int imagenb = 0; //image nb of the image currently read
static String VideoFileName; //video file to play
byte[] frame; //buffer used to store the video frames
static VideoStream video; //videoStream object used to access video frames
static int VIDEO_LENGTH = 500; //length of the video in frames
//Statistics variables:
//------------------
double statTotalPlayTime; //time in milliseconds of video playing since beginning
double statDataRate; //rate of video data received in bytes/s
int statTotalBytes; //total number of bytes received in a session
double statStartTime; //time in milliseconds when start is pressed
FrameSynchronizer fsynch;
//--------------------------
//Constructor
//--------------------------
public Player() {
//Build GUI
//--------------------------
//Buttons
buttonPanel.setLayout(new GridLayout(1,0));
buttonPanel.add(playButton);
buttonPanel.add(pauseButton);
buttonPanel.add(tearButton);
playButton.addActionListener(new playButtonListener());
pauseButton.addActionListener(new pauseButtonListener());
tearButton.addActionListener(new tearButtonListener());
//Statistics
statLabel1.setText("Total Bytes Received: 0");
statLabel2.setText("Data Rate (bytes/sec): 0");
statLabel3.setText("Play frame #");
//Image display label
iconLabel.setIcon(null);
//Frame layout
mainPanel.setLayout(null);
mainPanel.add(iconLabel);
mainPanel.add(buttonPanel);
mainPanel.add(statLabel1);
mainPanel.add(statLabel2);
mainPanel.add(statLabel3);
iconLabel.setBounds(0,0,380,280);
buttonPanel.setBounds(0,280,380,50);
statLabel1.setBounds(0,330,380,20);
statLabel2.setBounds(0,350,380,20);
statLabel3.setBounds(0,370,380,20);
f.getContentPane().add(mainPanel, BorderLayout.CENTER);
f.setSize(new Dimension(380,420));
f.setVisible(true);
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
timer.stop();
System.exit(0);
}
});
//Init timer
timer = new Timer(20, new timerListener());
timer.setInitialDelay(0);
timer.setCoalesce(true);
//Allocate enough memory for the buffer used for frames
frame = new byte[15000];
//Create the frame synchronizer
fsynch = new FrameSynchronizer(100);
}
//------------------------------------
// Main
//------------------------------------
public static void main(String argv[]) throws Exception {
//get video filename to request:
VideoFileName = argv[0];
video = new VideoStream(VideoFileName);
new Player();
}
//------------------------------------
// Handler for timer
//------------------------------------
class timerListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
//If the current image nb is less than the length of the video
if (imagenb < VIDEO_LENGTH) {
//Update current imagenb
imagenb++;
try {
double curTime = System.currentTimeMillis();
statTotalPlayTime += curTime - statStartTime;
statStartTime = curTime;
//Get next frame to play, as well as its size
int image_length = video.getnextframe(frame);
//Get to total length of the full frame
int packet_length = frame.length;
statDataRate = statTotalPlayTime == 0 ? 0 : (statTotalBytes / (statTotalPlayTime / 1000.0));
statTotalBytes += packet_length;
//Update GUI
updateStatsLabel();
//Get an Image object from the frame
Toolkit toolkit = Toolkit.getDefaultToolkit();
fsynch.addFrame(toolkit.createImage(frame, 0, packet_length), imagenb);
//Display the image as an ImageIcon object
icon = new ImageIcon(fsynch.nextFrame());
iconLabel.setIcon(icon);
System.out.println("Play frame #" + imagenb + ", Frame size: " + image_length + " (" + packet_length + ")");
}
catch (InterruptedIOException iioe) {
System.out.println("Nothing to read");
}
catch (IOException ioe) {
System.out.println("Exception caught: "+ioe);
System.exit(0);
}
catch(Exception ex) {
System.out.println("Exception caught: "+ex);
System.exit(0);
}
}
else {
//if we have reached the end of the video file, stop the timer
timer.stop();
}
}
}
//------------------------------------
// Handler for buttons
//------------------------------------
// Handler for Play button
//-----------------------
class playButtonListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
//Start to save the time in stats
statStartTime = System.currentTimeMillis();
System.out.println("Play Button pressed!");
//Start the timer
timer.start();
}
}
// Handler for Pause button
//-----------------------
class pauseButtonListener implements ActionListener {
public void actionPerformed(ActionEvent e){
System.out.println("Pause Button pressed!");
//Stop the timer
timer.stop();
}
}
// Handler for Teardown button
//-----------------------
class tearButtonListener implements ActionListener {
public void actionPerformed(ActionEvent e){
System.out.println("Teardown Button pressed !");
//Exit
timer.stop();
System.exit(0);
}
}
//------------------------------------
// Synchronize frames
//------------------------------------
class FrameSynchronizer {
private ArrayDeque<Image> queue;
private int bufSize;
private int curSeqNb;
private Image lastImage;
public FrameSynchronizer(int bsize) {
curSeqNb = 1;
bufSize = bsize;
queue = new ArrayDeque<Image>(bufSize);
}
//Synchronize frames based on their sequence number
public void addFrame(Image image, int seqNum) {
if (seqNum < curSeqNb) {
queue.add(lastImage);
}
else if (seqNum > curSeqNb) {
for (int i = curSeqNb; i < seqNum; i++) {
queue.add(lastImage);
}
queue.add(image);
}
else {
queue.add(image);
}
}
//Get the next synchronized frame
public Image nextFrame() {
curSeqNb++;
lastImage = queue.peekLast();
return queue.remove();
}
}
private void updateStatsLabel() {
DecimalFormat formatter = new DecimalFormat("###,###.##");
statLabel1.setText("Total Bytes played: " + statTotalBytes + " bytes");
statLabel2.setText("Data Rate (bytes/sec): " + formatter.format(statDataRate) + " bytes/s");
statLabel3.setText("Play frame #" + imagenb);
}
}