From 183ad84a8e2feb6be3d845d50a1477fae9f57adf Mon Sep 17 00:00:00 2001 From: Mark Calderbank Date: Sat, 11 Aug 2007 16:30:16 +0000 Subject: [PATCH] Demuxer/stream changes, phase I: Make PESPacket independent from Demuxer --- demuxer.cc | 351 ++++++++++++++++++++++++++------------------------ demuxer.h | 125 +++++++++--------- demuxerts.cc | 33 ++++- demuxerts.h | 3 +- demuxervdr.cc | 58 +++++---- demuxervdr.h | 12 +- 6 files changed, 315 insertions(+), 267 deletions(-) diff --git a/demuxer.cc b/demuxer.cc index e925834..5054dfb 100644 --- a/demuxer.cc +++ b/demuxer.cc @@ -1,5 +1,6 @@ /* - Copyright 2005-2006 Mark Calderbank + Copyright 2005-2007 Mark Calderbank + Copyright 2007 Marten Richter (AC3 support) This file is part of VOMP. @@ -27,21 +28,116 @@ #define __BYTE_ORDER __LITTLE_ENDIAN #endif -#if __BYTE_ORDER == __BIG_ENDIAN #define DEMUXER_SEQ_HEAD 0x000001B3 -#else -#define DEMUXER_SEQ_HEAD 0xB3010000 -#endif - #define DEMUXER_PIC_HEAD 0x00000101 #define SEEK_THRESHOLD 150000 // About 1.5 seconds +// Statics const int Demuxer::FrameRates[9] = { 0, 23, 24, 25, 29, 30, 50, 59, 60 }; -const ULLONG Demuxer::PESPacket::PTS_INVALID = (1LL << 33); - +const ULLONG PESPacket::PTS_INVALID = (1LL << 33); Demuxer* Demuxer::instance = NULL; +// PESPacket methods +PESPacket::PESPacket() +{ + data[0] = 0x00; + data[1] = 0x00; + data[2] = 0x01; + init(0); +} + +void PESPacket::init(UCHAR type) +{ + length = 0; size = 6; + data[3] = type; + data[4] = data[5] = 0; + packetType = type; + pts = PTS_INVALID; + seq_header = 1; // Unknown seq_header status +} + +void PESPacket::truncate() +{ + init(packetType); +} + +int PESPacket::write(UCHAR *buf, int len) +{ + if (length + len > 0xFFFA) return 0; + memcpy(data+length+6, buf, len); + length += len; + size += len; + data[4] = (length >> 8); + data[5] = (length & 0xFF); + // We have added data - reset seq_header indicator if necessary + if (seq_header == 0) seq_header = 1; // Reset to 'unknown' + // Extract PTS if this is the first write to reach 14 bytes + if (size - len < 14 && size >= 14 && data[7] & 0x80 && + ( (packetType >= Demuxer::PESTYPE_AUD0 && + packetType <= Demuxer::PESTYPE_AUDMAX) + || + (packetType >= Demuxer::PESTYPE_VID0 && + packetType <= Demuxer::PESTYPE_VIDMAX) + )) + { + // 14 bytes are now in, and PTS_DTS_flags indicate PTS + pts = ( (ULLONG)(data[ 9] & 0x0E) << 29 ) | + ( (ULLONG)(data[10]) << 22 ) | + ( (ULLONG)(data[11] & 0xFE) << 14 ) | + ( (ULLONG)(data[12]) << 7 ) | + ( (ULLONG)(data[13] & 0xFE) >> 1 ); + } + return 1; +} + +UCHAR PESPacket::operator[] (UINT index) +{ + if (index >= size) + return 0; + else + return data[index]; +} + +UINT PESPacket::findPictureHeader() +{ + if (size < 12) return 0; + UINT pattern = ( ((UINT)data[ 8] << 24) | + ((UINT)data[ 9] << 16) | + ((UINT)data[10] << 8) | + (UINT)data[11] ); + UINT pos = 11; + while (pattern != DEMUXER_PIC_HEAD) + { + if (++pos >= size) return 0; + pattern = (pattern << 8) | data[pos]; + } + return pos-3; +} + +UINT PESPacket::findSeqHeader() +{ + if (seq_header != 1) return seq_header; + if (size < 12) return 0; + UINT pattern = ( ((UINT)data[ 8] << 24) | + ((UINT)data[ 9] << 16) | + ((UINT)data[10] << 8) | + (UINT)data[11] ); + UINT pos = 11; + while (pattern != DEMUXER_SEQ_HEAD) + { + if (++pos >= size) + { + seq_header = 0; + return 0; + } + pattern = (pattern << 8) | data[pos]; + } + seq_header = pos - 3; + return seq_header; +} + +// Demuxer methods Demuxer::Demuxer() { if (instance) return; @@ -166,136 +262,89 @@ bool Demuxer::writeVideo() return videostream.drain(); } -Demuxer::PESPacket::PESPacket() -{ - data[0] = 0x00; - data[1] = 0x00; - data[2] = 0x01; - init(0); -} - -void Demuxer::PESPacket::init(UCHAR type) -{ - length = submitted = 0; - size = 6; closed = false; - data[3] = type; - data[4] = data[5] = 0; - packetType = type; - pts = PTS_INVALID; - seq_header = false; -} - -void Demuxer::PESPacket::truncate() -{ - init(packetType); -} - -int Demuxer::PESPacket::write(UCHAR *buf, int len) -{ - if (closed) return 0; - if (length + len > 0xFFFA) return 0; - memcpy(data+length+6, buf, len); - length += len; - size += len; - data[4] = (length >> 8); - data[5] = (length & 0xFF); - return 1; -} - -int Demuxer::PESPacket::submit() +bool Demuxer::submitPacket(PESPacket& packet) { - if (submitted >= size) return 0; - if (!closed) parseDetails(); + UINT sent = 0; + UCHAR packet_type = packet.getPacketType(); - closed = true; - Demuxer* dx = Demuxer::getInstance(); - int sent = 0; - if (packetType >= PESTYPE_VID0 && packetType <= PESTYPE_VIDMAX) + if (packet_type >= PESTYPE_VID0 && packet_type <= PESTYPE_VIDMAX) { - if (dx->video_current == -1) dx->video_current = packetType; - if (dx->video_current == packetType && !dx->vid_seeking) - sent = dx->videostream.put(data+submitted, size-submitted, MPTYPE_VIDEO); + if (video_current == -1) video_current = packet_type; + if (video_current == packet_type && !vid_seeking) + sent = videostream.put(packet.getData(), packet.getSize(), MPTYPE_VIDEO); else - sent = size-submitted; + sent = packet.getSize(); } - else if (packetType >= PESTYPE_AUD0 && packetType <= PESTYPE_AUDMAX) + else if (packet_type >= PESTYPE_AUD0 && packet_type <= PESTYPE_AUDMAX) { - if (dx->audio_current == -1) dx->audio_current = packetType; - - dx->avail_mpaudchan[packetType-PESTYPE_AUD0]=true; - - if (dx->audio_current == packetType && !dx->aud_seeking) - sent = dx->audiostream.put(data+submitted, size-submitted, MPTYPE_MPEG_AUDIO); + if (audio_current == -1) audio_current = packet_type; + avail_mpaudchan[packet_type - PESTYPE_AUD0] = true; + if (audio_current == packet_type && !aud_seeking) + sent = audiostream.put(packet.getData(), packet.getSize(), MPTYPE_MPEG_AUDIO); else - sent = size-submitted; + sent = packet.getSize(); } - else if (packetType == PESTYPE_PRIVATE_1) + else if (packet_type == PESTYPE_PRIVATE_1) { - if (substream >= PESTYPE_SUBSTREAM_AC30 && substream <= PESTYPE_SUBSTREAM_AC3MAX) + if (packet.getSubstream() >= PESTYPE_SUBSTREAM_AC30 && + packet.getSubstream() <= PESTYPE_SUBSTREAM_AC3MAX) { - dx->avail_ac3audchan[substream-PESTYPE_SUBSTREAM_AC30]=true; - if (substream == dx->audio_current) + avail_ac3audchan[packet.getSubstream() - PESTYPE_SUBSTREAM_AC30] = true; + if (packet.getSubstream() == audio_current) { - sent = dx->audiostream.put(data+submitted,size-submitted,(dx->ispre_1_3_19)?MPTYPE_AC3_PRE13:MPTYPE_AC3); + sent = audiostream.put(packet.getData(), packet.getSize(), (ispre_1_3_19)? MPTYPE_AC3_PRE13 : MPTYPE_AC3); } else { - sent = size-submitted; + sent = packet.getSize(); } } } else { - sent = size-submitted; + sent = packet.getSize(); } - submitted += sent; - if (submitted < size) // Stream is full. - return 0; + if (sent < packet.getSize()) // Stream is full. + return false; else - return 1; + return true; } -void Demuxer::PESPacket::parseDetails() +void Demuxer::parsePacketDetails(PESPacket& packet) { - Demuxer* dx = Demuxer::getInstance(); - if (packetType >= PESTYPE_AUD0 && packetType <= PESTYPE_AUDMAX) + if (packet.getPacketType() >= PESTYPE_AUD0 && + packet.getPacketType() <= PESTYPE_AUDMAX) { // Extract audio PTS if it exists - if ( size >= 14 && (data[7] & 0x80) ) // PTS_DTS_flags indicate PTS + if (packet.hasPTS()) { - dx->audio_pts = pts = ( (ULLONG)(data[9] & 0x0E) << 29 ) | - ( (ULLONG)(data[10]) << 22 ) | - ( (ULLONG)(data[11] & 0xFE) << 14 ) | - ( (ULLONG)(data[12]) << 7 ) | - ( (ULLONG)(data[13] & 0xFE) >> 1 ); - + audio_pts = packet.getPTS(); // We continue to seek on the audio if the video PTS that we // are trying to match is ahead of the audio PTS by at most // SEEK_THRESHOLD. We consider the possibility of PTS wrap. - if (dx->aud_seeking && !dx->vid_seeking && - !( (dx->video_pts_seek > dx->audio_pts && - dx->video_pts_seek - dx->audio_pts < SEEK_THRESHOLD) + if (aud_seeking && !vid_seeking && + !( (video_pts_seek > audio_pts && + video_pts_seek - audio_pts < SEEK_THRESHOLD) || - (dx->video_pts_seek < dx->audio_pts && - dx->video_pts_seek + (1LL<<33) - - dx->audio_pts < SEEK_THRESHOLD) )) + (video_pts_seek < audio_pts && + video_pts_seek + (1LL<<33) - audio_pts < SEEK_THRESHOLD) )) { - dx->aud_seeking = 0; + aud_seeking = 0; Log::getInstance()->log("Demuxer", Log::DEBUG, - "Leaving audio sync: Audio PTS = %llu", dx->audio_pts); + "Leaving audio sync: Audio PTS = %llu", audio_pts); } } } - else if (packetType == PESTYPE_PRIVATE_1) //Private Stream + else if (packet.getPacketType() == PESTYPE_PRIVATE_1) // Private stream { //Inspired by vdr's device.c - int payload_begin = data[8]+9; - unsigned char substream_id = data[payload_begin]; + int payload_begin = packet[8]+9; + unsigned char substream_id = packet[payload_begin]; unsigned char substream_type = substream_id & 0xF0; unsigned char substream_index = substream_id & 0x1F; pre_1_3_19_Recording: //This is for old recordings stuff - if (dx->ispre_1_3_19) + if (ispre_1_3_19) { substream_id = PESTYPE_PRIVATE_1; substream_type = 0x80; @@ -309,107 +358,77 @@ pre_1_3_19_Recording: //This is for old recordings stuff case 0xA0: //LPCM //not supported yet, is there any LPCM transmissio out there? break; case 0x80: //ac3, currently only one ac3 track per recording supported - substream=substream_type+substream_index; + packet.setSubstream(substream_type+substream_index); // Extract audio PTS if it exists - if ( size >= 14 && (data[7] & 0x80) ) // PTS_DTS_flags indicate PTS + if (packet.hasPTS()) { - dx->audio_pts = pts = ( (ULLONG)(data[9] & 0x0E) << 29 ) | - ( (ULLONG)(data[10]) << 22 ) | - ( (ULLONG)(data[11] & 0xFE) << 14 ) | - ( (ULLONG)(data[12]) << 7 ) | - ( (ULLONG)(data[13] & 0xFE) >> 1 ); + audio_pts = packet.getPTS(); // We continue to seek on the audio if the video PTS that we // are trying to match is ahead of the audio PTS by at most // SEEK_THRESHOLD. We consider the possibility of PTS wrap. - if (dx->aud_seeking && !dx->vid_seeking && - !( (dx->video_pts_seek > dx->audio_pts && - dx->video_pts_seek - dx->audio_pts < SEEK_THRESHOLD) + if (aud_seeking && !vid_seeking && + !( (video_pts_seek > audio_pts && + video_pts_seek - audio_pts < SEEK_THRESHOLD) || - (dx->video_pts_seek < dx->audio_pts && - dx->video_pts_seek + (1LL<<33) - - dx->audio_pts < SEEK_THRESHOLD) )) + (video_pts_seek < audio_pts && + video_pts_seek + (1LL<<33) - audio_pts < SEEK_THRESHOLD) )) { - dx->aud_seeking = 0; - Log::getInstance()->log("Demuxer", Log::DEBUG, "Leaving audio sync: Audio PTS = %llu", dx->audio_pts); + aud_seeking = 0; + Log::getInstance()->log("Demuxer", Log::DEBUG, "Leaving audio sync: Audio PTS = %llu", audio_pts); } } break; default: - if (!dx->ispre_1_3_19) + if (!ispre_1_3_19) { - dx->ispre_1_3_19=true; //switching to compat mode + ispre_1_3_19=true; //switching to compat mode goto pre_1_3_19_Recording; } else { - substream=0; + packet.setSubstream(0); } break; } } - else if (packetType >= PESTYPE_VID0 && packetType <= PESTYPE_VIDMAX) + else if (packet.getPacketType() >= PESTYPE_VID0 && + packet.getPacketType() <= PESTYPE_VIDMAX) { // Extract video PTS if it exists - if ( size >= 14 && (data[7] & 0x80) ) // PTS_DTS_flags indicate PTS - { - dx->video_pts = pts = ( (ULLONG)(data[9] & 0x0E) << 29 ) | - ( (ULLONG)(data[10]) << 22 ) | - ( (ULLONG)(data[11] & 0xFE) << 14 ) | - ( (ULLONG)(data[12]) << 7 ) | - ( (ULLONG)(data[13] & 0xFE) >> 1 ); - } + if (packet.hasPTS()) video_pts = packet.getPTS(); - // Now, scan for a sequence header and extract information - UINT pos = 9; // Start searching from byte 9 - while (pos < size - 5) + // If there is a sequence header, extract information + UINT pos = packet.findSeqHeader(); + if (pos > 1) { - UINT pattern = *(UINT*)(data+pos); - if (pattern == DEMUXER_SEQ_HEAD) + pos += 4; + if (pos+6 >= packet.getSize()) return; + horizontal_size = ((int)packet[pos] << 4) | ((int)packet[pos+1] >> 4); + vertical_size = (((int)packet[pos+1] & 0xf) << 8) | (int)packet[pos+2]; + setAspectRatio((enum AspectRatio)(packet[pos+3] >> 4)); + frame_rate = packet[pos+3] & 0x0f; + if (frame_rate >= 1 && frame_rate <= 8) + frame_rate = FrameRates[frame_rate]; + else + frame_rate = 0; + bit_rate = ((int)packet[pos+4] << 10) | + ((int)packet[pos+5] << 2) | + ((int)packet[pos+6] >> 6); + if (vid_seeking) { - seq_header = true; - pos += 4; - if (pos+6 >= size) return; - dx->horizontal_size = ((int)data[pos] << 4) | ((int)data[pos+1] >> 4); - dx->vertical_size = (((int)data[pos+1] & 0xf) << 8) | (int)data[pos+2]; - dx->setAspectRatio((enum AspectRatio)(data[pos+3] >> 4)); - dx->frame_rate = data[pos+3] & 0x0f; - if (dx->frame_rate >= 1 && dx->frame_rate <= 8) - dx->frame_rate = FrameRates[dx->frame_rate]; - else - dx->frame_rate = 0; - dx->bit_rate = ((int)data[pos+4] << 10) | - ((int)data[pos+5] << 2) | - ((int)data[pos+6] >> 6); - if (dx->vid_seeking) - { - dx->vid_seeking = 0; - dx->video_pts_seek = dx->video_pts; - Log::getInstance()->log("Demuxer", Log::DEBUG, - "Entering audio sync: Video PTS = %llu", dx->video_pts); - Log::getInstance()->log("Demuxer", Log::DEBUG, - "Entering audio sync: Audio PTS = %llu", dx->audio_pts); - } - return; + vid_seeking = 0; + video_pts_seek = video_pts; + Log::getInstance()->log("Demuxer", Log::DEBUG, + "Entering audio sync: Video PTS = %llu", video_pts); + Log::getInstance()->log("Demuxer", Log::DEBUG, + "Entering audio sync: Audio PTS = %llu", audio_pts); } - else pos++; + return; } } } -UINT Demuxer::PESPacket::findPictureHeader() -{ - if (size < 12) return 0; - UINT pattern = *(UINT*)(data+8); - UINT pos = 11; - while (pattern != DEMUXER_PIC_HEAD) - { - if (++pos >= size) return 0; - pattern = (pattern << 8) | data[pos]; - } - return pos-3; -} - UINT Demuxer::stripAudio(UCHAR* buf, UINT len) { UINT read_pos = 0, write_pos = 0; diff --git a/demuxer.h b/demuxer.h index 104ed96..10ffee4 100644 --- a/demuxer.h +++ b/demuxer.h @@ -1,5 +1,6 @@ /* - Copyright 2005-2006 Mark Calderbank + Copyright 2005-2007 Mark Calderbank + Copyright 2007 Marten Richter (AC3 support) This file is part of VOMP. @@ -20,8 +21,8 @@ /* -Thanks goes to Jon Gettler of the MVPMC project and Stephen Rice for -the demuxer in mvpmc. It was used in the creation of this Demuxer, +Thanks go to Jon Gettler of the MVPMC project and Stephen Rice for +the demuxer in mvpmc. It was used in the creation of this demuxer; however, no code was copied verbatim. */ @@ -37,37 +38,39 @@ however, no code was copied verbatim. #include "callback.h" #include "draintarget.h" -#define PES_AUDIO_START 0xc0 -#define PES_AUDIO_END 0xcf +class PESPacket +{ + public: + PESPacket(); + void init(UCHAR type); + void truncate(); + int write(UCHAR* buf, int len); + + UCHAR operator[] (UINT index); // return data[index] if in bounds, else 0 + // so no proper error condition but never mind for now + const UCHAR* getData() { return data; } + UINT getLength() { return length; } + UINT getSize() { return size; } + UCHAR getPacketType() { return packetType; } + void setSubstream(UCHAR s) { substream = s; } + UCHAR getSubstream() { return substream; } + bool hasPTS() { return (pts != PTS_INVALID); } + ULLONG getPTS() { return pts; } + + UINT findPictureHeader(); + UINT findSeqHeader(); + static const ULLONG PTS_INVALID; + protected: + UCHAR data[0x10000]; + UINT length, size; + UCHAR packetType; + UCHAR substream; + ULLONG pts; + UINT seq_header; // 0 = no, 1 = unknown, else = header offset +}; class Demuxer { -protected: - class PESPacket - { - public: - PESPacket(); - void init(UCHAR type); - void truncate(); - int write(UCHAR* buf, int len); - int submit(); - protected: - UCHAR data[0x10000]; - UINT length, size; - bool closed; - UCHAR packetType; - UCHAR substream; //for ac3 - ULLONG pts; - bool seq_header; - UINT submitted; - virtual void parseDetails(); - UINT findPictureHeader(); - - - static const ULLONG PTS_INVALID; - }; - friend class PESPacket; - public: Demuxer(); virtual ~Demuxer(); @@ -119,34 +122,6 @@ protected: // *static function* static bool scanForVideo(UCHAR* buf, UINT len); - protected: - // General demuxer objects and status indicators - static Demuxer* instance; - Stream videostream; - Stream audiostream; - int shutdown(); - bool initted; - bool vid_seeking; - bool aud_seeking; - int video_current, audio_current; - - // Video stream information - void setAspectRatio(enum AspectRatio); - Callback* callback; - - int horizontal_size; - int vertical_size; - enum AspectRatio aspect_ratio; - int arcnt; - int frame_rate; - int bit_rate; - ULLONG video_pts; - ULLONG video_pts_seek; - ULLONG audio_pts; - - // Constants - static const int FrameRates[9]; - enum PESTYPE { PESTYPE_PRIVATE_1 = 0xBD, @@ -178,6 +153,38 @@ protected: PESTYPE_SUBSTREAM_AC3MAX = PESTYPE_SUBSTREAM_AC37 }; + protected: + // Operations on PES packets + bool submitPacket(PESPacket&); + void parsePacketDetails(PESPacket&); + + // General demuxer objects and status indicators + static Demuxer* instance; + Stream videostream; + Stream audiostream; + int shutdown(); + bool initted; + bool vid_seeking; + bool aud_seeking; + int video_current, audio_current; + + // Video stream information + void setAspectRatio(enum AspectRatio); + Callback* callback; + + int horizontal_size; + int vertical_size; + enum AspectRatio aspect_ratio; + int arcnt; + int frame_rate; + int bit_rate; + ULLONG video_pts; + ULLONG video_pts_seek; + ULLONG audio_pts; + + // Constants + static const int FrameRates[9]; + bool ispre_1_3_19; bool avail_mpaudchan[PESTYPE_AUDMAX-PESTYPE_AUD0+1]; bool avail_ac3audchan[PESTYPE_SUBSTREAM_AC3MAX-PESTYPE_SUBSTREAM_AC30+1]; diff --git a/demuxerts.cc b/demuxerts.cc index da454f3..f139d56 100644 --- a/demuxerts.cc +++ b/demuxerts.cc @@ -1,5 +1,5 @@ /* - Copyright 2006 Mark Calderbank + Copyright 2006-2007 Mark Calderbank This file is part of VOMP. @@ -29,6 +29,7 @@ DemuxerTS::DemuxerTS(int p_vID, int p_aID) void DemuxerTS::flush() { partPacket = 0; + parsed = false; Demuxer::flush(); vPacket.init(0xE0); aPacket.init(0xC0); @@ -177,10 +178,27 @@ int DemuxerTS::processTS(UCHAR* buf) { int rc = 1; - if (pid == vID) rc = vPacket.submit(); - if (pid == aID) rc = aPacket.submit(); + if (pid == vID) + { + if (!parsed) + { + parsePacketDetails(vPacket); + parsed = true; + } + rc = submitPacket(vPacket); + } + if (pid == aID) + { + if (!parsed) + { + parsePacketDetails(aPacket); + parsed = true; + } + rc = submitPacket(aPacket); + } if (rc == 0) return 0; + parsed = false; if (pid == vID) { vPacket.init(0xE0); @@ -200,8 +218,13 @@ int DemuxerTS::processTS(UCHAR* buf) { if (packet->write(buf, datalen) == 0) { // Writing to packet failed. It has overflowed. - if (packet->submit() == 0) - return 0; + if (!parsed) + { + parsePacketDetails(*packet); + parsed = true; + } + if (submitPacket(*packet) == 0) return 0; + parsed = false; packet->truncate(); packet->write((UCHAR*)"\200\000\000", 3); packet->write(buf, datalen); diff --git a/demuxerts.h b/demuxerts.h index 0303917..9a6ede0 100644 --- a/demuxerts.h +++ b/demuxerts.h @@ -1,5 +1,5 @@ /* - Copyright 2006 Mark Calderbank + Copyright 2006-2007 Mark Calderbank This file is part of VOMP. @@ -43,6 +43,7 @@ class DemuxerTS : public Demuxer UCHAR store[TS_SIZE]; // Storage for partial packets int partPacket; // Length of partial packet stored from previous put() + bool parsed; // Whether PES packet to be submitted has been parsed yet PESPacket vPacket; // Video PES packet under construction PESPacket aPacket; // Audio PES packet under construction int vID, aID; // TS IDs for video/audio diff --git a/demuxervdr.cc b/demuxervdr.cc index 12ccbaa..715433a 100644 --- a/demuxervdr.cc +++ b/demuxervdr.cc @@ -1,5 +1,5 @@ /* - Copyright 2005-2006 Mark Calderbank + Copyright 2005-2007 Mark Calderbank This file is part of VOMP. @@ -155,7 +155,7 @@ int DemuxerVDR::put(UCHAR* buf, int len) int ret = 0; // return number of bytes consumed if (submitting) { - if (packet.submit() == 0) // Still full! + if (submitPacket(packet) == 0) // Still full! return ret; else submitting = false; @@ -168,7 +168,8 @@ int DemuxerVDR::put(UCHAR* buf, int len) packet.write(buf, state); buf += state; len -= state; ret += state; state = 0; - if (packet.submit() == 0) // Stream is full + parseVDRPacketDetails(); + if (submitPacket(packet) == 0) // Stream is full { submitting = true; return ret; @@ -228,7 +229,8 @@ int DemuxerVDR::put(UCHAR* buf, int len) packet.write(buf, packetLength); buf += packetLength; len -= packetLength; ret += packetLength; state = 0; - if (packet.submit() == 0) // Stream is full + parseVDRPacketDetails(); + if (submitPacket(packet) == 0) // Stream is full { submitting = true; return ret; @@ -294,49 +296,49 @@ Log::getInstance()->log("Demuxer", Log::DEBUG, "STILL USING OLD REF"); return ref_frame + difference * Video::getInstance()->getFPS() / 90000; } -void DemuxerVDR::PESPacketVDR::parseDetails() +void DemuxerVDR::parseVDRPacketDetails() { - DemuxerVDR* dx = (DemuxerVDR*)(DemuxerVDR::getInstance()); - PESPacket::parseDetails(); + parsePacketDetails(packet); - if (dx->packetCounting && - packetType >= PESTYPE_AUD0 && packetType <= PESTYPE_AUDMAX) + if (packetCounting && packet.getPacketType() >= PESTYPE_AUD0 && + packet.getPacketType() <= PESTYPE_AUDMAX) { - dx->packetNumber++; + packetNumber++; } - if (dx->frameCounting && findPictureHeader() && - packetType >= PESTYPE_VID0 && packetType <= PESTYPE_VIDMAX) + if (frameCounting && packet.findPictureHeader() && + packet.getPacketType() >= PESTYPE_VID0 && + packet.getPacketType() <= PESTYPE_VIDMAX) { - ULONG frame_num = (dx->frameNumber)++; - if (seq_header && pts != PTS_INVALID) + ULONG frame_num = (frameNumber)++; + if (packet.findSeqHeader() > 1 && packet.hasPTS()) { PTSMapEntry me; - dx->pts_map_mutex.Lock(); - if (dx->pts_map.empty()) + pts_map_mutex.Lock(); + if (pts_map.empty()) { - me.pts = pts; + me.pts = packet.getPTS(); me.frame = frame_num; - dx->pts_map_mutex.Unlock(); + pts_map_mutex.Unlock(); Log::getInstance()->log("Demuxer", Log::DEBUG, "+* PTS INIT *+ %llu %u", me.pts, me.frame); - dx->pts_map_mutex.Lock(); - dx->pts_map.push_front(me); + pts_map_mutex.Lock(); + pts_map.push_front(me); } - me = dx->pts_map.front(); - dx->pts_map_mutex.Unlock(); + me = pts_map.front(); + pts_map_mutex.Unlock(); UINT fps = Video::getInstance()->getFPS(); ULLONG pts_expected = me.pts + 90000*(frame_num - me.frame) / fps; while (pts_expected > (1LL<<33)) pts_expected -= (1LL<<33); - if (PTSDistance(pts_expected, pts) > PTS_JUMP_MARGIN) // PTS jump! + if (PTSDistance(pts_expected, packet.getPTS()) > PTS_JUMP_MARGIN) // PTS jump! { -Log::getInstance()->log("Demuxer", Log::DEBUG, "+* PTS JUMP *+ %llu %u", pts, frame_num); - me.pts = pts; +Log::getInstance()->log("Demuxer", Log::DEBUG, "+* PTS JUMP *+ %llu %u", packet.getPTS(), frame_num); + me.pts = packet.getPTS(); me.frame = frame_num; - dx->pts_map_mutex.Lock(); - dx->pts_map.push_front(me); - dx->pts_map_mutex.Unlock(); + pts_map_mutex.Lock(); + pts_map.push_front(me); + pts_map_mutex.Unlock(); } } } diff --git a/demuxervdr.h b/demuxervdr.h index cdfa914..27230e7 100644 --- a/demuxervdr.h +++ b/demuxervdr.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2006 Mark Calderbank + Copyright 2005-2007 Mark Calderbank This file is part of VOMP. @@ -28,12 +28,6 @@ class DemuxerVDR : public Demuxer { - class PESPacketVDR : public PESPacket - { - void parseDetails(); - }; - friend class PESPacketVDR; - public: DemuxerVDR(); void reset(); @@ -50,7 +44,7 @@ class DemuxerVDR : public Demuxer int state; bool submitting; int packetLength; - PESPacketVDR packet; + PESPacket packet; ULONG frameNumber, packetNumber; bool frameCounting, packetCounting; @@ -58,6 +52,8 @@ class DemuxerVDR : public Demuxer typedef std::deque PTSMap; PTSMap pts_map; Mutex pts_map_mutex; + + void parseVDRPacketDetails(); }; #endif -- 2.39.2