]> git.vomp.tv Git - vompserver.git/blob - libdvbmpeg/cpptools.cc
Initial import
[vompserver.git] / libdvbmpeg / cpptools.cc
1 /*
2  *  dvb-mpegtools for the Siemens Fujitsu DVB PCI card
3  *
4  * Copyright (C) 2000, 2001 Marcus Metzler 
5  *            for convergence integrated media GmbH
6  * Copyright (C) 2002  Marcus Metzler 
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  * 
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
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23  * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
24  * 
25
26  * The author can be reached at mocm@metzlerbros.de
27  */
28
29 #include "cpptools.hh"
30
31 #define HEX(N) "0x" << hex << setw(2) << setfill('0') \
32 << int(N) << " " << dec
33 #define HHEX(N,M) "0x" << hex << setw(M) << setfill('0') \
34 << int(N) << " " << dec
35 #define LHEX(N,M) "0x" << hex << setw(M) << setfill('0') \
36 << long(N) << " " << dec
37
38 #define MAX_SEARCH 1024 * 1024
39
40 ostream & operator << (ostream & stream, PES_Packet & x){
41   
42         if (x.info){
43                 cerr << "PES Packet: " ;
44                 switch ( x.p.stream_id ) {
45                                 
46                 case PROG_STREAM_MAP:
47                         cerr << "Program Stream Map";
48                         break;
49                 case PRIVATE_STREAM2:
50                         cerr << "Private Stream 2";
51                         break;
52                 case PROG_STREAM_DIR:
53                         cerr << "Program Stream Directory";
54                         break;
55                 case ECM_STREAM     :
56                         cerr << "ECM Stream";
57                         break;
58                 case EMM_STREAM     :
59                         cerr << "EMM Stream";
60                         break;
61                 case PADDING_STREAM :
62                         cerr << "Padding Stream";
63                         break;
64                 case DSM_CC_STREAM  :
65                         cerr << "DSM Stream";
66                         break;
67                 case ISO13522_STREAM:
68                         cerr << "ISO13522 Stream";
69                         break;
70                 case PRIVATE_STREAM1:
71                         cerr << "Private Stream 1";
72                         break;
73                 case AUDIO_STREAM_S ... AUDIO_STREAM_E:
74                         cerr << "Audio Stream " << HEX(x.p.stream_id);
75                         break;
76                 case VIDEO_STREAM_S ... VIDEO_STREAM_E:
77                         cerr << "Video Stream " << HEX(x.p.stream_id);
78                         break;
79                         
80                 }
81                 cerr << " MPEG" << x.p.mpeg << endl;
82                 if ( x.p.mpeg == 2 ){
83                         cerr << "    FLAGS: ";
84
85                         if (x.p.flags1 & SCRAMBLE_FLAGS){
86                                 cerr << " SCRAMBLE(";
87                                 cerr << ((x.p.flags1 & SCRAMBLE_FLAGS)>>4);
88                                 cerr << ")";
89                         }
90                         if (x.p.flags1 & PRIORITY_FLAG) 
91                                 cerr << " PRIORITY";    
92                         if (x.p.flags1 & DATA_ALIGN_FLAG)
93                                 cerr << " DATA_ALIGN";  
94                         if (x.p.flags1 & COPYRIGHT_FLAG) 
95                                 cerr << " COPYRIGHT";   
96                         if (x.p.flags1 & ORIGINAL_FLAG) 
97                                 cerr << " ORIGINAL";   
98
99                         if (x.p.flags2 & PTS_DTS_FLAGS){
100                                 cerr << " PTS_DTS(";
101                                 cerr << ((x.p.flags2 & PTS_DTS_FLAGS)>>6);
102                                 cerr << ")";
103                         }
104                         if (x.p.flags2 & ESCR_FLAG) 
105                                 cerr << " ESCR";
106                         if (x.p.flags2 & ES_RATE_FLAG)
107                                 cerr << " ES_RATE";   
108                         if (x.p.flags2 & DSM_TRICK_FLAG)
109                                 cerr << " DSM_TRICK";   
110                         if (x.p.flags2 & ADD_CPY_FLAG)
111                                 cerr << " ADD_CPY";     
112                         if (x.p.flags2 & PES_CRC_FLAG) 
113                                 cerr << " CRC";     
114                         if (x.p.flags2 & PES_EXT_FLAG)
115                                 cerr << " EXT";     
116
117                         cerr << endl;
118
119                         if ((x.p.flags2 & PTS_DTS_FLAGS) == PTS_ONLY)
120                                 cerr << "   PTS: " 
121                                      << LHEX(ntohl(x.WPTS()),8)
122                                      << "(h" << int(x.high_pts()) << ")"
123                                      << endl; 
124                         else if ((x.p.flags2 & PTS_DTS_FLAGS) == PTS_DTS){
125                                 cerr << "   PTS: " 
126                                      << LHEX(ntohl(x.WPTS()),8)
127                                      << "(h" << int(x.high_pts()) << ")";
128                                 cerr << "   DTS: " 
129                                      << LHEX(ntohl(x.WDTS()),8)
130                                      << "(h" << int(x.high_dts()) << ")"
131                                      << endl; 
132                         }
133 /*                      
134                         if (x.p.flags2 & ESCR_FLAG)
135
136                         
137                         if (x.p.flags2 & ES_RATE_FLAG)
138
139                         
140                         if (x.p.flags2 & DSM_TRICK_FLAG)
141
142                         
143                         if (x.p.flags2 & ADD_CPY_FLAG)
144
145                         
146                         if (x.p.flags2 & PES_CRC_FLAG)
147
148                         
149                         if (x.p.flags2 & PES_EXT_FLAG){
150                                 
151                                 if (x.p.priv_flags & PRIVATE_DATA)
152                                         stream.write(x.p.pes_priv_data,16);
153                                 
154                                 if (x.p.priv_flags & HEADER_FIELD){
155                                         stream.write(&x.p.pack_field_length,1);
156                                         x.p.pack_header = new 
157                                                 uint8_t[x.p.pack_field_length];
158                                         stream.write(x.p.pack_header,
159                                                      x.p.pack_field_length);
160                                 }
161                                 
162                                 if ( x.p.priv_flags & PACK_SEQ_CTR){
163                                         stream.write(&x.p.pck_sqnc_cntr,1);
164                                         stream.write(&x.p.org_stuff_length,1);
165                                 }
166                                 
167                                 if ( x.p.priv_flags & P_STD_BUFFER)
168                                         stream.write(x.p.p_std,2);
169                                 
170                                 if ( x.p.priv_flags & PES_EXT_FLAG2){
171                                         stream.write(&x.p.pes_ext_lngth,1);
172                                         x.p.pes_ext = new 
173                                                 uint8_t[x.p.pes_ext_lngth];
174                                         stream.write(x.p.pes_ext,
175                                                      x.p.pes_ext_lngth);
176                                 }
177                         }
178                 } else {
179                         if ((x.p.flags2 & PTS_DTS_FLAGS) == PTS_ONLY)
180                                 stream.write(x.p.pts,5);
181                         else if ((x.p.flags2 & PTS_DTS_FLAGS) == 
182                                  PTS_DTS){
183                                 stream.write(x.p.pts,5);
184                                 stream.write(x.p.dts,5);
185                         }
186 */      
187                 }                       
188                 cerr << endl << endl;
189                 return stream;
190         }
191
192         int l = x.p.length+x.p.pes_hlength+9;
193         uint8_t buf[l];
194         int length = cwrite_pes(buf,&(x.p),l);
195         stream.write((char *)buf,length);
196         
197         return stream;
198 }
199
200 static unsigned int find_length(istream & stream){
201         streampos p = 0;
202         streampos start = 0;
203         streampos q = 0;
204         int found = 0;
205         uint8_t sync4[4];
206
207         start = stream.tellg();
208         start -=2;
209         stream.seekg(start);
210         while ( !stream.eof() && !found ){
211                 p = stream.tellg();
212                 stream.read((char *)&sync4,4);
213                 if (sync4[0] == 0x00 && sync4[1] == 0x00 && sync4[2] == 0x01) {
214                         switch ( sync4[3] ) {
215                                 
216                         case PROG_STREAM_MAP:
217                         case PRIVATE_STREAM2:
218                         case PROG_STREAM_DIR:
219                         case ECM_STREAM     :
220                         case EMM_STREAM     :
221                         case PADDING_STREAM :
222                         case DSM_CC_STREAM  :
223                         case ISO13522_STREAM:
224                         case PRIVATE_STREAM1:
225                         case AUDIO_STREAM_S ... AUDIO_STREAM_E:
226                         case VIDEO_STREAM_S ... VIDEO_STREAM_E:
227                                 found = 1;
228                                 break;
229                         default:
230                                 q = stream.tellg();
231                                 break;
232                         }       
233                 } 
234         }
235         q = stream.tellg();
236         stream.seekg(streampos(2)+start);
237         if (found) return (unsigned int)(q-start)-4-2;
238         else return (unsigned int)(q-start)-2;
239         
240 }
241
242 istream & operator >> (istream & stream, PES_Packet & x){
243         
244         uint8_t sync4[4];
245         int found=0;
246         int done=0;
247         streampos p = 0;
248         
249         while (!stream.eof() && !found) {
250                 p = stream.tellg();
251                 stream.read((char *)&sync4,4);
252                 if (sync4[0] == 0x00 && sync4[1] == 0x00 && sync4[2] == 0x01) {
253                         x.p.stream_id = sync4[3];
254
255                         switch ( sync4[3] ) {
256                                 
257                         case PROG_STREAM_MAP:
258                         case PRIVATE_STREAM2:
259                         case PROG_STREAM_DIR:
260                         case ECM_STREAM     :
261                         case EMM_STREAM     :
262                                 found = 1;
263                                 stream.read((char *)x.p.llength,2);
264                                 x.setlength();
265                                 if (!x.p.length){ 
266                                         x.p.length = find_length(stream);
267                                         x.Nlength();
268                                 }
269                                 stream.read((char *)x.p.pes_pckt_data,x.p.length);
270                                 done = 1;
271                                 break;
272                         case PADDING_STREAM :
273                                 found = 1;
274                                 stream.read((char *)x.p.llength,2);
275                                 x.setlength();
276                                 if (!x.p.length){ 
277                                         x.p.length = find_length(stream);
278                                         x.Nlength();
279                                 }
280                                 x.p.padding = x.p.length;
281                                 stream.read((char *)x.p.pes_pckt_data,x.p.length);
282                                 done = 1;
283                                 break;
284                                 
285                         case DSM_CC_STREAM  :
286                         case ISO13522_STREAM:
287                         case PRIVATE_STREAM1:
288                         case AUDIO_STREAM_S ... AUDIO_STREAM_E:
289                         case VIDEO_STREAM_S ... VIDEO_STREAM_E:
290                                 stream.read((char *)x.p.llength,2);
291                                 x.setlength();
292                                 if (!x.p.length){ 
293                                         x.p.length = find_length(stream);
294                                         x.Nlength();
295                                 }
296                                 found = 1;
297                                 break;
298                                 
299                         default:
300                                 stream.seekg(p+streampos(1));
301                         break;
302                         }       
303                 } else stream.seekg(p+streampos(1));
304         }
305         
306         if ( found && !done) {
307                 p = stream.tellg();
308                 stream.read((char *)&x.p.flags1,1);
309                 if ( (x.p.flags1 & 0xC0) == 0x80 )
310                         x.p.mpeg = 2;
311                 else
312                         x.p.mpeg = 1;
313                 if ( x.p.mpeg == 2 ){
314                         stream.read((char *)&x.p.flags2,1);
315                         stream.read((char *)&x.p.pes_hlength,1);
316                         
317                         if ((int)x.p.length > x.p.pes_hlength+3)
318                                 x.p.length -=x.p.pes_hlength+3;
319                         else 
320                                 return stream;
321
322                         uint8_t count = x.p.pes_hlength;
323
324                         if ((x.p.flags2 & PTS_DTS_FLAGS) == PTS_ONLY){
325                                 stream.read((char *)x.p.pts,5);
326                                 count -=5;
327                         } else 
328                                 if ((x.p.flags2 & PTS_DTS_FLAGS) == PTS_DTS){
329                                         stream.read((char *)x.p.pts,5);
330                                         stream.read((char *)x.p.dts,5);
331                                         count -= 10;
332                                 }
333
334                         if (x.p.flags2 & ESCR_FLAG){
335                                 stream.read((char *)x.p.escr,6);
336                                 count -= 6;
337                         }
338
339                         if (x.p.flags2 & ES_RATE_FLAG){
340                                 stream.read((char *)x.p.es_rate,3);
341                                 count -= 6;
342                         }
343
344                         if (x.p.flags2 & DSM_TRICK_FLAG){
345                                 stream.read((char *)&x.p.trick,1);
346                                 count -= 1;
347                         }
348
349                         if (x.p.flags2 & ADD_CPY_FLAG){
350                                 stream.read((char *)&x.p.add_cpy,1);
351                                 count -= 1;
352                         }
353
354                         if (x.p.flags2 & PES_CRC_FLAG){
355                                 stream.read((char *)x.p.prev_pes_crc,2);
356                                 count -= 2;
357                         }                       
358
359                         if (x.p.flags2 & PES_EXT_FLAG){
360                                 stream.read((char *)&x.p.priv_flags,1);
361                                 count -= 1;
362                                 
363                                 if (x.p.priv_flags & PRIVATE_DATA){
364                                         stream.read((char *)x.p.pes_priv_data,16);
365                                         count -= 16;
366                                 }
367
368                                 if (x.p.priv_flags & HEADER_FIELD){
369                                         stream.read((char *)&x.p.pack_field_length,1);
370                                         x.p.pack_header = new 
371                                                 uint8_t[x.p.pack_field_length];
372                                         stream.read((char *)x.p.pack_header,
373                                                     x.p.pack_field_length);
374                                         count -= 1+x.p.pack_field_length;
375                                 }
376                                 
377                                 if ( x.p.priv_flags & PACK_SEQ_CTR){
378                                         stream.read((char *)&x.p.pck_sqnc_cntr,1);
379                                         stream.read((char *)&x.p.org_stuff_length,1);
380                                         count -= 2;
381                                 }
382
383                                 if ( x.p.priv_flags & P_STD_BUFFER){
384                                         stream.read((char *)x.p.p_std,2);
385                                         count -= 2;
386                                 }
387
388                                 if ( x.p.priv_flags & PES_EXT_FLAG2){
389                                         stream.read((char *)&x.p.pes_ext_lngth,1);
390                                         x.p.pes_ext = new 
391                                                 uint8_t[x.p.pes_ext_lngth];
392                                         stream.read((char *)x.p.pes_ext,
393                                                     x.p.pes_ext_lngth);
394                                         count -= 1+x.p.pes_ext_lngth;
395                                 }
396                         }
397                         x.p.stuffing = count;
398                         uint8_t dummy;
399                         for(int i = 0; i< count ;i++) 
400                                 stream.read((char *)&dummy,1);
401                         
402                 } else {
403                         uint8_t check;
404                         x.p.mpeg1_pad = 1;
405                         check = x.p.flags1;
406                         while (check == 0xFF){
407                                 stream.read((char *)&check,1);
408                                 x.p.mpeg1_pad++;
409                         }
410                     
411                         if ( (check & 0xC0) == 0x40){
412                                 stream.read((char *)&check,1);
413                                 x.p.mpeg1_pad++;
414                                 stream.read((char *)&check,1);
415                                 x.p.mpeg1_pad++;
416                         }
417                         x.p.flags2 = 0;
418                         x.p.length -= x.p.mpeg1_pad;
419
420                         stream.seekg(p);
421                         if ( (check & 0x30)){
422                                 x.p.length ++;
423                                 x.p.mpeg1_pad --;
424
425                                 if (check == x.p.flags1){
426                                         x.p.pes_hlength = 0;
427                                 } else {
428                                         x.p.mpeg1_headr = 
429                                                 new uint8_t[x.p.mpeg1_pad];
430                                         x.p.pes_hlength = x.p.mpeg1_pad;
431                                         stream.read((char *)x.p.mpeg1_headr,
432                                                     x.p.mpeg1_pad);
433                                 }
434
435                                 x.p.flags2 = (check & 0xF0) << 2;
436                                 if ((x.p.flags2 & PTS_DTS_FLAGS) == PTS_ONLY){
437                                         stream.read((char *)x.p.pts,5);
438                                         x.p.length -= 5;
439                                         x.p.pes_hlength += 5;
440                                 }
441                                 else if ((x.p.flags2 & PTS_DTS_FLAGS) == 
442                                          PTS_DTS){
443                                         stream.read((char *)x.p.pts,5);
444                                         stream.read((char *)x.p.dts,5);
445                                         x.p.length -= 10;
446                                         x.p.pes_hlength += 10;
447                                 }
448                         } else {
449                                 x.p.mpeg1_headr = new uint8_t[x.p.mpeg1_pad];
450                                 x.p.pes_hlength = x.p.mpeg1_pad;
451                                 stream.read((char *)x.p.mpeg1_headr,x.p.mpeg1_pad);
452                         }
453                 }
454                 stream.read((char *)x.p.pes_pckt_data,x.p.length);
455         }
456         return stream;
457 }
458
459 ostream & operator << (ostream & stream, TS_Packet & x){
460
461         uint8_t buf[TS_SIZE];
462         int length = cwrite_ts(buf,&(x.p),TS_SIZE);
463         stream.write((char *)buf,length);
464
465         return stream;
466 }
467
468 istream & operator >> (istream & stream, TS_Packet & x){
469         uint8_t sync;
470         int found=0;
471         streampos p,q;
472
473         sync=0;
474         while (!stream.eof() && !found) {
475                 stream.read((char *)&sync,1);
476                 if (sync == 0x47) 
477                         found = 1;
478         }
479         stream.read((char *)x.p.pid,2);
480         stream.read((char *)&x.p.flags,1);
481         x.p.count = x.p.flags & COUNT_MASK;
482          
483         if (!(x.p.flags & ADAPT_FIELD) && (x.p.flags & PAYLOAD)){
484                 //no adapt. field only payload
485                 stream.read((char *)x.p.data,184);
486                 x.p.rest = 184;
487                 return stream;
488         } 
489
490         if ( x.p.flags & ADAPT_FIELD ) {
491                 // adaption field
492                 stream.read((char *)&x.p.adapt_length,1);
493                 if (x.p.adapt_length){
494                         p = stream.tellg();
495                         stream.read((char *)&x.p.adapt_flags,1);
496                         
497                         if ( x.p.adapt_flags & PCR_FLAG )
498                                 stream.read((char *) x.p.pcr,6);
499
500                         if ( x.p.adapt_flags & OPCR_FLAG )
501                                 stream.read((char *) x.p.opcr,6);
502
503                         if ( x.p.adapt_flags & SPLICE_FLAG )
504                                 stream.read((char *) &x.p.splice_count,1);
505                         
506                         if( x.p.adapt_flags & TRANS_PRIV){
507                                 stream.read((char *)&x.p.priv_dat_len,1);
508                                 x.p.priv_dat = new uint8_t[x.p.priv_dat_len];
509                                 stream.read((char *)x.p.priv_dat,x.p.priv_dat_len);
510                         }
511                         
512                         if( x.p.adapt_flags & ADAP_EXT_FLAG){
513                                 stream.read((char *)&x.p.adapt_ext_len,1);
514                                 stream.read((char *)&x.p.adapt_eflags,1);
515                                 if( x.p.adapt_eflags & LTW_FLAG)
516                                         stream.read((char *)x.p.ltw,2);
517                                 
518                                 if( x.p.adapt_eflags & PIECE_RATE)
519                                         stream.read((char *)x.p.piece_rate,3);
520                                 
521                                 if( x.p.adapt_eflags & SEAM_SPLICE)
522                                         stream.read((char *)x.p.dts,5);
523                         }
524                         q = stream.tellg();
525                         x.p.stuffing = x.p.adapt_length -(q-p);
526                         x.p.rest = 183-x.p.adapt_length;
527                         stream.seekg(q+streampos(x.p.stuffing));
528                         if (x.p.flags & PAYLOAD) // payload
529                                 stream.read((char *)x.p.data,x.p.rest);
530                         else 
531                                 stream.seekg(q+streampos(x.p.rest));
532                 } else {
533                         x.p.rest = 182;
534                         stream.read((char *)x.p.data, 183);
535                         return stream;
536                 }
537
538         }
539         return stream;
540 }
541
542
543 ostream & operator << (ostream & stream, PS_Packet & x){
544
545         uint8_t buf[PS_MAX];
546         int length = cwrite_ps(buf,&(x.p),PS_MAX);
547         stream.write((char *)buf,length);
548
549         return stream;
550 }
551
552 istream & operator >> (istream & stream, PS_Packet & x){
553         uint8_t headr[4];
554         int found=0;
555         streampos p = 0;
556         streampos q = 0;
557         int count = 0;
558
559         p = stream.tellg();
560         while (!stream.eof() && !found && count < MAX_SEARCH) {
561                 stream.read((char *)&headr,4);
562                 if (headr[0] == 0x00 && headr[1] == 0x00 && headr[2] == 0x01)
563                         if ( headr[3] == 0xBA ) 
564                                 found = 1;
565                         else if ( headr[3] == 0xB9 ) break;
566                         else stream.seekg(p+streampos(1));
567                 count++;
568         }
569         
570         if (found){
571                 stream.read((char *)x.p.scr,6);
572                 if (x.p.scr[0] & 0x40)
573                         x.p.mpeg = 2;
574                 else
575                         x.p.mpeg = 1;
576
577                 if (x.p.mpeg == 2){
578                         stream.read((char *)x.p.mux_rate,3);
579                         stream.read((char *)&x.p.stuff_length,1);
580                         p = stream.tellg();
581                         stream.seekg(p+streampos(x.p.stuff_length & 3));
582                 } else {
583                         x.p.mux_rate[0] = x.p.scr[5]; //mpeg1 scr is only 5 bytes
584                         stream.read((char *)x.p.mux_rate+1,2);
585                 }
586                         
587                 p=stream.tellg();
588                 stream.read((char *)headr,4);
589                 if (headr[0] == 0x00 && headr[1] == 0x00 && 
590                     headr[2] == 0x01 && headr[3] == 0xBB ) {
591                         stream.read((char *)x.p.sheader_llength,2);
592                         x.setlength();
593                         if (x.p.mpeg == 2){
594                                 stream.read((char *)x.p.rate_bound,3);
595                                 stream.read((char *)&x.p.audio_bound,1);
596                                 stream.read((char *)&x.p.video_bound,1);
597                                 stream.read((char *)&x.p.reserved,1);
598                         }
599                         stream.read((char *)x.p.data,x.p.sheader_length);
600                 } else {
601                         stream.seekg(p);
602                         x.p.sheader_length = 0;
603                 }
604
605                 int i = 0;
606                 int done = 0;
607                 q = stream.tellg();
608                 PES_Packet pes;
609                 do {
610                         p=stream.tellg();
611                         stream.read((char *)headr,4);
612                         stream.seekg(p);
613                         if ( headr[0] == 0x00 && headr[1] == 0x00 
614                              && headr[2] == 0x01 && headr[3] != 0xBA){
615                                 pes.init();
616                                 stream >> pes;
617                                 i++;
618                         } else done = 1;
619                 } while (!stream.eof() && !done);
620                 x.p.npes = i;
621                 stream.seekg(q);
622         } 
623         return stream;
624 }
625
626 void extract_audio_from_PES(istream &in, ostream &out){
627         PES_Packet pes;
628         
629         while(!in.eof()){
630                 pes.init();
631                 in >> pes ;
632                 if (pes.Stream_ID() == 0xC0)
633                         out << pes;
634         }
635 }
636
637 void extract_video_from_PES(istream &in, ostream &out){
638         PES_Packet pes;
639         
640         while(!in.eof()){
641                 pes.init();
642                 in >> pes ;
643                 if (pes.Stream_ID() == 0xE0)
644                         out << pes;
645         }
646 }
647
648 void extract_es_audio_from_PES(istream &in, ostream &out){
649         PES_Packet pes;
650         
651         while(!in.eof()){
652                 pes.init();
653                 in >> pes ;
654                 if (pes.Stream_ID() == 0xC0)
655                   out.write((char *)pes.Data(),pes.Length());
656         }
657 }
658
659 void extract_es_video_from_PES(istream &in, ostream &out){
660         PES_Packet pes;
661         
662         while(!in.eof()){
663                 pes.init();
664                 in >> pes ;
665                 if (pes.Stream_ID() == 0xE0)
666                   out.write((char *)pes.Data(),pes.Length());
667         }
668 }
669
670
671
672 #define MAX_PID 20
673 int TS_PIDS(istream &in, ostream &out){
674         int pid[MAX_PID];
675         TS_Packet ts;
676         int npid=0;
677         
678         for (int i=0 ; i<MAX_PID; i++)
679                 pid[i] = -1;
680         while (!in.eof()) {
681                 ts.init();
682                 in >> ts;
683                 int j;
684                 int found = 0;
685                 for (j=0;j<npid;j++){
686                         if ( ts.PID() == pid[j] )
687                                 found = 1;
688                 }
689                 if (! found){ 
690                         out << ts.PID() << " ";
691                         pid[npid] = ts.PID();
692                         npid++;
693                         if (npid == MAX_PID) return -1;
694                 }
695         }
696         out << endl;
697         return 0;
698 }
699
700 int tv_norm(istream &stream){
701         uint8_t headr[4];
702         int found=0;
703         streampos p = 0;
704         streampos q = 0;
705         int hsize,vsize;
706         int form= 0;
707
708         q = stream.tellg();
709         while (!stream.eof() && !found) {
710                 p = stream.tellg();
711                 stream.read((char *)headr,4);
712                 if (headr[0] == 0x00 && headr[1] == 0x00 && headr[2] == 0x01)
713                         if ( headr[3] == 0xB3 ){ 
714                                 found = 1;
715                         }
716                 if (! found) stream.seekg(p+streampos(1));
717         }
718         stream.read((char *)headr,4);
719
720         hsize = (headr[1] &0xF0) >> 4 | headr[0] << 4;
721         vsize = (headr[1] &0x0F) << 8 | headr[2];
722         cerr << "SIZE: " << hsize << "x" << vsize << endl;
723         
724         switch(((headr[3]&0xF0) >>4)){
725         case 1:
726                 cerr << "ASPECT: 1:1" << endl;
727                 break;
728         case 2:
729                 cerr << "ASPECT: 4:3" << endl;
730                 break;
731         case 3:
732                 cerr << "ASPECT: 16:9" << endl;
733                 break;
734         case 4:
735                 cerr << "ASPECT: 2.21:1" << endl;
736                 break;
737         }
738
739         switch (int(headr[3]&0x0F)){
740         case 1:
741                 cerr << "FRAMERATE: 23.976" << endl;
742                 form = pDUNNO;
743                 break;
744         case 2:
745                 cerr << "FRAMERATE: 24" << endl;
746                 form = pDUNNO;
747                 break;
748         case 3:
749                 cerr << "FRAMERATE: 25" << endl;
750                 form = pPAL;
751                 break;
752         case 4:
753                 cerr << "FRAMERATE: 29.97" << endl;
754                 form = pNTSC;
755                 break;
756         case 5:
757                 cerr << "FRAMERATE: 30" << endl;
758                 form = pNTSC;
759                 break;
760         case 6:
761                 cerr << "FRAMERATE: 50" << endl;
762                 form = pPAL;
763                 break;
764         case 7:
765                 cerr << "FRAMERATE: 59.94" << endl;
766                 form = pNTSC;
767                 break;
768         case 8:
769                 cerr << "FRAMERATE: 60" << endl;
770                 form = pNTSC;
771                 break;
772         }
773
774         int mpeg = 0;
775         found = 0;
776         while (!stream.eof() && !found) {
777                 p = stream.tellg();
778                 stream.read((char *)headr,4);
779                 if (headr[0] == 0x00 && headr[1] == 0x00 && headr[2] == 0x01)
780                         if ( headr[3] == 0xB5 ){ 
781                                 char *profile[] = {"reserved", "High", "Spatially Scalable",
782                                                    "SNR Scalable", "Main", "Simple", "undef",
783                                                    "undef"};
784                                 char *level[]   = {"res", "res", "res", "res",
785                                                    "High","res", "High 1440", "res",
786                                                    "Main","res", "Low", "res",
787                                                    "res", "res", "res", "res"};
788                                 char *chroma[]  = {"res", "4:2:0", "4:2:2", "4:4:4:"};
789                                 mpeg = 2;
790                                 stream.read((char *)headr,4);
791                                 cerr << "PROFILE: " << profile[headr[0] & 0x7] << endl;
792                                 cerr << "LEVEL: " << level[headr[1]>>4 & 0xF] << endl;
793                                 cerr << "CHROMA: " << chroma[headr[1]>>1 & 0x3] << endl;
794                                 found = 1;
795                         } else {
796                                 mpeg = 1;
797                                 found = 1;
798                         }                               
799                 if (! found) stream.seekg(p+streampos(1));
800         }
801
802         stream.seekg(q);
803         return (form | mpeg << 4);
804 }
805
806
807
808 int stream_type(istream &fin){
809         uint8_t headr[4];
810         streampos p=fin.tellg();
811         
812         TS_Packet ts;
813         fin >> ts;
814         fin.read((char *)headr,1);
815         fin.seekg(p);
816         if(fin && headr[0] == 0x47){
817                 return TS_STREAM;
818         }
819
820         PS_Packet ps;
821         fin >> ps;
822         PES_Packet pes;
823         for(int j=0;j < ps.NPES();j++){
824                 fin >> pes;
825         }
826         fin.read((char *)headr,4);
827         fin.seekg(p);
828         if (fin && headr[0] == 0x00 && headr[1] == 0x00
829             && headr[2] == 0x01 && headr[3] == 0xBA){
830                 return PS_STREAM;
831         }
832         
833         fin >> pes;
834         fin.read((char *)!headr,4);
835                         fin.seekg(p);
836         if (fin && headr[0] == 0x00 && headr[1] == 0x00
837             && headr[2] == 0x01 ){
838                 int found = 0;
839                 switch ( headr[3] ) {
840                         
841                 case PROG_STREAM_MAP:
842                 case PRIVATE_STREAM2:
843                 case PROG_STREAM_DIR:
844                 case ECM_STREAM     :
845                 case EMM_STREAM     :
846                 case PADDING_STREAM :
847                 case DSM_CC_STREAM  :
848                 case ISO13522_STREAM:
849                 case PRIVATE_STREAM1:
850                 case AUDIO_STREAM_S ... AUDIO_STREAM_E:
851                 case VIDEO_STREAM_S ... VIDEO_STREAM_E:
852                         found = 1;
853                         break;
854                 }
855                 if (found){
856                         return PES_STREAM;
857                 }
858         }
859
860         
861
862         return -1;
863 }
864
865
866 void analyze(istream &fin)
867 {
868         PS_Packet ps;
869         PES_Packet pes;
870         int fc = 0;
871         char *frames[3] = {"I-Frame","P-Frame","B-Frame"};
872                         
873         while(fin){
874                 uint32_t pts;
875                 fin >> ps;
876                 cerr << "SCR base: " << hex << setw(5) 
877                      << setfill('0') \
878                      << ps.SCR_base() << " " << dec
879                      << "ext : " << ps.SCR_ext();
880
881                 cerr << "   MUX rate: " << ps.MUX()*50*8/1000000.0
882                      << " Mbit/s   ";
883                 cerr << "RATE bound: " << ps.Rate()*50*8/1000000.0
884                      << " Mbit/s" << endl;
885                 cerr << "                             Audio bound: " 
886                      << hex << "0x" 
887                      << int(ps.P()->audio_bound);
888                 cerr << "         Video bound: " << hex << "0x" 
889                      << int(ps.P()->video_bound)
890                      << dec
891                      << endl;
892                 cerr << endl;
893
894                 for (int i=0; i < ps.NPES(); i++){
895                         pes.init();
896                         fin >> pes;
897                         pts2pts((uint8_t *)&pts,pes.PTS());
898                         pes.Info() = 1;
899                         cerr  << pes;
900
901                         uint8_t *buf = pes.P()->pes_pckt_data;
902                         int c = 0;
903                         int l;
904                         switch (pes.P()->stream_id){
905                         case VIDEO_STREAM_S ... VIDEO_STREAM_E:
906                                 l=pes.P()->length;
907                                 break;
908                         default:
909                                 l = 0;
910                                 break;
911                         }
912                         while ( c < l - 6){
913                                 if (buf[c] == 0x00 && 
914                                     buf[c+1] == 0x00 &&
915                                     buf[c+2] == 0x01 && 
916                                     buf[c+3] == 0xB8) {
917                                         c += 4;
918                                         cerr << "TIME   hours: " 
919                                              << int((buf[c]>>2)& 0x1F)
920                                              << "  minutes: "
921                                              << int(((buf[c]<<4)& 0x30)|
922                                                     ((buf[c+1]>>4)& 0x0F))
923                                              << " seconds: "
924                                              << int(((buf[c+1]<<3)& 0x38)|
925                                                     ((buf[c+2]>>5)& 0x0F))
926                                              << endl;
927                                 }
928                                 
929                                 if ( buf[c] == 0x00 && 
930                                      buf[c+1] == 0x00 &&
931                                      buf[c+2] == 0x01 && 
932                                      buf[c+3] == 0x00) {
933                                         fc++;
934                                         c += 4;
935                                         cerr << "picture: " 
936                                              << fc 
937                                              << " ("
938                                              << frames[((buf[c+1]&0x38) >>3)-1]
939                                              << ")" << endl << endl;
940                                 } else c++;
941                         }
942                 }
943         }
944 }
945
946