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

File 2006-01-16.2.uvc.mythphone.patch, 29.2 KB (added by ynutcase-mythtv@…, 14 years ago)

revised patch

  • 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    void ShutdownMMAP();
     147    int ReadFrame(unsigned char *outbuf);
    150148
    151149#ifdef WIN32
    152150    HWND hwndCap;
     
    166164    int hDev;
    167165    QString DevName;
    168166    unsigned char *picbuff1;
     167    unsigned char *workbuff;
    169168    int imageLen;
    170169    int frameSize;
    171170    int fps;
    172171    int actualFps;
    173172    bool killWebcamThread;
    174     int wcFormat;
    175173    bool wcFlip;
    176174
    177175    QTime cameraTime;
    178176    int frameCount;
    179177    int totalCaptureMs;
    180178
     179    MJPEGContainer *decoder;
     180
    181181    // OS specific data structures
    182182#ifdef WIN32
    183183    CAPTUREPARMS capParams;
    184184    BITMAPINFO bitmapInfo;
    185185#else
    186     struct video_capability vCaps;
    187     struct video_window vWin;
    188     struct video_picture vPic;
    189     struct video_clip vClips;
     186    struct v4l2_capability vCaps;
     187    struct v4l2_format vFormat;
     188    struct v4l2_control brightness;
     189    struct v4l2_control contrast;
     190    struct v4l2_control colour;
     191    struct v4l2_control hue;
     192    struct v4l2_clip vClips;
     193    void *mmapBuf[WC_MMAP_BUFFERS];
     194    v4l2_buffer mmapBufDesc[WC_MMAP_BUFFERS];
    190195#endif
    191196
    192197};
  • 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
     276void Webcam::ShutdownMMAP() {
     277#ifndef WIN32
     278  if ((vCaps.capabilities & V4L2_CAP_READWRITE) ||
     279      (!vCaps.capabilities & V4L2_CAP_STREAMING)) {
     280    return;
     281  }
     282
     283  int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
     284  if (ioctl(hDev, VIDIOC_STREAMOFF, &type) != 0) {
     285    cerr << "Webcam: Unable to stop streaming.  ioctl(VIDIOC_STREAMOFF) failed" << endl;
     286  }
     287  for (int i = 0; i < WC_MMAP_BUFFERS; i++) {
     288    if (mmapBuf[i] != NULL) {
     289      if (munmap(mmapBuf[i], mmapBufDesc[i].m.offset) != 0) {
     290        cerr << "Webcam: munmap() " << i << " failed" << endl;
     291      }
     292    }
     293    mmapBuf[i] = NULL;
     294    memset(&mmapBufDesc[i], 0, sizeof(mmapBufDesc[i]));
     295  }
     296#endif /* !WIN32 */
     297}
     298
    201299void Webcam::camClose()
    202300{
    203301    KillThread();
    204302
    205303#ifndef WIN32
     304   
     305    ShutdownMMAP();
    206306    if (hDev <= 0)
    207307        cerr << "Can't close a camera that isn't open" << endl;
    208308    else
    209309    {
    210310        // There must be a widget procedure called close so make
    211311        // sure we call the proper one. Screwed me up for ages!
    212         ::close(hDev);
    213         hDev = 0;
     312        if (::close(hDev) != 0) {
     313            cerr << "Unable to close webcam" << endl;
     314        }
     315        hDev = 0;
    214316    }
     317
    215318#else
    216319    capCaptureStop(hwndCap);
    217320    capPreview(hwndCap, false);
     
    219322
    220323    if (picbuff1)
    221324        delete picbuff1;
     325    picbuff1 = NULL;
    222326
    223     picbuff1 = 0;
     327    if (workbuff)
     328        delete workbuff;
     329    workbuff = NULL;
     330
     331    if (decoder) {
     332      decoder->MJPEGStopDecoder();
     333      delete decoder;
     334    }
     335    decoder = NULL;
    224336}
    225337
    226338
     
    261373#ifndef WIN32
    262374    if (hDev > 0)
    263375    {
    264         ioctl(hDev, VIDIOCGCAP, &vCaps);
    265         ioctl(hDev, VIDIOCGWIN, &vWin);
    266         ioctl(hDev, VIDIOCGPICT, &vPic);
     376      if (ioctl(hDev, VIDIOC_QUERYCAP, &vCaps) != 0) {
     377        cerr << "Webcam: Error getting webcam capabilities" << endl;
     378      }
     379      if (ioctl(hDev, VIDIOC_G_FMT, &vFormat) != 0) {
     380        cerr << "Webcam: Error getting webcam format" << endl;
     381      }
    267382    }
    268383#else
    269384    capCaptureGetSetup(hwndCap, &capParams, sizeof(capParams));
     
    276391{
    277392    // Note you can't call this whilst the webcam is open because all the buffers will be the wrong size
    278393#ifndef WIN32
    279     memset(&vWin, 0, sizeof(struct video_window));
    280     vWin.width = width;
    281     vWin.height = height;
     394    vFormat.fmt.pix.width = width;
     395    vFormat.fmt.pix.height = height;
    282396
    283     if (ioctl(hDev, VIDIOCSWIN, &vWin) == -1)
    284         cerr << "Webcam: Error setting capture size " << width << "x" << height << endl;
     397    if (ioctl(hDev, VIDIOC_S_FMT, &vFormat) != 0)
     398      cerr << "Webcam: Error setting capture size " << width << "x" << height << endl;
    285399#else
    286400    bitmapInfo.bmiHeader.biHeight = height;
    287401    bitmapInfo.bmiHeader.biWidth = width;
     
    294408
    295409bool Webcam::SetPalette(unsigned int palette)
    296410{
     411#ifndef WIN32
     412    vFormat.fmt.pix.pixelformat = palette;
     413    ioctl(hDev, VIDIOC_S_FMT, &vFormat);
     414#else
    297415    int depth;
    298416
    299417    switch(palette)
    300418    {
    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;
     419    case V4L2_PIX_FMT_YVU420: depth = 12;  break;
     420    case V4L2_PIX_FMT_YUYV:    depth = 16;  break;
     421    case V4L2_PIX_FMT_YUV422P: depth = 16;  break;
     422    case V4L2_PIX_FMT_BGR32:   depth = 32;  break;
     423    case V4L2_PIX_FMT_BGR24:   depth = 24;  break;
     424    default:                   depth = 0;   break;
    307425    }
    308426
    309 #ifndef WIN32
    310     vPic.palette = palette;
    311     vPic.depth = depth;
    312     ioctl(hDev, VIDIOCSPICT, &vPic);
    313 #else
    314427    int winPalette = 0;
    315428    switch(palette)
    316429    {
    317430    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;
     431    case V4L2_PIX_FMT_YVU420:  winPalette = (MAKEFOURCC('I', 'Y', 'U', 'V'));   break;
     432    case V4L2_PIX_FMT_YUYV:    winPalette = (MAKEFOURCC('U', 'Y', 'V', 'Y'));   break;
     433    case V4L2_PIX_FMT_YUV422P: winPalette = (MAKEFOURCC('Y', 'V', '1', '6'));   break;
     434    case V4L2_PIX_FMT_BGR32:   winPalette = 0;                                  break;
     435    case V4L2_PIX_FMT_BGR24:   winPalette = 0;                                  break;
     436    case V4L2_PIX_FMT_MJPEG:   winPalette = 0;                                  break;
    323437    }
    324438    bitmapInfo.bmiHeader.biCompression = winPalette;
    325439    bitmapInfo.bmiHeader.biBitCount = depth;
     
    329443    readCaps();
    330444
    331445#ifndef WIN32
    332     return (vPic.palette == palette ? true : false);
     446    return (vFormat.fmt.pix.pixelformat == palette ? true : false);
    333447#else
    334448    return ((bitmapInfo.bmiHeader.biCompression == winPalette) && (bitmapInfo.bmiHeader.biBitCount == depth) ? true : false);
    335449#endif
     
    339453unsigned int Webcam::GetPalette(void)
    340454{
    341455#ifndef WIN32
    342     return (vPic.palette);
     456    return (vFormat.fmt.pix.pixelformat);
    343457#else
    344458    int winPalette = 0;
    345459    switch(bitmapInfo.bmiHeader.biCompression)
    346460    {
    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;
     461    case MAKEFOURCC('I', 'Y', 'U', 'V'):    return V4L2_PIX_FMT_YVU420;
     462    case MAKEFOURCC('U', 'Y', 'V', 'Y'):    return V4L2_PIX_FMT_YUYV;
     463    case MAKEFOURCC('Y', 'V', '1', '6'):    return V4L2_PIX_FMT_YUV422P;
    350464    default:                   
    351465    case 0:
    352466        if (bitmapInfo.bmiHeader.biBitCount == 24)
    353             return VIDEO_PALETTE_RGB24;
     467            return V4L2_PIX_FMT_BGR24;
    354468        else if (bitmapInfo.bmiHeader.biBitCount == 32)
    355             return VIDEO_PALETTE_RGB32;
     469            return V4L2_PIX_FMT_BGR32;
    356470    }
    357471    return 0;
    358472#endif
     
    367481  {
    368482    if (hDev > 0)
    369483    {
    370       vPic.brightness = v;
     484      brightness.id = V4L2_CID_BRIGHTNESS;
     485      brightness.value = v;
    371486
    372       if (ioctl(hDev, VIDIOCSPICT, &vPic) == -1)
     487      if (ioctl(hDev, VIDIOC_S_CTRL, &brightness) == -1)
    373488          cerr << "Error setting brightness" << endl;
    374489
    375490      readCaps();
     
    377492  }
    378493  else
    379494    cerr << "Invalid Brightness parameter" << endl;
    380   return vPic.brightness;
     495  return brightness.value;
    381496}
    382497
    383498int Webcam::SetContrast(int v)
     
    386501  {
    387502    if (hDev > 0)
    388503    {
    389       vPic.contrast = v ;
     504      contrast.id = V4L2_CID_CONTRAST;
     505      contrast.value = v ;
    390506
    391       if (ioctl(hDev, VIDIOCSPICT, &vPic) == -1)
     507      if (ioctl(hDev, VIDIOC_S_CTRL, &contrast) == -1)
    392508          cerr << "Error setting contrast" << endl;
    393509
    394510      readCaps();
     
    396512  }
    397513  else
    398514    cerr << "Invalid contrast parameter" << endl;
    399   return vPic.contrast;
     515  return contrast.value;
    400516}
    401517
    402518
     
    406522  {
    407523    if (hDev > 0)
    408524    {
    409       vPic.colour = v;
     525      colour.id = V4L2_CID_SATURATION;
     526      colour.value = v;
    410527
    411       if (ioctl(hDev, VIDIOCSPICT, &vPic) == -1)
     528      if (ioctl(hDev, VIDIOC_S_CTRL, &colour) == -1)
    412529          cerr << "Error setting colour" << endl;
    413530
    414531      readCaps();
     
    416533  }
    417534  else
    418535    cerr << "Invalid colour parameter" << endl;
    419   return vPic.colour;
     536  return colour.value;
    420537}
    421538
    422539
     
    426543  {
    427544    if (hDev > 0)
    428545    {
    429       vPic.hue = v;
     546      hue.id = V4L2_CID_HUE;
     547      hue.value = v;
    430548
    431       if (ioctl(hDev, VIDIOCSPICT, &vPic) == -1)
     549      if (ioctl(hDev, VIDIOC_S_CTRL, &hue) == -1)
    432550          cerr << "Error setting hue" << endl;
    433551
    434552      readCaps();
     
    436554  }
    437555  else
    438556    cerr << "Invalid hue parameter" << endl;
    439   return vPic.hue;
     557  return hue.value;
    440558}
    441559
    442560#endif
     
    463581  return actualFps;
    464582}
    465583
    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 
    484584void Webcam::GetCurSize(int *x, int *y)
    485585{
    486586    *y = WCHEIGHT;
     
    492592#ifdef WIN32
    493593    return false;
    494594#else
    495     return ((vCaps.type & VID_TYPE_MONOCHROME) ? true : false);
     595    struct v4l2_fmtdesc fmt;
     596    int i = 0;
     597    int greyonly = true;
     598    while (1) {
     599      memset(&fmt, 0, sizeof(fmt));
     600      fmt.index = i;
     601      fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
     602      if (ioctl(hDev, VIDIOC_ENUM_FMT, (void *) &fmt) != 0) {
     603        return greyonly;
     604      }
     605      if (fmt.pixelformat != V4L2_PIX_FMT_GREY) {
     606        greyonly = false;
     607      }
     608      i++;
     609    }
     610    /* never reached */
     611    return false;
    496612#endif
    497613};
    498614
     
    517633
    518634    switch (format)
    519635    {
    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;
     636    case V4L2_PIX_FMT_BGR24:
     637      client->format = PIX_FMT_BGR24;
     638      break;
     639    case V4L2_PIX_FMT_BGR32:
     640      client->format = PIX_FMT_RGBA32;
     641      break;
     642    case V4L2_PIX_FMT_YVU420: 
     643      client->format = PIX_FMT_YUV420P;   
     644      break;
     645    case V4L2_PIX_FMT_YUV422P:
     646      client->format = PIX_FMT_YUV422P;   
     647      break;
    524648    default:
    525649        cerr << "SIP: Attempt to register unsupported Webcam format\n";
    526650        delete client;
    527651        return 0;
    528652    }
     653    client->frameSize = avpicture_get_size(client->format, WCWIDTH, WCHEIGHT);
    529654
    530655    // Create some buffers for the client
    531656    for (int i=0; i<WC_CLIENT_BUFFERS; i++)
     
    630755    WebcamThreadWorker();
    631756}
    632757
     758int Webcam::ReadFrame(unsigned char *outbuf) {
     759#ifndef WIN32
     760  int len;
     761  if ((!(vCaps.capabilities & V4L2_CAP_READWRITE)) &&
     762      (!(vCaps.capabilities & V4L2_CAP_STREAMING))) {
     763    cerr << "webcam: no supported mechanisms for reading image data" << endl;
     764    return -1;
     765  }
     766
     767  memset(outbuf, 0, frameSize);
     768
     769  if (vCaps.capabilities & V4L2_CAP_READWRITE) {
     770    len = read(hDev, outbuf, frameSize);
     771    return len;
     772  }
     773 
     774  if (vCaps.capabilities & V4L2_CAP_STREAMING) {
     775    v4l2_buffer readBuf;
     776    memset(&readBuf, 0, sizeof(readBuf));
     777    readBuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
     778    readBuf.memory = V4L2_MEMORY_MMAP;
     779    if (ioctl(hDev, VIDIOC_DQBUF, &readBuf) != 0) {
     780      cerr << "Webcam: Unable to fetch streaming buffer" << endl;
     781      return -1;
     782    }
     783    len = readBuf.bytesused;
     784    if (len > frameSize) {
     785      cerr << "Webcam: outbuf not big enough" << endl;
     786      return -1;
     787    }
     788    memcpy(outbuf, mmapBuf[readBuf.index], len);
     789    if (ioctl(hDev, VIDIOC_QBUF, &readBuf) != 0) {
     790      cerr << "Webcam: Unable to requeue buffer" << endl;
     791    }
     792    return len;
     793  }
     794
     795#endif /* !WIN32 */
     796  return -1;
     797}
     798
    633799void Webcam::WebcamThreadWorker()
    634800{
    635801#ifndef WIN32
     
    637803
    638804    while((!killWebcamThread) && (hDev > 0))
    639805    {
    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;
     806      int len = ReadFrame(workbuff);
     807
     808      /*
     809       * See if any special handling (decompression) is required
     810       * for this frame
     811       */
     812      if (GetPalette() == V4L2_PIX_FMT_MJPEG) {
     813        if (!decoder->MJPEGDecodeFrame(workbuff, len, picbuff1, frameSize)) {
     814          cerr << "Unable to decode MJPEG frame" << endl;
     815          len = -1;
     816        } else {
     817          len = frameSize;
     818        }
     819      } else {
     820        memcpy(picbuff1, workbuff, frameSize);
     821      }
     822
     823      if (len == frameSize) {
     824        if (killWebcamThread)
     825          break;
     826       
     827        ProcessFrame(picbuff1, frameSize);
     828      }
     829      else
     830        cerr << "Error reading from webcam; got " << len << " bytes; expected " << frameSize << endl;
    649831    }
    650832#endif
    651833}
     
    663845    if (totalCaptureMs != 0)
    664846        actualFps = (frameCount*1000)/totalCaptureMs;
    665847
     848    int wcFormat = PIX_FMT_NONE;
     849    switch(GetPalette())
     850      {
     851      case V4L2_PIX_FMT_YVU420:     wcFormat = PIX_FMT_YUV420P;       break;
     852      case V4L2_PIX_FMT_MJPEG:      wcFormat = decoder->getPixFmt();  break;
     853      case V4L2_PIX_FMT_YUV422P:    wcFormat = PIX_FMT_YUV422P;       break;
     854      case V4L2_PIX_FMT_BGR24:      wcFormat = PIX_FMT_BGR24;         break;
     855      case V4L2_PIX_FMT_BGR32:      wcFormat = PIX_FMT_RGBA32;        break;
     856      default:
     857        cerr << "Webcam: Unsupported palette mode " << GetPalette() << endl;
     858      }
     859           
    666860    // Check if the webcam needs flipped (some webcams deliver pics upside down)
    667     if (wcFlip)
     861    if (wcFlip && wcFormat != PIX_FMT_NONE)
    668862    {
    669863        switch(wcFormat)
    670864        {
  • 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