Doxygen Source Code Documentation
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
|
Definition at line 37 of file extract_mpeg2.c. Referenced by ps_loop(), and pva_loop(). |
|
|
|
|
|
Definition at line 99 of file extract_mpeg2.c. |
|
|
|
Value: do { \ if (header != head_buf) \ buf = header + (x); \ } while (0) |
|
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) |
|
|
Function Documentation
|
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 } |
|
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 } |
|
Definition at line 439 of file extract_mpeg2.c. References argc, handle_args(), O_BINARY, ps_loop(), pva_loop(), and ts_loop().
|
|
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 } |
|
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 } |
|
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 } |
|
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 } |
|
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
|
Definition at line 38 of file extract_mpeg2.c. Referenced by ps_loop(), pva_loop(), and ts_loop(). |
|
Definition at line 41 of file extract_mpeg2.c. Referenced by demux(), handle_args(), and ts_loop(). |
|
Definition at line 42 of file extract_mpeg2.c. Referenced by handle_args(). |
|
Definition at line 40 of file extract_mpeg2.c. Referenced by demux(), and handle_args(). |
|
Definition at line 39 of file extract_mpeg2.c. Referenced by handle_args(), ps_loop(), pva_loop(), and ts_loop(). |