mpeg2demux.cc
上传用户:aoeyumen
上传日期:2007-01-06
资源大小:3329k
文件大小:23k
- /*
- File: mpeg2demux.cc
- Description:
- The MPEG 2 demultiplexer class reads MPEG 2 TS, PS and PES data
- and demultiplexes a Transport Stream or Program Stream in its
- Packetized Elementary Streams. Elementary Streams are just passed
- through.
- Created: February 1996, Alex Theo de Jong, NIST
- */
- #include "athread.hh"
- #include <stdio.h>
- #include <stdlib.h>
- #include <String.h>
- #include <fstream.h>
- #include <sys/errno.h>
- #ifdef IRIX
- #include <dmedia/audio.h>
- #endif
- #ifdef SOLARIS
- #include <sys/audioio.h>
- #endif
- // network stuff
- #include <sys/types.h>
- #include <sys/uio.h>
- #include <unistd.h>
- #include <errno.h>
- #include "error.hh"
- #include "debug.hh"
- #include "util.hh"
- #include "sync.hh"
- #include "mpeg2const.hh"
- #include "mpeg2buff.hh"
- #include "mpeg2audio.hh"
- #include "mpeg2video.hh"
- #include "mpeg2demux.hh"
- #include "network.hh"
- // Options for Audio and Video player
- extern int audio_argc;
- extern char** audio_argv;
- extern int video_argc;
- extern char** video_argv;
- extern int time_stamp_qsize;
- extern int frame_stamp_qsize;
- extern int audio_buffer_size;
- extern int video_buffer_size;
- // Input socket
- extern SocketMulti* sock;
- #ifdef TRACE
- Mpeg2Buffer* ab=0;
- Mpeg2Buffer* vb=0;
- Synchronization* ds=0;
- #endif
- #define DELIMITER 0x001B8
- /*
- *
- * De-multiplexor
- *
- */
- Mpeg2Demux::Mpeg2Demux(int pdu_size, int sel_vstream, int sel_astream, int a_on, int v_on, int s_on, int q) :
- pes_audio_bytes(0),
- pes_video_bytes(0),
- pes_audio_time(0.0),
- pes_video_time(0.0),
- audio_on(a_on),
- video_on(v_on),
- sync_on(s_on),
- quiet(q),
- vstream(sel_vstream),
- astream(sel_astream)
- {
- audio_buffer=new Mpeg2Buffer(audio_buffer_size);
- video_buffer=new Mpeg2Buffer(video_buffer_size);
- #ifdef TRACE
- ::ab=audio_buffer;
- ::vb=video_buffer;
- #endif
- aalpdu_size=pdu_size;
- aalpdu=new unsigned char[aalpdu_size+1];
- aalpdu_max=aalpdu+aalpdu_size;
- // input counters
- bytecount=0;
- byteptr=0;
- pdu_mpeg_packet=aalpdu_max; // set to max for proper init
- // MPEG packet counters
- counter=0;
- transport_packets=0;
- transport_packet_errors=0;
- sync_byte_errors=0;
- lost_packets=0;
- adaptation_fields=0;
- program_association_tables=0;
- pes_packets=0;
- psi_packets=0;
- audio_packets=0;
- video_packets=0;
- // transport packet header information
- transport_error_indicator=0;
- payload_unit_start_indicator=0;
- pid=0;
- audio_pid=-1;
- video_pid=-1;
- adaptation_field_control=0;
- audio=0;
- video=0;
- sync=0;
- int err;
- #ifdef EOFEXIT
- Mpeg2Demux::init(this);
- #else
- if ((err=athr_create((void*(*)(void*))Mpeg2Demux::init, this, &thread_id))<0){
- error("could not create thread");
- }
- sched_param param;
- int policy;
- if ((err=athr_getschedparam(thread_id, &policy, ¶m))<0){
- warning("could not get thread prio - ignored");
- }
- else {
- #ifdef LINUX
- param.sched_priority+=1;
- // policy = SCHED_RR;
- TRACER("TIMERPRIORITY=" << param.sched_priority << "(" << param.sched_priority-1 << ")");
- #else
- param.prio+=1;
- TRACER("TIMERPRIORITY=" << param.prio << "(" << param.prio-1 << ")");
- #endif
- if ((err=athr_setschedparam(thread_id, policy, ¶m))<0){
- warning("could not set thread prio - ignored");
- }
- }
- // TRACER("DEMUXPRIORITY=" << param.prio);
- #endif
- terminated=0;
- }
- Mpeg2Demux::~Mpeg2Demux(){
- TRACER("Mpeg2Demux::~Mpeg2Demux()");
- if (!terminated){ // check if thread is still alive
- TRACER("waiting for demux thread to terminate ...");
- athr_join(thread_id);
- }
- TRACER("delete video ...");
- delete video;
- TRACER("video deletedndelete audio ...");
- delete audio;
- TRACER("audio deletedndelete sync ...");
- delete sync;
- TRACER("sync deletedndemux deleted");
- delete aalpdu;
- delete audio_buffer;
- delete video_buffer;
- }
- int Mpeg2Demux::stop(){
- terminate=1;
- if (!terminated){ // check to see if thread is available
- athr_join(thread_id);
- gettimeofday(&tstop,(struct timezone *)NULL);
- int runtime = 1000*(tstop.tv_sec-tstart.tv_sec) + (tstop.tv_usec-tstart.tv_usec)/1000;
- msg("Bitrate: ");
- msg(dtoa(counter*MPEG2_TS_Packet_size*8/runtime));
- message(" Kbps");
- }
- return terminated;
- }
- void* Mpeg2Demux::init(Mpeg2Demux* base){
- TRACER("void* Mpeg2Demux::init(Mpeg2Demux* base)");
- base->terminate=0;
- base->terminated=0;
- if (base->sync_on){
- if (base->video_on && base->audio_on)
- base->sync=new Synchronization(0, time_stamp_qsize, frame_stamp_qsize); // sync video/audio
- if (base->video_on && !base->audio_on)
- base->sync=new Synchronization(1, time_stamp_qsize, frame_stamp_qsize); // just video
- if (!base->video_on && base->audio_on)
- base->sync=new Synchronization(2, time_stamp_qsize, frame_stamp_qsize); // just audio
- }
- else base->sync=0;
- if (base->video_on)
- base->video=new Mpeg2Video(base->video_buffer, base->sync, video_argc, video_argv);
- else base->video=0;
- if (base->audio_on)
- base->audio=new Mpeg2Audio(base->audio_buffer, base->sync, base->audio_on, audio_argc, audio_argv);
- else base->audio=0;
- // wait for network connection or file to be ready!
- sock->accept();
- if (0){
- error("could not receive connection!");
- athr_exit(0);
- }
- if (base->nextpacket()<=0){ // init first pdu
- error("could not read first packet");
- athr_exit(0);
- }
- unsigned int bits=base->nextbits32();
- gettimeofday(&base->tstart,(struct timezone *)NULL);
- if (((bits >> 24) & 0xff)==Sync_byte){
- message("Playing MPEG 2 TS Audio/Video");
- #ifdef TRACE
- ::ds=base->sync;
- #endif
- base->transport_stream();
- }
- else if (bits == Pack_start_code){
- // Create players and start
- message("Playing MPEG 2 PS Audio/Video");
- base->program_stream();
- }
- else if (base->audio_on && (bits & 0xfff00000)==0xfff00000){ // just plain audio
- message("Playing MPEG 2 PES Audio");
- base->pes_stream_audio();
- }
- else if (base->video_on && bits==Sequence_start_code){ // just video
- message("Playing MPEG 2 PES Video");
- base->pes_stream_video();
- }
- else error("Stream is not valid MPEG 2 Stream (TS, PS, Audio ES, Video ES)");
- base->stop();
- base->terminated=1;
- TRACER("demux thread done");
- #ifdef EOFEXIT
- exit(0); // stop everything right here (after EOF!)
- #else
- athr_exit(0);
- #endif
- return 0;
- }
- int Mpeg2Demux::copybytes(Mpeg2Buffer* output, int length){
- if (bytecount+length>MPEG2_TS_Packet_size){
- warning("copying bytes beyond transport packet length");
- length=MPEG2_TS_Packet_size-bytecount;
- }
- if (output->write(byteptr, length)!=length){
- error("failed to copy input to output"); // write to output
- }
- bytecount+=length;
- byteptr+=length;
- return length;
- }
- int Mpeg2Demux::skipbytes(int length){
- int i = length;
- while(i--)
- getbits8();
- return length;
- if (bytecount+length>MPEG2_TS_Packet_size){
- warning("skipping bytes beyond transport packet length");
- length=MPEG2_TS_Packet_size - bytecount;
- }
- bytecount+=length;
- byteptr+=length;
- return length;
- }
- int Mpeg2Demux::copy_ps_bytes(Mpeg2Buffer* output, unsigned int *header,int len){
- unsigned char c;
- // if (video_on == 2) {
- if (output->write(byteptr, len)!=len){
- error("failed to copy input to output"); // write to output
- }
- if (!nextpacket()) {
- *header = 0;
- return 1;
- }
- *header = getbits32();
- #if 0
- }
- else {
- *header = getbits32();
- while ((*header <= DELIMITER) || (*header > 0x1ff)) {
- c = *header >> 24;
- *header = (*header << 8) | getbits8();
- if (output->write(&c, 1)!=1){
- error("failed to copy input to output"); // write to output
- }
- }
- }
- #endif
- return 0;
- }
- int Mpeg2Demux::skip_ps_bytes(unsigned int *header){
- // if (video_on==2) {
- if (!nextpacket()) {
- *header = 0;
- return 1;
- }
- *header = getbits32();
- return 0;
- #if 0
- }
- else {
- *header = getbits32();
- while ((*header <= DELIMITER) || (*header > 0x1ff)){
- *header = (*header << 8) | getbits8();
- }
- }
- #endif
- return 0;
- }
- int Mpeg2Demux::nextpacket(){
- DEBUGGER("int Mpeg2Demux::nextpacket()");
- if (pdu_mpeg_packet>=aalpdu_max){
- DEBUGGER("sock->recv()");
- if ((lastpdu_size=sock->recv(aalpdu, aalpdu_size))!=aalpdu_size){
- if (lastpdu_size==0){
-
- // if (audio_buffer)
- // while (audio_buffer->used() > 10000 ) sleep(1);
- // if (video_buffer)
- // while (video_buffer->used() > 30000 ) sleep(1);
- sleep(1);
- terminate=1;
- if (sync) sync->stop();
- if (audio) audio->stop();
- if (video) video->stop();
- sleep(1);
- if (sync) sync->stop();
- TRACER("EOF!");
- return 0; // eof
- }
- error("invalid pdu size (" << itoa(lastpdu_size) << ")");
- return -1;
- }
- byteptr=pdu_mpeg_packet=aalpdu;
- pdu_mpeg_packet+=MPEG2_TS_Packet_size;
- bytecount=0;
- }
- else {
- byteptr=pdu_mpeg_packet;
- pdu_mpeg_packet+=MPEG2_TS_Packet_size;
- bytecount=0;
- }
- return 1;
- }
- /*
- *
- * Mpeg Transport Stream
- *
- */
- int Mpeg2Demux::transport_stream(){
- do {
- counter++;
- if (!get_transport_packet()){
- if (!quiet){
- String err("incorrect packet ");
- err+=itoa(counter);
- error(err.chars());
- }
- }
- if (!quiet){
- if ((counter % 100)==0) msg(".");
- if ((counter % 5000)==0){
- message(itoa(counter));
- athr_yield();
- }
- }
- if (terminate){
- if ((!sync || sync->stop()) && (!audio || audio->stop()) && (!video || video->stop()))
- break; // continue until all threads terminated
- }
- }
- while (nextpacket());
- TRACER("closing audio buffer ...");
- audio_buffer->close();
- TRACER("closed audio buffernclosing video buffer ...");
- video_buffer->close();
- TRACER("closed video buffer");
- file.close();
- return (counter==0) ? 0 : 1;
- }
- int Mpeg2Demux::get_transport_packet(){
- if (get_sync_byte()){ // align with sync
- transport_packets++;
- unsigned int bits=(getbits24() & 0x0000ffff); // drop sync byte
- // printf("First 2 bytes: %dn", bits);
- // exit(0);
- transport_error_indicator=bits >> 15;
- payload_unit_start_indicator=(bits >> 14) & 1;
- pid=bits & 0x00001fff;
- transport_scrambling_control=(nextbits8() >> 6)&0x3;
- adaptation_field_control=(nextbits8() >> 4)&0x3;
- continuity_counter=(getbits8()&0xf);
- if (transport_error_indicator){
- transport_packet_errors++;
- return 0; // error set!
- }
- if (pid==0x1fff){
- return 1; // padding; just go to next
- }
- int i;
- for (i=0; pidtable[i]!=0 && pid!=pidtable[i]; i++); // get pid
- if (pidtable[i]==0){ // not in table yet
- pidtable[i]=pid;
- continuity_counters[i]=continuity_counter; // init
- pidtable[i+1]=0;
- }
-
- if (pid!=(int)Program_Association_Table && pid!=(int)Conditional_Access_Table
- && (adaptation_field_control==1 || adaptation_field_control==3)){
- // Check counters
- if (continuity_counters[i]!=continuity_counter){
- if (!quiet){
- String err("lost MPEG ");
- err+=itoa(continuity_counter-continuity_counters[i]);
- err+=" packet(s)";
- error(err.chars());
- }
- continuity_counters[i]=continuity_counter; // reset
- lost_packets++;
- }
- if (++continuity_counters[i]>15) continuity_counters[i]=0;
- }
- if (adaptation_field_control==2 || adaptation_field_control==3)
- get_adaptation_field();
- if (adaptation_field_control==1 || adaptation_field_control==3)
- get_payload();
- }
- else {
- sync_byte_errors++;
- return 0;
- }
- return 1;
- }
- int Mpeg2Demux::get_adaptation_field(){
- adaptation_fields++;
- int length=getbits8(); // get adaptation field length
- // int discontinuity_indicator=(nextbits8() >> 7);
- // int random_access_indicator=(nextbits8() >> 6) & 1;
- // int elem_prio_indicator=(nextbits8() >> 5) & 1; // not used at this point;
- int pcr_flag=(getbits8() >> 4) & 1; // get first byte
- if (pcr_flag){
- unsigned long clk_ref_base=getbits32();
- unsigned int clk_ref_ext=getbits16();
- if (clk_ref_base>0x7fffffff){ // correct for invalid numbers
- clk_ref_base=0; // ie. longer than 32 bits when multiplied by 2
- clk_ref_ext=0; // multiplied by 2 corresponds to shift left 1 (<<=1)
- }
- else {
- clk_ref_base<<=1; // Create space for bit
- clk_ref_base|=(clk_ref_ext >> 15); // Take bit
- clk_ref_ext&=0x01ff; // Only lower 9 bits
- }
-
- double time=clk_ref_base + clk_ref_ext/300;
- TRACER("Time: " << dtoa(time));
- if (sync) sync->put(time); // id=0, Timer
- if (length) skipbytes(length - 7);
- }
- else skipbytes(length - 1);
- return 1;
- }
- int Mpeg2Demux::get_payload(){
- if (payload_unit_start_indicator){
- if (pid==0) get_program_association_table();
- else if (nextbits24()==Packet_start_code_prefix) get_pes_packet();
- else skipbytes(MPEG2_TS_Packet_size - bytecount); // get_psi_packet();
- }
- else {
- if (pid==audio_pid) get_audio_data();
- else if (pid==video_pid) get_video_data();
- else skipbytes(MPEG2_TS_Packet_size - bytecount);
- }
- return 1;
- }
- int Mpeg2Demux::get_program_association_table(){
- program_association_tables++;
- table_id=getbits8();
- section_length=getbits16() & 0xfff; // last 12 bits
- transport_stream_id=getbits16();
-
- skipbytes(MPEG2_TS_Packet_size-bytecount);
- /*
- for (int i=0; i<section_length-9; i+=4) getbits32();
- i-=4;
- if ((i+9)>(MPEG2_TS_Packet_size-4)) error("too many bytes in program association table");
- */
- return 1;
- }
- int Mpeg2Demux::get_pes_packet_data(int stream_id){
- unsigned long pts(0), dts(0);
- if ((stream_id >> 4)==12 || (stream_id >> 4)==13){
- // Just pick the first available stream if no ID is set
- if (astream==-1)
- astream=(stream_id & 0x0f);
- if ((stream_id & 0x0f)==astream && audio_on){
- if (sync && pes_audio_bytes){
- TRACER("AudioTime: " << dtoa(pes_audio_time) << " " << itoa(pes_audio_bytes));
- sync->put(2, pes_audio_time, pes_audio_bytes); // id=2, Audio
- pes_audio_time=0;
- pes_audio_bytes=0;
- }
- get_pes_packet_header(pts, dts);
- pes_audio_time=pts;
- audio_pid=pid;
- return get_audio_data();
- }
- }
- else if ((stream_id >> 4)==14){
- // Just pick the first available stream if no ID is set
- if (vstream==-1)
- vstream=(stream_id & 0x0f);
- if ((stream_id & 0x0f)==vstream && video_on){
- if (sync && pes_video_bytes){
- TRACER("VideoTime: " << dtoa(pes_video_time) << " " << itoa(pes_video_bytes));
- sync->put(1, pes_video_time, pes_video_bytes); // id=1, Video
- pes_video_time=0;
- pes_video_bytes=0;
- }
- get_pes_packet_header(pts, dts);
- pes_video_time=pts;
- video_pid=pid;
- return get_video_data();
- }
- }
- else {
- return get_unknown_data();
- }
- skipbytes(MPEG2_TS_Packet_size - bytecount);
- return 1;
- }
- int Mpeg2Demux::get_pes_packet_header(unsigned long& pts, unsigned long& dts){
- unsigned int pes_header_bytes(0);
- getbits8(); // drop first 8 bits
- short PTS_DTS_flags=(getbits8() >> 6) & 0x3;
- int PES_header_data_length=getbits8();
- // Get Presentation Time stamps and Decoding Time Stamps
- if (PTS_DTS_flags==2){
- pts=(getbits8() >> 1) & 7; // Only low 4 bits (7==1111)
- pts<<=15;
- pts|=(getbits16() >> 1);
- pts<<=15;
- pts|=(getbits16() >> 1);
- pes_header_bytes+=5;
- }
- else if (PTS_DTS_flags==3){
- pts=(getbits8() >> 1) & 7; // Only low 4 bits (7==1111)
- pts<<=15;
- pts|=(getbits16() >> 1);
- pts<<=15;
- pts|=(getbits16() >> 1);
- dts=(getbits8() >> 1) & 7; // Only low 4 bits (7==1111)
- dts<<=15;
- dts|=(getbits16() >> 1);
- dts<<=15;
- dts|=(getbits16() >> 1);
- pes_header_bytes+=10;
- }
- // extract other stuff here!
-
- skipbytes(PES_header_data_length - pes_header_bytes);
- return 1;
- }
- int Mpeg2Demux::get_pes_packet(){
- pes_packets++;
- getbits24(); // skip startcode
- unsigned int stream_id=getbits8();
- // int pes_packet_length= // Not used at this point; just drop
- getbits16();
- if (stream_id!=Private_stream_2 && stream_id!=Padding_stream){
- return get_pes_packet_data(stream_id);
- }
- else if (stream_id==Private_stream_2){
- // Dump private data!
- error("private stream");
- skipbytes(MPEG2_TS_Packet_size - bytecount);
- }
- else if (stream_id==Padding_stream){
- skipbytes(MPEG2_TS_Packet_size - bytecount);
- // Nothing; the next search for a sync byte will just skip the stuffing bytes
- }
- else {
- error("unknown stream_id in pes packet");
- skipbytes(MPEG2_TS_Packet_size - bytecount);
- }
- return 1;
- }
- int Mpeg2Demux::get_psi_packet(){
- psi_packets++;
- table_id=getbits8();
- section_length=getbits16() & 0x0fff;
- skipbytes(MPEG2_TS_Packet_size - bytecount);
- return 1;
- }
- int Mpeg2Demux::get_audio_data(){
- audio_packets++;
- pes_audio_bytes+=copybytes(audio_buffer, MPEG2_TS_Packet_size - bytecount);
- return 1;
- }
- int Mpeg2Demux::get_video_data(){
- video_packets++;
- pes_video_bytes+=copybytes(video_buffer, MPEG2_TS_Packet_size - bytecount);
- return 1;
- }
- int Mpeg2Demux::get_unknown_data(){
- warning("unknown data in PSI or PES packet");
- return skipbytes(MPEG2_TS_Packet_size - bytecount);
- }
- /*
- *
- * MPEG Program Stream
- *
- */
- int Mpeg2Demux::program_stream(){
- if (!get_program_pack()){
- error("failure in programm pack");
- return 0;
- }
- audio_buffer->close();
- video_buffer->close();
- return 1;
- }
- int Mpeg2Demux::get_program_pack(){
- static unsigned int header;
- header = getbits32();
- while (1) {
- if (header == Pack_start_code) {
- get_pack_header(&header);
- }
- else if ((header >> 8) == Packet_start_code_prefix) {
- counter++;
- get_ps_pes_packet(&header);
- }
- else {
- return 0;
- }
- if (!quiet){
- if ((counter % 100)==0) msg(".");
- if ((counter % 5000)==0){
- message(itoa(counter));
- }
- }
-
- if (terminate){
- // if ((!sync || sync->stop()) && (!audio && audio->stop()) && (!video && video->stop()))
- break;
- }
- }
- return 1;
- }
- int Mpeg2Demux::get_ps_pes_packet(unsigned int *header){
- static unsigned long pts(0),dts(0);
- int PES_header_data_length;
- pes_packets++;
- int stream_id=*header & 0xff;
- unsigned int pes_packet_length=getbits16();
- if (stream_id!=(int)Private_stream_2 && stream_id!=(int)Padding_stream){
- pts = 0;
- if ((nextbits8() & 0xc0) == 0x40) {
- pes_packet_length -= 12;
- skipbytes(12);
- }
- else {
- int pes_header_bytes=0;
- int scrambling = (getbits8() >> 4 ) & 3;
- // if (scrambling) {
- // message("scrambled data");
- // skip_ps_bytes(header);
- // return 1;
- // }
- int PTS_DTS_flags=(getbits8() >> 6) & 0x3;
- PES_header_data_length=getbits8();
- // Get Presentation Time stamps and Decoding Time Stamps
- if (PTS_DTS_flags==2){
- pts=(getbits8() >> 1) & 7; // Only low 4 bits (7==1111)
- pts<<=15;
- pts|=(getbits16() >> 1);
- pts<<=15;
- pts|=(getbits16() >> 1);
- pes_header_bytes+=5;
- }
- else if (PTS_DTS_flags==3){
- pts=(getbits8() >> 1) & 7; // Only low 4 bits (7==1111)
- pts<<=15;
- pts|=(getbits16() >> 1);
- pts<<=15;
- pts|=(getbits16() >> 1);
- dts=(getbits8() >> 1) & 7; // Only low 4 bits (7==1111)
- dts<<=15;
- dts|=(getbits16() >> 1);
- dts<<=15;
- dts|=(getbits16() >> 1);
- pes_header_bytes+=10;
- }
- // extract other stuff here!
- pes_packet_length -=3;
- if (PES_header_data_length) {
- pes_packet_length -= PES_header_data_length;
- skipbytes (PES_header_data_length - pes_header_bytes);
- }
- }
- if ((stream_id >> 4)==12 || (stream_id >> 4)==13){
- if ((stream_id & 0x0f)== astream && audio_on==1){
- if (sync && pes_audio_bytes && pts ){
- TRACER("AudioTime: " << dtoa(pes_audio_time));
- sync->put(2, pes_audio_time, pes_audio_bytes); // id=2, Audio
- pes_audio_time=0;
- pes_audio_bytes=0;
-
- }
- if (pts)
- pes_audio_time=pts;
- pes_audio_bytes+=pes_packet_length;
- copy_ps_bytes(audio_buffer, header,pes_packet_length);
- }
- else {
- skip_ps_bytes(header);
- }
- }
- else if ((stream_id >> 4)==14){
- if ((stream_id & 0x0f)== vstream && video_on){
- if (sync && pes_video_bytes && pts){
- TRACER("VideoTime: " << dtoa(pes_video_time) << " " << itoa(pes_video_bytes));
- sync->put(1, pes_video_time,pes_video_bytes); // id=1, Video
- pes_video_time=0;
- pes_video_bytes=0;
- }
- if (pts)
- pes_video_time=pts;
- pes_video_bytes += pes_packet_length;
- copy_ps_bytes(video_buffer, header,pes_packet_length);
- }
- else {
- skip_ps_bytes(header);
- }
- }
- else if (stream_id == 0xbd){
- if ( (*byteptr == (0x80+astream) ) && audio_on==2){ /* AC-3 Data */
- if (sync && pes_audio_bytes && pts){
- TRACER("AudioTime: " << dtoa(pes_audio_time) << " " << itoa(pes_audio_bytes));
- sync->put(2, pes_audio_time, pes_audio_bytes); // id=2, Audio
- pes_audio_time=0;
- pes_audio_bytes=0;
- }
- if (pts)
- pes_audio_time=pts;
- pes_audio_bytes+=pes_packet_length-4;
- skipbytes(4);
- copy_ps_bytes(audio_buffer, header,pes_packet_length-4);
- }
- else {
- skip_ps_bytes(header);
- }
- }
- else if (stream_id == 0xbc){
- skip_ps_bytes(header);
- }
- else {
- skip_ps_bytes(header);
- }
- }
- else if (stream_id==(int)Private_stream_2){
- skip_ps_bytes(header);
- }
- else if (stream_id == (int)Padding_stream){
- skip_ps_bytes(header);
- }
- else error("unknown stream_id in pes packet");
- return 1;
- }
- int Mpeg2Demux::get_pack_header(unsigned int *header){
- static double old_time = 0.0;
- unsigned long i,j;
- unsigned long clock_ref,clock_ref_ext;
- i = getbits32();
- j = getbits16();
- if (i & 0x40000000) {
- clock_ref = ((i & 0x31000000) << 3);
- clock_ref |= ((i & 0x03fff800) << 4);
- clock_ref |= ((i & 0x000003ff) << 5);
- clock_ref |= ((j & 0xf800) >> 11);
- clock_ref_ext = (j >> 1) & 0x1ff;
- double time=clock_ref + clock_ref_ext/300;
- TRACER("Time: " << dtoa(time));
- if (sync && (old_time + 6000 < time)) {
- sync->put(time); // id=0, Timer
- old_time = time;
- }
-
- skipbytes(3);
- i = getbits8() & 0x7;
- while (i--)
- getbits8(); // stuffing
- }
- else
- skipbytes(2);
- *header = getbits32();
-
- if (*header == System_start_code) {
- get_system_header();
- *header = getbits32();
- }
- return 1;
- }
- int Mpeg2Demux::get_system_header(){
- int i;
- i = getbits16(); // get length
- while (i--)
- getbits8();
- return 1;
- }
- /*
- * Packetized Elementary Stream (PES)
- */
- int Mpeg2Demux::pes_stream_audio(){
- do {
- counter++;
- get_audio_data();
- if (!quiet){
- if ((counter % 100)==0) msg(".");
- if ((counter % 5000)==0){
- message(itoa(counter));
- }
- }
- }
- while (nextpacket());
- audio_buffer->close();
- return 1;
- }
-
- int Mpeg2Demux::pes_stream_video(){
- do {
- counter++;
- get_video_data();
- if (!quiet){
- if ((counter % 100)==0) msg(".");
- if ((counter % 5000)==0){
- message(itoa(counter));
- }
- }
- }
- while (nextpacket());
- video_buffer->close();
- return 1;
- }