Skip to content

AFNI/NIfTI Server

Sections
Personal tools
You are here: Home » AFNI » Documentation

Doxygen Source Code Documentation


Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals   Search  

extract_mpeg2.c File Reference

#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <getopt.h>
#include <inttypes.h>

Go to the source code of this file.


Defines

#define BUFFER_SIZE   4096
#define DEMUX_PAYLOAD_START   1
#define DEMUX_HEADER   0
#define DEMUX_DATA   1
#define DEMUX_SKIP   2
#define NEEDBYTES(x)
#define DONEBYTES(x)
#define PACKETS   (BUFFER_SIZE / 188)

Functions

void print_usage (char **argv)
void handle_args (int argc, char **argv)
int demux (uint8_t *buf, uint8_t *end, int flags)
void ps_loop (void)
int pva_demux (uint8_t *buf, uint8_t *end)
void pva_loop (void)
void ts_loop (void)
int main (int argc, char **argv)

Variables

uint8_t buffer [BUFFER_SIZE]
FILE * in_file
int demux_track = 0xe0
int demux_pid = 0
int demux_pva = 0

Define Documentation

#define BUFFER_SIZE   4096
 

Definition at line 37 of file extract_mpeg2.c.

Referenced by ps_loop(), and pva_loop().

#define DEMUX_DATA   1
 

#define DEMUX_HEADER   0
 

#define DEMUX_PAYLOAD_START   1
 

Definition at line 99 of file extract_mpeg2.c.

Referenced by demux(), and ts_loop().

#define DEMUX_SKIP   2
 

#define DONEBYTES  
 

Value:

do {                    \
        if (header != head_buf) \
            buf = header + (x); \
    } while (0)

#define NEEDBYTES  
 

Value:

do {                                                    \
        int missing;                                            \
                                                                \
        missing = (x) - bytes;                                  \
        if (missing > 0) {                                      \
            if (header == head_buf) {                           \
                if (missing <= end - buf) {                     \
                    memcpy (header + bytes, buf, missing);      \
                    buf += missing;                             \
                    bytes = (x);                                \
                } else {                                        \
                    memcpy (header + bytes, buf, end - buf);    \
                    state_bytes = bytes + end - buf;            \
                    return 0;                                   \
                }                                               \
            } else {                                            \
                memcpy (head_buf, header, bytes);               \
                state = DEMUX_HEADER;                           \
                state_bytes = bytes;                            \
                return 0;                                       \
            }                                                   \
        }                                                       \
    } while (0)

#define PACKETS   (BUFFER_SIZE / 188)
 


Function Documentation

int demux uint8_t   buf,
uint8_t   end,
int    flags
[static]
 

Definition at line 100 of file extract_mpeg2.c.

References DEMUX_PAYLOAD_START, demux_pid, demux_track, flags, and uint8_t.

