Bug Summary

File:mpeg2desc.c
Location:line 765, column 33
Description:Value stored to 'eptr' is never read

Annotated Source Code

1/*
2 Utility to extract audio/video streams and dump information about
3 packetes in an MPEG stream.
4*/
5/*
6 * Copyright (C) 2002 Scott Smith (trckjunky@users.sourceforge.net)
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or (at
11 * your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
21 * MA 02110-1301 USA.
22 */
23
24#include "config.h"
25
26#include "compat.h"
27
28#include <setjmp.h>
29#include <assert.h>
30#include <errno(*__errno_location ()).h>
31#include <fcntl.h>
32
33// this is needed for FreeBSD and Windows
34#include <sys/time.h>
35
36#include "common.h"
37
38// #define SHOWDATA
39
40static unsigned int
41 inputpos = 0, /* position in stdin */
42 queuedlen = 0; /* total nr bytes awaiting writing to output files */
43
44const char * const frametype = "0IPB4567";
45
46#define SCRTIME27000000 27000000
47#define PTSTIME90000 90000
48
49#define WAITLEN(256*1024) (256*1024)
50
51#define BUFLEN(65536) (65536)
52
53struct fdbuf
54 {
55 int pos,len;
56 struct fdbuf *next;
57 unsigned char buf[BUFLEN(65536)];
58 };
59
60#define MAX_FILES256 256
61 /* how many output files I can write at once -- can't have
62 more than this number of MPEG streams anyway */
63
64/* values for ofd.fd: */
65#define FD_TOOPEN(-2) (-2) /* open file named ofd.fname on first write */
66#define FD_CLOSED(-1) (-1)
67
68struct ofd
69 {
70 int fd;
71 char *fname;
72 struct fdbuf *firstbuf,**lastbufptr; /* queue of buffers awaiting writing */
73 int len;
74 bool_Bool isvalid;
75 } outputfds[256]; /* files to write, indexed by stream id */
76
77static int
78 ofdlist[MAX_FILES256], /* indexes of used entries in outputfds */
79 numofd; /* contiguous used size of ofdlist */
80
81static int firstpts[256]; /* indexed by stream id */
82
83static bool_Bool
84 outputenglish = true1,
85 nounknown = false0,
86 closing = false0,
87 outputmplex = false0;
88static int
89 audiodrop = 0;
90
91static fd_set
92 /* should be local to dowork routine */
93 rfd, wfd;
94
95static int64_t readpts(const unsigned char *buf)
96 {
97 return
98 (int64_t)((buf[0] & 0xf) >> 1) << 30
99 |
100 ((int64_t)buf[1] << 8 | buf[2]) >> 1 << 15
101 |
102 ((int64_t)buf[3] << 8 | buf[4]) >> 1;
103 } /*readpts*/
104
105static bool_Bool hasbecomevalid(int stream, const struct ofd *o)
106 /* checks if there is a valid packet header at the start of the data to be
107 written to the specified output stream. Assumes there is at least 4 bytes
108 of data waiting to be written. */
109 {
110 bool_Bool valid = false0;
111 unsigned int realquad;
112 const struct fdbuf * const f1 = o->firstbuf;
113 if (f1 != 0)
114 {
115 unsigned char quad[4];
116 int i;
117 const struct fdbuf * const f2 = f1->next;
118 valid = true1; /* next assumption */
119 for (i = 0; valid && i < 4; i++)
120 {
121 if (f1->len - f1->pos - i > 0)
122 quad[i] = f1->buf[f1->pos + i];
123 else if (f2 != 0)
124 quad[i] = f2->buf[f2->pos + i - (f1->len - f1->pos)];
125 else
126 valid = false0;
127 } /*for*/
128 if (valid)
129 {
130 realquad =
131 quad[0] << 24
132 |
133 quad[1] << 16
134 |
135 quad[2] << 8
136 |
137 quad[3];
138 } /*if*/
139 } /*if*/
140 return
141 valid
142 &&
143 (
144 stream >= MPID_AUDIO_FIRST
145 &&
146 stream <= MPID_AUDIO_LAST
147 &&
148 (realquad & 0xFFE00000) == 0xFFE00000
149 ||
150 stream >= MPID_VIDEO_FIRST
151 &&
152 stream <= MPID_VIDEO_LAST
153 &&
154 realquad == 0x100 + MPID_SEQUENCE
155 );
156 } /*hasbecomevalid*/
157
158static bool_Bool dowork
159 (
160 bool_Bool checkin /* whether to check if bytes are available to be read from stdin */
161 )
162 /* writes pending packets to output streams. This is done concurrently to allow
163 for use with pipes. Returns true iff stdin has input available. */
164 {
165 int highestfd = -1;
166 struct timeval tv;
167 if (!numofd)
168 return checkin;
169 if (checkin)
170 {
171 FD_SET(STDIN_FILENO, &rfd)((void) (((&rfd)->fds_bits)[((0) / (8 * (int) sizeof (
__fd_mask)))] |= ((__fd_mask) 1 << ((0) % (8 * (int) sizeof
(__fd_mask))))))
;
172 highestfd = STDIN_FILENO0;
173 }
174 else
175 {
176 FD_CLR(STDIN_FILENO, &rfd)((void) (((&rfd)->fds_bits)[((0) / (8 * (int) sizeof (
__fd_mask)))] &= ~((__fd_mask) 1 << ((0) % (8 * (int
) sizeof (__fd_mask))))))
;
177 } /*if*/
178 while (true1)
179 {
180 int i, minq = -1;
181 for (i = 0; i < numofd; i++)
182 {
183 struct ofd *o = &outputfds[ofdlist[i]];
184 if (o->fd != FD_CLOSED(-1))
185 {
186 if (o->fd == FD_TOOPEN(-2))
187 {
188 int fd;
189 fd = open(o->fname, O_CREAT0100 | O_WRONLY01 | O_NONBLOCK04000, 0666);
190 if (fd == -1 && errno(*__errno_location ()) == ENXIO6)
191 {
192 continue; /* try again later, in case pipe not created yet */
193 } /*if*/
194 if (fd == -1)
195 {
196 fprintf(stderrstderr,"Cannot open %s: %s\n",o->fname,strerror(errno(*__errno_location ())));
197 exit(1);
198 } /*if*/
199 o->fd = fd;
200 } /*if*/
201 // at this point, fd >= 0
202 if (minq == -1 || o->len < minq)
203 {
204 minq = o->len;
205 } /*if*/
206 if ((o->len > 0 && o->isvalid) || o->len >= 4)
207 {
208 if (o->fd > highestfd)
209 highestfd = o->fd;
210 FD_SET(o->fd, &wfd)((void) (((&wfd)->fds_bits)[((o->fd) / (8 * (int) sizeof
(__fd_mask)))] |= ((__fd_mask) 1 << ((o->fd) % (8 *
(int) sizeof (__fd_mask))))))
;
211 }
212 else
213 {
214 FD_CLR(o->fd, &wfd)((void) (((&wfd)->fds_bits)[((o->fd) / (8 * (int) sizeof
(__fd_mask)))] &= ~((__fd_mask) 1 << ((o->fd) %
(8 * (int) sizeof (__fd_mask))))))
;
215 if (closing)
216 {
217 close(o->fd);
218 o->fd = FD_CLOSED(-1);
219 } /*if*/
220 } /*if*/
221 } /*if*/
222 } /*for*/
223 // if all the open files have more then WAITLEN bytes of data
224 // queued up, then don't process anymore
225 if (minq >= WAITLEN(256*1024))
226 {
227 FD_CLR(STDIN_FILENO, &rfd)((void) (((&rfd)->fds_bits)[((0) / (8 * (int) sizeof (
__fd_mask)))] &= ~((__fd_mask) 1 << ((0) % (8 * (int
) sizeof (__fd_mask))))))
;
228 break;
229 }
230 else if (minq >= 0 || outputmplex) // as long as one file is open, continue
231 break;
232 sleep(1);
233 } /*while*/
234 if (highestfd == -1)
235 return false0; /* nothing to do */
236 tv.tv_sec = 1; // set timeout to 1 second just in case any files need to be opened
237 tv.tv_usec = 0;
238 if (select(highestfd + 1, &rfd, &wfd, NULL((void*)0), &tv) > 0)
239 {
240 int i;
241 for (i = 0; i < numofd; i++)
242 {
243 struct ofd * const o = &outputfds[ofdlist[i]];
244 if (o->fd >= 0 && FD_ISSET(o->fd, &wfd)((((&wfd)->fds_bits)[((o->fd) / (8 * (int) sizeof (
__fd_mask)))] & ((__fd_mask) 1 << ((o->fd) % (8 *
(int) sizeof (__fd_mask))))) != 0)
)
245 {
246 struct fdbuf * const f = o->firstbuf;
247 int written;
248 if (!o->isvalid && hasbecomevalid(ofdlist[i], o))
249 o->isvalid = true1;
250 if (o->isvalid)
251 written = write(o->fd, f->buf + f->pos, f->len - f->pos);
252 else if (f->len - f->pos > 0)
253 written = 1; /* discard one byte while waiting for valid packet */
254 else
255 written = 0;
256 if (written == -1)
257 {
258 fprintf(stderrstderr,"Error writing to fifo: %s\n",strerror(errno(*__errno_location ())));
259 exit(1);
260 } /*if*/
261 queuedlen -= written;
262 f->pos += written;
263 if (f->pos == f->len)
264 {
265 /* finished writing buffer at head of queue */
266 o->firstbuf = f->next;
267 if (o->lastbufptr == &f->next)
268 o->lastbufptr = &o->firstbuf;
269 free(f);
270 } /*if*/
271 o->len -= written;
272 } /*if*/
273 } /*for*/
274 if (FD_ISSET(STDIN_FILENO, &rfd)((((&rfd)->fds_bits)[((0) / (8 * (int) sizeof (__fd_mask
)))] & ((__fd_mask) 1 << ((0) % (8 * (int) sizeof (
__fd_mask))))) != 0)
)
275 return true1;
276 } /*if*/
277 return false0;
278 } /*dowork*/
279
280static void flushwork(void)
281 /* flushes the work queue. */
282 {
283 closing = true1;
284 while (queuedlen)
285 dowork(false0);
286 } /*flushwork*/
287
288static void forceread(void *ptr, int len, bool_Bool required)
289 /* reads the specified number of bytes from standard input, finishing processing
290 if EOF is reached. */
291 {
292 int nrbytes;
293 while (!dowork(true1))
294 /* flush output queues while waiting for more input */;
295 nrbytes = fread(ptr, 1, len, stdinstdin);
296 if (nrbytes != len)
297 {
298 bool_Bool success = true1;
299 if (nrbytes < 0)
300 {
301 fprintf(stderrstderr, "Error %d reading: %s\n", errno(*__errno_location ()), strerror(errno(*__errno_location ())));
302 success = false0;
303 }
304 else if (nrbytes < len && required)
305 {
306 fprintf(stderrstderr, "Unexpected read EOF\n");
307 success = false0;
308 } /*if*/
309 flushwork();
310 exit(success ? 0 : 1);
311 } /*if*/
312 inputpos += len;
313 } /*forceread*/
314
315static void writetostream(int stream, unsigned char *buf, int len)
316 /* queues more data to be written to the output file for the specified stream id,
317 if I am writing it. */
318 {
319 struct ofd * const o = &outputfds[stream];
320 if (o->fd == FD_CLOSED(-1)) /* not extracting this stream */
321 return;
322 while (len > 0)
323 {
324 int thislen;
325 struct fdbuf *fb;
326 if (!o->lastbufptr[0])
327 {
328 o->lastbufptr[0] = malloc(sizeof(struct fdbuf));
329 o->lastbufptr[0]->pos = 0;
330 o->lastbufptr[0]->len = 0;
331 o->lastbufptr[0]->next = 0;
332 } /*if*/
333 fb = o->lastbufptr[0];
334 thislen = BUFLEN(65536) - fb->len;
335 if (!thislen)
336 {
337 o->lastbufptr = &fb->next;
338 continue;
339 } /*if*/
340 if (thislen > len)
341 thislen = len;
342 o->len += thislen;
343 memcpy(fb->buf + fb->len, buf, thislen);
344 fb->len += thislen;
345 len -= thislen;
346 buf += thislen;
347 queuedlen += thislen;
348 } /*while*/
349 } /*writetostream*/
350
351static void process_packets
352 (
353 void (*readinput)(void *ptr, int len, bool_Bool required),
354 bool_Bool recursed
355 )
356 {
357 unsigned char hdr[4];
358 unsigned char buf[200];
359 bool_Bool fetchhdr = true1;
360 while (true1)
361 {
362 const int disppos = fetchhdr ? inputpos : inputpos - 4; /* where packet actually started */
363 bool_Bool handled = true1;
364 int hdrid;
365 if (fetchhdr)
366 {
367 readinput(hdr, 4, false0);
368 } /*if*/
369 fetchhdr = true1; /* initial assumption */
370 hdrid =
371 hdr[0] << 24
372 |
373 hdr[1] << 16
374 |
375 hdr[2] << 8
376 |
377 hdr[3];
378 switch (hdrid)
379 {
380 // start codes:
381 case 0x100 + MPID_PICTURE: // picture header
382 readinput(buf, 4, true1);
383 if (outputenglish)
384 printf
385 (
386 "%08x: picture hdr, frametype=%c, temporal=%d\n",
387 disppos,
388 frametype[buf[1] >> 3 & 7],
389 buf[0] << 2 | buf[1] >> 6
390 );
391 break;
392
393 case 0x100 + MPID_SEQUENCE: // sequence header
394 readinput(buf, 8, true1);
395 if (outputenglish)
396 printf
397 (
398 "%08x: sequence hdr: %dx%d, a/f:%02x, bitrate=%d\n",
399 disppos,
400 buf[0] << 4 | buf[1] >> 4,
401 buf[1] << 8 & 0xf00 | buf[2],
402 buf[3],
403 buf[4] << 10 | buf[5] << 2 | buf[6] >> 6
404 );
405 if (buf[7] & 2)
406 readinput(buf + 8, 64, true1);
407 if (buf[7] & 1)
408 readinput(buf + 8, 64, true1);
409 break;
410
411 case 0x100 + MPID_EXTENSION: // extension header
412 readinput(buf, 1, true1);
413 switch (buf[0] >> 4)
414 {
415 case 1:
416 if (outputenglish)
417 printf("%08x: sequence extension hdr\n", disppos);
418 readinput(buf + 1, 5, true1);
419 break;
420 case 2:
421 if (outputenglish)
422 printf("%08x: sequence display extension hdr\n", disppos);
423 readinput(buf + 1, (buf[0] & 1) ? 7 : 3, true1);
424 break;
425 case 7:
426 if (outputenglish)
427 printf("%08x: picture display extension hdr\n", disppos);
428 break;
429 case 8:
430 readinput(buf + 1, 4, true1);
431 if (buf[4] & 64)
432 readinput(buf + 5, 2, true1);
433 if (outputenglish)
434 {
435 printf
436 (
437 "%08x: picture coding extension hdr%s%s\n",
438 disppos,
439 (buf[3] & 0x80) ? ", top" : ", bottom",
440 (buf[3] & 2) ? ", repeat" : ""
441 );
442 } /*if*/
443 break;
444 default:
445 if (outputenglish)
446 printf("%08x: extension hdr %x\n", disppos, buf[0] >> 4);
447 break;
448 } /*switch*/
449 break;
450
451 case 0x100 + MPID_SEQUENCE_END: // end of sequence
452 if (outputenglish)
453 printf("%08x: end of sequence\n", disppos);
454 break;
455
456 case 0x100 + MPID_GOP: // group of pictures
457 readinput(buf, 4, true1);
458 if (outputenglish)
459 {
460 printf
461 (
462 "%08x: GOP: %s%d:%02d:%02d.%02d, %s%s\n",
463 disppos,
464 buf[0] & 128 ? "drop, " : "",
465 buf[0] >> 2 & 31,
466 (buf[0] << 4 | buf[1] >> 4) & 63,
467 (buf[1] << 3 | buf[2] >> 5) & 63,
468 (buf[2] << 1 | buf[3] >> 7) & 63,
469 buf[3] & 64 ? "closed" : "open",
470 buf[3] & 32 ? ", broken" : ""
471 );
472 } /*if*/
473 break;
474
475 case 0x100 + MPID_PROGRAM_END: // end of program stream
476 if (outputenglish)
477 printf("%08x: end of program stream\n", disppos);
478 break;
479
480 case 0x100 + MPID_PACK: // mpeg_pack_header
481 {
482 uint32_t scr,scrhi,scrext;
483 int64_t fulltime;
484 bool_Bool mpeg2 = true1;
485 readinput(buf, 8, true1);
486 if ((buf[0] & 0xC0) == 0x40)
487 {
488 readinput(buf + 8, 2, true1);
489 scrhi = (buf[0] & 0x20) >> 5;
490 scr =
491 (buf[0] & 0x18) << 27
492 |
493 (buf[0] & 3) << 28
494 |
495 buf[1] << 20
496 |
497 (buf[2] & 0xf8) << 12
498 |
499 (buf[2] & 3) << 13
500 |
501 buf[3] << 5
502 |
503 (buf[4] & 0xf8) >> 3;
504 scrext =
505 (buf[4] & 3) << 7
506 |
507 buf[5] >> 1;
508 if (scrext >= 300 && outputenglish)
509 {
510 printf("WARN: scrext in pack hdr > 300: %u\n", scrext);
511 } /*if*/
512 fulltime = (int64_t)scrhi << 32 | (int64_t)scr;
513 fulltime *= 300;
514 fulltime += scrext;
515 mpeg2 = true1;
516 }
517 else if ((buf[0] & 0xF0) == 0x20)
518 {
519 mpeg2 = false0;
520 fulltime = readpts(buf);
521 fulltime *= 300;
522 }
523 else
524 {
525 if (outputenglish)
526 printf("WARN: unknown pack header version\n");
527 fulltime = 0;
528 } /*if*/
529 if (outputenglish)
530 printf
531 (
532 "%08x: mpeg%c pack hdr, %" PRId64"l" "d" ".%03" PRId64"l" "d" " sec\n",
533 disppos,
534 mpeg2 ? '2' : '1',
535 fulltime / SCRTIME27000000,
536 (fulltime % SCRTIME27000000) / (SCRTIME27000000 / 1000)
537 );
538 }
539 break;
540 default:
541 handled = false0;
542 break;
543 } /*switch*/
544 if
545 (
546 !handled
547 &&
548 !recursed
549 &&
550 (
551 hdrid == 0x100 + MPID_SYSTEM
552 ||
553 hdrid == 0x100 + MPID_PRIVATE1
554 ||
555 hdrid == 0x100 + MPID_PAD
556 ||
557 hdrid == 0x100 + MPID_PRIVATE2
558 ||
559 hdrid >= 0x100 + MPID_AUDIO_FIRST && hdrid <= 0x100 + MPID_AUDIO_LAST
560 ||
561 hdrid >= 0x100 + MPID_VIDEO_FIRST && hdrid <= 0x100 + MPID_VIDEO_LAST
562 )
563 )
564 {
565 bool_Bool has_extension = false0;
566 unsigned int headerlen, packetlen, contentoffs;
567 int readlen;
568 bool_Bool dowrite = !recursed;
569 const int packetid = hdrid & 255;
570 if (outputenglish)
571 printf("%08x: ", disppos);
572 if (packetid == MPID_SYSTEM)
573 {
574 if (outputenglish)
575 printf("system header");
576 }
577 else if (packetid == MPID_PRIVATE1)
578 {
579 if (outputenglish)
580 printf("pes private1");
581 has_extension = true1;
582 }
583 else if (packetid == MPID_PAD)
584 {
585 if (outputenglish)
586 printf("pes padding");
587 }
588 else if (packetid == MPID_PRIVATE2)
589 {
590 if (outputenglish)
591 printf("pes private2");
592 }
593 else if (packetid >= MPID_AUDIO_FIRST && packetid <= MPID_AUDIO_LAST)
594 {
595 if (outputenglish)
596 printf("pes audio %d", packetid - MPID_AUDIO_FIRST);
597 if (audiodrop)
598 {
599 dowrite = false0;
600 audiodrop--;
601 } /*if*/
602 has_extension = true1;
603 }
604 else if (packetid >= MPID_VIDEO_FIRST && packetid <= MPID_VIDEO_LAST)
605 {
606 if (outputenglish)
607 printf("pes video %d", packetid - MPID_VIDEO_FIRST);
608 has_extension = true1;
609 } /*if*/
610 readinput(buf, 2, true1); // pes packet length
611 packetlen = buf[0] << 8 | buf[1];
612 readlen = packetlen > sizeof buf ? sizeof buf : packetlen;
613 readinput(buf, readlen, true1);
614 packetlen -= readlen;
615 headerlen = buf[2]; /* length of packet header */
616 contentoffs = 3 + headerlen; /* beginning of packet content */
617 if (outputenglish)
618 {
619 if (packetid == MPID_PRIVATE1) // private stream 1
620 {
621 const int sid = buf[contentoffs]; /* substream ID is first byte after header */
622 switch (sid & 0xf8)
623 {
624 case 0x20:
625 case 0x28:
626 case 0x30:
627 case 0x38:
628 printf(", subpicture %d", sid & 0x1f);
629 break;
630 case 0x80:
631 printf(", AC3 audio %d", sid & 7);
632 break;
633 case 0x88:
634 printf(", DTS audio %d", sid & 7);
635 case 0xa0:
636 printf(", LPCM audio %d", sid & 7);
637 break;
638 default:
639 printf(", substream id 0x%02x", sid);
640 break;
641 } /*switch*/
642 }
643 else if (packetid == MPID_PRIVATE2) // private stream 2
644 {
645 const int sid = buf[0];
646 switch (sid)
647 {
648 case 0:
649 printf(", PCI");
650 break;
651 case 1:
652 printf(", DSI");
653 break;
654 default:
655 printf(", substream id 0x%02x", sid);
656 break;
657 } /*switch*/
658 } /*if*/
659 printf("; length=%d", packetlen + readlen);
660 if (has_extension)
661 {
662 int eptr;
663 bool_Bool has_std = false0, has_pts, has_dts;
664 int hdroffs, std=0, std_scale=0;
665 const bool_Bool mpeg2 = (buf[0] & 0xC0) == 0x80;
666 if (mpeg2)
667 {
668 hdroffs = contentoffs;
669 eptr = 3;
670 has_pts = (buf[1] & 128) != 0;
671 has_dts = (buf[1] & 64) != 0;
672 }
673 else
674 {
675 hdroffs = 0;
676 while (buf[hdroffs] == 0xff && hdroffs < sizeof(buf))
677 hdroffs++;
678 if ((buf[hdroffs] & 0xC0) == 0x40)
679 {
680 has_std = true1;
681 std_scale = (buf[hdroffs] & 32) ? 1024 : 128;
682 std = ((buf[hdroffs] & 31) * 256 + buf[hdroffs + 1]) * std_scale;
683 hdroffs += 2;
684 } /*if*/
685 eptr = hdroffs;
686 has_pts = (buf[hdroffs] & 0xE0) == 0x20;
687 has_dts = (buf[hdroffs] & 0xF0) == 0x30;
688 } /*if*/
689 printf("; hdr=%d", hdroffs);
690 if (has_pts)
691 {
692 int64_t pts;
693 pts = readpts(buf + eptr);
694 eptr += 5;
695 printf
696 (
697 "; pts %" PRId64"l" "d" ".%03" PRId64"l" "d" " sec",
698 pts / PTSTIME90000,
699 (pts % PTSTIME90000) / (PTSTIME90000 / 1000)
700 );
701 } /*if*/
702 if (has_dts)
703 {
704 int64_t dts;
705 dts = readpts(buf + eptr);
706 eptr += 5;
707 printf
708 (
709 "; dts %" PRId64"l" "d" ".%03" PRId64"l" "d" " sec",
710 dts / PTSTIME90000,
711 (dts % PTSTIME90000) / (PTSTIME90000 / 1000)
712 );
713 } /*if*/
714 if (mpeg2)
715 {
716 if (buf[1] & 32)
717 {
718 printf("; escr");
719 eptr += 6;
720 } /*if*/
721 if (buf[1] & 16)
722 {
723 printf("; es");
724 eptr += 2;
725 } /*if*/
726 if (buf[1] & 4)
727 {
728 printf("; ci");
729 eptr++;
730 } /*if*/
731 if (buf[1] & 2)
732 {
733 printf("; crc");
734 eptr += 2;
735 } /*if*/
736 if (buf[1] & 1)
737 {
738 int pef = buf[eptr];
739 eptr++;
740 printf("; (pext)");
741 if (pef & 128)
742 {
743 printf("; user");
744 eptr += 16;
745 } /*if*/
746 if (pef & 64)
747 {
748 printf("; pack");
749 eptr++;
750 } /*if*/
751 if (pef & 32)
752 {
753 printf("; ppscf");
754 eptr += 2;
755 } /*if*/
756 if (pef & 16)
757 {
758 std_scale = (buf[eptr] & 32) ? 1024 : 128;
759 printf
760 (
761 "; pstd=%d (scale=%d)",
762 ((buf[eptr] & 31) * 256 + buf[eptr + 1]) * std_scale,
763 std_scale
764 );
765 eptr += 2;
Value stored to 'eptr' is never read
766 } /*if*/
767 if (pef & 1)
768 {
769 printf("; (pext2)");
770 /* eptr += 2; */ /* not further used */
771 } /*if*/
772 } /*if*/
773 }
774 else
775 {
776 if (has_std)
777 printf("; pstd=%d (scale=%d)", std, std_scale);
778 } /*if*/
779 } /*if*/
780 printf("\n");
781 } /*if*/
782 if (outputmplex && has_extension)
783 {
784 if ((buf[1] & 128) != 0 && firstpts[packetid] == -1)
785 firstpts[packetid] = readpts(buf + 3);
786 if (firstpts[MPID_AUDIO_FIRST] != -1 && firstpts[MPID_VIDEO_FIRST] != -1)
787 {
788 printf("%d\n", firstpts[MPID_VIDEO_FIRST] - firstpts[MPID_AUDIO_FIRST]);
789 fflush(stdoutstdout);
790 close(1);
791 outputmplex = false0;
792 if (!numofd)
793 exit(0);
794 } /*if*/
795 } /*if*/
796#ifdef SHOWDATA
797 if (has_extension && outputenglish)
798 {
799 int j;
800 printf(" ");
801 for (j=0; j<16; j++)
802 printf(" %02x", buf[j + contentoffs]);
803 printf("\n");
804 } /*if*/
805#endif
806 if (!recursed)
807 {
808 if (has_extension && dowrite)
809 {
810 writetostream(packetid, buf + contentoffs, readlen - contentoffs);
811 } /*if*/
812#if defined(HAVE_NESTED_ROUTINES)
813 if (outputenglish && packetid >= MPID_VIDEO_FIRST && packetid <= MPID_VIDEO_LAST)
814 {
815 /* look inside PES packet to report on details of video packets */
816 unsigned int remaining = readlen;
817 jmp_buf resume;
818 /* GCC extension! nested routine */
819 void bufread(void *ptr, int len, bool_Bool required)
820 {
821 const unsigned int tocopy = remaining > len ? len : remaining;
822 if (tocopy != 0)
823 {
824 memcpy(ptr, buf + contentoffs, tocopy);
825 ptr = (unsigned char *)ptr + tocopy;
826 len -= tocopy;
827 contentoffs += tocopy;
828 remaining -= tocopy;
829 inputpos += tocopy;
830 } /*if*/
831 if (len != 0)
832 {
833 /* read more of packet */
834 const unsigned int toread = packetlen < len ? packetlen : len;
835 readinput(ptr, toread, required);
836 if (dowrite)
837 {
838 writetostream(packetid, ptr, toread);
839 } /*if*/
840 packetlen -= toread;
841 len -= toread;
842 if (len != 0)
843 {
844 if (false0 /*required*/)
845 {
846 fprintf(stderrstderr, "Unexpected nested read EOF\n");
847 } /*if*/
848 longjmp(resume, 1);
849 } /*if*/
850 } /*if*/
851 } /*bufread*/
852 inputpos -= remaining; /* rewind to start of packet content */
853 if (!setjmp(resume)_setjmp (resume))
854 {
855 process_packets(bufread, true1);
856 } /*if*/
857 }
858 else
859#endif
860 {
861 while (packetlen != 0)
862 {
863 readlen = packetlen > sizeof buf ? sizeof(buf) : packetlen;
864 readinput(buf, readlen, true1);
865 if (dowrite)
866 {
867 writetostream(packetid, buf, readlen);
868 } /*if*/
869 packetlen -= readlen;
870 } /*while*/
871 } /*if*/
872 } /*if*/
873 handled = true1;
874 } /*if*/
875 if (!handled)
876 {
877 do
878 {
879 if (!recursed && outputenglish && !nounknown)
880 printf("%08x: unknown hdr: %08x\n", disppos, hdrid);
881 hdr[0] = hdr[1];
882 hdr[1] = hdr[2];
883 hdr[2] = hdr[3];
884 readinput(hdr + 3, 1, false0);
885 hdrid =
886 hdr[0] << 24
887 |
888 hdr[1] << 16
889 |
890 hdr[2] << 8
891 |
892 hdr[3];
893 }
894 while ((hdrid & 0xffffff00) != 0x100);
895 fetchhdr = false0; /* already got it */
896 } /*if*/
897 } /*while*/
898 } /*process_packets*/
899
900int main(int argc,char **argv)
901 {
902 bool_Bool skiptohdr = false0;
903 fputs(PACKAGE_HEADER("mpeg2desc")"DVDAuthor" "::" "mpeg2desc" ", version " "0.7.1+" ".\nBuild options:"
" gnugetopt" " graphicsmagick" " iconv" " freetype" " fribidi"
" fontconfig" "\nSend bug reports to <" "dvdauthor-users@lists.sourceforge.net"
">\n\n"
, stderrstderr);
904 {
905 int outputstream = 0, oc, i;
906 for (oc = 0; oc < 256; oc++)
907 outputfds[oc].fd = FD_CLOSED(-1);
908 while (-1 != (oc = getopt(argc,argv,"ha:v:o:msd:u")))
909 {
910 switch (oc)
911 {
912 case 'd':
913 audiodrop = strtounsigned(optarg, "audio drop count");
914 break;
915 case 'a':
916 case 'v':
917 if (outputstream)
918 {
919 fprintf(stderrstderr,"can only output one stream to stdout at a time\n; use -o to output more than\none stream\n");
920 exit(1);
921 } /*if*/
922 outputstream = (oc == 'a' ? MPID_AUDIO_FIRST : MPID_VIDEO_FIRST) + strtounsigned(optarg, "stream id");
923 break;
924 case 'm':
925 outputmplex = true1;
926 break;
927 case 's':
928 skiptohdr = true1;
929 break;
930 case 'o':
931 if (!outputstream)
932 {
933 fprintf(stderrstderr,"no stream selected for '%s'\n",optarg);
934 exit(1);
935 } /*if*/
936 outputfds[outputstream].fd = FD_TOOPEN(-2);
937 outputfds[outputstream].fname = optarg;
938 outputstream = 0;
939 break;
940 case 'u':
941 nounknown = true1;
942 break;
943 // case 'h':
944 default:
945 fprintf(stderrstderr,
946 "usage: mpeg2desc [options] < movie.mpg\n"
947 "\t-a #: output audio stream # to stdout\n"
948 "\t-v #: output video stream # to stdout\n"
949 "\t-o FILE: output previous stream to FILE instead of stdout\n"
950 "\t-s: skip to first valid header -- ensures mplex can handle output\n"
951 "\t-m: output mplex offset to stdout\n"
952 "\t-u: ignore unknown hdrs\n"
953 "\t-h: help\n"
954 );
955 exit(1);
956 break;
957 } /*switch*/
958 } /*while*/
959 if (outputstream)
960 {
961 outputenglish = false0;
962 outputfds[outputstream].fd = STDOUT_FILENO1;
963 } /*if*/
964 if (outputmplex)
965 {
966 if (!outputenglish)
967 {
968 fprintf(stderrstderr,"Cannot output a stream and the mplex offset at the same time\n");
969 exit(1);
970 } /*if*/
971 outputenglish = false0;
972 } /*if*/
973 numofd = 0;
974 for (oc = 0; oc < MAX_FILES256; oc++)
975 if (outputfds[oc].fd != -1)
976 {
977 ofdlist[numofd++] = oc;
978 outputfds[oc].firstbuf = 0;
979 outputfds[oc].lastbufptr = &outputfds[oc].firstbuf;
980 outputfds[oc].len = 0;
981 outputfds[oc].isvalid = !skiptohdr;
982 } /*if; for*/
983 FD_ZERO(&rfd)do { int __d0, __d1; __asm__ __volatile__ ("cld; rep; " "stosq"
: "=c" (__d0), "=D" (__d1) : "a" (0), "0" (sizeof (fd_set) /
sizeof (__fd_mask)), "1" (&((&rfd)->fds_bits)[0])
: "memory"); } while (0)
;
984 FD_ZERO(&wfd)do { int __d0, __d1; __asm__ __volatile__ ("cld; rep; " "stosq"
: "=c" (__d0), "=D" (__d1) : "a" (0), "0" (sizeof (fd_set) /
sizeof (__fd_mask)), "1" (&((&wfd)->fds_bits)[0])
: "memory"); } while (0)
;
985 for (i = 0; i < 256; i++)
986 {
987 firstpts[i] = -1;
988 } /*for*/
989 }
990 process_packets(forceread, false0);
991 } /*main*/