diff options
author | Jochen Dolze <vdr@dolze.de> | 2010-11-22 22:08:27 +0100 |
---|---|---|
committer | Jochen Dolze <vdr@dolze.de> | 2010-11-22 22:08:27 +0100 |
commit | 83de61beb75c5554ec5773f63840990584d5da57 (patch) | |
tree | d789573a77fd0c0fc0b287a073193b4087df2753 | |
parent | 2e9d23ab5e3cc12ce58042afdc2d77d098fd498e (diff) | |
download | vdr-plugin-markad-83de61beb75c5554ec5773f63840990584d5da57.tar.gz vdr-plugin-markad-83de61beb75c5554ec5773f63840990584d5da57.tar.bz2 |
Added SeekPATPMT when there is no PAT/PMT on start of the TS-recording
Added info about nalu filler
Made demuxer more fault tolerant
-rw-r--r-- | command/demux.cpp | 2 | ||||
-rw-r--r-- | command/markad-standalone.cpp | 152 | ||||
-rw-r--r-- | command/markad-standalone.h | 5 | ||||
-rw-r--r-- | command/marks.cpp | 2 | ||||
-rw-r--r-- | command/streaminfo.cpp | 9 |
5 files changed, 104 insertions, 66 deletions
diff --git a/command/demux.cpp b/command/demux.cpp index c3580c5..752b300 100644 --- a/command/demux.cpp +++ b/command/demux.cpp @@ -207,7 +207,7 @@ int cMarkAdDemux::GetMinNeeded(MarkAdPid Pid, uchar *Data, int Count, bool *Offc } else { - return 0; + return -1; // skip one byte (maybe we get another header!) } } diff --git a/command/markad-standalone.cpp b/command/markad-standalone.cpp index 35527f0..e361306 100644 --- a/command/markad-standalone.cpp +++ b/command/markad-standalone.cpp @@ -1258,12 +1258,22 @@ bool cMarkAdStandalone::ProcessFile(int Number) { if (vpkt.Data) { + if ((macontext.Info.VPid.Type==MARKAD_PIDTYPE_VIDEO_H264) && (!noticeFILLER)) + { + if ((vpkt.Data[4] & 0x1F)==0x0C) + { + isyslog("H264 video stream with filler nalu"); + noticeFILLER=true; + } + } + bool dRes=false; if (streaminfo->FindVideoInfos(&macontext,vpkt.Data,vpkt.Length)) { if ((macontext.Video.Info.Height) && (!noticeHEADER)) { - isyslog("%s %i%c%0.f",(macontext.Video.Info.Height>576) ? "HDTV" : "SDTV", + isyslog("%s %ix%i%c%0.f",(macontext.Video.Info.Height>576) ? "HDTV" : "SDTV", + macontext.Video.Info.Width, macontext.Video.Info.Height, macontext.Video.Info.Interlaced ? 'i' : 'p', macontext.Video.Info.FramesPerSecond); @@ -1785,67 +1795,64 @@ bool cMarkAdStandalone::SaveInfo() return (err==false); } -time_t cMarkAdStandalone::GetBroadcastStartPES() +time_t cMarkAdStandalone::GetBroadcastStart(time_t start, int fd) { - // get broadcast start from atime of directory (if the volume is mounted with noatime) - // fallback to the time of the directory - struct mntent *ent; - FILE *mounts=setmntent(_PATH_MOUNTED,"r"); - while ((ent=getmntent(mounts))!=NULL) + if (isTS) { - if (strstr(directory,ent->mnt_dir)) + } + else + { + // get broadcast start from atime of directory (if the volume is mounted with noatime) + struct mntent *ent; + struct stat statbuf; + FILE *mounts=setmntent(_PATH_MOUNTED,"r"); + while ((ent=getmntent(mounts))!=NULL) { - if (strstr(ent->mnt_opts,"noatime")) + if (strstr(directory,ent->mnt_dir)) { - struct stat statbuf; - if (stat(directory,&statbuf)!=-1) + if (strstr(ent->mnt_opts,"noatime")) { - endmntent(mounts); - isyslog("getting broadcast start from directory atime"); - return statbuf.st_atime; + if (stat(directory,&statbuf)!=-1) + { + endmntent(mounts); + isyslog("getting broadcast start from directory atime"); + return statbuf.st_atime; + } } } } - } - endmntent(mounts); + endmntent(mounts); - const char *timestr=strrchr(directory,'/'); - if (timestr) - { - timestr++; - if (isdigit(*timestr)) + // try to get from mtime + // (and hope info.vdr has not changed after the start of the recording) + if (fstat(fd,&statbuf)!=-1) + { + if (fabs(difftime(start,statbuf.st_mtime))<1800) return (time_t) statbuf.st_mtime; + } + + // fallback to the timer -> worst time we can use! + const char *timestr=strrchr(directory,'/'); + if (timestr) { - time_t now = time(NULL); - struct tm tm_r; - struct tm t = *localtime_r(&now, &tm_r); // init timezone - if (sscanf(timestr, "%4d-%02d-%02d.%02d%*c%02d", &t.tm_year, &t.tm_mon, &t.tm_mday, - &t.tm_hour, & t.tm_min)==5) + timestr++; + if (isdigit(*timestr)) { - t.tm_year-=1900; - t.tm_mon--; - t.tm_sec=0; - t.tm_isdst=-1; - isyslog("getting broadcast start from timer"); - return mktime(&t); + time_t now = time(NULL); + struct tm tm_r; + struct tm t = *localtime_r(&now, &tm_r); // init timezone + if (sscanf(timestr, "%4d-%02d-%02d.%02d%*c%02d", &t.tm_year, &t.tm_mon, &t.tm_mday, + &t.tm_hour, & t.tm_min)==5) + { + t.tm_year-=1900; + t.tm_mon--; + t.tm_sec=0; + t.tm_isdst=-1; + isyslog("getting broadcast start from timer"); + return mktime(&t); + } } } - } - return (time_t) 0; -} - -time_t cMarkAdStandalone::GetBroadcastStart(time_t start, int fd) -{ - if (isTS) - { - } - else - { - /* with PES we can get the exact starttime only from - info.vdr (if its not changed afterwards) */ - struct stat statbuf; - if (fstat(fd,&statbuf)==-1) return (time_t) 0; - if (fabs(difftime(start,statbuf.st_mtime))>14400) return (time_t) 0; - return statbuf.st_mtime; + return (time_t) 0; } return (time_t) 0; } @@ -1919,6 +1926,11 @@ bool cMarkAdStandalone::LoadInfo() { macontext.Video.Info.FramesPerSecond=fps; setFrameRate=false; + if (fps<40) + { + // assumption + macontext.Video.Info.Interlaced=true; + } } } if (line[0]=='X') @@ -1997,11 +2009,6 @@ bool cMarkAdStandalone::LoadInfo() time_t rStart=GetBroadcastStart(startTime,fileno(f)); if (rStart) { - if (rStart>startTime+(time_t) length) - { - rStart=GetBroadcastStartPES(); - } - tStart=(int) (startTime-rStart); if (tStart<0) { @@ -2117,15 +2124,46 @@ bool cMarkAdStandalone::CheckVDRHD() return false; } -bool cMarkAdStandalone::CheckPATPMT() +off_t cMarkAdStandalone::SeekPATPMT() { char *buf; + if (asprintf(&buf,"%s/00001.ts",directory)==-1) return (off_t) -1; + + int fd=open(buf,O_RDONLY); + free(buf); + if (fd==-1) return (off_t) -1; + uchar peek_buf[188]; + for (int i=0; i<5000; i++) + { + if (read(fd,peek_buf,sizeof(peek_buf))!=sizeof(peek_buf)) + { + close(fd); + return (off_t) -1; + } + if ((peek_buf[0]==0x47) && (peek_buf[1]==0x40) && (peek_buf[2]==00)) + { + off_t ret=lseek(fd,0,SEEK_CUR); + close(fd); + return ret-188; + } + + } + close(fd); + return (off_t) -1; +} + +bool cMarkAdStandalone::CheckPATPMT(off_t Offset) +{ + if (Offset==(off_t) -1) return false; + char *buf; if (asprintf(&buf,"%s/00001.ts",directory)==-1) return false; int fd=open(buf,O_RDONLY); free(buf); if (fd==-1) return false; + if (lseek(fd,Offset,SEEK_SET)==(off_t)-1) return false; + uchar patpmt_buf[564]; uchar *patpmt; @@ -2350,7 +2388,7 @@ cMarkAdStandalone::cMarkAdStandalone(const char *Directory, const MarkAdConfig * noticeVDR_MP2=false; noticeVDR_AC3=false; noticeHEADER=false; - + noticeFILLER=false; sleepcnt=0; waittime=iwaittime=0; @@ -2440,7 +2478,7 @@ cMarkAdStandalone::cMarkAdStandalone(const char *Directory, const MarkAdConfig * if (isTS) { - if (!CheckPATPMT()) + if (!CheckPATPMT(SeekPATPMT())) { esyslog("no PAT/PMT found -> cannot process"); abort=true; diff --git a/command/markad-standalone.h b/command/markad-standalone.h index 669b2f5..25d19bb 100644 --- a/command/markad-standalone.h +++ b/command/markad-standalone.h @@ -198,6 +198,7 @@ unsigned Descriptor_Length: bool noticeVDR_MP2; bool noticeVDR_AC3; bool noticeHEADER; + bool noticeFILLER; bool bDecodeVideo; bool bDecodeAudio; @@ -223,7 +224,6 @@ unsigned Descriptor_Length: int chkLEFT; int chkRIGHT; - time_t GetBroadcastStartPES(); time_t GetBroadcastStart(time_t start, int fd); void CheckBroadcastLength(); bool CheckIndexGrowing(); @@ -250,7 +250,8 @@ unsigned Descriptor_Length: void ChangeMarks(clMark **Mark1, clMark **Mark2, MarkAdPos *NewPos); bool CheckVDRHD(); - bool CheckPATPMT(); + off_t SeekPATPMT(); + bool CheckPATPMT(off_t Offset=0); bool CheckTS(); bool LoadInfo(); bool SaveInfo(); diff --git a/command/marks.cpp b/command/marks.cpp index 2ebef9f..130ff42 100644 --- a/command/marks.cpp +++ b/command/marks.cpp @@ -545,7 +545,7 @@ bool clMarks::CheckIndex(const char *Directory, bool isTS, int *FrameCnt, int *I { framecnt=statbuf.st_size/sizeof(struct tIndexVDR); } - if (framecnt!=*FrameCnt) + if (abs(framecnt-*FrameCnt)>2000) { *FrameCnt=framecnt; *IndexError=IERR_TOOSHORT; diff --git a/command/streaminfo.cpp b/command/streaminfo.cpp index 4de2665..e52ca0b 100644 --- a/command/streaminfo.cpp +++ b/command/streaminfo.cpp @@ -120,7 +120,6 @@ bool cMarkAdStreamInfo::FindH264VideoInfos(MarkAdContext *maContext, uchar *pkt, if (nalu==NAL_AUD) { - if (!maContext->Video.Info.Width) return false; if (pkt[5]==0x10) { maContext->Video.Info.Pict_Type=MA_I_TYPE; @@ -139,19 +138,19 @@ bool cMarkAdStreamInfo::FindH264VideoInfos(MarkAdContext *maContext, uchar *pkt, int nal_len = nalUnescape(nal_data, pkt + 5, len - 5); cBitStream bs(nal_data, nal_len); - int profile_idc, pic_order_cnt_type, i, j; - uint32_t width=0; uint32_t height=0; uint32_t aspect_ratio_idc=0; double frame_rate=0; int sar_width=1,sar_height=1; - profile_idc = bs.getU8(); // profile_idc + int profile_idc = bs.getU8(); // profile_idc bs.skipBits(8); // constraint_setN_flags and reserved_zero_Nbits bs.skipBits(8); // level_idc bs.skipUeGolomb(); // seq_parameter_set_id + int i,j; + if ((profile_idc == 100) || (profile_idc == 110) || (profile_idc == 122) || (profile_idc == 244) || (profile_idc==44) || (profile_idc==83) || (profile_idc==86)) { @@ -179,7 +178,7 @@ bool cMarkAdStreamInfo::FindH264VideoInfos(MarkAdContext *maContext, uchar *pkt, } // H264.log2_max_frame_num=bs.getUeGolomb()+4; bs.skipUeGolomb(); // log2_max_frame_num_minus4 - pic_order_cnt_type = bs.getUeGolomb(); // pic_order_cnt_type + int pic_order_cnt_type = bs.getUeGolomb(); // pic_order_cnt_type if (pic_order_cnt_type == 0) bs.skipUeGolomb(); // log2_max_pic_order_cnt_lsb_minus4 else if (pic_order_cnt_type == 1) |