00101 {
00102     static int mpeg1_skip_table[16] = {
00103         0, 0, 4, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
00104     };
00105 
00106     /*
00107      * the demuxer keeps some state between calls:
00108      * if "state" = DEMUX_HEADER, then "head_buf" contains the first
00109      *     "bytes" bytes from some header.
00110      * if "state" == DEMUX_DATA, then we need to copy "bytes" bytes
00111      *     of ES data before the next header.
00112      * if "state" == DEMUX_SKIP, then we need to skip "bytes" bytes
00113      *     of data before the next header.
00114      *
00115      * NEEDBYTES makes sure we have the requested number of bytes for a
00116      * header. If we dont, it copies what we have into head_buf and returns,
00117      * so that when we come back with more data we finish decoding this header.
00118      *
00119      * DONEBYTES updates "buf" to point after the header we just parsed.
00120      */
00121 
00122 #define DEMUX_HEADER 0
00123 #define DEMUX_DATA 1
00124 #define DEMUX_SKIP 2
00125     static int state = DEMUX_SKIP;
00126     static int state_bytes = 0;
00127     static uint8_t head_buf[264];
00128 
00129     uint8_t * header;
00130     int bytes;
00131     int len;
00132 
00133 #define NEEDBYTES(x)                                            \
00134     do {                                                        \
00135         int missing;                                            \
00136                                                                 \
00137         missing = (x) - bytes;                                  \
00138         if (missing > 0) {                                      \
00139             if (header == head_buf) {                           \
00140                 if (missing <= end - buf) {                     \
00141                     memcpy (header + bytes, buf, missing);      \
00142                     buf += missing;                             \
00143                     bytes = (x);                                \
00144                 } else {                                        \
00145                     memcpy (header + bytes, buf, end - buf);    \
00146                     state_bytes = bytes + end - buf;            \
00147                     return 0;                                   \
00148                 }                                               \
00149             } else {                                            \
00150                 memcpy (head_buf, header, bytes);               \
00151                 state = DEMUX_HEADER;                           \
00152                 state_bytes = bytes;                            \
00153                 return 0;                                       \
00154             }                                                   \
00155         }                                                       \
00156     } while (0)
00157 
00158 #define DONEBYTES(x)            \
00159     do {                        \
00160         if (header != head_buf) \
00161             buf = header + (x); \
00162     } while (0)
00163 
00164     if (flags & DEMUX_PAYLOAD_START)
00165         goto payload_start;
00166     switch (state) {
00167     case DEMUX_HEADER:
00168         if (state_bytes > 0) {
00169             header = head_buf;
00170             bytes = state_bytes;
00171             goto continue_header;
00172         }
00173         break;
00174     case DEMUX_DATA:
00175         if (demux_pid || (state_bytes > end - buf)) {
00176             fwrite (buf, end - buf, 1, stdout);
00177             state_bytes -= end - buf;
00178             return 0;
00179         }
00180         fwrite (buf, state_bytes, 1, stdout);
00181         buf += state_bytes;
00182         break;
00183     case DEMUX_SKIP:
00184         if (demux_pid || (state_bytes > end - buf)) {
00185             state_bytes -= end - buf;
00186             return 0;
00187         }
00188         buf += state_bytes;
00189         break;
00190     }
00191 
00192     while (1) {
00193         if (demux_pid) {
00194             state = DEMUX_SKIP;
00195             return 0;
00196         }
00197     payload_start:
00198         header = buf;
00199         bytes = end - buf;
00200     continue_header:
00201         NEEDBYTES (4);
00202         if (header[0] || header[1] || (header[2] != 1)) {
00203             if (demux_pid) {
00204                 state = DEMUX_SKIP;
00205                 return 0;
00206             } else if (header != head_buf) {
00207                 buf++;
00208                 goto payload_start;
00209             } else {
00210                 header[0] = header[1];
00211                 header[1] = header[2];
00212                 header[2] = header[3];
00213                 bytes = 3;
00214                 goto continue_header;
00215             }
00216         }
00217         if (demux_pid) {
00218             if ((header[3] >= 0xe0) && (header[3] <= 0xef))
00219                 goto pes;
00220             fprintf (stderr, "bad stream id %x\n", header[3]);
00221             exit (1);
00222         }
00223         switch (header[3]) {
00224         case 0xb9:      /* program end code */
00225             /* DONEBYTES (4); */
00226             /* break;         */
00227             return 1;
00228         case 0xba:      /* pack header */
00229             NEEDBYTES (12);
00230             if ((header[4] & 0xc0) == 0x40) {   /* mpeg2 */
00231                 NEEDBYTES (14);
00232                 len = 14 + (header[13] & 7);
00233                 NEEDBYTES (len);
00234                 DONEBYTES (len);
00235                 /* header points to the mpeg2 pack header */
00236             } else if ((header[4] & 0xf0) == 0x20) {    /* mpeg1 */
00237                 DONEBYTES (12);
00238                 /* header points to the mpeg1 pack header */
00239             } else {
00240                 fprintf (stderr, "weird pack header\n");
00241                 exit (1);
00242             }
00243             break;
00244         default:
00245             if (header[3] == demux_track) {
00246             pes:
00247                 NEEDBYTES (7);
00248                 if ((header[6] & 0xc0) == 0x80) {       /* mpeg2 */
00249                     NEEDBYTES (9);
00250                     len = 9 + header[8];
00251                     NEEDBYTES (len);
00252                     /* header points to the mpeg2 pes header */
00253                 } else {        /* mpeg1 */
00254                     len = 7;
00255                     while ((header-1)[len] == 0xff) {
00256                         len++;
00257                         NEEDBYTES (len);
00258                         if (len > 23) {
00259                             fprintf (stderr, "too much stuffing\n");
00260                             break;
00261                         }
00262                     }
00263                     if (((header-1)[len] & 0xc0) == 0x40) {
00264                         len += 2;
00265                         NEEDBYTES (len);
00266                     }
00267                     len += mpeg1_skip_table[(header - 1)[len] >> 4];
00268                     NEEDBYTES (len);
00269                     /* header points to the mpeg1 pes header */
00270                 }
00271                 DONEBYTES (len);
00272                 bytes = 6 + (header[4] << 8) + header[5] - len;
00273                 if (demux_pid || (bytes > end - buf)) {
00274                     fwrite (buf, end - buf, 1, stdout);
00275                     state = DEMUX_DATA;
00276                     state_bytes = bytes - (end - buf);
00277                     return 0;
00278                 } else if (bytes <= 0)
00279                     continue;
00280                 fwrite (buf, bytes, 1, stdout);
00281                 buf += bytes;
00282             } else if (header[3] < 0xb9) {
00283                 fprintf (stderr,
00284                          "looks like a video stream, not system stream\n");
00285                 DONEBYTES (4);
00286             } else {
00287                 NEEDBYTES (6);
00288                 DONEBYTES (6);
00289                 bytes = (header[4] << 8) + header[5];
00290                 if (bytes > end - buf) {
00291                     state = DEMUX_SKIP;
00292                     state_bytes = bytes - (end - buf);
00293                     return 0;
00294                 }
00295                 buf += bytes;
00296             }
00297         }
00298     }
00299 }

