Annotation of multiplexer/showts.c, revision 1.4

1.2       oskar       1: /*
                      2:  * tiny debugging tool.
                      3:  * when fed with a transport stream to stdin, produces one char
                      4:  * per packet to stdout, and a few informative messages to stderr.
                      5:  * Upper case letters denote a continuity counter mismatch.
                      6:  *
                      7:  * Author: Jacob Schroeder (jacob@convergence.de)
1.3       oskar       8:  *
                      9:  * This program is free software; you can redistribute it and/or modify
                     10:  * it under the terms of the GNU General Public License as published by
                     11:  * the Free Software Foundation; either version 2 of the License, or
                     12:  * (at your option) any later version.
                     13:  *
                     14:  * This program is distributed in the hope that it will be useful,
                     15:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     16:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     17:  * GNU General Public License for more details.
                     18:  *
                     19:  * You should have received a copy of the GNU General Public License
                     20:  * along with this program; if not, write to the Free Software
                     21:  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
1.2       oskar      22:  */
                     23: 
1.1       jacob      24: #include <stdlib.h>
                     25: #include <stdio.h>
                     26: #include <unistd.h>
                     27: 
1.4     ! jacob      28: #include <getopt.h>
        !            29: #include <string.h>
        !            30: #include <errno.h>
        !            31: #include <signal.h>
        !            32: #include <sys/types.h>
        !            33: #include <sys/wait.h>
        !            34: #include <sys/time.h>
        !            35: #include <sys/resource.h>
        !            36: 
1.1       jacob      37: #define MAXPID 0x1fff
                     38: 
1.4     ! jacob      39: static struct option long_options[] = {
        !            40:        {"help"   , 0, NULL, 'h'},
        !            41:        {"summary", 0, NULL, 's'},
        !            42:        {"analyse", 0, NULL, 'a'},
        !            43:        {NULL, 0, NULL, 0}
        !            44: };
        !            45: 
        !            46: static const char *program = NULL;
        !            47: 
        !            48: static int         show_analysis = 0;
        !            49: static int         show_summary = 0;
        !            50: static int         show_packets = 1;
        !            51: static int         show_pids    = 1;
        !            52: 
        !            53: static int         pid_cnt = 0;
        !            54: static int         packet_cnt = 0;
        !            55: static int         broken_sync_cnt = 0;
        !            56: static int         broken_alen_cnt = 0;
        !            57: static int         unusual_cc_cnt  = 0;
        !            58: 
        !            59: static void usage ()
        !            60: {
        !            61:        printf("Usage: %s [OPTION] < <TS file>\n"
        !            62:                         " -h, --help                    show usage\n"
        !            63:                         " -s, --summary                 show summary\n"
        !            64:                         " -a, --analyse                 analyse stream statistics\n"
        !            65:                        , program);
        !            66: }
        !            67: 
        !            68: 
