/* * trovapid - Trova i PID video e audio all'interno di un file .TS * Scritto da Piergorgio Ghezzo * Il programma e' liberamente distribuibile * * * Compilare con il comando: * * gcc -o trovapid trovapid.c -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE * * * HISTORY: * * 11/03/2003 1.0 Prima versione pubblica * */ #include #include #include #include #include #include #include #include #define TS_SIZE 188 #define IN_SIZE TS_SIZE*10 #define PID_MASK_HI 0x1F #define MAX_PIDS 16 #define PROG_STREAM_MAP 0xBC #define PRIVATE_STREAM1 0xBD #define PRIVATE_STREAM2 0xBF #define PADDING_STREAM 0xBE #define AUDIO_STREAM_S 0xC0 #define AUDIO_STREAM_E 0xDF #define VIDEO_STREAM_S 0xE0 #define VIDEO_STREAM_E 0xEF // Pulisce l'array passato come argomento impostando tutti gli elementi a 0 void clear_pids (uint16_t *array) { int Ciclo; for (Ciclo = 0; Ciclo <= MAX_PIDS; Ciclo++) array[Ciclo] = 0; return; } // Aggiunge un PID all'array verificando che non sia gia' presente void insert_pid (uint16_t *array, uint16_t pid) { int Ciclo; if (pid == 0) return; for (Ciclo = 0; Ciclo <= MAX_PIDS; Ciclo++) { if (array[Ciclo] == 0) { // Copio il PID dentro l'array array[Ciclo] = pid; return; } else { if (array[Ciclo] == pid) { // Il PID e' gia presente return; } } } return; } // Visualizza tutti i valori presenti nell'array void print_pids (uint16_t *array) { int Ciclo; for (Ciclo = 0; Ciclo <= MAX_PIDS && array[Ciclo] != 0; Ciclo++) printf ("%s0x%x (%d)", (Ciclo == 0 ? "" : ", "), array[Ciclo], array[Ciclo]); printf ("\n"); return; } // Inverte i byte del PID passato come argomento uint16_t get_pid(uint8_t *pid) { uint16_t pp = 0; pp = (pid[0] & PID_MASK_HI)<<8; pp |= pid[1]; return pp; } // Cerca i PID nel flusso MPEG void find_avpids(int fd, uint16_t *vpid, uint16_t *apid) { uint8_t Buffer[IN_SIZE]; int Count; int Ciclo, Ciclo2; int Offset = 0; for (Ciclo = 0; Ciclo < 1000; Ciclo++) { Count = read(fd, Buffer, IN_SIZE); // Cerco un PID all'interno del pacchetto for (Ciclo2 = 0; Ciclo2 < Count-7; Ciclo2++) { if (Buffer[Ciclo2] == 0x47) { // Controllo se si tratta del primo pacchetto TS // di un pacchetto MPEG frammentato (mi serve per // vedere il tipo di flusso if (Buffer[Ciclo2 + 1] & 0x40) { Offset = 0; // Controllo se c'e' uno spostamento dei dati if ( Buffer[Ciclo2 + 3] & 0x20) Offset = Buffer[Ciclo2 + 4] + 1; switch (Buffer[Ciclo2 + 7 + Offset]) { case VIDEO_STREAM_S ... VIDEO_STREAM_E: insert_pid(vpid, get_pid(Buffer + Ciclo2 + 1)); break; case AUDIO_STREAM_S ... AUDIO_STREAM_E: insert_pid(apid, get_pid(Buffer + Ciclo2 + 1)); break; } } } Ciclo2 += 187; } } } /* * Programma principale */ int main(int argc, char *argv[]) { int in; uint16_t pidv[MAX_PIDS]; uint16_t pida[MAX_PIDS]; // Azzero gli array dei PID clear_pids(pidv); clear_pids(pida); // Verifico che il numero di parametri sia corretto // Deve essere passato solo il nome del file da analizzare if (argc != 2) { printf ("Sintassi: %s \n", argv[0]); exit (1); } //printf ("Ora cerco i pid all'interno del file MPEG '%s'\n", argv[1]); /*** Apro il file lettura ***/ if ((in=open(argv[1], O_RDONLY | O_LARGEFILE)) < 0) { fprintf(stderr, "%s: '%s': %s\n", argv[0], argv[1], strerror(errno)); exit(2); } // Cerco i PID all'interno del file find_avpids(in, pidv, pida); // Chiudo il file ed esco close (in); // Visualizzo i PID trovati printf ("PID video: "); print_pids(pidv); printf ("PID audio: "); print_pids(pida); exit (0); }