void handle_args int    argc,
char **    argv
[static]
 

Definition at line 55 of file extract_mpeg2.c.

References argc, c, demux_pid, demux_pva, demux_track, getopt(), in_file, and print_usage().

00056 {
00057     int c;
00058     char * s;
00059 
00060     while ((c = getopt (argc, argv, "s:t:p")) != -1)
00061         switch (c) {
00062         case 's':
00063             demux_track = strtol (optarg, &s, 0);
00064             if (demux_track < 0xe0)
00065                 demux_track += 0xe0;
00066             if ((demux_track < 0xe0) || (demux_track > 0xef) || (*s)) {
00067                 fprintf (stderr, "Invalid track number: %s\n", optarg);
00068                 print_usage (argv);
00069             }
00070             break;
00071 
00072         case 't':
00073             demux_pid = strtol (optarg, &s, 0);
00074             if ((demux_pid < 0x10) || (demux_pid > 0x1ffe) || (*s)) {
00075                 fprintf (stderr, "Invalid pid: %s\n", optarg);
00076                 print_usage (argv);
00077             }
00078             break;
00079 
00080         case 'p':
00081             demux_pva = 1;
00082             break;
00083 
00084         default:
00085             print_usage (argv);
00086         }
00087 
00088     if (optind < argc) {
00089         in_file = fopen (argv[optind], "rb");
00090         if (!in_file) {
00091             fprintf (stderr, "%s - could not open file %s\n", strerror (errno),
00092                      argv[optind]);
00093             exit (1);
00094         }
00095     } else
00096         in_file = stdin;
00097 }

int main int    argc,
char **    argv
 

Definition at line 439 of file extract_mpeg2.c.

References argc, handle_args(), O_BINARY, ps_loop(), pva_loop(), and ts_loop().

00440 {
00441 #ifdef HAVE_IO_H
00442     setmode (fileno (stdout), O_BINARY);
00443 #endif
00444 
00445     handle_args (argc, argv);
00446 
00447     if (demux_pva)
00448         pva_loop ();
00449     if (demux_pid)
00450         ts_loop ();
00451     else
00452         ps_loop ();
00453 
00454     return 0;
00455 }

void print_usage char **    argv [static]
 

Definition at line 44 of file extract_mpeg2.c.

00045 {
00046     fprintf (stderr, "usage: %s [-s <track>] [-t <pid>] [-p] <file>\n"
00047              "\t-s\tset track number (0-15 or 0xe0-0xef)\n"
00048              "\t-t\tuse transport stream demultiplexer, pid 0x10-0x1ffe\n"
00049              "\t-p\tuse pva demultiplexer\n",
00050              argv[0]);
00051 
00052     exit (1);
00053 }

void ps_loop void    [static]
 

Definition at line 301 of file extract_mpeg2.c.

References buffer, BUFFER_SIZE, demux(), in_file, and uint8_t.

Referenced by main().

00302 {
00303     uint8_t * end;
00304 
00305     do {
00306         end = buffer + fread (buffer, 1, BUFFER_SIZE, in_file);
00307         if (demux (buffer, end, 0))
00308             break;      /* hit program_end_code */
00309     } while (end == buffer + BUFFER_SIZE);
00310 }

int pva_demux uint8_t   buf,
uint8_t   end
[static]
 

Definition at line 312 of file extract_mpeg2.c.

References uint8_t.

