| 1 | /*************************************************************** |
|---|
| 2 | ** |
|---|
| 3 | ** Broadcom Corp. Confidential |
|---|
| 4 | ** Copyright 1998-2001 Broadcom Corp. All Rights Reserved. |
|---|
| 5 | ** |
|---|
| 6 | ** THIS SOFTWARE MAY ONLY BE USED SUBJECT TO AN EXECUTED |
|---|
| 7 | ** SOFTWARE LICENSE AGREEMENT BETWEEN THE USER AND BROADCOM. |
|---|
| 8 | ** YOU HAVE NO RIGHT TO USE OR EXPLOIT THIS MATERIAL EXCEPT |
|---|
| 9 | ** SUBJECT TO THE TERMS OF SUCH AN AGREEMENT. |
|---|
| 10 | ** |
|---|
| 11 | ** File: main.c |
|---|
| 12 | ** Description: Broadcom Stream Indexer Main |
|---|
| 13 | ** |
|---|
| 14 | ** Created: 05/16/2001 by Marcus Kellerman |
|---|
| 15 | ** |
|---|
| 16 | ** REVISION: |
|---|
| 17 | ** |
|---|
| 18 | ** $Log: $ |
|---|
| 19 | ** |
|---|
| 20 | ** |
|---|
| 21 | ****************************************************************/ |
|---|
| 22 | #include <stdio.h> |
|---|
| 23 | #include <stdlib.h> |
|---|
| 24 | #include <string.h> /* strcmp() */ |
|---|
| 25 | #include <sys/stat.h> |
|---|
| 26 | #if !defined(__vxworks) |
|---|
| 27 | #include <sys/timeb.h> /* ftime() */ |
|---|
| 28 | #endif |
|---|
| 29 | #include "tsindexer.h" |
|---|
| 30 | #include "bcmindexer.h" |
|---|
| 31 | #include "brcm_dbg.h" |
|---|
| 32 | |
|---|
| 33 | #define NUM_STREAM_BYTES_TO_READ (188*1024) |
|---|
| 34 | #define NUM_SC_BYTES_TO_READ (sizeof(sIndexEntry)*1024) |
|---|
| 35 | |
|---|
| 36 | void TimetoString( long ctime, char *outStr ) |
|---|
| 37 | { |
|---|
| 38 | long hh,mm,ss; |
|---|
| 39 | char *p; |
|---|
| 40 | |
|---|
| 41 | ss = ctime % 60; |
|---|
| 42 | mm = (ctime/60) % 60; |
|---|
| 43 | hh = (ctime/3600) % 24; |
|---|
| 44 | |
|---|
| 45 | p = outStr; |
|---|
| 46 | *p++ = (hh/10) + 0x30; |
|---|
| 47 | *p++ = (hh%10) + 0x30; |
|---|
| 48 | *p++ = ':'; |
|---|
| 49 | *p++ = (mm/10) + 0x30; |
|---|
| 50 | *p++ = (mm%10) + 0x30; |
|---|
| 51 | *p++ = ':'; |
|---|
| 52 | *p++ = (ss/10) + 0x30; |
|---|
| 53 | *p++ = (ss%10) + 0x30; |
|---|
| 54 | *p++ = 0; |
|---|
| 55 | } |
|---|
| 56 | |
|---|
| 57 | double getms( void ) |
|---|
| 58 | { |
|---|
| 59 | #if defined(__vxworks) |
|---|
| 60 | return 0; |
|---|
| 61 | #else |
|---|
| 62 | double usec1; |
|---|
| 63 | struct timeb t; |
|---|
| 64 | |
|---|
| 65 | ftime( &t ); |
|---|
| 66 | |
|---|
| 67 | usec1 = t.time + t.millitm/1000.0; |
|---|
| 68 | return usec1; |
|---|
| 69 | #endif |
|---|
| 70 | } |
|---|
| 71 | |
|---|
| 72 | void OffsetToString( long offset, char *outStr ) |
|---|
| 73 | { |
|---|
| 74 | long mb, kb, b; |
|---|
| 75 | |
|---|
| 76 | b = offset % 1000; |
|---|
| 77 | kb = (offset/1000)%1000; |
|---|
| 78 | mb = (offset/(1000*1000)) % (1000*1000); |
|---|
| 79 | |
|---|
| 80 | sprintf( outStr, "%ld,%03ld,%03ld", mb, kb, b ); |
|---|
| 81 | } |
|---|
| 82 | |
|---|
| 83 | /** |
|---|
| 84 | * Feed from tsindexer to bcmindexer. |
|---|
| 85 | **/ |
|---|
| 86 | static unsigned long write_to_bcmindexer( const void *p_bfr, unsigned long entrySize, |
|---|
| 87 | unsigned long numEntries, void *fp ) |
|---|
| 88 | { |
|---|
| 89 | return |
|---|
| 90 | BNAV_Indexer_Feed( |
|---|
| 91 | (BNAV_Indexer_Handle)fp, |
|---|
| 92 | (BSCT_Entry *)p_bfr, |
|---|
| 93 | (numEntries * entrySize) / sizeof(BSCT_Entry)) |
|---|
| 94 | * sizeof(BSCT_Entry) / entrySize; |
|---|
| 95 | } |
|---|
| 96 | |
|---|
| 97 | void printHeader() |
|---|
| 98 | { |
|---|
| 99 | printf("\ncreateindex, built on %s\n\n", __DATE__); |
|---|
| 100 | printf("Broadcom Corp. Confidential\n"); |
|---|
| 101 | printf("Copyright 1998-2003 Broadcom Corp. All Rights Reserved.\n\n"); |
|---|
| 102 | } |
|---|
| 103 | |
|---|
| 104 | /** |
|---|
| 105 | * This is a modification of createindex which allows |
|---|
| 106 | * the stuff of gigabytes of bogus MPEG into the |
|---|
| 107 | * index in order to test wrap-detection. |
|---|
| 108 | * |
|---|
| 109 | * This was needed to test PR7218. |
|---|
| 110 | **/ |
|---|
| 111 | #define FAKE_GAP |
|---|
| 112 | |
|---|
| 113 | #ifdef FAKE_GAP |
|---|
| 114 | off_t fake_data_sent = 0; |
|---|
| 115 | #endif |
|---|
| 116 | |
|---|
| 117 | static FILE *g_mpegFile = NULL; // global hack |
|---|
| 118 | int mpegSizeCallback(BNAV_Indexer_Handle handle, unsigned long *hi, unsigned long *lo) |
|---|
| 119 | { |
|---|
| 120 | off_t o = ftello(g_mpegFile); |
|---|
| 121 | if (o == -1) |
|---|
| 122 | return -1; |
|---|
| 123 | |
|---|
| 124 | #ifdef FAKE_GAP |
|---|
| 125 | o += fake_data_sent; |
|---|
| 126 | #endif |
|---|
| 127 | *hi = o >> 32; |
|---|
| 128 | *lo = o & 0xFFFFFFFF; |
|---|
| 129 | return 0; |
|---|
| 130 | } |
|---|
| 131 | |
|---|
| 132 | /** |
|---|
| 133 | * This is the entry point for VxWorks. |
|---|
| 134 | * |
|---|
| 135 | * input: 0=ts,1=pes,2=sct |
|---|
| 136 | * output: 0=sct,1=bcm |
|---|
| 137 | **/ |
|---|
| 138 | int createindex(const char *inputfile, const char *outputfile, int pid, |
|---|
| 139 | int input, int output, BNAV_Version navVersion) |
|---|
| 140 | { |
|---|
| 141 | unsigned char *bfr; |
|---|
| 142 | FILE *fin, *fout; |
|---|
| 143 | sTsIndexer *indexer = NULL; |
|---|
| 144 | BNAV_Indexer_Handle bcmindexer = NULL; |
|---|
| 145 | unsigned long readBytes; |
|---|
| 146 | unsigned long totalBytes = 0; |
|---|
| 147 | double time1, time2; |
|---|
| 148 | int pesId = 0; |
|---|
| 149 | int generateBcmIndex = 0; |
|---|
| 150 | int sctInput = 0; |
|---|
| 151 | unsigned long numBytesToRead; |
|---|
| 152 | |
|---|
| 153 | printHeader(); |
|---|
| 154 | |
|---|
| 155 | time1 = getms(); |
|---|
| 156 | |
|---|
| 157 | if (input == 1) |
|---|
| 158 | pesId = pid; |
|---|
| 159 | else if (input == 2) |
|---|
| 160 | sctInput = 1; |
|---|
| 161 | if (sctInput) |
|---|
| 162 | numBytesToRead = NUM_SC_BYTES_TO_READ; |
|---|
| 163 | else |
|---|
| 164 | numBytesToRead = NUM_STREAM_BYTES_TO_READ; |
|---|
| 165 | if (output == 1) |
|---|
| 166 | generateBcmIndex = 1; |
|---|
| 167 | |
|---|
| 168 | if (pid == 0 && !sctInput) |
|---|
| 169 | printf( |
|---|
| 170 | "WARNING\n" |
|---|
| 171 | "WARNING\n" |
|---|
| 172 | "WARNING: Are you sure you want PID == 0 ??????????????\n" |
|---|
| 173 | "WARNING\n" |
|---|
| 174 | "WARNING\n" |
|---|
| 175 | "\n" |
|---|
| 176 | ); |
|---|
| 177 | if (sctInput && !generateBcmIndex) { |
|---|
| 178 | printf("If your input is a start code index, then -bcm is required.\n"); |
|---|
| 179 | exit(1); |
|---|
| 180 | } |
|---|
| 181 | |
|---|
| 182 | bfr = malloc( numBytesToRead ); |
|---|
| 183 | |
|---|
| 184 | if (!strcmp(inputfile, "-")) { |
|---|
| 185 | fin = stdin; |
|---|
| 186 | inputfile = "stdin"; |
|---|
| 187 | } |
|---|
| 188 | else if( (fin = fopen(inputfile, "rb" )) == NULL ) |
|---|
| 189 | { |
|---|
| 190 | printf("Unable to open input file %s\n", inputfile); |
|---|
| 191 | exit(255); |
|---|
| 192 | } |
|---|
| 193 | |
|---|
| 194 | if (!strcmp(outputfile, "-")) { |
|---|
| 195 | fout = stdout; |
|---|
| 196 | outputfile = "stdout"; |
|---|
| 197 | } |
|---|
| 198 | else if( (fout = fopen(outputfile, "wb" )) == NULL ) |
|---|
| 199 | { |
|---|
| 200 | printf("Unable to open output file %s\n", outputfile); |
|---|
| 201 | fclose(fin); |
|---|
| 202 | exit(255); |
|---|
| 203 | } |
|---|
| 204 | |
|---|
| 205 | printf("Processing %s 0x%X from %s input file '%s'.\n", |
|---|
| 206 | pesId?"StreamID":"PID", |
|---|
| 207 | pesId?pesId:pid, |
|---|
| 208 | pesId?"MPEG PES":sctInput?"SCT":"MPEG TS", |
|---|
| 209 | inputfile); |
|---|
| 210 | if (generateBcmIndex) |
|---|
| 211 | printf("Writing BCM index (ver %d) to '%s'.\n", navVersion, outputfile); |
|---|
| 212 | else |
|---|
| 213 | printf("Writing SCT index to '%s'.\n", outputfile); |
|---|
| 214 | |
|---|
| 215 | if (generateBcmIndex) |
|---|
| 216 | { |
|---|
| 217 | BNAV_Indexer_Settings settings; |
|---|
| 218 | BNAV_Indexer_GetDefaultSettings(&settings); |
|---|
| 219 | settings.writeCallback = (INDEX_WRITE_CB)fwrite; |
|---|
| 220 | settings.filePointer = (void *)fout; |
|---|
| 221 | settings.navVersion = navVersion; |
|---|
| 222 | if (!sctInput) { |
|---|
| 223 | settings.mpegSizeCallback = mpegSizeCallback; |
|---|
| 224 | g_mpegFile = fin; |
|---|
| 225 | } |
|---|
| 226 | if (BNAV_Indexer_Open(&bcmindexer, &settings)) |
|---|
| 227 | { |
|---|
| 228 | exit(1); |
|---|
| 229 | } |
|---|
| 230 | } |
|---|
| 231 | if (!sctInput) |
|---|
| 232 | { |
|---|
| 233 | if (generateBcmIndex) |
|---|
| 234 | /* pass through to bcmindex */ |
|---|
| 235 | indexer = tsindex_allocate( (INDEX_WRITE_CB)write_to_bcmindexer, (void *)bcmindexer, (unsigned short)pid, -1 ); |
|---|
| 236 | else |
|---|
| 237 | indexer = tsindex_allocate( (INDEX_WRITE_CB)fwrite, (void *)fout, (unsigned short)pid, -1 ); |
|---|
| 238 | if( pesId ) |
|---|
| 239 | tsindex_setPesId( indexer, (unsigned char)pesId ); |
|---|
| 240 | } |
|---|
| 241 | |
|---|
| 242 | while( (readBytes = fread( bfr, 1, numBytesToRead, fin )) != 0 ) |
|---|
| 243 | { |
|---|
| 244 | totalBytes += readBytes; |
|---|
| 245 | |
|---|
| 246 | if ( totalBytes%(1*numBytesToRead) == 0 ) |
|---|
| 247 | { |
|---|
| 248 | double rate1; char timeStr[32], offsetStr[32]; |
|---|
| 249 | time2 = getms() - time1; |
|---|
| 250 | rate1 = (totalBytes/1024)/time2; |
|---|
| 251 | TimetoString( (long)time2, timeStr ); |
|---|
| 252 | OffsetToString( totalBytes, offsetStr ); |
|---|
| 253 | printf( "Byte Offset: %s Rate: %0.1fK/s, Elapsed Time: %s \r", offsetStr, rate1, timeStr ); |
|---|
| 254 | } |
|---|
| 255 | |
|---|
| 256 | if (sctInput) |
|---|
| 257 | { |
|---|
| 258 | BNAV_Indexer_Feed(bcmindexer, (BSCT_Entry*)bfr, readBytes/sizeof(BSCT_Entry) ); |
|---|
| 259 | } |
|---|
| 260 | else if( pesId ) |
|---|
| 261 | { |
|---|
| 262 | tsindex_feedPes( indexer, bfr, readBytes ); |
|---|
| 263 | } |
|---|
| 264 | else |
|---|
| 265 | { |
|---|
| 266 | tsindex_feed( indexer, bfr, readBytes ); |
|---|
| 267 | } |
|---|
| 268 | |
|---|
| 269 | #ifdef FAKE_GAP |
|---|
| 270 | #define START_OF_JUNK (10 * 1024 * 1024) |
|---|
| 271 | #define AMOUNT_OF_JUNK1 ((unsigned long)1024 * 1024 * 1024) |
|---|
| 272 | #define AMOUNT_OF_JUNK2 16 |
|---|
| 273 | { |
|---|
| 274 | static int doonce = 0; |
|---|
| 275 | if (sctInput || pesId) { |
|---|
| 276 | BRCM_DBG_ERR(("FAKE_GAP must use TS in")); |
|---|
| 277 | exit(1); |
|---|
| 278 | } |
|---|
| 279 | if (!doonce && totalBytes >= START_OF_JUNK) { |
|---|
| 280 | int i,j; |
|---|
| 281 | unsigned char junkbuf[188]; |
|---|
| 282 | |
|---|
| 283 | doonce = 1; |
|---|
| 284 | junkbuf[0] = 0x47; // just enough to fake it out |
|---|
| 285 | printf("\nFeeding junk\n"); |
|---|
| 286 | for (j=0;j<AMOUNT_OF_JUNK2;j++) |
|---|
| 287 | for (i=0;i<AMOUNT_OF_JUNK1;i+=188) { |
|---|
| 288 | tsindex_feed(indexer, junkbuf, 188); |
|---|
| 289 | fake_data_sent += 188; |
|---|
| 290 | } |
|---|
| 291 | } |
|---|
| 292 | } |
|---|
| 293 | #endif |
|---|
| 294 | } |
|---|
| 295 | |
|---|
| 296 | if (bcmindexer) |
|---|
| 297 | BNAV_Indexer_Close( bcmindexer ); |
|---|
| 298 | if (indexer) |
|---|
| 299 | tsindex_free( indexer ); |
|---|
| 300 | |
|---|
| 301 | fclose( fin ); |
|---|
| 302 | fclose( fout ); |
|---|
| 303 | free( bfr ); |
|---|
| 304 | printf("\n"); |
|---|
| 305 | exit(0); |
|---|
| 306 | } |
|---|
| 307 | |
|---|
| 308 | #if !defined(__vxworks) |
|---|
| 309 | void printUsage() |
|---|
| 310 | { |
|---|
| 311 | printf( |
|---|
| 312 | "Parses an MPEG stream or SCT index and creates either a SCT index\n" |
|---|
| 313 | " or Broadcom index.\n" |
|---|
| 314 | "\n" |
|---|
| 315 | "Usage: createindex inputfile outputfile [pid] [-ts|-pes|-sct] [-bcm [-bcmver VERSION]]\n" |
|---|
| 316 | "\n" |
|---|
| 317 | " inputfile Filename of input mpeg (either TS or PES stream), or\n" |
|---|
| 318 | " input startcode index (if -sct is specified or ends with\n" |
|---|
| 319 | " .sct or .idx)\n" |
|---|
| 320 | " outputfile Filename of output index file that will be created.\n" |
|---|
| 321 | " If -bcm option is used, or file ends with .nav, it will be\n" |
|---|
| 322 | " a NAV table, otherwise a start code index.\n" |
|---|
| 323 | " pid Pid (or stream id in PES mode). Not needed if inputfile is\n" |
|---|
| 324 | " a startcode index. Prefix with 0x for hex, otherwise decimal.\n" |
|---|
| 325 | "\n" |
|---|
| 326 | "Optional Parameters:\n" |
|---|
| 327 | " -ts Inputfile is a TS stream\n" |
|---|
| 328 | " -pes Inputfile is a PES stream\n" |
|---|
| 329 | " -sct Inputfile is a startcode index\n" |
|---|
| 330 | " -bcm Generate a BCM index file from either\n" |
|---|
| 331 | " a TS stream or startcode index.\n" |
|---|
| 332 | " -bcmver VERSION Specify the BCM index format. See eBcmNavVersion.\n" |
|---|
| 333 | ); |
|---|
| 334 | } |
|---|
| 335 | |
|---|
| 336 | int main( int argc, char **argv ) |
|---|
| 337 | { |
|---|
| 338 | brcmDbgSetOutputLevel(kBrcmDbgOutputWrn); |
|---|
| 339 | |
|---|
| 340 | if (argc < 3) { |
|---|
| 341 | printHeader(); |
|---|
| 342 | printUsage(); |
|---|
| 343 | return 1; |
|---|
| 344 | } |
|---|
| 345 | else { |
|---|
| 346 | int pid = 0; |
|---|
| 347 | int nextparam = 3; |
|---|
| 348 | int input = -1; |
|---|
| 349 | int output = -1; |
|---|
| 350 | const char *source = argv[1]; |
|---|
| 351 | const char *dest = argv[2]; |
|---|
| 352 | BNAV_Version navVersion = BNAV_VersionLatest; |
|---|
| 353 | |
|---|
| 354 | if (argc>3 && argv[3][0] != '-') { |
|---|
| 355 | if (strstr(argv[3], "0x") == argv[3]) |
|---|
| 356 | sscanf( argv[3], "0x%X", &pid ); |
|---|
| 357 | else |
|---|
| 358 | pid = atoi( argv[3] ); |
|---|
| 359 | ++nextparam; |
|---|
| 360 | } |
|---|
| 361 | |
|---|
| 362 | while (nextparam < argc) { |
|---|
| 363 | if (!strcmp(argv[nextparam], "-ts")) |
|---|
| 364 | input = 0; |
|---|
| 365 | else if (!strcmp(argv[nextparam], "-pes")) |
|---|
| 366 | input = 1; |
|---|
| 367 | else if (!strcmp(argv[nextparam], "-sct")) |
|---|
| 368 | input = 2; |
|---|
| 369 | else if (!strcmp(argv[nextparam], "-bcm")) |
|---|
| 370 | output = 1; |
|---|
| 371 | else if (!strcmp(argv[nextparam], "-bcmver") && nextparam+1 < argc) |
|---|
| 372 | navVersion = atoi(argv[++nextparam]); |
|---|
| 373 | nextparam++; |
|---|
| 374 | } |
|---|
| 375 | |
|---|
| 376 | if (input == -1) { |
|---|
| 377 | char *s; |
|---|
| 378 | // check the suffix of the inputfile |
|---|
| 379 | if (((s = strstr(source, ".sct")) && !s[4]) || |
|---|
| 380 | ((s = strstr(source, ".idx")) && !s[4])) |
|---|
| 381 | { |
|---|
| 382 | input = 2; |
|---|
| 383 | } |
|---|
| 384 | else if ((s = strstr(source, ".pes")) && !s[4]) |
|---|
| 385 | { |
|---|
| 386 | input = 1; |
|---|
| 387 | } |
|---|
| 388 | else |
|---|
| 389 | input = 0; |
|---|
| 390 | } |
|---|
| 391 | if (output == -1) { |
|---|
| 392 | char *s; |
|---|
| 393 | if (((s = strstr(dest, ".nav")) && !s[4]) || |
|---|
| 394 | ((s = strstr(dest, ".bcm")) && !s[4])) |
|---|
| 395 | output = 1; |
|---|
| 396 | else |
|---|
| 397 | output = 0; |
|---|
| 398 | } |
|---|
| 399 | |
|---|
| 400 | return createindex(source,dest,pid,input,output,navVersion); |
|---|
| 401 | } |
|---|
| 402 | } |
|---|
| 403 | #endif |
|---|
| 404 | |
|---|