From c2966475942fcb9d4b8d41dbf026ff57630a1ad6 Mon Sep 17 00:00:00 2001 From: Klaus Schmidinger Date: Tue, 6 Jan 2009 20:31:53 +0100 Subject: =?UTF-8?q?Version=201.7.3=20-=20Updated=20the=20Russian=20OSD=20t?= =?UTF-8?q?exts=20(thanks=20to=20Oleg=20Roitburd).=20-=20Fixed=20handling?= =?UTF-8?q?=20the=20'pointer=20field'=20in=20generating=20and=20parsing=20?= =?UTF-8?q?PAT/PMT=20(thanks=20to=20=20=20Frank=20Schmirler).=20-=20Fixed?= =?UTF-8?q?=20handling=20modulation=20types=20for=20DVB-S=20transponders?= =?UTF-8?q?=20when=20processing=20the=20NIT.=20-=20Changed=20cDvbDevice::G?= =?UTF-8?q?rabImage()=20to=20use=20V4L2=20(thanks=20to=20Marco=20Schl=FC?= =?UTF-8?q?=DFler).=20-=20Added=20a=20poll=20to=20cDvbDevice::PlayVideo()?= =?UTF-8?q?=20and=20cDvbDevice::PlayAudio()=20to=20avoid=20=20=20excessive?= =?UTF-8?q?=20CPU=20load=20(this=20is=20just=20a=20makeshift=20solution=20?= =?UTF-8?q?until=20the=20FF=20DVB=20cards=20=20=20can=20play=20TS=20direct?= =?UTF-8?q?ly).=20-=20The=20recording=20format=20is=20now=20Transport=20St?= =?UTF-8?q?ream.=20Existing=20recordings=20in=20PES=20format=20=20=20can?= =?UTF-8?q?=20still=20be=20replayed=20and=20edited,=20but=20new=20recordin?= =?UTF-8?q?gs=20are=20done=20in=20TS.=20=20=20All=20code=20for=20recording?= =?UTF-8?q?=20in=20PES=20has=20been=20removed.=20=20=20The=20following=20c?= =?UTF-8?q?hanges=20were=20made=20to=20switch=20to=20TS=20recording=20form?= =?UTF-8?q?at:=20=20=20+=20The=20index=20file=20format=20has=20been=20chan?= =?UTF-8?q?ged=20to=20support=20file=20sizes=20of=20up=20to=201TB=20=20=20?= =?UTF-8?q?=20=20(previously=202GB),=20and=20up=20to=2065535=20separate=20?= =?UTF-8?q?files=20per=20recording=20(previously=20=20=20=20=20255).=20=20?= =?UTF-8?q?=20+=20The=20recording=20file=20names=20are=20now=20of=20the=20?= =?UTF-8?q?form=2000001.ts=20(previously=20001.vdr).=20=20=20+=20The=20fra?= =?UTF-8?q?me=20rate=20is=20now=20detected=20by=20looking=20at=20two=20sub?= =?UTF-8?q?sequent=20PTS=20values.=20=20=20=20=20The=20"frame=20duration"?= =?UTF-8?q?=20(in=20multiples=20of=201/90000)=20is=20stored=20in=20the=20i?= =?UTF-8?q?nfo.vdr=20=20=20=20=20file=20using=20the=20new=20tag=20F=20(tha?= =?UTF-8?q?nks=20to=20Artur=20Skawina=20for=20helping=20to=20get=20the=20?= =?UTF-8?q?=20=20=20=20IndexToHMSF()=20calculation=20right).=20=20=20+=20S?= =?UTF-8?q?everal=20functions=20now=20have=20an=20additional=20parameter?= =?UTF-8?q?=20FramesPerSecond.=20=20=20+=20Several=20functions=20now=20hav?= =?UTF-8?q?e=20an=20additional=20parameter=20IsPesRecording.=20=20=20+=20T?= =?UTF-8?q?he=20functionality=20of=20cFileWriter=20was=20moved=20into=20cR?= =?UTF-8?q?ecorder,=20and=20cRemux=20is=20=20=20=20=20now=20obsolete.=20Th?= =?UTF-8?q?is=20also=20avoids=20one=20level=20of=20data=20copying=20while?= =?UTF-8?q?=20recording.=20=20=20+=20cRemux,=20cRingBufferLinearPes,=20cTS?= =?UTF-8?q?2PES=20and=20all=20c*Repacker=20classes=20have=20been=20=20=20?= =?UTF-8?q?=20=20removed.=20=20=20+=20A=20PAT/PMT=20is=20inserted=20before?= =?UTF-8?q?=20every=20independent=20frame,=20so=20that=20no=20extra=20=20?= =?UTF-8?q?=20=20=20measures=20need=20to=20be=20taken=20when=20editing=20a?= =?UTF-8?q?=20recording.=20=20=20+=20The=20directory=20name=20for=20a=20re?= =?UTF-8?q?cording=20has=20been=20changed=20from=20=20=20=20=20YYYY-MM-DD-?= =?UTF-8?q?hh[.:]mm.pr.lt.rec=20(pr=3Dpriority,=20lt=3Dlifetime)=20to=20?= =?UTF-8?q?=20=20=20=20YYYY-MM-DD-hh.mm.ch-ri.rec=20(ch=3Dchannel,=20ri=3D?= =?UTF-8?q?resumeId).=20=20=20=20=20Priority=20and=20Lifetime=20are=20now?= =?UTF-8?q?=20stored=20in=20the=20info.vdr=20file=20with=20the=20new=20=20?= =?UTF-8?q?=20=20=20tags=20P=20and=20L=20(if=20no=20such=20file=20exists,?= =?UTF-8?q?=20the=20maximum=20values=20are=20assumed=20by=20=20=20=20=20de?= =?UTF-8?q?fault,=20which=20avoids=20inadvertently=20deleting=20a=20record?= =?UTF-8?q?ing=20if=20disk=20space=20=20=20=20=20is=20low).=20No=20longer?= =?UTF-8?q?=20storing=20Priority=20and=20Lifetime=20in=20the=20directory?= =?UTF-8?q?=20name=20=20=20=20=20avoids=20starting=20a=20new=20recording?= =?UTF-8?q?=20if=20one=20of=20these=20is=20changed=20in=20the=20timer=20?= =?UTF-8?q?=20=20=20=20and=20the=20recording=20is=20re-started=20for=20som?= =?UTF-8?q?e=20reason.=20=20=20=20=20Instead=20of=20Priority=20and=20Lifet?= =?UTF-8?q?ime,=20the=20directory=20name=20now=20contains=20the=20=20=20?= =?UTF-8?q?=20=20channel=20number=20from=20which=20the=20recording=20was?= =?UTF-8?q?=20made,=20and=20the=20"resume=20id"=20of=20=20=20=20=20this=20?= =?UTF-8?q?instance=20of=20VDR.=20This=20avoids=20problems=20if=20several?= =?UTF-8?q?=20VDR=20instances=20record=20=20=20=20=20the=20same=20show=20o?= =?UTF-8?q?n=20different=20channels,=20or=20even=20on=20the=20same=20chann?= =?UTF-8?q?el.=20=20=20=20=20The=20'-'=20between=20channel=20number=20and?= =?UTF-8?q?=20resumeId=20prevents=20older=20versions=20of=20=20=20=20=20VD?= =?UTF-8?q?R=20from=20"seeing"=20these=20recordings,=20which=20makes=20sur?= =?UTF-8?q?e=20they=20won't=20even=20try=20=20=20=20=20to=20replay=20them,?= =?UTF-8?q?=20or=20remove=20them=20in=20case=20the=20disk=20runs=20full.?= =?UTF-8?q?=20=20=20+=20The=20semantics=20of=20PlayTs*()=20have=20been=20c?= =?UTF-8?q?hanged.=20These=20functions=20are=20now=20=20=20=20=20required?= =?UTF-8?q?=20to=20return=20the=20given=20Length=20(which=20is=20TS=5FSIZE?= =?UTF-8?q?)=20if=20they=20have=20=20=20=20=20processed=20the=20TS=20packe?= =?UTF-8?q?t.=20=20=20+=20The=20files=20"index",=20"info",=20"marks"=20and?= =?UTF-8?q?=20"resume"=20within=20a=20TS=20recording=20=20=20=20=20directo?= =?UTF-8?q?ry=20are=20now=20created=20without=20the=20".vdr"=20extension.?= =?UTF-8?q?=20=20=20+=20The=20"resume"=20file=20is=20no=20longer=20a=20bin?= =?UTF-8?q?ary=20file,=20but=20contains=20tagged=20lines=20=20=20=20=20to?= =?UTF-8?q?=20be=20able=20to=20store=20additional=20information,=20like=20?= =?UTF-8?q?the=20selected=20audio=20or=20=20=20=20=20subtitle=20track.=20?= =?UTF-8?q?=20=20+=20cDevice::StillPicture()=20will=20now=20be=20called=20?= =?UTF-8?q?with=20either=20TS=20or=20PES=20data.=20=20=20+=20cDvbPlayer::G?= =?UTF-8?q?oto()=20no=20longer=20appends=20a=20"sequence=20end=20code"=20t?= =?UTF-8?q?o=20the=20data.=20=20=20=20=20If=20the=20output=20device=20need?= =?UTF-8?q?s=20this,=20it=20has=20to=20take=20care=20of=20it=20by=20itself?= =?UTF-8?q?.=20-=20Fixed=20cPatPmtParser::ParsePmt()=20to=20reset=20vpid?= =?UTF-8?q?=20and=20vtype=20when=20switching=20from=20=20=20a=20video=20to?= =?UTF-8?q?=20an=20audio=20channel=20(thanks=20to=20Reinhard=20Nissl).=20-?= =?UTF-8?q?=20cDvbDevice=20now=20uses=20the=20FE=5FCAN=5F2G=5FMODULATION?= =?UTF-8?q?=20flag=20to=20determine=20whether=20a=20device=20=20=20can=20h?= =?UTF-8?q?andle=20DVB-S2.=20The=20#define=20is=20still=20there=20to=20all?= =?UTF-8?q?ow=20people=20with=20older=20drivers=20=20=20who=20don't=20need?= =?UTF-8?q?=20DVB-S2=20to=20use=20this=20version=20without=20pathcing.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dvbdevice.c | 168 ++++++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 107 insertions(+), 61 deletions(-) (limited to 'dvbdevice.c') diff --git a/dvbdevice.c b/dvbdevice.c index e0b05a1..6aa0056 100644 --- a/dvbdevice.c +++ b/dvbdevice.c @@ -4,13 +4,13 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: dvbdevice.c 2.6 2008/12/13 14:38:07 kls Exp $ + * $Id: dvbdevice.c 2.10 2009/01/06 14:52:54 kls Exp $ */ #include "dvbdevice.h" #include #include -#include +#include #include #include #include @@ -491,7 +491,7 @@ cDvbDevice::cDvbDevice(int n) if (fd_frontend >= 0) { if (ioctl(fd_frontend, FE_GET_INFO, &frontendInfo) >= 0) { switch (frontendInfo.type) { - case FE_QPSK: frontendType = (frontendInfo.caps & FE_CAN_2ND_GEN_MODULATION) ? SYS_DVBS2 : SYS_DVBS; break; + case FE_QPSK: frontendType = (frontendInfo.caps & FE_CAN_2G_MODULATION) ? SYS_DVBS2 : SYS_DVBS; break; case FE_OFDM: frontendType = SYS_DVBT; break; case FE_QAM: frontendType = SYS_DVBC_ANNEX_AC; break; case FE_ATSC: frontendType = SYS_ATSC; break; @@ -604,69 +604,103 @@ uchar *cDvbDevice::GrabImage(int &Size, bool Jpeg, int Quality, int SizeX, int S int videoDev = open(buffer, O_RDWR); if (videoDev >= 0) { uchar *result = NULL; - struct video_mbuf mbuf; - if (ioctl(videoDev, VIDIOCGMBUF, &mbuf) == 0) { - int msize = mbuf.size; - unsigned char *mem = (unsigned char *)mmap(0, msize, PROT_READ | PROT_WRITE, MAP_SHARED, videoDev, 0); - if (mem && mem != (unsigned char *)-1) { - // set up the size and RGB - struct video_capability vc; - if (ioctl(videoDev, VIDIOCGCAP, &vc) == 0) { - struct video_mmap vm; - vm.frame = 0; - if ((SizeX > 0) && (SizeX <= vc.maxwidth) && - (SizeY > 0) && (SizeY <= vc.maxheight)) { - vm.width = SizeX; - vm.height = SizeY; - } - else { - vm.width = vc.maxwidth; - vm.height = vc.maxheight; - } - vm.format = VIDEO_PALETTE_RGB24; - if (ioctl(videoDev, VIDIOCMCAPTURE, &vm) == 0 && ioctl(videoDev, VIDIOCSYNC, &vm.frame) == 0) { - // make RGB out of BGR: - int memsize = vm.width * vm.height; - unsigned char *mem1 = mem; - for (int i = 0; i < memsize; i++) { - unsigned char tmp = mem1[2]; - mem1[2] = mem1[0]; - mem1[0] = tmp; - mem1 += 3; - } - - if (Quality < 0) - Quality = 100; - - dsyslog("grabbing to %s %d %d %d", Jpeg ? "JPEG" : "PNM", Quality, vm.width, vm.height); - if (Jpeg) { - // convert to JPEG: - result = RgbToJpeg(mem, vm.width, vm.height, Size, Quality); - if (!result) - esyslog("ERROR: failed to convert image to JPEG"); - } - else { - // convert to PNM: - char buf[32]; - snprintf(buf, sizeof(buf), "P6\n%d\n%d\n255\n", vm.width, vm.height); - int l = strlen(buf); - int bytes = memsize * 3; - Size = l + bytes; - result = MALLOC(uchar, Size); - if (result) { - memcpy(result, buf, l); - memcpy(result + l, mem, bytes); + // set up the size and RGB + v4l2_format fmt; + memset(&fmt, 0, sizeof(fmt)); + fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + fmt.fmt.pix.width = SizeX; + fmt.fmt.pix.height = SizeY; + fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_BGR24; + fmt.fmt.pix.field = V4L2_FIELD_ANY; + if (ioctl(videoDev, VIDIOC_S_FMT, &fmt) == 0) { + v4l2_requestbuffers reqBuf; + memset(&reqBuf, 0, sizeof(reqBuf)); + reqBuf.count = 2; + reqBuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + reqBuf.memory = V4L2_MEMORY_MMAP; + if (ioctl(videoDev, VIDIOC_REQBUFS, &reqBuf) >= 0) { + v4l2_buffer mbuf; + memset(&mbuf, 0, sizeof(mbuf)); + mbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + mbuf.memory = V4L2_MEMORY_MMAP; + if (ioctl(videoDev, VIDIOC_QUERYBUF, &mbuf) == 0) { + int msize = mbuf.length; + unsigned char *mem = (unsigned char *)mmap(0, msize, PROT_READ | PROT_WRITE, MAP_SHARED, videoDev, 0); + if (mem && mem != (unsigned char *)-1) { + v4l2_buffer buf; + memset(&buf, 0, sizeof(buf)); + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_MMAP; + buf.index = 0; + if (ioctl(videoDev, VIDIOC_QBUF, &buf) == 0) { + v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + if (ioctl (videoDev, VIDIOC_STREAMON, &type) == 0) { + memset(&buf, 0, sizeof(buf)); + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_MMAP; + buf.index = 0; + if (ioctl(videoDev, VIDIOC_DQBUF, &buf) == 0) { + if (ioctl(videoDev, VIDIOC_STREAMOFF, &type) == 0) { + // make RGB out of BGR: + int memsize = fmt.fmt.pix.width * fmt.fmt.pix.height; + unsigned char *mem1 = mem; + for (int i = 0; i < memsize; i++) { + unsigned char tmp = mem1[2]; + mem1[2] = mem1[0]; + mem1[0] = tmp; + mem1 += 3; + } + + if (Quality < 0) + Quality = 100; + + dsyslog("grabbing to %s %d %d %d", Jpeg ? "JPEG" : "PNM", Quality, fmt.fmt.pix.width, fmt.fmt.pix.height); + if (Jpeg) { + // convert to JPEG: + result = RgbToJpeg(mem, fmt.fmt.pix.width, fmt.fmt.pix.height, Size, Quality); + if (!result) + esyslog("ERROR: failed to convert image to JPEG"); + } + else { + // convert to PNM: + char buf[32]; + snprintf(buf, sizeof(buf), "P6\n%d\n%d\n255\n", fmt.fmt.pix.width, fmt.fmt.pix.height); + int l = strlen(buf); + int bytes = memsize * 3; + Size = l + bytes; + result = MALLOC(uchar, Size); + if (result) { + memcpy(result, buf, l); + memcpy(result + l, mem, bytes); + } + else + esyslog("ERROR: failed to convert image to PNM"); + } + } + else + esyslog("ERROR: video device VIDIOC_STREAMOFF failed"); + } + else + esyslog("ERROR: video device VIDIOC_DQBUF failed"); } else - esyslog("ERROR: failed to convert image to PNM"); + esyslog("ERROR: video device VIDIOC_STREAMON failed"); } + else + esyslog("ERROR: video device VIDIOC_QBUF failed"); + munmap(mem, msize); } + else + esyslog("ERROR: failed to memmap video device"); } - munmap(mem, msize); + else + esyslog("ERROR: video device VIDIOC_QUERYBUF failed"); } else - esyslog("ERROR: failed to memmap video device"); + esyslog("ERROR: video device VIDIOC_REQBUFS failed"); } + else + esyslog("ERROR: video device VIDIOC_S_FMT failed"); close(videoDev); return result; } @@ -1179,7 +1213,11 @@ void cDvbDevice::Mute(void) void cDvbDevice::StillPicture(const uchar *Data, int Length) { - if (Data[0] == 0x00 && Data[1] == 0x00 && Data[2] == 0x01 && (Data[3] & 0xF0) == 0xE0) { + if (Data[0] == 0x47) { + // TS data + cDevice::StillPicture(Data, Length); + } + else if (Data[0] == 0x00 && Data[1] == 0x00 && Data[2] == 0x01 && (Data[3] & 0xF0) == 0xE0) { // PES data char *buf = MALLOC(char, Length); if (!buf) @@ -1269,6 +1307,10 @@ int cDvbDevice::PlayVideo(const uchar *Data, int Length) int w; do { w = WriteAllOrNothing(fd_video, Data, Length, 1000, 10); + if (w < 0 && errno == EAGAIN) { + cPoller Poller(fd_video, true); + Poller.Poll(200); + } } while (w != Length); return w; } @@ -1278,6 +1320,10 @@ int cDvbDevice::PlayAudio(const uchar *Data, int Length, uchar Id) int w; do { w = WriteAllOrNothing(fd_audio, Data, Length, 1000, 10); + if (w < 0 && errno == EAGAIN) { + cPoller Poller(fd_audio, true); + Poller.Poll(200); + } } while (w != Length); return w; } @@ -1289,8 +1335,8 @@ int cDvbDevice::PlayTsVideo(const uchar *Data, int Length) int cDvbDevice::PlayTsAudio(const uchar *Data, int Length) { - Length = TsGetPayload(&Data); - return PlayAudio(Data, Length, 0); + int w = PlayAudio(Data, TsGetPayload(&Data), 0); + return w >= 0 ? Length : w; } bool cDvbDevice::OpenDvr(void) -- cgit v1.2.3