From 084e16c057ab195a76c2117c631a2fe10a904238 Mon Sep 17 00:00:00 2001 From: Klaus Schmidinger Date: Sun, 25 Jan 2009 13:13:00 +0100 Subject: =?UTF-8?q?Version=201.7.4=20-=20Removed=20the=20'#define=20FE=5FC?= =?UTF-8?q?AN=5F2ND=5FGEN=5FMODULATION',=20since=20it=20was=20wrong=20and?= =?UTF-8?q?=20the=20=20=20flag=20is=20now=20in=20the=20driver,=20anyway.?= =?UTF-8?q?=20-=20The=20full-featured=20DVB=20cards=20are=20now=20given=20?= =?UTF-8?q?the=20TS=20data=20directly=20for=20replay=20=20=20(thanks=20to?= =?UTF-8?q?=20Oliver=20Endriss=20for=20enhancing=20the=20av7110=20driver?= =?UTF-8?q?=20to=20make=20it=20replay=20=20=20TS=20data).=20The=20patch=20?= =?UTF-8?q?from=20ftp://ftp.cadsoft.de/vdr/Developer/av7110=5Fts=5Freplay?= =?UTF-8?q?=5F=5F1.diff=20=20=20implements=20this=20change=20in=20the=20dr?= =?UTF-8?q?iver.=20=20=20The=20patch=20av7110=5Fv4ldvb=5Fapi5=5Faudiobuf?= =?UTF-8?q?=5Ftest=5F1.diff=20mentioned=20in=20version=201.7.2=20=20=20is?= =?UTF-8?q?=20still=20necessary=20to=20avoid=20audio=20and=20video=20glitc?= =?UTF-8?q?hes=20on=20some=20channels.=20-=20Added=20a=20typecast=20in=20c?= =?UTF-8?q?UnbufferedFile::Write()=20to=20avoid=20an=20error=20message=20w?= =?UTF-8?q?hen=20=20=20compiling=20on=2064=20bit=20systems.=20-=20Added=20?= =?UTF-8?q?some=20missing=20'const'=20statements=20to=20cBitmap=20(thanks?= =?UTF-8?q?=20to=20Andreas=20Regel).=20-=20Fixed=20returning=20complete=20?= =?UTF-8?q?PES=20packets=20in=20cTsToPes::GetPes()=20(thanks=20to=20Reinha?= =?UTF-8?q?rd=20=20=20Nissl).=20-=20Added=20a=20missing=20Detach()=20in=20?= =?UTF-8?q?cTransfer::Activate()=20(thanks=20to=20Marco=20Schl=FC=DFler).?= =?UTF-8?q?=20-=20Added=20clearing=20the=20TS=20buffers=20in=20cDevice::De?= =?UTF-8?q?tach()=20(thanks=20to=20Marco=20Schl=FC=DFler).=20-=20Fixed=20i?= =?UTF-8?q?ncrementing=20the=20continuity=20counter=20in=20cPatPmtGenerato?= =?UTF-8?q?r::GetPmt()=20(thanks=20=20=20to=20Johann=20Friedrichs).=20-=20?= =?UTF-8?q?Fixed=20removing=20deleted=20recordings=20in=20case=20there=20i?= =?UTF-8?q?s=20a=20problem.=20Once=20a=20recording=20=20=20caused=20a=20pr?= =?UTF-8?q?oblem=20with=20removing,=20no=20others=20were=20removed=20any?= =?UTF-8?q?=20more=20and=20an=20ongoing=20=20=20recording=20could=20fill?= =?UTF-8?q?=20up=20the=20disk=20and=20cause=20other=20recordings=20to=20be?= =?UTF-8?q?=20deleted=20=20=20automatically=20(reported=20by=20Reinhard=20?= =?UTF-8?q?Nissl).=20-=20Added=20"DEFINES=20+=3D=20-D=5FFILE=5FOFFSET=5FBI?= =?UTF-8?q?TS=3D64=20-D=5FLARGEFILE=5FSOURCE=20-D=5FLARGEFILE64=5FSOURCE"?= =?UTF-8?q?=20=20=20to=20Make.config.template=20(thanks=20to=20Johann=20Fr?= =?UTF-8?q?iedrichs=20for=20pointing=20this=20out).=20=20=20Plugin=20autho?= =?UTF-8?q?rs=20should=20add=20this=20line=20to=20their=20Makefile=20or=20?= =?UTF-8?q?Make.config=20if=20they=20use=20=20=20file=20access=20functions?= =?UTF-8?q?=20that=20need=20special=20versions=20for=2064=20bit=20offsets.?= =?UTF-8?q?=20-=20The=20new=20command=20line=20option=20-i=20can=20be=20us?= =?UTF-8?q?ed=20to=20set=20an=20"instance=20id",=20which=20will=20=20=20be?= =?UTF-8?q?=20used=20to=20distinguish=20recordings=20of=20the=20same=20bro?= =?UTF-8?q?adcast=20made=20by=20different=20instances=20=20=20of=20VDR=20(?= =?UTF-8?q?suggested=20by=20Frank=20Schmirler).=20This=20replaces=20the=20?= =?UTF-8?q?use=20of=20the=20"resume=20id"=20=20=20that=20was=20introduced?= =?UTF-8?q?=20in=20version=201.7.3.=20-=20Added=20checking=20mutexCurrentA?= =?UTF-8?q?udioTrack=20to=20cDevice::PlayTs()=20(thanks=20to=20Reinhard=20?= =?UTF-8?q?=20=20Nissl=20for=20pointing=20this=20out).=20-=20Fixed=20handl?= =?UTF-8?q?ing=20the=20pointer=20field=20in=20cPatPmtParser::ParsePmt()=20?= =?UTF-8?q?(thanks=20to=20Frank=20=20=20Schmirler=20-=20sorry=20I=20swappe?= =?UTF-8?q?d=20two=20lines=20when=20adopting=20the=20original=20patch).=20?= =?UTF-8?q?-=20Checking=20the=20remaining=20packet=20length=20after=20proc?= =?UTF-8?q?essing=20the=20pointer=20field=20in=20=20=20cPatPmtParser::Pars?= =?UTF-8?q?ePat()=20and=20cPatPmtParser::ParsePmt()=20(suggested=20by=20Fr?= =?UTF-8?q?ank=20=20=20Schmirler).=20-=20Checking=20the=20pointer=20field?= =?UTF-8?q?=20in=20cPatPmtParser::ParsePmt()=20only=20in=20'payload=20star?= =?UTF-8?q?t'=20=20=20packets=20(suggested=20by=20Frank=20Schmirler).=20-?= =?UTF-8?q?=20Changed=20cPatPmtGenerator=20to=20make=20sure=20the=20PMT=20?= =?UTF-8?q?pid=20doesn't=20collide=20with=20any=20of=20=20=20the=20actual?= =?UTF-8?q?=20pids=20of=20the=20channel.=20-=20Fixed=20cDevice::PlayTsAudi?= =?UTF-8?q?o()=20and=20made=20cDevice::PlayTsVideo()=20return=200=20if=20?= =?UTF-8?q?=20=20PlayVideo()=20didn't=20play=20anything.=20-=20Added=20an?= =?UTF-8?q?=20'int'=20typecast=20to=20calculations=20involving=20FramesPer?= =?UTF-8?q?Second()=20to=20avoid=20=20=20compiler=20warnings=20(reported?= =?UTF-8?q?=20by=20Winfried=20Koehler).=20-=20Fixed=20detecting=20frames?= =?UTF-8?q?=20for=20pure=20audio=20recordings.=20-=20Fixed=20editing=20PES?= =?UTF-8?q?=20recordings.=20The=20frame=20type=20in=20the=20index.vdr=20fi?= =?UTF-8?q?le=20generated=20for=20=20=20the=20edited=20PES=20recording=20i?= =?UTF-8?q?s=20set=20to=201=20for=20I-frames=20and=202=20for=20all=20other?= =?UTF-8?q?s=20(P-=20and=20=20=20B-frames).=20The=20exact=20frame=20type?= =?UTF-8?q?=20doesn't=20matter=20for=20VDR,=20it=20only=20needs=20to=20kno?= =?UTF-8?q?w=20if=20=20=20it's=20an=20I-frame=20or=20not.=20-=20The=20PAT/?= =?UTF-8?q?PMT=20is=20now=20only=20processed=20if=20its=20version=20change?= =?UTF-8?q?s=20(reported=20by=20Reinhard=20=20=20Nissl).=20-=20Fixed=20han?= =?UTF-8?q?dling=20the=20maximum=20video=20file=20size=20(reported=20by=20?= =?UTF-8?q?Udo=20Richter).=20-=20Improved=20fast-forward/-rewind=20for=20a?= =?UTF-8?q?udio=20recordings.=20The=20actual=20data=20is=20now=20sent=20?= =?UTF-8?q?=20=20to=20the=20output=20device,=20so=20that=20it=20can=20be?= =?UTF-8?q?=20replayed=20and=20thus=20cause=20the=20proper=20delay.=20=20?= =?UTF-8?q?=20For=20pure=20audio=20recordings=20the=20audio=20is=20no=20lo?= =?UTF-8?q?nger=20muted=20in=20fast-forward/-rewind=20=20=20mode,=20so=20t?= =?UTF-8?q?hat=20some=20orientation=20regarding=20the=20position=20within?= =?UTF-8?q?=20the=20recording=20is=20=20=20possible.=20There=20may=20still?= =?UTF-8?q?=20be=20some=20offset=20in=20the=20replay=20position=20displaye?= =?UTF-8?q?d=20by=20the=20=20=20progress=20indicator=20when=20switching=20?= =?UTF-8?q?from=20fast-forward/-rewind=20to=20play=20mode,=20as=20well=20?= =?UTF-8?q?=20=20as=20in=20the=20current=20position=20during=20normal=20pl?= =?UTF-8?q?ay=20mode.=20This=20is=20due=20to=20the=20various=20=20=20buffe?= =?UTF-8?q?rs=20between=20the=20player=20and=20the=20output=20device=20and?= =?UTF-8?q?=20will=20be=20addressed=20later.=20=20=20Note=20the=20new=20fu?= =?UTF-8?q?nction=20cDevice::IsPlayingVideo(),=20which=20is=20used=20to=20?= =?UTF-8?q?inform=20the=20=20=20player=20whether=20there=20is=20video=20da?= =?UTF-8?q?ta=20in=20the=20currently=20replayed=20stream.=20If=20a=20deriv?= =?UTF-8?q?ed=20=20=20cDevice=20class=20reimplements=20PlayTs()=20or=20Pla?= =?UTF-8?q?yPes(),=20it=20also=20needs=20to=20make=20sure=20this=20=20=20n?= =?UTF-8?q?ew=20function=20works=20as=20expected.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- remux.c | 102 ++++++++++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 77 insertions(+), 25 deletions(-) (limited to 'remux.c') diff --git a/remux.c b/remux.c index 840f5df..b008621 100644 --- a/remux.c +++ b/remux.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: remux.c 2.5 2009/01/06 14:46:21 kls Exp $ + * $Id: remux.c 2.13 2009/01/24 13:44:45 kls Exp $ */ #include "remux.h" @@ -111,13 +111,14 @@ void cRemux::SetBrokenLink(uchar *Data, int Length) // --- cPatPmtGenerator ------------------------------------------------------ -cPatPmtGenerator::cPatPmtGenerator(void) +cPatPmtGenerator::cPatPmtGenerator(cChannel *Channel) { numPmtPackets = 0; patCounter = pmtCounter = 0; patVersion = pmtVersion = 0; + pmtPid = 0; esInfoLength = NULL; - GeneratePat(); + SetChannel(Channel); } void cPatPmtGenerator::IncCounter(int &Counter, uchar *TsPacket) @@ -206,16 +207,31 @@ int cPatPmtGenerator::MakeCRC(uchar *Target, const uchar *Data, int Length) } #define P_TSID 0x8008 // pseudo TS ID -#define P_PNR 0x0084 // pseudo Program Number #define P_PMT_PID 0x0084 // pseudo PMT pid +#define MAXPID 0x2000 // the maximum possible number of pids + +void cPatPmtGenerator::GeneratePmtPid(cChannel *Channel) +{ + bool Used[MAXPID] = { false }; +#define SETPID(p) { if ((p) >= 0 && (p) < MAXPID) Used[p] = true; } +#define SETPIDS(l) { const int *p = l; while (*p) { SETPID(*p); p++; } } + SETPID(Channel->Vpid()); + SETPID(Channel->Ppid()); + SETPID(Channel->Tpid()); + SETPIDS(Channel->Apids()); + SETPIDS(Channel->Dpids()); + SETPIDS(Channel->Spids()); + for (pmtPid = P_PMT_PID; Used[pmtPid]; pmtPid++) + ; +} void cPatPmtGenerator::GeneratePat(void) { memset(pat, 0xFF, sizeof(pat)); uchar *p = pat; int i = 0; - p[i++] = 0x47; // TS indicator - p[i++] = 0x40; // flags (3), pid hi (5) + p[i++] = TS_SYNC_BYTE; // TS indicator + p[i++] = TS_PAYLOAD_START; // flags (3), pid hi (5) p[i++] = 0x00; // pid lo p[i++] = 0x10; // flags (4), continuity counter (4) p[i++] = 0x00; // pointer field (payload unit start indicator is set) @@ -229,22 +245,21 @@ void cPatPmtGenerator::GeneratePat(void) p[i++] = 0xC1 | (patVersion << 1); // dummy (2), version number (5), current/next indicator (1) p[i++] = 0x00; // section number p[i++] = 0x00; // last section number - p[i++] = P_PNR >> 8; // program number hi - p[i++] = P_PNR & 0xFF; // program number lo - p[i++] = 0xE0 | (P_PMT_PID >> 8); // dummy (3), PMT pid hi (5) - p[i++] = P_PMT_PID & 0xFF; // PMT pid lo + p[i++] = pmtPid >> 8; // program number hi + p[i++] = pmtPid & 0xFF; // program number lo + p[i++] = 0xE0 | (pmtPid >> 8); // dummy (3), PMT pid hi (5) + p[i++] = pmtPid & 0xFF; // PMT pid lo pat[SectionLength] = i - SectionLength - 1 + 4; // -2 = SectionLength storage, +4 = length of CRC MakeCRC(pat + i, pat + PayloadStart, i - PayloadStart); IncVersion(patVersion); } -void cPatPmtGenerator::GeneratePmt(tChannelID ChannelID) +void cPatPmtGenerator::GeneratePmt(cChannel *Channel) { // generate the complete PMT section: uchar buf[MAX_SECTION_SIZE]; memset(buf, 0xFF, sizeof(buf)); numPmtPackets = 0; - cChannel *Channel = Channels.GetByChannelID(ChannelID); if (Channel) { int Vpid = Channel->Vpid(); uchar *p = buf; @@ -253,8 +268,8 @@ void cPatPmtGenerator::GeneratePmt(tChannelID ChannelID) int SectionLength = i; p[i++] = 0xB0; // section syntax indicator (1), dummy (3), section length hi (4) p[i++] = 0x00; // section length lo (filled in later) - p[i++] = P_PNR >> 8; // program number hi - p[i++] = P_PNR & 0xFF; // program number lo + p[i++] = pmtPid >> 8; // program number hi + p[i++] = pmtPid & 0xFF; // program number lo p[i++] = 0xC1 | (pmtVersion << 1); // dummy (2), version number (5), current/next indicator (1) p[i++] = 0x00; // section number p[i++] = 0x00; // last section number @@ -292,9 +307,9 @@ void cPatPmtGenerator::GeneratePmt(tChannelID ChannelID) while (i > 0) { uchar *p = pmt[numPmtPackets++]; int j = 0; - p[j++] = 0x47; // TS indicator - p[j++] = (pusi ? 0x40 : 0x00) | (P_PNR >> 8); // flags (3), pid hi (5) - p[j++] = P_PNR & 0xFF; // pid lo + p[j++] = TS_SYNC_BYTE; // TS indicator + p[j++] = (pusi ? TS_PAYLOAD_START : 0x00) | (pmtPid >> 8); // flags (3), pid hi (5) + p[j++] = pmtPid & 0xFF; // pid lo p[j++] = 0x10; // flags (4), continuity counter (4) if (pusi) { p[j++] = 0x00; // pointer field (payload unit start indicator is set) @@ -307,8 +322,15 @@ void cPatPmtGenerator::GeneratePmt(tChannelID ChannelID) } IncVersion(pmtVersion); } - else - esyslog("ERROR: can't find channel %s", *ChannelID.ToString()); +} + +void cPatPmtGenerator::SetChannel(cChannel *Channel) +{ + if (Channel) { + GeneratePmtPid(Channel); + GeneratePat(); + GeneratePmt(Channel); + } } uchar *cPatPmtGenerator::GetPat(void) @@ -320,7 +342,7 @@ uchar *cPatPmtGenerator::GetPat(void) uchar *cPatPmtGenerator::GetPmt(int &Index) { if (Index < numPmtPackets) { - IncCounter(patCounter, pmt[Index]); + IncCounter(pmtCounter, pmt[Index]); return pmt[Index++]; } return NULL; @@ -329,19 +351,33 @@ uchar *cPatPmtGenerator::GetPmt(int &Index) // --- cPatPmtParser --------------------------------------------------------- cPatPmtParser::cPatPmtParser(void) +{ + Reset(); +} + +void cPatPmtParser::Reset(void) { pmtSize = 0; + patVersion = pmtVersion = -1; pmtPid = -1; vpid = vtype = 0; } void cPatPmtParser::ParsePat(const uchar *Data, int Length) { + // Unpack the TS packet: + int PayloadOffset = TsPayloadOffset(Data); + Data += PayloadOffset; + Length -= PayloadOffset; // The PAT is always assumed to fit into a single TS packet + if ((Length -= Data[0] + 1) <= 0) + return; Data += Data[0] + 1; // process pointer_field SI::PAT Pat(Data, false); if (Pat.CheckCRCAndParse()) { dbgpatpmt("PAT: TSid = %d, c/n = %d, v = %d, s = %d, ls = %d\n", Pat.getTransportStreamId(), Pat.getCurrentNextIndicator(), Pat.getVersionNumber(), Pat.getSectionNumber(), Pat.getLastSectionNumber()); + if (patVersion == Pat.getVersionNumber()) + return; SI::PAT::Association assoc; for (SI::Loop::Iterator it; Pat.associationLoop.getNext(assoc, it); ) { dbgpatpmt(" isNITPid = %d\n", assoc.isNITPid()); @@ -350,6 +386,7 @@ void cPatPmtParser::ParsePat(const uchar *Data, int Length) dbgpatpmt(" service id = %d, pid = %d\n", assoc.getServiceId(), assoc.getPid()); } } + patVersion = Pat.getVersionNumber(); } else esyslog("ERROR: can't parse PAT"); @@ -357,10 +394,17 @@ void cPatPmtParser::ParsePat(const uchar *Data, int Length) void cPatPmtParser::ParsePmt(const uchar *Data, int Length) { + // Unpack the TS packet: + bool PayloadStart = TsPayloadStart(Data); + int PayloadOffset = TsPayloadOffset(Data); + Data += PayloadOffset; + Length -= PayloadOffset; // The PMT may extend over several TS packets, so we need to assemble them - if (pmtSize == 0) { + if (PayloadStart) { + pmtSize = 0; + if ((Length -= Data[0] + 1) <= 0) + return; Data += Data[0] + 1; // this is the first packet - Length -= Data[0] + 1; if (SectionLength(Data, Length) > Length) { if (Length <= int(sizeof(pmt))) { memcpy(pmt, Data, Length); @@ -372,7 +416,7 @@ void cPatPmtParser::ParsePmt(const uchar *Data, int Length) } // the packet contains the entire PMT section, so we run into the actual parsing } - else { + else if (pmtSize > 0) { // this is a following packet, so we add it to the pmt storage if (Length <= int(sizeof(pmt)) - pmtSize) { memcpy(pmt + pmtSize, Data, Length); @@ -387,10 +431,14 @@ void cPatPmtParser::ParsePmt(const uchar *Data, int Length) // the PMT section is now complete, so we run into the actual parsing Data = pmt; } + else + return; // fragment of broken packet - ignore SI::PMT Pmt(Data, false); if (Pmt.CheckCRCAndParse()) { dbgpatpmt("PMT: sid = %d, c/n = %d, v = %d, s = %d, ls = %d\n", Pmt.getServiceId(), Pmt.getCurrentNextIndicator(), Pmt.getVersionNumber(), Pmt.getSectionNumber(), Pmt.getLastSectionNumber()); dbgpatpmt(" pcr = %d\n", Pmt.getPCRPid()); + if (pmtVersion == Pmt.getVersionNumber()) + return; cDevice::PrimaryDevice()->ClrAvailableTracks(false, true); int NumApids = 0; int NumDpids = 0; @@ -496,6 +544,7 @@ void cPatPmtParser::ParsePmt(const uchar *Data, int Length) cDevice::PrimaryDevice()->EnsureAudioTrack(true); cDevice::PrimaryDevice()->EnsureSubtitleTrack(); } + pmtVersion = Pmt.getVersionNumber(); } else esyslog("ERROR: can't parse PMT"); @@ -559,8 +608,10 @@ const uchar *cTsToPes::GetPes(int &Length) } else { Length = PesLength(data); - offset = Length; // to make sure we break out in case of garbage data - return data; + if (Length <= length) { + offset = Length; // to make sure we break out in case of garbage data + return data; + } } } return NULL; @@ -703,6 +754,7 @@ int cFrameDetector::Analyze(const uchar *Data, int Length) if (frameDuration) { newFrame = true; independentFrame = true; + scanning = false; } else framesPerPayloadUnit = 1; -- cgit v1.2.3