1.1       jacob      69: int main (int argc, char **argv)
                     70: {
                     71: 
1.4     ! jacob      72:   int    pids[MAXPID+1];
        !            73:   int    ccs[MAXPID+1];
        !            74:   int    pid_count = 0;
        !            75:   int    i;
        !            76:   int    count = 0;
        !            77: 
        !            78:   char **next_arg = argv+1;
        !            79:   int    option_index = 0;
        !            80: 
        !            81:   if ((program = strrchr(argv[0], '/')) != NULL) {
        !            82:       program++;
        !            83:   } else {
        !            84:       program = argv[0];
        !            85:   }
        !            86: 
        !            87:   while (1) {
        !            88:       int opt;
        !            89:       // char *endptr;
        !            90: 
        !            91:       opt = getopt_long (argc, argv, "+hsa", long_options, &option_index);
        !            92:       if (opt == -1) break;
        !            93: 
        !            94:       switch (opt) {
        !            95:         case 'a':
        !            96:           show_analysis = 1;
        !            97:           show_packets = 0;
        !            98:           break;
        !            99: 
        !           100:         case 's':
        !           101:           show_summary = 1;
        !           102:           show_packets = 0;
        !           103:           break;
        !           104: 
        !           105:         case 'h':
        !           106:           usage ();
        !           107:           exit (0);
        !           108: 
        !           109:         default:
        !           110:           usage ();
        !           111:           exit (1);
        !           112:       }
        !           113:   }
        !           114: 
        !           115:   next_arg = argv + optind;
1.1       jacob     116: 
                    117:   for (i = 0; i <= MAXPID; i++)
1.2       oskar     118:     {
                    119:       pids[i] = -1;
                    120:       ccs[i] = -1;
                    121:     }
1.1       jacob     122: 
                    123:   while (1)
                    124:     {
                    125:       unsigned char buffer[188];
                    126:       int           bytes_read;
                    127: 
                    128:       int n;
                    129: 
                    130: 
                    131:       bytes_read = 0;
                    132: 
1.4     ! jacob     133:       do
1.1       jacob     134:         {
                    135:           n = read (0, buffer + bytes_read, sizeof (buffer) - bytes_read);
                    136: 
                    137:           if (n < 0)
                    138:             {
1.4     ! jacob     139:               if (errno == EINTR)
        !           140:                 continue;
        !           141: 
1.1       jacob     142:               perror ("read");
                    143:               exit (1);
                    144:             }
                    145: 
                    146:           bytes_read += n;
                    147:         }
                    148:       while (bytes_read < sizeof (buffer) && n > 0);
                    149: 
                    150:       if (n == 0)
                    151:         {
1.4     ! jacob     152:           int exit_value = 0;
        !           153: 
1.1       jacob     154:           if (bytes_read && bytes_read < sizeof (buffer))
                    155:             {
                    156:               fprintf (stderr, "incomplete ts packet read, size = %d\n", bytes_read);
                    157:             }
1.4     ! jacob     158: 
        !           159:           if (show_summary)
        !           160:             {
        !           161:               printf ("packets:                        %-6d\n", packet_cnt);
        !           162:               printf ("pids:                           %-6d\n", pid_cnt);
        !           163:               printf ("sync errors:                    %-6d\n",
        !           164:                       broken_sync_cnt);
        !           165:               printf ("adaptation field length errors: %-6d\n",
        !           166:                       broken_alen_cnt);
        !           167:               printf ("unusual cc increments:          %-6d\n",
        !           168:                       unusual_cc_cnt);
        !           169:               printf ("\n");
        !           170:             }
        !           171: 
        !           172:           if (show_analysis)
        !           173:             {
        !           174:               int quality = 1;
        !           175: 
        !           176:               if (pid_cnt > packet_cnt / 10)
        !           177:                 {
        !           178:                   printf ("The number of different PIDs is higher than 10%% of the packet count.\n");
        !           179:                   quality = -1;
        !           180:                 }
        !           181:               else if (pid_cnt > packet_cnt / 100)
        !           182:                 {
        !           183:                   printf ("The number of different PIDs is higher than 1%% of the packet count.\n");
        !           184:                   if (quality > 0)
        !           185:                     quality = 0;
        !           186:                 }
        !           187: 
        !           188:               if (pid_cnt > 2048)
        !           189:                 {
        !           190:                   printf ("The number of different PIDs is higher than 2048.\n");
        !           191:                   quality = -1;
        !           192:                 }
        !           193: 
        !           194:               if (broken_sync_cnt > 0)
        !           195:                 {
        !           196:                   if (broken_sync_cnt < packet_cnt / 100)
        !           197:                     {
        !           198:                       printf ("There are packets with a broken sync byte but it's less than 1%%.\n");
        !           199:                       if (quality > 0)
        !           200:                         quality = 0;
        !           201:                     }
        !           202:                   else if (broken_sync_cnt > packet_cnt / 10)
        !           203:                     {
        !           204:                       printf ("More than 10%% of the packets have a broken sync byte.\n");
        !           205:                       quality = -2;
        !           206:                     }
        !           207:                   else
        !           208:                     {
        !           209:                       printf ("More than 1%% of the packets have a broken sync byte.\n");
        !           210:                       if (quality > -1)
        !           211:                         quality = -1;
        !           212:                     }
        !           213:                 }
        !           214: 
        !           215:               if (broken_alen_cnt > 0)
        !           216:                 {
        !           217:                   if (broken_alen_cnt == 0)
        !           218:                     {
        !           219:                       printf ("All packets with a correct sync seem to have a consistent TS header.\n");
        !           220:                     }
        !           221:                   else if (broken_alen_cnt < packet_cnt / 100)
        !           222:                     {
        !           223:                       printf ("There are packets with an inconsistent TS header but it's less than 1%%.\n");
        !           224:                       if (quality > 0)
        !           225:                         quality = 0;
        !           226:                     }
        !           227:                   else if (broken_alen_cnt > packet_cnt / 10)
        !           228:                     {
        !           229:                       printf ("More than 10%% of the packets have an inconsistent TS header.\n");
        !           230:                       quality = -2;
        !           231:                     }
        !           232:                   else
        !           233:                     {
        !           234:                       printf ("More than 1%% of the packets have an inconsistent TS header.\n");
        !           235:                       if (quality > -1)
        !           236:                         quality = -1;
        !           237:                     }
        !           238:                 }
        !           239: 
        !           240:               if (quality == 1)
        !           241:                 {
        !           242:                   printf ("This transport stream seems to be ok.\n");
        !           243:                 }
        !           244:               else if (quality == 0)
        !           245:                 {
        !           246:                   printf ("This transport stream has some flaws, but it might be ok.\n");
        !           247:                 }
        !           248:               else if (quality == -1)
        !           249:                 {
        !           250:                   printf ("It is very likely, that this transport stream is broken.\n");
        !           251:                   exit_value = 2;
        !           252:                 }
        !           253:               else
        !           254:                 {
        !           255:                   printf ("This transport stream is broken.\n");
        !           256:                   exit_value = 3;
        !           257:                 }
        !           258:             }
        !           259: 
        !           260:           exit (exit_value);
1.1       jacob     261:         }
                    262: 
1.4     ! jacob     263:       packet_cnt++;
        !           264: 
1.1       jacob     265:       // printf ("%02x%02x%02x%02x\n", buffer[0], buffer[1], buffer[2], buffer[3]);
                    266:       {
                    267:         int   sync;
                    268:         int   pid;
                    269:         int   cc;
1.2       oskar     270:         int   ccok;
1.1       jacob     271: 
1.4     ! jacob     272:         int   error_ind;
        !           273:         int   unit_start;
        !           274:         int   priority;
        !           275:         int   scrambling;
        !           276:         int   adaptation;
        !           277: 
        !           278:         int   alen = 0;
        !           279:         int   real_alen = 0;
        !           280: 
        !           281:         int   disc = 0;
        !           282:         int   random = 0;
        !           283:         int   espri = 0;
        !           284:         int   pcr = 0;
        !           285:         int   opcr = 0;
        !           286:         int   splpt = 0;
        !           287:         int   priv = 0;
        !           288:         int   afext = 0;
        !           289: 
        !           290:         int   priv_len = 0;
        !           291:         int   afext_len = 0;
        !           292: 
1.1       jacob     293:         char  outbuf[1];
                    294: 
                    295:         int   pidtype;
                    296: 
                    297:         sync = buffer[0];
1.4     ! jacob     298:         error_ind  = (buffer[1] & 0x80) >> 7;
        !           299:         unit_start = (buffer[1] & 0x40) >> 6;
        !           300:         priority   = (buffer[1] & 0x20) >> 5;
1.1       jacob     301:         pid  = ((buffer[1] & 0x1f) << 8) | buffer[2];
1.4     ! jacob     302:         scrambling  = (buffer[3] & 0x60) >> 6;
        !           303:         adaptation  = (buffer[3] & 0x30) >> 4;
1.1       jacob     304:         cc   = buffer[3] & 0x0f;
                    305: 
1.4     ! jacob     306:         if (adaptation & 0x02)
        !           307:           {
        !           308:             alen = buffer[4];
        !           309:             if (alen > 0)
        !           310:               {
        !           311:                 disc   = (buffer[5] & 0x80) >> 7;
        !           312:                 random = (buffer[5] & 0x40) >> 6;
        !           313:                 espri  = (buffer[5] & 0x20) >> 5;
        !           314:                 pcr    = (buffer[5] & 0x10) >> 4;
        !           315:                 opcr   = (buffer[5] & 0x08) >> 3;
        !           316:                 splpt  = (buffer[5] & 0x04) >> 2;
        !           317:                 priv   = (buffer[5] & 0x02) >> 1;
        !           318:                 afext  = (buffer[5] & 0x01) >> 0;
        !           319:               }
        !           320:             real_alen += 1;
        !           321: 
        !           322:             if (pcr)
        !           323:               real_alen += 6;
        !           324: 
        !           325:             if (opcr)
        !           326:               real_alen += 6;
        !           327: 
        !           328:             if (priv)
        !           329:               {
        !           330:                 priv_len = buffer[5+real_alen];
        !           331:                 real_alen += 1 + priv_len;
        !           332:               }
        !           333: 
        !           334:             if (afext)
        !           335:               {
        !           336:                 afext_len = buffer[5+real_alen];
        !           337:                 real_alen += 1 + afext_len;
        !           338:               }
        !           339:           }
        !           340: 
1.1       jacob     341:         // fprintf (stderr, "pid = 0x%04x, cc = 0x%x\n", pid, cc);
                    342: 
                    343:         if (sync != 0x47)
                    344:           {
                    345:             // TODO, skip to next package
1.4     ! jacob     346:             if (show_packets)
        !           347:               write (1, "?", 1);
        !           348: 
        !           349:             broken_sync_cnt++;
        !           350:             goto char_written;
1.1       jacob     351:           }
1.4     ! jacob     352: 
        !           353:         pidtype = pids[pid];
        !           354: 
        !           355:         if (pidtype == -1)
1.2       oskar     356:           {
1.4     ! jacob     357:             pid_cnt++;
1.1       jacob     358: 
1.4     ! jacob     359:             if (pid == 0)
1.1       jacob     360:               {
1.4     ! jacob     361:                 fprintf (stderr, "# =  pid 0x0000 (PAT)\n");
        !           362:                 pidtype = pids[pid] = 0;
        !           363:               }
        !           364:             else if (pid == 0x1fff)
        !           365:               {
        !           366:                 fprintf (stderr, "\" '  pid 0x1fff (invalid)\n");
        !           367:                 pidtype = pids[pid] = 0;
1.1       jacob     368:               }
1.2       oskar     369:             else
1.1       jacob     370:               {
1.4     ! jacob     371:                 if (pid_count < 26)
        !           372:                   pid_count++;
        !           373: 
        !           374:                 pidtype = pids[pid] = pid_count;
        !           375: 
        !           376:                 if (show_pids)
        !           377:                   fprintf (stderr, "%c %c  pid 0x%04x  "
        !           378:                            "%s%s%s%s%s%s%s%s%s%s%s%salen=%d\n",
        !           379:                            0x40 + pidtype, 0x60 + pidtype,  pid,
        !           380:                            priority ? "pri, " : "",
        !           381:                            adaptation & 0x02 ? "adapt, " : "",
        !           382:                            adaptation & 0x01 ? "payld, " : "",
        !           383:                            scrambling > 0 ? "scrmb, " : "",
        !           384:                            disc > 0 ? "disc, " : "",
        !           385:                            random > 0 ? "rnd, " : "",
        !           386:                            espri > 0 ? "ESpri, " : "",
        !           387:                            pcr > 0 ? "PCR, " : "",
        !           388:                            opcr > 0 ? "OPCR, " : "",
        !           389:                            splpt > 0 ? "splpt, " : "",
        !           390:                            priv > 0 ? "priv, " : "",
        !           391:                            afext > 0 ? "afext, " : "",
        !           392:                            alen
        !           393:                           );
        !           394:               }
        !           395: 
        !           396:             if ((adaptation == 1 && alen != 0) ||
        !           397:                 (adaptation == 2 && alen != 183) ||
        !           398:                 (adaptation == 3 && alen >= 183))
        !           399:               {
        !           400:                 fprintf (stderr, "!!! pid 0x%04x: invalid adaptation_field_length %d\n",
        !           401:                          pid, alen);
1.1       jacob     402:               }
1.2       oskar     403: 
1.4     ! jacob     404:             if ((adaptation & 2) != 0 && real_alen > alen )
        !           405:               {
        !           406:                 fprintf (stderr, "!!! pid 0x%04x: adaptation field to long %d > %d\n",
        !           407:                          pid, real_alen, alen);
        !           408:               }
        !           409: 
        !           410:             ccok = 1;
        !           411:           }
        !           412:         else
        !           413:           {
        !           414:             ccok = ccs[pid] == cc ? 1 : 0;
        !           415:           }
        !           416: 
        !           417:         if (!ccok)
        !           418:           unusual_cc_cnt++;
        !           419: 
        !           420:         if ((adaptation == 0x01 && alen != 0) ||
        !           421:             (adaptation == 0x10 && alen != 183) ||
        !           422:             (adaptation == 0x11 && alen >= 183) ||
        !           423:             (alen < real_alen))
        !           424:           {
        !           425:             if (show_packets)
        !           426:               write (1, "@", 1);
1.1       jacob     427: 
1.4     ! jacob     428:             broken_alen_cnt++;
        !           429:             goto char_written;
1.1       jacob     430:           }
                    431: 
1.4     ! jacob     432:         if (pid == 0)
        !           433:           outbuf[0] = ccok ? '=' : '#';
        !           434:         else if (pid == 0x1fff)
        !           435:           outbuf[0] = ccok ? '\'' : '"';
        !           436:         else
        !           437:           outbuf[0] = 0x40 + pidtype + (ccok ? 0x20 : 0);
        !           438: 
        !           439:         ccs[pid] = (cc + 1) & 0x0F;
        !           440: 
        !           441:         if (show_packets)
        !           442:           write (1, outbuf, 1);
        !           443: 
        !           444: char_written:
1.1       jacob     445:         count++;
1.4     ! jacob     446:         if ((count % 64) == 0 && show_packets)
1.1       jacob     447:           write (1, "\n", 1);
                    448:       }
                    449:     }
                    450: }

LinuxTV legacy CVS <linuxtv.org/cvs>