2 * dvb-mpegtools for the Siemens Fujitsu DVB PCI card
4 * Copyright (C) 2000, 2001 Marcus Metzler
5 * for convergence integrated media GmbH
6 * Copyright (C) 2002 Marcus Metzler
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.
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.
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
26 * The author can be reached at mocm@metzlerbros.de
29 #include "cpptools.hh"
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
38 #define MAX_SEARCH 1024 * 1024
40 ostream & operator << (ostream & stream, PES_Packet & x){
43 cerr << "PES Packet: " ;
44 switch ( x.p.stream_id ) {
47 cerr << "Program Stream Map";
50 cerr << "Private Stream 2";
53 cerr << "Program Stream Directory";
62 cerr << "Padding Stream";
68 cerr << "ISO13522 Stream";
71 cerr << "Private Stream 1";
73 case AUDIO_STREAM_S ... AUDIO_STREAM_E:
74 cerr << "Audio Stream " << HEX(x.p.stream_id);
76 case VIDEO_STREAM_S ... VIDEO_STREAM_E:
77 cerr << "Video Stream " << HEX(x.p.stream_id);
81 cerr << " MPEG" << x.p.mpeg << endl;
85 if (x.p.flags1 & SCRAMBLE_FLAGS){
87 cerr << ((x.p.flags1 & SCRAMBLE_FLAGS)>>4);
90 if (x.p.flags1 & PRIORITY_FLAG)
92 if (x.p.flags1 & DATA_ALIGN_FLAG)
93 cerr << " DATA_ALIGN";
94 if (x.p.flags1 & COPYRIGHT_FLAG)
96 if (x.p.flags1 & ORIGINAL_FLAG)
99 if (x.p.flags2 & PTS_DTS_FLAGS){
101 cerr << ((x.p.flags2 & PTS_DTS_FLAGS)>>6);
104 if (x.p.flags2 & ESCR_FLAG)
106 if (x.p.flags2 & ES_RATE_FLAG)
108 if (x.p.flags2 & DSM_TRICK_FLAG)
109 cerr << " DSM_TRICK";
110 if (x.p.flags2 & ADD_CPY_FLAG)
112 if (x.p.flags2 & PES_CRC_FLAG)
114 if (x.p.flags2 & PES_EXT_FLAG)
119 if ((x.p.flags2 & PTS_DTS_FLAGS) == PTS_ONLY)
121 << LHEX(ntohl(x.WPTS()),8)
122 << "(h" << int(x.high_pts()) << ")"
124 else if ((x.p.flags2 & PTS_DTS_FLAGS) == PTS_DTS){
126 << LHEX(ntohl(x.WPTS()),8)
127 << "(h" << int(x.high_pts()) << ")";
129 << LHEX(ntohl(x.WDTS()),8)
130 << "(h" << int(x.high_dts()) << ")"
134 if (x.p.flags2 & ESCR_FLAG)
137 if (x.p.flags2 & ES_RATE_FLAG)
140 if (x.p.flags2 & DSM_TRICK_FLAG)
143 if (x.p.flags2 & ADD_CPY_FLAG)
146 if (x.p.flags2 & PES_CRC_FLAG)
149 if (x.p.flags2 & PES_EXT_FLAG){
151 if (x.p.priv_flags & PRIVATE_DATA)
152 stream.write(x.p.pes_priv_data,16);
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);
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);
167 if ( x.p.priv_flags & P_STD_BUFFER)
168 stream.write(x.p.p_std,2);
170 if ( x.p.priv_flags & PES_EXT_FLAG2){
171 stream.write(&x.p.pes_ext_lngth,1);
173 uint8_t[x.p.pes_ext_lngth];
174 stream.write(x.p.pes_ext,
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) ==
183 stream.write(x.p.pts,5);
184 stream.write(x.p.dts,5);
188 cerr << endl << endl;
192 int l = x.p.length+x.p.pes_hlength+9;
194 int length = cwrite_pes(buf,&(x.p),l);
195 stream.write((char *)buf,length);
200 static unsigned int find_length(istream & stream){
207 start = stream.tellg();
210 while ( !stream.eof() && !found ){
212 stream.read((char *)&sync4,4);
213 if (sync4[0] == 0x00 && sync4[1] == 0x00 && sync4[2] == 0x01) {
214 switch ( sync4[3] ) {
216 case PROG_STREAM_MAP:
217 case PRIVATE_STREAM2:
218 case PROG_STREAM_DIR:
221 case PADDING_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:
236 stream.seekg(streampos(2)+start);
237 if (found) return (unsigned int)(q-start)-4-2;
238 else return (unsigned int)(q-start)-2;
242 istream & operator >> (istream & stream, PES_Packet & x){
249 while (!stream.eof() && !found) {
251 stream.read((char *)&sync4,4);
252 if (sync4[0] == 0x00 && sync4[1] == 0x00 && sync4[2] == 0x01) {
253 x.p.stream_id = sync4[3];
255 switch ( sync4[3] ) {
257 case PROG_STREAM_MAP:
258 case PRIVATE_STREAM2:
259 case PROG_STREAM_DIR:
263 stream.read((char *)x.p.llength,2);
266 x.p.length = find_length(stream);
269 stream.read((char *)x.p.pes_pckt_data,x.p.length);
272 case PADDING_STREAM :
274 stream.read((char *)x.p.llength,2);
277 x.p.length = find_length(stream);
280 x.p.padding = x.p.length;
281 stream.read((char *)x.p.pes_pckt_data,x.p.length);
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);
293 x.p.length = find_length(stream);
300 stream.seekg(p+streampos(1));
303 } else stream.seekg(p+streampos(1));
306 if ( found && !done) {
308 stream.read((char *)&x.p.flags1,1);
309 if ( (x.p.flags1 & 0xC0) == 0x80 )
313 if ( x.p.mpeg == 2 ){
314 stream.read((char *)&x.p.flags2,1);
315 stream.read((char *)&x.p.pes_hlength,1);
317 if ((int)x.p.length > x.p.pes_hlength+3)
318 x.p.length -=x.p.pes_hlength+3;
322 uint8_t count = x.p.pes_hlength;
324 if ((x.p.flags2 & PTS_DTS_FLAGS) == PTS_ONLY){
325 stream.read((char *)x.p.pts,5);
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);
334 if (x.p.flags2 & ESCR_FLAG){
335 stream.read((char *)x.p.escr,6);
339 if (x.p.flags2 & ES_RATE_FLAG){
340 stream.read((char *)x.p.es_rate,3);
344 if (x.p.flags2 & DSM_TRICK_FLAG){
345 stream.read((char *)&x.p.trick,1);
349 if (x.p.flags2 & ADD_CPY_FLAG){
350 stream.read((char *)&x.p.add_cpy,1);
354 if (x.p.flags2 & PES_CRC_FLAG){
355 stream.read((char *)x.p.prev_pes_crc,2);
359 if (x.p.flags2 & PES_EXT_FLAG){
360 stream.read((char *)&x.p.priv_flags,1);
363 if (x.p.priv_flags & PRIVATE_DATA){
364 stream.read((char *)x.p.pes_priv_data,16);
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;
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);
383 if ( x.p.priv_flags & P_STD_BUFFER){
384 stream.read((char *)x.p.p_std,2);
388 if ( x.p.priv_flags & PES_EXT_FLAG2){
389 stream.read((char *)&x.p.pes_ext_lngth,1);
391 uint8_t[x.p.pes_ext_lngth];
392 stream.read((char *)x.p.pes_ext,
394 count -= 1+x.p.pes_ext_lngth;
397 x.p.stuffing = count;
399 for(int i = 0; i< count ;i++)
400 stream.read((char *)&dummy,1);
406 while (check == 0xFF){
407 stream.read((char *)&check,1);
411 if ( (check & 0xC0) == 0x40){
412 stream.read((char *)&check,1);
414 stream.read((char *)&check,1);
418 x.p.length -= x.p.mpeg1_pad;
421 if ( (check & 0x30)){
425 if (check == x.p.flags1){
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,
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);
439 x.p.pes_hlength += 5;
441 else if ((x.p.flags2 & PTS_DTS_FLAGS) ==
443 stream.read((char *)x.p.pts,5);
444 stream.read((char *)x.p.dts,5);
446 x.p.pes_hlength += 10;
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);
454 stream.read((char *)x.p.pes_pckt_data,x.p.length);
459 ostream & operator << (ostream & stream, TS_Packet & x){
461 uint8_t buf[TS_SIZE];
462 int length = cwrite_ts(buf,&(x.p),TS_SIZE);
463 stream.write((char *)buf,length);
468 istream & operator >> (istream & stream, TS_Packet & x){
474 while (!stream.eof() && !found) {
475 stream.read((char *)&sync,1);
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;
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);
490 if ( x.p.flags & ADAPT_FIELD ) {
492 stream.read((char *)&x.p.adapt_length,1);
493 if (x.p.adapt_length){
495 stream.read((char *)&x.p.adapt_flags,1);
497 if ( x.p.adapt_flags & PCR_FLAG )
498 stream.read((char *) x.p.pcr,6);
500 if ( x.p.adapt_flags & OPCR_FLAG )
501 stream.read((char *) x.p.opcr,6);
503 if ( x.p.adapt_flags & SPLICE_FLAG )
504 stream.read((char *) &x.p.splice_count,1);
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);
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);
518 if( x.p.adapt_eflags & PIECE_RATE)
519 stream.read((char *)x.p.piece_rate,3);
521 if( x.p.adapt_eflags & SEAM_SPLICE)
522 stream.read((char *)x.p.dts,5);
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);
531 stream.seekg(q+streampos(x.p.rest));
534 stream.read((char *)x.p.data, 183);
543 ostream & operator << (ostream & stream, PS_Packet & x){
546 int length = cwrite_ps(buf,&(x.p),PS_MAX);
547 stream.write((char *)buf,length);
552 istream & operator >> (istream & stream, PS_Packet & x){
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 )
565 else if ( headr[3] == 0xB9 ) break;
566 else stream.seekg(p+streampos(1));
571 stream.read((char *)x.p.scr,6);
572 if (x.p.scr[0] & 0x40)
578 stream.read((char *)x.p.mux_rate,3);
579 stream.read((char *)&x.p.stuff_length,1);
581 stream.seekg(p+streampos(x.p.stuff_length & 3));
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);
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);
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);
599 stream.read((char *)x.p.data,x.p.sheader_length);
602 x.p.sheader_length = 0;
611 stream.read((char *)headr,4);
613 if ( headr[0] == 0x00 && headr[1] == 0x00
614 && headr[2] == 0x01 && headr[3] != 0xBA){
619 } while (!stream.eof() && !done);
626 void extract_audio_from_PES(istream &in, ostream &out){
632 if (pes.Stream_ID() == 0xC0)
637 void extract_video_from_PES(istream &in, ostream &out){
643 if (pes.Stream_ID() == 0xE0)
648 void extract_es_audio_from_PES(istream &in, ostream &out){
654 if (pes.Stream_ID() == 0xC0)
655 out.write((char *)pes.Data(),pes.Length());
659 void extract_es_video_from_PES(istream &in, ostream &out){
665 if (pes.Stream_ID() == 0xE0)
666 out.write((char *)pes.Data(),pes.Length());
673 int TS_PIDS(istream &in, ostream &out){
678 for (int i=0 ; i<MAX_PID; i++)
685 for (j=0;j<npid;j++){
686 if ( ts.PID() == pid[j] )
690 out << ts.PID() << " ";
691 pid[npid] = ts.PID();
693 if (npid == MAX_PID) return -1;
700 int tv_norm(istream &stream){
709 while (!stream.eof() && !found) {
711 stream.read((char *)headr,4);
712 if (headr[0] == 0x00 && headr[1] == 0x00 && headr[2] == 0x01)
713 if ( headr[3] == 0xB3 ){
716 if (! found) stream.seekg(p+streampos(1));
718 stream.read((char *)headr,4);
720 hsize = (headr[1] &0xF0) >> 4 | headr[0] << 4;
721 vsize = (headr[1] &0x0F) << 8 | headr[2];
722 cerr << "SIZE: " << hsize << "x" << vsize << endl;
724 switch(((headr[3]&0xF0) >>4)){
726 cerr << "ASPECT: 1:1" << endl;
729 cerr << "ASPECT: 4:3" << endl;
732 cerr << "ASPECT: 16:9" << endl;
735 cerr << "ASPECT: 2.21:1" << endl;
739 switch (int(headr[3]&0x0F)){
741 cerr << "FRAMERATE: 23.976" << endl;
745 cerr << "FRAMERATE: 24" << endl;
749 cerr << "FRAMERATE: 25" << endl;
753 cerr << "FRAMERATE: 29.97" << endl;
757 cerr << "FRAMERATE: 30" << endl;
761 cerr << "FRAMERATE: 50" << endl;
765 cerr << "FRAMERATE: 59.94" << endl;
769 cerr << "FRAMERATE: 60" << endl;
776 while (!stream.eof() && !found) {
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",
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:"};
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;
799 if (! found) stream.seekg(p+streampos(1));
803 return (form | mpeg << 4);
808 int stream_type(istream &fin){
810 streampos p=fin.tellg();
814 fin.read((char *)headr,1);
816 if(fin && headr[0] == 0x47){
823 for(int j=0;j < ps.NPES();j++){
826 fin.read((char *)headr,4);
828 if (fin && headr[0] == 0x00 && headr[1] == 0x00
829 && headr[2] == 0x01 && headr[3] == 0xBA){
834 fin.read((char *)!headr,4);
836 if (fin && headr[0] == 0x00 && headr[1] == 0x00
837 && headr[2] == 0x01 ){
839 switch ( headr[3] ) {
841 case PROG_STREAM_MAP:
842 case PRIVATE_STREAM2:
843 case PROG_STREAM_DIR:
846 case PADDING_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:
866 void analyze(istream &fin)
871 char *frames[3] = {"I-Frame","P-Frame","B-Frame"};
876 cerr << "SCR base: " << hex << setw(5)
878 << ps.SCR_base() << " " << dec
879 << "ext : " << ps.SCR_ext();
881 cerr << " MUX rate: " << ps.MUX()*50*8/1000000.0
883 cerr << "RATE bound: " << ps.Rate()*50*8/1000000.0
884 << " Mbit/s" << endl;
885 cerr << " Audio bound: "
887 << int(ps.P()->audio_bound);
888 cerr << " Video bound: " << hex << "0x"
889 << int(ps.P()->video_bound)
894 for (int i=0; i < ps.NPES(); i++){
897 pts2pts((uint8_t *)&pts,pes.PTS());
901 uint8_t *buf = pes.P()->pes_pckt_data;
904 switch (pes.P()->stream_id){
905 case VIDEO_STREAM_S ... VIDEO_STREAM_E:
913 if (buf[c] == 0x00 &&
918 cerr << "TIME hours: "
919 << int((buf[c]>>2)& 0x1F)
921 << int(((buf[c]<<4)& 0x30)|
922 ((buf[c+1]>>4)& 0x0F))
924 << int(((buf[c+1]<<3)& 0x38)|
925 ((buf[c+2]>>5)& 0x0F))
929 if ( buf[c] == 0x00 &&
938 << frames[((buf[c+1]&0x38) >>3)-1]
939 << ")" << endl << endl;