00313 {
00314     static int state = DEMUX_SKIP;
00315     static int state_bytes = 0;
00316     static uint8_t head_buf[12];
00317 
00318     uint8_t * header;
00319     int bytes;
00320     int len;
00321 
00322     switch (state) {
00323     case DEMUX_HEADER:
00324         if (state_bytes > 0) {
00325             header = head_buf;
00326             bytes = state_bytes;
00327             goto continue_header;
00328         }
00329         break;
00330     case DEMUX_DATA:
00331         if (state_bytes > end - buf) {
00332             fwrite (buf, end - buf, 1, stdout);
00333             state_bytes -= end - buf;
00334             return 0;
00335         }
00336         fwrite (buf, state_bytes, 1, stdout);
00337         buf += state_bytes;
00338         break;
00339     case DEMUX_SKIP:
00340         if (state_bytes > end - buf) {
00341             state_bytes -= end - buf;
00342             return 0;
00343         }
00344         buf += state_bytes;
00345         break;
00346     }
00347 
00348     while (1) {
00349     payload_start:
00350         header = buf;
00351         bytes = end - buf;
00352     continue_header:
00353         NEEDBYTES (2);
00354         if (header[0] != 0x41 || header[1] != 0x56) {
00355             if (header != head_buf) {
00356                 buf++;
00357                 goto payload_start;
00358             } else {
00359                 header[0] = header[1];
00360                 bytes = 1;
00361                 goto continue_header;
00362             }
00363         }
00364         NEEDBYTES (8);
00365         if (header[2] != 1) {
00366             DONEBYTES (8);
00367             bytes = (header[6] << 8) + header[7];
00368             if (bytes > end - buf) {
00369                 state = DEMUX_SKIP;
00370                 state_bytes = bytes - (end - buf);
00371                 return 0;
00372             } 
00373             buf += bytes; 
00374         } else {
00375             len = 8;
00376             if (header[5] & 0x10) {
00377                 len = 12;
00378                 NEEDBYTES (len);
00379             }
00380             DONEBYTES (len);
00381             bytes = (header[6] << 8) + header[7] + 8 - len;
00382             if (bytes > end - buf) {
00383                 fwrite (buf, end - buf, 1, stdout);
00384                 state = DEMUX_DATA;
00385                 state_bytes = bytes - (end - buf);
00386                 return 0;
00387             } else if (bytes > 0) {
00388                 fwrite (buf, bytes, 1, stdout);
00389                 buf += bytes;
00390             }
00391         }
00392     }
00393 }

void pva_loop void    [static]
 

Definition at line 395 of file extract_mpeg2.c.

References buffer, BUFFER_SIZE, in_file, pva_demux(), and uint8_t.

Referenced by main().

00396 {
00397     uint8_t * end;
00398 
00399     do {
00400         end = buffer + fread (buffer, 1, BUFFER_SIZE, in_file);
00401         pva_demux (buffer, end);
00402     } while (end == buffer + BUFFER_SIZE);
00403 }

void ts_loop void    [static]
 

Definition at line 405 of file extract_mpeg2.c.

References buffer, demux(), DEMUX_PAYLOAD_START, demux_pid, i, in_file, and uint8_t.

Referenced by main().

00406 {
00407 #define PACKETS (BUFFER_SIZE / 188)
00408     uint8_t * buf;
00409     uint8_t * data;
00410     uint8_t * end;
00411     int packets;
00412     int i;
00413     int pid;
00414 
00415     do {
00416         packets = fread (buffer, 188, PACKETS, in_file);
00417         for (i = 0; i < packets; i++) {
00418             buf = buffer + i * 188;
00419             end = buf + 188;
00420             if (buf[0] != 0x47) {
00421                 fprintf (stderr, "bad sync byte\n");
00422                 exit (1);
00423             }
00424             pid = ((buf[1] << 8) + buf[2]) & 0x1fff;
00425             if (pid != demux_pid)
00426                 continue;
00427             data = buf + 4;
00428             if (buf[3] & 0x20) {        /* buf contains an adaptation field */
00429                 data = buf + 5 + buf[4];
00430                 if (data > end)
00431                     continue;
00432             }
00433             if (buf[3] & 0x10)
00434                 demux (data, end, (buf[1] & 0x40) ? DEMUX_PAYLOAD_START : 0);
00435         }
00436     } while (packets == PACKETS);
00437 }

Variable Documentation

uint8_t buffer[BUFFER_SIZE] [static]
 

Definition at line 38 of file extract_mpeg2.c.

Referenced by ps_loop(), pva_loop(), and ts_loop().

int demux_pid = 0 [static]
 

Definition at line 41 of file extract_mpeg2.c.

Referenced by demux(), handle_args(), and ts_loop().

int demux_pva = 0 [static]
 

Definition at line 42 of file extract_mpeg2.c.

Referenced by handle_args().

int demux_track = 0xe0 [static]
 

Definition at line 40 of file extract_mpeg2.c.

Referenced by demux(), and handle_args().

FILE* in_file [static]
 

Definition at line 39 of file extract_mpeg2.c.

Referenced by handle_args(), ps_loop(), pva_loop(), and ts_loop().

 

Powered by Plone

This site conforms to the following standards: