📄 vidinput_v4l.cxx
字号:
PTRACE(3,"PVideoInputV4lDevice\t SetFrameSize "<<width<<"x"<<height<<" FAILED"); return FALSE; } ClearMapping(); if (!VerifyHardwareFrameSize(width, height)) { PTRACE(3,"PVideoInputV4lDevice\t SetFrameSize failed for "<<width<<"x"<<height); PTRACE(3,"VerifyHardwareFrameSize failed."); return FALSE; } frameBytes = CalculateFrameBytes(frameWidth, frameHeight, colourFormat); return TRUE;}PINDEX PVideoInputV4lDevice::GetMaxFrameBytes(){ if (converter != NULL) { PINDEX bytes = converter->GetMaxDstFrameBytes(); if (bytes > frameBytes) return bytes; } return frameBytes;}BOOL PVideoInputV4lDevice::GetFrame(PBYTEArray & frame){ PINDEX returned; if (!GetFrameData(frame.GetPointer(GetMaxFrameBytes()), &returned)) return FALSE; frame.SetSize(returned); return TRUE;}BOOL PVideoInputV4lDevice::GetFrameData(BYTE *buffer, PINDEX *bytesReturned){ if(frameRate>0) { frameTimeError += msBetweenFrames; do { if ( !GetFrameDataNoDelay(buffer, bytesReturned)) { return FALSE; } PTime now; PTimeInterval delay = now - previousFrameTime; frameTimeError -= (int)delay.GetMilliSeconds(); previousFrameTime = now; } while(frameTimeError > 0) ; return TRUE; } return GetFrameDataNoDelay(buffer, bytesReturned);}BOOL PVideoInputV4lDevice::GetFrameDataNoDelay(BYTE * buffer, PINDEX * bytesReturned){ if (canMap < 0) { //When canMap is < 0, it is the first use of GetFrameData. Check for memory mapping. if (::ioctl(videoFd, VIDIOCGMBUF, &frame) < 0) { canMap=0; PTRACE(3, "VideoGrabber " << deviceName << " cannot do memory mapping - GMBUF failed."); //This video device cannot do memory mapping. } else { videoBuffer = (BYTE *)::mmap(0, frame.size, PROT_READ|PROT_WRITE, MAP_SHARED, videoFd, 0); if (videoBuffer < 0) { canMap = 0; PTRACE(3, "VideoGrabber " << deviceName << " cannot do memory mapping - ::mmap failed."); //This video device cannot do memory mapping. } else { canMap = 1; frameBuffer[0].frame = 0; frameBuffer[0].format = colourFormatCode; frameBuffer[0].width = frameWidth; frameBuffer[0].height = frameHeight; frameBuffer[1].frame = 1; frameBuffer[1].format = colourFormatCode; frameBuffer[1].width = frameWidth; frameBuffer[1].height = frameHeight; currentFrame = 0; int ret; ret = ::ioctl(videoFd, VIDIOCMCAPTURE, &frameBuffer[currentFrame]); if (ret < 0) { PTRACE(1,"PVideoInputV4lDevice::GetFrameData mcapture1 failed : " << ::strerror(errno)); ClearMapping(); canMap = 0; //This video device cannot do memory mapping. } pendingSync[currentFrame] = TRUE; } } } if (canMap == 0) { return NormalReadProcess(buffer, bytesReturned); } /***************************** * The xawtv package from http://bytesex.org/xawtv/index.html * contains a programming-FAQ by Gerd Knorr. * For streaming video with video4linux at the full frame rate * (25 hz PAL, 30 hz NTSC) you need to, * * videoiomcapture frame 0 (setup) * * loop: * videoiomcapture frame 1 (returns immediately) * videoiocsync frame 0 (waits on the data) * goto loop: * * the loop body could also have been: * videoiomcapture frame 0 (returns immediately) * videoiocsync frame 1 (waits on the data) * * The driver requires each mcapture has a corresponding sync. * Thus, you use the pendingSync array. * * After the loop is finished, you need a videoiocsync 0. */ // trigger capture of next frame in this buffer. // fallback to read() on errors. int ret = -1; ret = ::ioctl(videoFd, VIDIOCMCAPTURE, &frameBuffer[ 1 - currentFrame ]); if ( ret < 0 ) { PTRACE(1,"PVideoInputV4lDevice::GetFrameData mcapture2 failed : " << ::strerror(errno)); ClearMapping(); canMap = 0; return NormalReadProcess(buffer, bytesReturned); } pendingSync[ 1 - currentFrame ] = TRUE; // device does support memory mapping, get data // wait for the frame to load. ret = ::ioctl(videoFd, VIDIOCSYNC, ¤tFrame); pendingSync[currentFrame] = FALSE; if (ret < 0) { PTRACE(1,"PVideoInputV4lDevice::GetFrameData csync failed : " << ::strerror(errno)); ClearMapping(); canMap = 0; return NormalReadProcess(buffer, bytesReturned); } // If converting on the fly do it from frame store to output buffer, otherwise do // straight copy. if (converter != NULL) converter->Convert(videoBuffer + frame.offsets[currentFrame], buffer, bytesReturned); else { memcpy(buffer, videoBuffer + frame.offsets[currentFrame], frameBytes); if (bytesReturned != NULL) *bytesReturned = frameBytes; } // change buffers currentFrame = 1 - currentFrame; return TRUE;}//This video device does not support memory mapping - so // use normal read process to extract a frame of video data.BOOL PVideoInputV4lDevice::NormalReadProcess(BYTE *resultBuffer, PINDEX *bytesReturned){ ssize_t ret; ret = -1; while (ret < 0) { ret = ::read(videoFd, resultBuffer, frameBytes); if ((ret < 0) && (errno == EINTR)) continue; if (ret < 0) { PTRACE(1,"PVideoInputV4lDevice::NormalReadProcess() failed"); return FALSE; } } if ((PINDEX)ret != frameBytes) { PTRACE(1,"PVideoInputV4lDevice::NormalReadProcess() returned a short read"); // Not a completely fatal. Maybe it should return FALSE instead of a partial // image though? // return FALSE; } if (converter != NULL) return converter->ConvertInPlace(resultBuffer, bytesReturned); if (bytesReturned != NULL) *bytesReturned = frameBytes; return TRUE;}void PVideoInputV4lDevice::ClearMapping(){ if ((canMap == 1) && (videoBuffer != NULL)) { for (int i=0; i<2; i++) if (pendingSync[i]) { int res = ::ioctl(videoFd, VIDIOCSYNC, &i); if (res < 0) PTRACE(1,"PVideoInputV4lDevice::GetFrameData csync failed : " << ::strerror(errno)); pendingSync[i] = FALSE; } ::munmap(videoBuffer, frame.size); } canMap = -1; videoBuffer = NULL;}BOOL PVideoInputV4lDevice::VerifyHardwareFrameSize(unsigned width, unsigned height){ struct video_window vwin; if (HINT(HINT_FORCE_LARGE_SIZE)) if( (width==352) && (height==288) ) { PTRACE(3,"PVideoInputV4lDevice\t VerifyHardwareFrameSize USB OK 352x288 "); return TRUE; } else { PTRACE(3,"PVideoInputV4lDevice\t VerifyHardwareFrameSize USB FAIL "<<width<<"x"<<height); return FALSE; } if (HINT(HINT_ALWAYS_WORKS_320_240) && (width==320) && (height==240) ) { PTRACE(3,"PVideoInputV4lDevice\t VerifyHardwareFrameSize OK for 320x240 "); return TRUE; } if (HINT(HINT_ALWAYS_WORKS_640_480) && (width==640) && (height==480) ) { PTRACE(3,"PVideoInputV4lDevice\t VerifyHardwareFrameSize OK for 640x480 "); return TRUE; } if (HINT(HINT_CGWIN_FAILS)) { PTRACE(3,"PVideoInputV4lDevice\t VerifyHardwareFrameSize fails for size " << width << "x" << height); return FALSE; } // Request current hardware frame size if (::ioctl(videoFd, VIDIOCGWIN, &vwin) < 0) { PTRACE(3,"PVideoInputV4lDevice\t VerifyHardwareFrameSize VIDIOCGWIN1 error::" << ::strerror(errno)); return FALSE; } // Request the width and height vwin.width = width; vwin.height = height; // The only defined flags appear to be as status indicators // returned in the CGWIN call. At least the bttv driver fails // when flags isn't zero. Check the driver hints for clearing // the flags. if (HINT(HINT_CSWIN_ZERO_FLAGS)) { PTRACE(1,"PVideoInputV4lDevice\t VerifyHardwareFrameSize: Clearing flags field"); vwin.flags = 0; } ::ioctl(videoFd, VIDIOCSWIN, &vwin); // Read back settings to be careful about existing (broken) V4L drivers if (::ioctl(videoFd, VIDIOCGWIN, &vwin) < 0) { PTRACE(3,"PVideoInputV4lDevice\t VerifyHardwareFrameSize VIDIOCGWIN2 error::" << ::strerror(errno)); return FALSE; } if ((vwin.width != width) || (vwin.height != height)) { PTRACE(3,"PVideoInputV4lDevice\t VerifyHardwareFrameSize Size mismatch."); return FALSE; } return TRUE;}int PVideoInputV4lDevice::GetBrightness() { if (!IsOpen()) return -1; struct video_picture vp; if (::ioctl(videoFd, VIDIOCGPICT, &vp) < 0) return -1; frameBrightness = vp.brightness; return frameBrightness; }int PVideoInputV4lDevice::GetWhiteness() { if (!IsOpen()) return -1; struct video_picture vp; if (::ioctl(videoFd, VIDIOCGPICT, &vp) < 0) return -1; frameWhiteness = vp.whiteness; return frameWhiteness;}int PVideoInputV4lDevice::GetColour() { if (!IsOpen()) return -1; struct video_picture vp; if (::ioctl(videoFd, VIDIOCGPICT, &vp) < 0) return -1; frameColour = vp.colour; return frameColour; }int PVideoInputV4lDevice::GetContrast() { if (!IsOpen()) return -1; struct video_picture vp; if (::ioctl(videoFd, VIDIOCGPICT, &vp) < 0) return -1; frameContrast = vp.contrast; return frameContrast; }int PVideoInputV4lDevice::GetHue() { if (!IsOpen()) return -1; struct video_picture vp; if (::ioctl(videoFd, VIDIOCGPICT, &vp) < 0) return -1; frameHue = vp.hue; return frameHue; }BOOL PVideoInputV4lDevice::SetBrightness(unsigned newBrightness) { if (!IsOpen()) return FALSE; struct video_picture vp; if (::ioctl(videoFd, VIDIOCGPICT, &vp) < 0) return FALSE; vp.brightness = newBrightness; if (::ioctl(videoFd, VIDIOCSPICT, &vp) < 0) return FALSE; frameBrightness=newBrightness; return TRUE;}BOOL PVideoInputV4lDevice::SetWhiteness(unsigned newWhiteness) { if (!IsOpen()) return FALSE; struct video_picture vp; if (::ioctl(videoFd, VIDIOCGPICT, &vp) < 0) return FALSE; vp.whiteness = newWhiteness; if (::ioctl(videoFd, VIDIOCSPICT, &vp) < 0) return FALSE; frameWhiteness = newWhiteness; return TRUE;}BOOL PVideoInputV4lDevice::SetColour(unsigned newColour) { if (!IsOpen()) return FALSE; struct video_picture vp; if (::ioctl(videoFd, VIDIOCGPICT, &vp) < 0) return FALSE; vp.colour = newColour; if (::ioctl(videoFd, VIDIOCSPICT, &vp) < 0) return FALSE; frameColour = newColour; return TRUE;}BOOL PVideoInputV4lDevice::SetContrast(unsigned newContrast) { if (!IsOpen()) return FALSE; struct video_picture vp; if (::ioctl(videoFd, VIDIOCGPICT, &vp) < 0) return FALSE; vp.contrast = newContrast; if (::ioctl(videoFd, VIDIOCSPICT, &vp) < 0) return FALSE; frameContrast = newContrast; return TRUE;}BOOL PVideoInputV4lDevice::SetHue(unsigned newHue) { if (!IsOpen()) return FALSE; struct video_picture vp; if (::ioctl(videoFd, VIDIOCGPICT, &vp) < 0) return FALSE; vp.hue = newHue; if (::ioctl(videoFd, VIDIOCSPICT, &vp) < 0) return FALSE; frameHue=newHue; return TRUE;}BOOL PVideoInputV4lDevice::GetParameters (int *whiteness, int *brightness, int *colour, int *contrast, int *hue){ if (!IsOpen()) return FALSE; struct video_picture vp; if (::ioctl(videoFd, VIDIOCGPICT, &vp) < 0) { PTRACE(3, "GetParams bombs out!"); return FALSE; } *brightness = vp.brightness; *colour = vp.colour; *contrast = vp.contrast; *hue = vp.hue; *whiteness = vp.whiteness; frameBrightness = *brightness; frameColour = *colour; frameContrast = *contrast; frameHue = *hue; frameWhiteness = *whiteness; return TRUE;}BOOL PVideoInputV4lDevice::TestAllFormats(){ return TRUE;}// End Of File ///////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -