Ticket #1051: 2006-01-16.uvc.mythphone.patch

File 2006-01-16.uvc.mythphone.patch, 28.6 KB (added by ynutcase-mythtv@…, 14 years ago)
  • webcam.h

     
    1919#include <sys/types.h>
    2020#include <sys/stat.h>
    2121#include <fcntl.h>
     22#include "mjpeg.h"
    2223
    2324#ifndef WIN32
    2425#include <sys/ioctl.h>
     
    3031#include <vfw.h>
    3132#endif
    3233
    33 
    34 #define RGB24_LEN(w,h)      ((w) * (h) * 3)
    35 #define RGB32_LEN(w,h)      ((w) * (h) * 4)
    36 #define YUV420P_LEN(w,h)    (((w) * (h) * 3) / 2)
    37 #define YUV422P_LEN(w,h)    ((w) * (h) * 2)
    38 
    3934// YUV --> RGB Conversion macros
    4035#define _S(a)           (a)>255 ? 255 : (a)<0 ? 0 : (a)
    4136#define _R(y,u,v) (0x2568*(y)                          + 0x3343*(u)) /0x2000
     
    4338#define _B(y,u,v) (0x2568*(y) + 0x40cf*(v))                                          /0x2000
    4439
    4540#ifdef WIN32
    46 #define VIDEO_PALETTE_YUV420P   0
    47 #define VIDEO_PALETTE_YUV422    1
    48 #define VIDEO_PALETTE_YUV422P   2
    49 #define VIDEO_PALETTE_RGB32     3
    50 #define VIDEO_PALETTE_RGB24     4
    51 #define VIDEO_PALETTE_GREY      5
     41#define V4L2_PIX_FMT_YVU420    0
     42#define V4L2_PIX_FMT_YUYV      1
     43#define V4L2_PIX_FMT_YUV422P   2
     44#define V4L2_PIX_FMT_BGR32     3
     45#define V4L2_PIX_FMT_BGR24     4
     46#define V4L2_PIX_FMT_GREY      5
     47#define V4L2_PIX_FMT_MJPEG     6
    5248#endif
    5349
    5450
     
    5652#define WCHEIGHT    bitmapInfo.bmiHeader.biHeight
    5753#define WCWIDTH     bitmapInfo.bmiHeader.biWidth
    5854#else
    59 #define WCWIDTH     vWin.width
    60 #define WCHEIGHT    vWin.height
     55#define WCWIDTH     vFormat.fmt.pix.width
     56#define WCHEIGHT    vFormat.fmt.pix.height
    6157#endif
    6258
    6359
    6460#define WC_CLIENT_BUFFERS   2
     61#define WC_MMAP_BUFFERS     4
    6562
    6663struct wcClient
    6764{
     
    117114    int  SetContrast(int v);
    118115    int  SetColour(int v);
    119116    int  SetHue(int v);
    120     int  GetBrightness(void) { return (vPic.brightness);};
    121     int  GetColour(void) { return (vPic.colour);};
    122     int  GetContrast(void) { return (vPic.contrast);};
    123     int  GetHue(void) { return (vPic.hue);};
    124     QString GetName(void) { return vCaps.name; };
     117    int  GetBrightness(void) { return (brightness.value);};
     118    int  GetColour(void) { return (colour.value);};
     119    int  GetContrast(void) { return (contrast.value);};
     120    int  GetHue(void) { return (hue.value);};
     121    QString GetName(void) { return (char *) vCaps.card; };
    125122#else
    126123    HWND GetHwnd() { return hwndCap; };   
    127124#endif
     
    130127
    131128    int  SetTargetFps(wcClient *client, int fps);
    132129    int  GetActualFps();
    133     void GetMaxSize(int *x, int *y);
    134     void GetMinSize(int *x, int *y);
    135130    void GetCurSize(int *x, int *y);
    136131    int isGreyscale(void);
    137132
     
    147142    void StartThread();
    148143    void KillThread();
    149144    void WebcamThreadWorker();
     145    void SetupMMAP();
     146    int ReadFrame(unsigned char *outbuf);
    150147
    151148#ifdef WIN32
    152149    HWND hwndCap;
     
    166163    int hDev;
    167164    QString DevName;
    168165    unsigned char *picbuff1;
     166    unsigned char *workbuff;
    169167    int imageLen;
    170168    int frameSize;
    171169    int fps;
    172170    int actualFps;
    173171    bool killWebcamThread;
    174     int wcFormat;
    175172    bool wcFlip;
    176173
    177174    QTime cameraTime;
    178175    int frameCount;
    179176    int totalCaptureMs;
    180177
     178    MJPEGContainer *decoder;
     179
    181180    // OS specific data structures
    182181#ifdef WIN32
    183182    CAPTUREPARMS capParams;
    184183    BITMAPINFO bitmapInfo;
    185184#else
    186     struct video_capability vCaps;
    187     struct video_window vWin;
    188     struct video_picture vPic;
    189     struct video_clip vClips;
     185    struct v4l2_capability vCaps;
     186    struct v4l2_format vFormat;
     187    struct v4l2_control brightness;
     188    struct v4l2_control contrast;
     189    struct v4l2_control colour;
     190    struct v4l2_control hue;
     191    struct v4l2_clip vClips;
     192    void *mmapBuf[WC_MMAP_BUFFERS];
     193    v4l2_buffer mmapBufDesc[WC_MMAP_BUFFERS];
    190194#endif
    191195
    192196};
  • phoneui.cpp

     
    140140            camBrightness = webcam->GetBrightness();
    141141            camContrast = webcam->GetContrast();
    142142            camColour = webcam->GetColour();
    143             localClient = webcam->RegisterClient(VIDEO_PALETTE_RGB32, 20, this);
     143            localClient = webcam->RegisterClient(V4L2_PIX_FMT_BGR32, 20, this);
    144144        }
    145145    }
    146146
     
    545545    if (h263->H263StartEncoder(txWidth, txHeight, txFps) &&
    546546        h263->H263StartDecoder(rxWidth, rxHeight))
    547547    {
    548         txClient = webcam->RegisterClient(VIDEO_PALETTE_YUV420P, txFps, this);
     548        txClient = webcam->RegisterClient(V4L2_PIX_FMT_YVU420, txFps, this);
    549549        wcDeliveredFrames = 0;
    550550        wcDroppedFrames = 0;
    551551        VideoOn = true;
  • mjpeg.h

     
     1/*
     2        mjpeg.h
     3
     4        (c) 2006 Nick Kralevich
     5       
     6    header for the mjpeg Container class
     7*/
     8
     9#ifndef MJPEG_CONTAINER_H_
     10#define MJPEG_CONTAINER_H_
     11
     12#ifndef WIN32
     13#include <mythtv/dialogbox.h>
     14#endif
     15
     16
     17extern "C" {
     18#ifdef WIN32
     19#include "libavcodec/avcodec.h"
     20#else
     21#include "mythtv/ffmpeg/avcodec.h"
     22#endif
     23}
     24
     25
     26class MJPEGContainer
     27{
     28  public:
     29    MJPEGContainer(void);
     30    virtual ~MJPEGContainer(void);
     31
     32    bool MJPEGStartDecoder(int w, int h);
     33    uchar *MJPEGDecodeFrame(const uchar *mjpegFrame, int mjpegFrameLen, uchar *outbuf, int outbufSize);
     34    void MJPEGStopDecoder();
     35    int getPixFmt();
     36
     37  private:
     38    AVFrame *pictureIn;
     39    AVCodec *mjpegDecoder;
     40    AVCodecContext *mjpegDecContext;
     41};
     42
     43#endif
  • webcam.cpp

     
    33
    44        (c) 2003 Paul Volkaerts
    55
     6        Modifications to support MJPEG, v4l2, and mmaped devices by Nick Kralevich
     7
    68    Webcam control and capture
    79*/
    810#include <qapplication.h>
     
    2022#include <fcntl.h>
    2123#include <linux/videodev.h>
    2224#include <mythtv/mythcontext.h>
     25#include <sys/mman.h>
    2326
    2427#include "config.h"
    2528#else
     
    4043{
    4144    hDev = 0;
    4245    DevName = "";
    43     picbuff1 = 0;
     46    picbuff1 = NULL;
     47    workbuff = NULL;
    4448    imageLen = 0;
    4549    frameSize = 0;
    4650    fps = 5;
    4751    killWebcamThread = true; // Leave true whilst its not running
    48     wcFormat = 0;
    4952    wcFlip = false;
     53    decoder = NULL;
    5054
    5155#ifndef WIN32
    5256    (void)parent;
    5357    (void)localVideoWidget;
    54     vCaps.name[0] = 0;
    55     vCaps.maxwidth = 0;
    56     vCaps.maxheight = 0;
    57     vCaps.minwidth = 0;
    58     vCaps.minheight = 0;
    59     memset(&vWin, 0, sizeof(struct video_window));
    60     vWin.width = 0;
    61     vWin.height = 0;
    62     vPic.brightness = 0;
    63     vPic.depth = 0;
    64     vPic.palette = 0;
    65     vPic.colour = 0;
    66     vPic.contrast = 0;
    67     vPic.hue = 0;
     58    memset(&vCaps, 0, sizeof(vCaps));
    6859
     60    memset(&vFormat, 0, sizeof(vFormat));
     61    vFormat.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
     62    vFormat.fmt.pix.width = 0;
     63    vFormat.fmt.pix.height = 0;
     64    vFormat.fmt.pix.pixelformat = 0;
     65    vFormat.fmt.pix.field = V4L2_FIELD_ANY;
     66    vFormat.fmt.pix.bytesperline = 0;
     67
     68    memset(&brightness, 0, sizeof(brightness));
     69    brightness.id = V4L2_CID_BRIGHTNESS;
     70    brightness.value = 0;
     71
     72    memset(&colour, 0, sizeof(colour));
     73    colour.id = V4L2_CID_SATURATION;
     74    colour.value = 0;
     75
     76    memset(&contrast, 0, sizeof(contrast));
     77    contrast.id = V4L2_CID_CONTRAST;
     78    contrast.value = 0;
     79
     80    memset(&hue, 0, sizeof(hue));
     81    hue.id = V4L2_CID_HUE;
     82    hue.value = 0;
     83
     84    for (int i = 0; i < WC_MMAP_BUFFERS; i++) {
     85      mmapBuf[i] = NULL;
     86      memset(&mmapBufDesc[i], 0, sizeof(mmapBufDesc[i]));
     87    }
    6988#else
    7089    wcMainWidget = parent;
    7190    hwndWebcam = localVideoWidget->winId();
     
    90109  if (handle <= 0)
    91110    return "";
    92111 
    93   struct video_capability tempCaps;
    94   ioctl(handle, VIDIOCGCAP, &tempCaps);
     112  struct v4l2_capability tempCaps;
     113  ioctl(handle, VIDIOC_QUERYCAP, &tempCaps);
    95114  ::close(handle);
    96   return tempCaps.name;
     115  return ((char *) tempCaps.card);
    97116#else
    98117  return "WIN32 Webcam (TODO)"; // TODO
    99118#endif
     
    132151    {
    133152        readCaps();
    134153
    135         if (!SetPalette(VIDEO_PALETTE_YUV420P) &&
    136             !SetPalette(VIDEO_PALETTE_YUV422P) &&
    137             !SetPalette(VIDEO_PALETTE_RGB24))
     154        if (!SetPalette(V4L2_PIX_FMT_YUV420) &&
     155            !SetPalette(V4L2_PIX_FMT_YUV422P) &&
     156            !SetPalette(V4L2_PIX_FMT_BGR24) &&
     157            !SetPalette(V4L2_PIX_FMT_MJPEG))
    138158        {
    139             cout << "Webcam does not support YUV420P, YUV422P, or RGB24 modes; these are the only ones currently supported. Closing webcam.\n";
     159            cout << "Webcam does not support YUV420P, YUV422P, RGB24, or MJPEG modes; these are the only ones currently supported. Closing webcam.\n";
    140160            camClose();
    141161            return false;
    142162        }
     
    153173            cout << "Could not set webcam to " << width << "x" << height << "; got " << actWidth << "x" << actHeight << " instead.\n";
    154174        }
    155175
     176        if (GetPalette() == V4L2_PIX_FMT_MJPEG) {
     177          decoder = new MJPEGContainer;
     178          decoder->MJPEGStartDecoder(WCWIDTH, WCHEIGHT);
     179        }
     180
    156181        //Allocate picture buffer memory
    157182        if (isGreyscale())
    158183        {
     
    165190        {
    166191            switch (GetPalette())
    167192            {
    168             case VIDEO_PALETTE_RGB24:   frameSize = RGB24_LEN(WCWIDTH, WCHEIGHT);   break;
    169             case VIDEO_PALETTE_RGB32:   frameSize = RGB32_LEN(WCWIDTH, WCHEIGHT);   break;
    170             case VIDEO_PALETTE_YUV420P: frameSize = YUV420P_LEN(WCWIDTH, WCHEIGHT); break;
    171             case VIDEO_PALETTE_YUV422P: frameSize = YUV422P_LEN(WCWIDTH, WCHEIGHT); break;
     193            case V4L2_PIX_FMT_BGR24:   
     194              frameSize = avpicture_get_size(PIX_FMT_BGR24, WCWIDTH, WCHEIGHT);
     195              break;
     196            case V4L2_PIX_FMT_BGR32:   
     197              frameSize = avpicture_get_size(PIX_FMT_RGBA32, WCWIDTH, WCHEIGHT);
     198              break;
     199            case V4L2_PIX_FMT_YVU420: 
     200              frameSize = avpicture_get_size(PIX_FMT_YUV420P, WCWIDTH, WCHEIGHT);
     201              break;
     202            case V4L2_PIX_FMT_MJPEG:   
     203              frameSize = avpicture_get_size(PIX_FMT_YUV422P, WCWIDTH, WCHEIGHT); //FIXME
     204              break;
     205            case V4L2_PIX_FMT_YUV422P:
     206              frameSize = avpicture_get_size(PIX_FMT_YUV422P, WCWIDTH, WCHEIGHT);
     207              break;
    172208            default:
    173                 cerr << "Palette mode " << GetPalette() << " not yet supported" << endl;
    174                 camClose();
    175                 return false;
    176                 break;
     209              cerr << "Palette mode " << GetPalette() << " not yet supported" << endl;
     210              camClose();
     211              return false;
     212              break;
    177213            }
    178214
    179215            picbuff1 = new unsigned char [frameSize];
     216            workbuff = new unsigned char [frameSize];
    180217        }
    181218
    182         switch(GetPalette())
    183         {
    184         case VIDEO_PALETTE_YUV420P:    wcFormat = PIX_FMT_YUV420P;    break;
    185         case VIDEO_PALETTE_YUV422P:    wcFormat = PIX_FMT_YUV422P;    break;
    186         case VIDEO_PALETTE_RGB24:      wcFormat = PIX_FMT_BGR24;      break;
    187         case VIDEO_PALETTE_RGB32:      wcFormat = PIX_FMT_RGBA32;     break;
    188         default:
    189             cerr << "Webcam: Unsupported palette mode " << GetPalette() << endl; // Should not get here, caught earlier
    190             camClose();
    191             return false;
    192             break;
    193         }
     219        SetupMMAP();
    194220
    195221        StartThread();
    196222    }
    197223    return opened;
    198224}
    199225
     226void Webcam::SetupMMAP() {
     227#ifndef WIN32
     228  if ((vCaps.capabilities & V4L2_CAP_READWRITE) ||
     229      (!vCaps.capabilities & V4L2_CAP_STREAMING)) {
     230    return;
     231  }
    200232
     233  struct v4l2_requestbuffers req;
     234  memset(&req, 0, sizeof(req));
     235  req.count   = WC_MMAP_BUFFERS;
     236  req.type    = V4L2_BUF_TYPE_VIDEO_CAPTURE;
     237  req.memory  = V4L2_MEMORY_MMAP;
     238  if (ioctl(hDev, VIDIOC_REQBUFS, &req) != 0) {
     239    cerr << "Webcam: VIDIOC_REQBUFS failed" << endl;
     240    return;
     241  }
     242  for (int i = 0; i < WC_MMAP_BUFFERS; i++) {
     243    mmapBufDesc[i].index = i;
     244    mmapBufDesc[i].type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
     245    mmapBufDesc[i].memory = V4L2_MEMORY_MMAP;
     246    if (ioctl(hDev, VIDIOC_QUERYBUF, &mmapBufDesc[i]) != 0) {
     247      cerr << "Webcam: VIDIOC_QUERYBUF failed" << endl;
     248      return;
     249    }
     250    mmapBuf[i] = mmap(0, /* start anywhere */
     251                      mmapBufDesc[i].length,
     252                      PROT_READ,
     253                      MAP_SHARED,
     254                      hDev,
     255                      mmapBufDesc[i].m.offset);
     256    if (mmapBuf[i] == MAP_FAILED) {
     257      cerr << "Webcam: Unable to mmap buffers" << endl;
     258      mmapBuf[i] = NULL;
     259      return;
     260    }
     261  }
     262
     263  for (int i = 0; i < WC_MMAP_BUFFERS; i++) {
     264    if (ioctl(hDev, VIDIOC_QBUF, &mmapBufDesc[i]) != 0) {
     265      cerr << "Webcam: failed to initially queue buffers" << endl;
     266    }
     267  } 
     268 
     269  int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
     270  if (ioctl(hDev, VIDIOC_STREAMON, &type) != 0) {
     271    cerr << "Webcam: Unable to start streaming.  ioctl(VIDIOC_STREAMON) failed" << endl;
     272  }
     273#endif /* !WIN32 */
     274}
     275
     276
    201277void Webcam::camClose()
    202278{
    203279    KillThread();
     
    212288        ::close(hDev);
    213289        hDev = 0;
    214290    }
     291
     292    int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
     293    if (ioctl(hDev, VIDIOC_STREAMOFF, &type) != 0) {
     294      cerr << "Webcam: Unable to stop streaming.  ioctl(VIDIOC_STREAMOFF) failed" << endl;
     295    }
     296    for(int i = 0; i < WC_MMAP_BUFFERS; i++) {
     297      if (mmapBuf[i] != NULL) {
     298        if (munmap(mmapBuf[i], mmapBufDesc[i].m.offset) != 0) {
     299          cerr << "Webcam: munmap() " << i << " failed" << endl;
     300        }
     301      }
     302      mmapBuf[i] = NULL;
     303      memset(&mmapBufDesc[i], 0, sizeof(mmapBufDesc[i]));
     304    }
    215305#else
    216306    capCaptureStop(hwndCap);
    217307    capPreview(hwndCap, false);
     
    220310    if (picbuff1)
    221311        delete picbuff1;
    222312
    223     picbuff1 = 0;
     313    picbuff1 = NULL;
     314
     315    if (workbuff)
     316        delete workbuff;
     317
     318    workbuff = NULL;
     319
     320    if (decoder) {
     321      decoder->MJPEGStopDecoder();
     322      delete decoder;
     323    }
     324    decoder = NULL;
    224325}
    225326
    226327
     
    261362#ifndef WIN32
    262363    if (hDev > 0)
    263364    {
    264         ioctl(hDev, VIDIOCGCAP, &vCaps);
    265         ioctl(hDev, VIDIOCGWIN, &vWin);
    266         ioctl(hDev, VIDIOCGPICT, &vPic);
     365      if (ioctl(hDev, VIDIOC_QUERYCAP, &vCaps) != 0) {
     366        cerr << "Webcam: Error getting webcam capabilities" << endl;
     367      }
     368      if (ioctl(hDev, VIDIOC_G_FMT, &vFormat) != 0) {
     369        cerr << "Webcam: Error getting webcam format" << endl;
     370      }
    267371    }
    268372#else
    269373    capCaptureGetSetup(hwndCap, &capParams, sizeof(capParams));
     
    276380{
    277381    // Note you can't call this whilst the webcam is open because all the buffers will be the wrong size
    278382#ifndef WIN32
    279     memset(&vWin, 0, sizeof(struct video_window));
    280     vWin.width = width;
    281     vWin.height = height;
     383    vFormat.fmt.pix.width = width;
     384    vFormat.fmt.pix.height = height;
    282385
    283     if (ioctl(hDev, VIDIOCSWIN, &vWin) == -1)
    284         cerr << "Webcam: Error setting capture size " << width << "x" << height << endl;
     386    if (ioctl(hDev, VIDIOC_S_FMT, &vFormat) != 0)
     387      cerr << "Webcam: Error setting capture size " << width << "x" << height << endl;
    285388#else
    286389    bitmapInfo.bmiHeader.biHeight = height;
    287390    bitmapInfo.bmiHeader.biWidth = width;
     
    294397
    295398bool Webcam::SetPalette(unsigned int palette)
    296399{
     400#ifndef WIN32
     401    vFormat.fmt.pix.pixelformat = palette;
     402    ioctl(hDev, VIDIOC_S_FMT, &vFormat);
     403#else
    297404    int depth;
    298405
    299406    switch(palette)
    300407    {
    301     case VIDEO_PALETTE_YUV420P: depth = 12;  break;
    302     case VIDEO_PALETTE_YUV422:  depth = 16;  break;
    303     case VIDEO_PALETTE_YUV422P: depth = 16;  break;
    304     case VIDEO_PALETTE_RGB32:   depth = 32;  break;
    305     case VIDEO_PALETTE_RGB24:   depth = 24;  break;
    306     default:                    depth = 0;   break;
     408    case V4L2_PIX_FMT_YVU420: depth = 12;  break;
     409    case V4L2_PIX_FMT_YUYV:    depth = 16;  break;
     410    case V4L2_PIX_FMT_YUV422P: depth = 16;  break;
     411    case V4L2_PIX_FMT_BGR32:   depth = 32;  break;
     412    case V4L2_PIX_FMT_BGR24:   depth = 24;  break;
     413    default:                   depth = 0;   break;
    307414    }
    308415
    309 #ifndef WIN32
    310     vPic.palette = palette;
    311     vPic.depth = depth;
    312     ioctl(hDev, VIDIOCSPICT, &vPic);
    313 #else
    314416    int winPalette = 0;
    315417    switch(palette)
    316418    {
    317419    default:                   
    318     case VIDEO_PALETTE_YUV420P: winPalette = (MAKEFOURCC('I', 'Y', 'U', 'V'));   break;
    319     case VIDEO_PALETTE_YUV422:  winPalette = (MAKEFOURCC('U', 'Y', 'V', 'Y'));   break;
    320     case VIDEO_PALETTE_YUV422P: winPalette = (MAKEFOURCC('Y', 'V', '1', '6'));   break;
    321     case VIDEO_PALETTE_RGB32:   winPalette = 0;                                  break;
    322     case VIDEO_PALETTE_RGB24:   winPalette = 0;                                  break;
     420    case V4L2_PIX_FMT_YVU420:  winPalette = (MAKEFOURCC('I', 'Y', 'U', 'V'));   break;
     421    case V4L2_PIX_FMT_YUYV:    winPalette = (MAKEFOURCC('U', 'Y', 'V', 'Y'));   break;
     422    case V4L2_PIX_FMT_YUV422P: winPalette = (MAKEFOURCC('Y', 'V', '1', '6'));   break;
     423    case V4L2_PIX_FMT_BGR32:   winPalette = 0;                                  break;
     424    case V4L2_PIX_FMT_BGR24:   winPalette = 0;                                  break;
     425    case V4L2_PIX_FMT_MJPEG:   winPalette = 0;                                  break;
    323426    }
    324427    bitmapInfo.bmiHeader.biCompression = winPalette;
    325428    bitmapInfo.bmiHeader.biBitCount = depth;
     
    329432    readCaps();
    330433
    331434#ifndef WIN32
    332     return (vPic.palette == palette ? true : false);
     435    return (vFormat.fmt.pix.pixelformat == palette ? true : false);
    333436#else
    334437    return ((bitmapInfo.bmiHeader.biCompression == winPalette) && (bitmapInfo.bmiHeader.biBitCount == depth) ? true : false);
    335438#endif
     
    339442unsigned int Webcam::GetPalette(void)
    340443{
    341444#ifndef WIN32
    342     return (vPic.palette);
     445    return (vFormat.fmt.pix.pixelformat);
    343446#else
    344447    int winPalette = 0;
    345448    switch(bitmapInfo.bmiHeader.biCompression)
    346449    {
    347     case MAKEFOURCC('I', 'Y', 'U', 'V'):    return VIDEO_PALETTE_YUV420P;
    348     case MAKEFOURCC('U', 'Y', 'V', 'Y'):    return VIDEO_PALETTE_YUV422;
    349     case MAKEFOURCC('Y', 'V', '1', '6'):    return VIDEO_PALETTE_YUV422P;
     450    case MAKEFOURCC('I', 'Y', 'U', 'V'):    return V4L2_PIX_FMT_YVU420;
     451    case MAKEFOURCC('U', 'Y', 'V', 'Y'):    return V4L2_PIX_FMT_YUYV;
     452    case MAKEFOURCC('Y', 'V', '1', '6'):    return V4L2_PIX_FMT_YUV422P;
    350453    default:                   
    351454    case 0:
    352455        if (bitmapInfo.bmiHeader.biBitCount == 24)
    353             return VIDEO_PALETTE_RGB24;
     456            return V4L2_PIX_FMT_BGR24;
    354457        else if (bitmapInfo.bmiHeader.biBitCount == 32)
    355             return VIDEO_PALETTE_RGB32;
     458            return V4L2_PIX_FMT_BGR32;
    356459    }
    357460    return 0;
    358461#endif
     
    367470  {
    368471    if (hDev > 0)
    369472    {
    370       vPic.brightness = v;
     473      brightness.id = V4L2_CID_BRIGHTNESS;
     474      brightness.value = v;
    371475
    372       if (ioctl(hDev, VIDIOCSPICT, &vPic) == -1)
     476      if (ioctl(hDev, VIDIOC_S_CTRL, &brightness) == -1)
    373477          cerr << "Error setting brightness" << endl;
    374478
    375479      readCaps();
     
    377481  }
    378482  else
    379483    cerr << "Invalid Brightness parameter" << endl;
    380   return vPic.brightness;
     484  return brightness.value;
    381485}
    382486
    383487int Webcam::SetContrast(int v)
     
    386490  {
    387491    if (hDev > 0)
    388492    {
    389       vPic.contrast = v ;
     493      contrast.id = V4L2_CID_CONTRAST;
     494      contrast.value = v ;
    390495
    391       if (ioctl(hDev, VIDIOCSPICT, &vPic) == -1)
     496      if (ioctl(hDev, VIDIOC_S_CTRL, &contrast) == -1)
    392497          cerr << "Error setting contrast" << endl;
    393498
    394499      readCaps();
     
    396501  }
    397502  else
    398503    cerr << "Invalid contrast parameter" << endl;
    399   return vPic.contrast;
     504  return contrast.value;
    400505}
    401506
    402507
     
    406511  {
    407512    if (hDev > 0)
    408513    {
    409       vPic.colour = v;
     514      colour.id = V4L2_CID_SATURATION;
     515      colour.value = v;
    410516
    411       if (ioctl(hDev, VIDIOCSPICT, &vPic) == -1)
     517      if (ioctl(hDev, VIDIOC_S_CTRL, &colour) == -1)
    412518          cerr << "Error setting colour" << endl;
    413519
    414520      readCaps();
     
    416522  }
    417523  else
    418524    cerr << "Invalid colour parameter" << endl;
    419   return vPic.colour;
     525  return colour.value;
    420526}
    421527
    422528
     
    426532  {
    427533    if (hDev > 0)
    428534    {
    429       vPic.hue = v;
     535      hue.id = V4L2_CID_HUE;
     536      hue.value = v;
    430537
    431       if (ioctl(hDev, VIDIOCSPICT, &vPic) == -1)
     538      if (ioctl(hDev, VIDIOC_S_CTRL, &hue) == -1)
    432539          cerr << "Error setting hue" << endl;
    433540
    434541      readCaps();
     
    436543  }
    437544  else
    438545    cerr << "Invalid hue parameter" << endl;
    439   return vPic.hue;
     546  return hue.value;
    440547}
    441548
    442549#endif
     
    463570  return actualFps;
    464571}
    465572
    466 void Webcam::GetMaxSize(int *x, int *y)
    467 {
    468 #ifdef WIN32
    469     *y=bitmapInfo.bmiHeader.biHeight; *x=bitmapInfo.bmiHeader.biWidth;
    470 #else
    471     *y=vCaps.maxheight; *x=vCaps.maxwidth;
    472 #endif
    473 };
    474 
    475 void Webcam::GetMinSize(int *x, int *y)
    476 {
    477 #ifdef WIN32
    478     *y=bitmapInfo.bmiHeader.biHeight; *x=bitmapInfo.bmiHeader.biWidth;
    479 #else
    480     *y=vCaps.minheight; *x=vCaps.minwidth;
    481 #endif
    482 };
    483 
    484573void Webcam::GetCurSize(int *x, int *y)
    485574{
    486575    *y = WCHEIGHT;
     
    492581#ifdef WIN32
    493582    return false;
    494583#else
    495     return ((vCaps.type & VID_TYPE_MONOCHROME) ? true : false);
     584    struct v4l2_fmtdesc fmt;
     585    int i = 0;
     586    int greyonly = true;
     587    while (1) {
     588      memset(&fmt, 0, sizeof(fmt));
     589      fmt.index = i;
     590      fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
     591      if (ioctl(hDev, VIDIOC_ENUM_FMT, (void *) &fmt) != 0) {
     592        return greyonly;
     593      }
     594      if (fmt.pixelformat != V4L2_PIX_FMT_GREY) {
     595        greyonly = false;
     596      }
     597      i++;
     598    }
     599    /* never reached */
     600    return false;
    496601#endif
    497602};
    498603
     
    517622
    518623    switch (format)
    519624    {
    520     case VIDEO_PALETTE_RGB24:   client->frameSize = RGB24_LEN(WCWIDTH, WCHEIGHT);   client->format = PIX_FMT_BGR24;      break;
    521     case VIDEO_PALETTE_RGB32:   client->frameSize = RGB32_LEN(WCWIDTH, WCHEIGHT);   client->format = PIX_FMT_RGBA32;     break;
    522     case VIDEO_PALETTE_YUV420P: client->frameSize = YUV420P_LEN(WCWIDTH, WCHEIGHT); client->format = PIX_FMT_YUV420P;    break;
    523     case VIDEO_PALETTE_YUV422P: client->frameSize = YUV422P_LEN(WCWIDTH, WCHEIGHT); client->format = PIX_FMT_YUV422P;    break;
     625    case V4L2_PIX_FMT_BGR24:
     626      client->format = PIX_FMT_BGR24;
     627      break;
     628    case V4L2_PIX_FMT_BGR32:
     629      client->format = PIX_FMT_RGBA32;
     630      break;
     631    case V4L2_PIX_FMT_YVU420: 
     632      client->format = PIX_FMT_YUV420P;   
     633      break;
     634    case V4L2_PIX_FMT_YUV422P:
     635      client->format = PIX_FMT_YUV422P;   
     636      break;
    524637    default:
    525638        cerr << "SIP: Attempt to register unsupported Webcam format\n";
    526639        delete client;
    527640        return 0;
    528641    }
     642    client->frameSize = avpicture_get_size(client->format, WCWIDTH, WCHEIGHT);
    529643
    530644    // Create some buffers for the client
    531645    for (int i=0; i<WC_CLIENT_BUFFERS; i++)
     
    630744    WebcamThreadWorker();
    631745}
    632746
     747int Webcam::ReadFrame(unsigned char *outbuf) {
     748#ifndef WIN32
     749  int len;
     750  if ((!(vCaps.capabilities & V4L2_CAP_READWRITE)) &&
     751      (!(vCaps.capabilities & V4L2_CAP_STREAMING))) {
     752    cerr << "webcam: no supported mechanisms for reading image data" << endl;
     753    return -1;
     754  }
     755
     756  memset(outbuf, 0, frameSize);
     757
     758  if (vCaps.capabilities & V4L2_CAP_READWRITE) {
     759    len = read(hDev, outbuf, frameSize);
     760    return len;
     761  }
     762 
     763  if (vCaps.capabilities & V4L2_CAP_STREAMING) {
     764    v4l2_buffer readBuf;
     765    memset(&readBuf, 0, sizeof(readBuf));
     766    readBuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
     767    readBuf.memory = V4L2_MEMORY_MMAP;
     768    if (ioctl(hDev, VIDIOC_DQBUF, &readBuf) != 0) {
     769      cerr << "Webcam: Unable to fetch streaming buffer" << endl;
     770      return -1;
     771    }
     772    len = readBuf.bytesused;
     773    if (len > frameSize) {
     774      cerr << "Webcam: outbuf not big enough" << endl;
     775      return -1;
     776    }
     777    memcpy(outbuf, mmapBuf[readBuf.index], len);
     778    if (ioctl(hDev, VIDIOC_QBUF, &readBuf) != 0) {
     779      cerr << "Webcam: Unable to requeue buffer" << endl;
     780    }
     781    return len;
     782  }
     783
     784#endif /* !WIN32 */
     785  return -1;
     786}
     787
    633788void Webcam::WebcamThreadWorker()
    634789{
    635790#ifndef WIN32
     
    637792
    638793    while((!killWebcamThread) && (hDev > 0))
    639794    {
    640         if ((len = read(hDev, picbuff1, frameSize)) == frameSize)
    641         {
    642             if (killWebcamThread)
    643                 break;
    644                
    645             ProcessFrame(picbuff1, frameSize);
    646         }
    647         else
    648             cerr << "Error reading from webcam; got " << len << " bytes; expected " << frameSize << endl;
     795      int len = ReadFrame(workbuff);
     796
     797      /*
     798       * See if any special handling (decompression) is required
     799       * for this frame
     800       */
     801      if (GetPalette() == V4L2_PIX_FMT_MJPEG) {
     802        if (!decoder->MJPEGDecodeFrame(workbuff, len, picbuff1, frameSize)) {
     803          cerr << "Unable to decode MJPEG frame" << endl;
     804          len = -1;
     805        } else {
     806          len = frameSize;
     807        }
     808      } else {
     809        memcpy(picbuff1, workbuff, frameSize);
     810      }
     811
     812      if (len == frameSize) {
     813        if (killWebcamThread)
     814          break;
     815       
     816        ProcessFrame(picbuff1, frameSize);
     817      }
     818      else
     819        cerr << "Error reading from webcam; got " << len << " bytes; expected " << frameSize << endl;
    649820    }
    650821#endif
    651822}
     
    663834    if (totalCaptureMs != 0)
    664835        actualFps = (frameCount*1000)/totalCaptureMs;
    665836
     837    int wcFormat = PIX_FMT_NONE;
     838    switch(GetPalette())
     839      {
     840      case V4L2_PIX_FMT_YVU420:     wcFormat = PIX_FMT_YUV420P;       break;
     841      case V4L2_PIX_FMT_MJPEG:      wcFormat = decoder->getPixFmt();  break;
     842      case V4L2_PIX_FMT_YUV422P:    wcFormat = PIX_FMT_YUV422P;       break;
     843      case V4L2_PIX_FMT_BGR24:      wcFormat = PIX_FMT_BGR24;         break;
     844      case V4L2_PIX_FMT_BGR32:      wcFormat = PIX_FMT_RGBA32;        break;
     845      default:
     846        cerr << "Webcam: Unsupported palette mode " << GetPalette() << endl;
     847      }
     848           
    666849    // Check if the webcam needs flipped (some webcams deliver pics upside down)
    667     if (wcFlip)
     850    if (wcFlip && wcFormat != PIX_FMT_NONE)
    668851    {
    669852        switch(wcFormat)
    670853        {
  • mjpeg.cpp

     
     1/*
     2        mjpeg.cpp
     3
     4        (c) 2006 Nick Kralevich
     5       
     6  Container class for the mjpeg Video Codec, which just interfaces to the libavcodec routines
     7
     8  TODO:-
     9    These are non reentrant so need a mutex implemented, if they are to be used elsewhere in the Myth frontend
     10*/
     11
     12#include <iostream>
     13using namespace std;
     14
     15#ifndef WIN32
     16#include "config.h"
     17#endif
     18
     19#include "mjpeg.h"
     20
     21MJPEGContainer::MJPEGContainer()
     22{
     23    mjpegDecoder = NULL;
     24    mjpegDecContext = NULL;
     25    pictureIn = NULL;
     26
     27    avcodec_init();
     28    avcodec_register_all();
     29}
     30
     31MJPEGContainer::~MJPEGContainer()
     32{
     33}
     34
     35bool MJPEGContainer::MJPEGStartDecoder(int w, int h)
     36{
     37    mjpegDecoder = avcodec_find_decoder(CODEC_ID_MJPEG);
     38    if (!mjpegDecoder)
     39    {
     40        cerr << "Could not find MJPEG decoder\n";
     41        return false;
     42    }
     43
     44    mjpegDecContext = avcodec_alloc_context();
     45    pictureIn = avcodec_alloc_frame();
     46
     47    mjpegDecContext->codec_id = CODEC_ID_MJPEG;
     48    mjpegDecContext->width = w;
     49    mjpegDecContext->height = h;
     50
     51    /* open it */
     52    if (avcodec_open(mjpegDecContext, mjpegDecoder) < 0)
     53    {
     54        cerr << "Could not open MJPEG Decoder\n";
     55        return false;
     56    }
     57   
     58    return true;
     59}
     60
     61int MJPEGContainer::getPixFmt() {
     62  return mjpegDecContext->pix_fmt;
     63}
     64
     65uchar *MJPEGContainer::MJPEGDecodeFrame(const uchar *mjpegFrame, int mjpegFrameLen, uchar *outbuf, int outbufSize)
     66{
     67    int got_picture;
     68
     69    memset(outbuf, 0, outbufSize);
     70
     71    int len = avcodec_decode_video(mjpegDecContext,
     72                                   pictureIn,
     73                                   &got_picture,
     74                                   (uint8_t *) mjpegFrame,
     75                                   mjpegFrameLen);
     76
     77    if (!got_picture) {
     78      cerr << "Webcam: expected picture but didn't get it..." << endl;
     79      return NULL;
     80    }
     81
     82    // int wrap = pictureIn->linesize[0];
     83    int xsize = mjpegDecContext->width;
     84    int ysize = mjpegDecContext->height;
     85    int pic_size = avpicture_get_size(mjpegDecContext->pix_fmt, xsize, ysize);
     86    if (pic_size != outbufSize) {
     87      cerr << "outbuf size mismatch.  pic_size: " << pic_size << " bufsize: " << outbufSize << endl;
     88      return NULL;
     89    }
     90   
     91    int size = avpicture_layout((AVPicture *)pictureIn,
     92                                mjpegDecContext->pix_fmt,
     93                                xsize,
     94                                ysize,
     95                                outbuf,
     96                                outbufSize);
     97    if (size != outbufSize) {
     98      cerr << "webcam: avpicture_layout error: " << size << endl;
     99      return NULL;
     100    }
     101    return outbuf;
     102}
     103
     104void MJPEGContainer::MJPEGStopDecoder()
     105{
     106    int got_picture;
     107
     108    // See if there is a last frame
     109    avcodec_decode_video(mjpegDecContext, pictureIn, &got_picture, NULL, 0);
     110
     111    if (mjpegDecContext)
     112    {
     113        avcodec_close(mjpegDecContext);
     114        av_free(mjpegDecContext);
     115        mjpegDecContext = 0;
     116    }
     117
     118    if (pictureIn)
     119        av_free(pictureIn);
     120    pictureIn = 0;
     121}
  • h263.cpp

     
    1515using namespace std;
    1616
    1717#ifndef WIN32
    18 #include <linux/videodev.h>
    1918#include "config.h"
    2019#endif
    2120