3
* Copyright (C) 2007 Garry Parker <parker13@gmail.com>
5
* Based on mpeg2dec_onroot.c (electricsheep):
6
* Copyright (C) 2000-2002 Michel Lespinasse <walken@zoy.org>
7
* Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
9
* This file is part of mpeg2dec, a free MPEG-2 video stream decoder.
10
* See http://libmpeg2.sourceforge.net/ for updates.
12
* mpeg2dec is free software; you can redistribute it and/or modify
13
* it under the terms of the GNU General Public License as published by
14
* the Free Software Foundation; either version 2 of the License, or
15
* (at your option) any later version.
17
* mpeg2dec is distributed in the hope that it will be useful,
18
* but WITHOUT ANY WARRANTY; without even the implied warranty of
19
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20
* GNU General Public License for more details.
22
* You should have received a copy of the GNU General Public License
23
* along with this program; if not, write to the Free Software
24
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26
#define _GNU_SOURCE /* for strcasestr */
36
#ifdef HAVE_SYS_TIME_H
42
#include <sys/types.h>
45
#include "video_out.h"
49
#define BUFFER_SIZE 4096
58
int window_id = -3; /* virtual root */
60
int target_fps = DEFFPS;
61
int numloops = DEFLOOP;
65
char fname[FILENAME_MAX];
73
static uint8_t buffer[BUFFER_SIZE];
74
static FILE * in_file;
75
static int demux_track = 0;
76
static int demux_pid = 0;
77
static int disable_accel = 0;
78
static mpeg2dec_t mpeg2dec;
79
static vo_open_t * output_open = NULL;
80
static char filename[FILENAME_MAX];
83
#ifdef HAVE_SYS_TIME_H
84
static void print_fps (int final);
86
static RETSIGTYPE signal_handler (int sig)
89
signal (sig, SIG_DFL);
93
static void print_fps (int final)
95
static uint32_t frame_counter = 0;
96
static struct timeval tv_beg, tv_start, tv_rate;
97
static int total_elapsed;
98
static int last_count = 0;
99
struct timeval tv_end;
100
int fps, tfps, frames, elapsed;
102
gettimeofday (&tv_end, NULL);
104
if (!frame_counter) {
105
tv_rate = tv_start = tv_beg = tv_end;
106
signal (SIGINT, signal_handler);
109
elapsed = (tv_end.tv_sec - tv_beg.tv_sec) * 100 +
110
(tv_end.tv_usec - tv_beg.tv_usec) / 10000;
111
total_elapsed = (tv_end.tv_sec - tv_start.tv_sec) * 100 +
112
(tv_end.tv_usec - tv_start.tv_usec) / 10000;
116
tfps = frame_counter * 10000 / total_elapsed;
121
fprintf (stderr,"\n%d frames decoded in %d.%02d "
122
"seconds (%d.%02d fps)\n", frame_counter,
123
total_elapsed / 100, total_elapsed % 100,
124
tfps / 100, tfps % 100);
131
if (elapsed < 50) /* only display every 0.50 seconds */
135
frames = frame_counter - last_count;
137
fps = frames * 10000 / elapsed; /* 100x */
138
tfps = frame_counter * 10000 / total_elapsed; /* 100x */
141
fprintf (stderr, "%d frames in %d.%02d sec (%d.%02d fps), "
142
"%d last %d.%02d sec (%d.%02d fps)\n", frame_counter,
143
total_elapsed / 100, total_elapsed % 100,
144
tfps / 100, tfps % 100, frames, elapsed / 100, elapsed % 100,
145
fps / 100, fps % 100);
147
last_count = frame_counter;
150
#else /* !HAVE_SYS_TIME_H */
151
static void print_fps (int final)
156
static void print_usage (char ** argv)
159
vo_driver_t * drivers;
162
"usage: %s [-l <numloops>] [-o <mode>] [-s [<track>]] [-t <pid>] [-c] "
163
"[-w <id>] [-f <fps>] <file>\n"
164
"\t-l\tnumber of times to loop each mpeg, \n"
165
"\t-s\tuse program stream demultiplexer, "
166
"track 0-15 or 0xe0-0xef\n"
167
"\t-t\tuse transport stream demultiplexer, pid 0x10-0x1ffe\n"
168
"\t-c\tuse c implementation, disables all accelerations\n"
170
"\t-f\ttarget frame rate\n"
171
"\t-o\tvideo output mode\n", argv[0]);
173
drivers = vo_drivers ();
174
for (i = 0; drivers[i].name; i++)
175
fprintf (stderr, "\t\t\t%s\n", drivers[i].name);
180
static void handle_args (int argc, char ** argv)
183
vo_driver_t * drivers;
187
drivers = vo_drivers ();
188
while ((c = getopt (argc, argv, "l:s::t:co:w:f:")) != -1)
191
for (i = 0; drivers[i].name != NULL; i++)
192
if (strcmp(drivers[i].name, optarg) == 0)
193
output_open = drivers[i].open;
195
if (output_open == NULL)
197
fprintf(stderr, "Invalid video driver: %s\n", optarg);
206
demux_track = strtol (optarg, &s, 16);
207
if (demux_track < 0xe0) demux_track += 0xe0;
209
if ((demux_track < 0xe0) || (demux_track > 0xef) || (*s))
211
fprintf (stderr, "Invalid track number: %s\n", optarg);
218
demux_pid = strtol (optarg, &s, 16);
219
if ((demux_pid < 0x10) || (demux_pid > 0x1ffe) || (*s))
221
fprintf (stderr, "Invalid pid: %s\n", optarg);
231
window_id = strtol (optarg, &s, 0);
235
target_fps = strtol (optarg, &s, 10);
238
fprintf(stderr, "target frame rate must be positive, not %d.\n", target_fps);
244
numloops = strtol(optarg, &s, 10);
247
fprintf(stderr, "number of loops be >= 0\n");
256
/* -o not specified, use a default driver */
257
if (output_open == NULL)
258
output_open = drivers[0].open;
262
in_file = fopen (argv[optind], "rb");
264
fprintf (stderr, "%s - couldnt open file %s\n", strerror (errno), argv[optind]);
271
strcpy(filename, argv[optind]);
274
fprintf (stderr, "Must specify a file or directory to play\n");
279
static void decode_mpeg2 (uint8_t * buf, uint8_t * end)
283
num_frames = mpeg2_decode_data (&mpeg2dec, buf, end);
288
#define DEMUX_PAYLOAD_START 1
289
static int demux (uint8_t * buf, uint8_t * end, int flags)
291
static int mpeg1_skip_table[16] = {
292
0, 0, 4, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
296
* the demuxer keeps some state between calls:
297
* if "state" = DEMUX_HEADER, then "head_buf" contains the first
298
* "bytes" bytes from some header.
299
* if "state" == DEMUX_DATA, then we need to copy "bytes" bytes
300
* of ES data before the next header.
301
* if "state" == DEMUX_SKIP, then we need to skip "bytes" bytes
302
* of data before the next header.
304
* NEEDBYTES makes sure we have the requested number of bytes for a
305
* header. If we dont, it copies what we have into head_buf and returns,
306
* so that when we come back with more data we finish decoding this header.
308
* DONEBYTES updates "buf" to point after the header we just parsed.
311
#define DEMUX_HEADER 0
314
static int state = DEMUX_SKIP;
315
static int state_bytes = 0;
316
static uint8_t head_buf[264];
322
#define NEEDBYTES(x) \
326
missing = (x) - bytes; \
328
if (header == head_buf) { \
329
if (missing <= end - buf) { \
330
memcpy (header + bytes, buf, missing); \
334
memcpy (header + bytes, buf, end - buf); \
335
state_bytes = bytes + end - buf; \
339
memcpy (head_buf, header, bytes); \
340
state = DEMUX_HEADER; \
341
state_bytes = bytes; \
347
#define DONEBYTES(x) \
349
if (header != head_buf) \
350
buf = header + (x); \
353
if (flags & DEMUX_PAYLOAD_START)
357
if (state_bytes > 0) {
360
goto continue_header;
364
if (demux_pid || (state_bytes > end - buf)) {
365
decode_mpeg2 (buf, end);
366
state_bytes -= end - buf;
369
decode_mpeg2 (buf, buf + state_bytes);
373
if (demux_pid || (state_bytes > end - buf)) {
374
state_bytes -= end - buf;
391
if (header[0] || header[1] || (header[2] != 1)) {
395
} else if (header != head_buf) {
399
header[0] = header[1];
400
header[1] = header[2];
401
header[2] = header[3];
403
goto continue_header;
407
if ((header[3] >= 0xe0) && (header[3] <= 0xef))
409
fprintf (stderr, "bad stream id %x\n", header[3]);
413
case 0xb9: /* program end code */
417
case 0xba: /* pack header */
419
if ((header[4] & 0xc0) == 0x40) { /* mpeg2 */
421
len = 14 + (header[13] & 7);
424
/* header points to the mpeg2 pack header */
425
} else if ((header[4] & 0xf0) == 0x20) { /* mpeg1 */
427
/* header points to the mpeg1 pack header */
429
fprintf (stderr, "weird pack header\n");
434
if (header[3] == demux_track) {
437
if ((header[6] & 0xc0) == 0x80) { /* mpeg2 */
441
/* header points to the mpeg2 pes header */
442
if (header[7] & 0x80) {
445
pts = (((buf[9] >> 1) << 30) |
446
(buf[10] << 22) | ((buf[11] >> 1) << 15) |
447
(buf[12] << 7) | (buf[13] >> 1));
448
mpeg2_pts (&mpeg2dec, pts);
455
while (header[len - 1] == 0xff) {
459
fprintf (stderr, "too much stuffing\n");
463
if ((header[len - 1] & 0xc0) == 0x40) {
468
len += mpeg1_skip_table[header[len - 1] >> 4];
470
/* header points to the mpeg1 pes header */
471
ptsbuf = header + len_skip;
472
if (ptsbuf[-1] & 0x20) {
475
pts = (((ptsbuf[-1] >> 1) << 30) |
476
(ptsbuf[0] << 22) | ((ptsbuf[1] >> 1) << 15) |
477
(ptsbuf[2] << 7) | (ptsbuf[3] >> 1));
478
mpeg2_pts (&mpeg2dec, pts);
482
bytes = 6 + (header[4] << 8) + header[5] - len;
483
if (demux_pid || (bytes > end - buf)) {
484
decode_mpeg2 (buf, end);
486
state_bytes = bytes - (end - buf);
488
} else if (bytes > 0) {
489
decode_mpeg2 (buf, buf + bytes);
492
} else if (header[3] < 0xb9) {
494
"looks like a video stream, not system stream\n");
499
bytes = (header[4] << 8) + header[5];
500
if (bytes > end - buf) {
502
state_bytes = bytes - (end - buf);
511
static void ps_loop (void)
516
end = buffer + fread (buffer, 1, BUFFER_SIZE, in_file);
517
if (demux (buffer, end, 0))
518
break; /* hit program_end_code */
519
} while (end == buffer + BUFFER_SIZE);
522
static void ts_loop (void)
524
#define PACKETS (BUFFER_SIZE / 188)
533
packets = fread (buffer, 188, PACKETS, in_file);
534
for (i = 0; i < packets; i++) {
535
buf = buffer + i * 188;
537
if (buf[0] != 0x47) {
538
fprintf (stderr, "bad sync byte\n");
541
pid = ((buf[1] << 8) + buf[2]) & 0x1fff;
542
if (pid != demux_pid)
545
if (buf[3] & 0x20) { /* buf contains an adaptation field */
546
data = buf + 5 + buf[4];
551
demux (data, end, (buf[1] & 0x40) ? DEMUX_PAYLOAD_START : 0);
553
} while (packets == PACKETS);
556
static void es_loop()
562
end = buffer + fread (buffer, 1, BUFFER_SIZE, in_file);
563
decode_mpeg2 (buffer, end);
564
} while (end == buffer + BUFFER_SIZE);
567
static void play_file(char *fname, int nloops, int fps)
571
target_fps=fps; /* global used by video_out_x11.c */
573
for (i=0; i<nloops; i++)
575
in_file = fopen(fname, "rb");
578
fprintf(stderr, "%s - couldn't open file %s\n", strerror(errno), fname);
582
/* printf("Playing '%s' %d %d\n", fname, nloops, fps);*/
586
else if (demux_track)
595
void parse_config(char *fname)
601
char name[FILENAME_MAX];
603
rc = fopen(fname, "r");
606
fprintf(stderr, "%s - couldn't open file %s\n", strerror(errno), fname);
610
while (fgets(buf, sizeof buf, rc))
618
case 1: strcpy(name, f); break;
619
case 2: nloops = atoi(f); break;
620
case 3: fps = atoi(f); break;
626
if (name[0]!='\0' && name[0]!='#')
628
strcpy(cfg[numclips].fname, name);
630
cfg[numclips].nloops = (nloops >= MINLOOP && nloops <= MAXLOOP) ? nloops : DEFLOOP;
631
cfg[numclips].fps = (fps >= MINFPS && fps <= MAXFPS) ? fps : DEFFPS;
633
printf("CFG[%i]: %s %d %d \n",
634
numclips, cfg[numclips].fname, cfg[numclips].nloops, cfg[numclips].fps);
641
static void play_files()
647
for (i=0; i<numclips; i++)
648
play_file(cfg[i].fname, cfg[i].nloops, cfg[i].fps);
652
/* "filename" can be a single .mpg file or a directory containing
655
static void process_dir(char *dname)
659
char fullpath[FILENAME_MAX];
661
/* Continually loop through the directory and play each
662
* .mpg file the requested number of times
666
if ((dp=opendir(dname))==NULL)
668
/* Assume it's a file and play it */
669
play_file(dname, numloops, target_fps);
673
/* Parse the directory */
674
while ((fp=readdir(dp)) != NULL)
676
if (strcasestr(fp->d_name, ".mpg") != NULL)
678
sprintf(fullpath, "%s/%s", dname, fp->d_name);
679
play_file(fullpath, numloops, target_fps);
687
int main (int argc, char ** argv)
689
vo_instance_t * output;
692
if (!quiet) fprintf (stderr, PACKAGE"-"VERSION
693
" - by Michel Lespinasse <walken@zoy.org> and Aaron Holtzman\n");
694
handle_args (argc, argv);
696
accel = disable_accel ? 0 : (mm_accel () | MM_ACCEL_MLIB);
699
output = vo_open (output_open);
700
if (output == NULL) {
701
fprintf (stderr, "Cannot open output\n");
704
mpeg2_init (&mpeg2dec, accel, output);
707
/* Check if we've been passed a config file */
708
if (strcasestr(filename, ".cfg") != NULL)
710
/* The config file tells us what to play and the settings for each file */
711
parse_config(filename);
716
/* Process the directory or file using default values */
717
process_dir(filename);
720
mpeg2_close (&mpeg2dec);