/* * inputffdvb.c: FF-DVB input for the Atmolight-plugin * * See the README file for copyright information and how to reach the author. * * $Id$ */ #include #include #include #include #include #include "defs.h" #include "calculations.h" #include "input.h" #include "inputffdvb.h" #define DEV_VIDEO "/dev/video" // --- cInputFFDVB ----------------------------------------------------------- cInputFFDVB::cInputFFDVB() { } cInputFFDVB::~cInputFFDVB() { } bool cInputFFDVB::Open(const char* param) { int res; // init variables ColorPacket.channel[0].r = ColorPacket.channel[0].g = ColorPacket.channel[0].g = 0; ColorPacket.channel[4] = ColorPacket.channel[3] = ColorPacket.channel[2] = ColorPacket.channel[1] = ColorPacket.channel[0]; fd = -1; nextframe = 0; actframe = -1; char buffer[20]; snprintf(buffer, sizeof(buffer), "%s%d", DEV_VIDEO, cDevice::PrimaryDevice()->DeviceNumber()); if ((fd = open(buffer, O_RDWR)) == -1) { esyslog("Atmolight: Error opening %s", buffer); return false; } // get capabilities and check if capture is possible struct video_capability cap; ioctl(fd,VIDIOCGCAP,&cap); // dsyslog("Atmolight: videosizes: minh=%d maxh=%d minw=%d maxw=%d",cap.minheight,cap.maxheight,cap.minwidth,cap.maxwidth); if ((cap.minheight > CAP_HEIGHT) || (cap.maxheight < CAP_HEIGHT) || (cap.minwidth > CAP_WIDTH) || (cap.maxwidth < CAP_WIDTH)) { esyslog("Atmolight: videosize not supported!"); return false; } // set capture parameters struct video_window win; res = ioctl(fd,VIDIOCGWIN,&win); win.x = win.y = win.chromakey = 0; win.width = CAP_WIDTH; win.height = CAP_HEIGHT; win.flags = 0; if (ioctl(fd,VIDIOCSWIN,&win) == -1) { esyslog("Atmolight: ioctl: VIDIOCSWIN"); return false; } struct video_picture pic; res = ioctl(fd,VIDIOCGPICT,&pic); // set parameters of captured pictures pic.depth = 24; pic.palette = VIDEO_PALETTE_RGB24; pic.brightness = pic.hue = pic.colour = pic.contrast = pic.whiteness = 32767; if (ioctl(fd,VIDIOCSPICT,&pic) == -1) { esyslog("Atmolight: ioctl: VIDIOCSPICT"); return false; } // assign capture buffer if (ioctl(fd,VIDIOCGMBUF,&m_buf) == -1) { esyslog("Atmolight: ioctl: VIDIOCGMBUF"); return false; } #if 0 if (m_buf.frames < 2) { esyslog("Atmolight: videodevice isn't able to capture 2 frames!"); return false; } #endif map = mmap(0,m_buf.size,PROT_READ | PROT_WRITE, MAP_SHARED,fd,0); if (map == MAP_FAILED) { esyslog("Atmolight: framebuffer not initialized!"); return false; } v_map.frame = 0; v_map.width = CAP_WIDTH; v_map.height = CAP_HEIGHT; v_map.format = VIDEO_PALETTE_RGB24; Start(); // start thread return true; } bool cInputFFDVB::Close(void) { Cancel(); // stop thread cCondWait::SleepMs(100); if (map) { munmap(map, m_buf.size); } if (fd != -1) { close(fd); fd = -1; return true; } return false; } void cInputFFDVB::Action(void) { cTimeMs t; while (Running()) // in this loop the picture is read and the colors are calculated { t.Set(0); CalcColors(); // read picture and calculate colors if (t.Elapsed() < 20) // wait 20ms to avoid 100% CPU usage { cCondWait::SleepMs(20); } } } void cInputFFDVB::CalcColors(void) { tRGBColor RGB_Img; tHSVColor HSV_Img[IMAGE_SIZE]; unsigned char *map; map = (unsigned char *) Capture(); if (map == NULL) { return; } // handle start problems ;-) // generate HSV image for (int i = 0; i < IMAGE_SIZE; i++) // walk through map { // generate RGB pixel RGB_Img.b = *map++; RGB_Img.g = *map++; RGB_Img.r = *map++; // generate HSV pixel HSV_Img[i] = RGB2HSV(RGB_Img); } ColorPacket = CalcColorsAnalyzeHSV(HSV_Img); } void* cInputFFDVB::Capture(void) { if (fd != -1) { v_map.frame = nextframe; // set frame to be captured until next if (ioctl(fd,VIDIOCMCAPTURE,&v_map) == -1) { dsyslog("Atmolight: ioctl: VIDIOCMCAPTURE"); return NULL; } v_map.frame = actframe; // set frame to read out now if (actframe != -1) { if (ioctl(fd,VIDIOCSYNC,&v_map) == -1) { dsyslog("Atmolight: ioctl: VIDIOSYNC"); return NULL; } if (actframe == 0) { actframe = 1; nextframe = 0; return (char*)map; } else { nextframe = 1; actframe = 0; return (char*)map+m_buf.offsets[1]; } } else { actframe = 0; nextframe = 1; return NULL; // no frame captured yet } } else { return NULL; // videodev not open } }