Beispiel #1
0
/******************************************************************************
 * Resize_config
 ******************************************************************************/
Int Resize_config(Resize_Handle hResize,
                  Buffer_Handle hSrcBuf, Buffer_Handle hDstBuf)
{
#ifdef CONFIG_DM365_IPIPE
    BufferGfx_Dimensions srcDim, dstDim;
    UInt                 hDif;
    UInt                 vDif;    
    struct rsz_channel_config rsz_chan_config;
    struct rsz_single_shot_config rsz_ss_config;

    /* Make sure our input parameters are valid */
    if (!hResize) {
        Dmai_err0("Resize_Handle parameter must not be NULL\n");
        return Dmai_EINVAL;
    }   
    
    if (!hSrcBuf) {
        Dmai_err0("Source buffer parameter must not be NULL\n");
        return Dmai_EINVAL;
    }   

    if (!hDstBuf) {
        Dmai_err0("Destination buffer parameter must not be NULL\n");
        return Dmai_EINVAL;
    }
    
    /* Buffer needs to be graphics buffers */
    if (Buffer_getType(hSrcBuf) != Buffer_Type_GRAPHICS ||
        Buffer_getType(hDstBuf) != Buffer_Type_GRAPHICS) {

        Dmai_err0("Src and dst buffers need to be graphics buffers\n");
        return Dmai_EINVAL;
    }

    BufferGfx_getDimensions(hSrcBuf, &srcDim);
    BufferGfx_getDimensions(hDstBuf, &dstDim);

    if (dstDim.width <= 0) {
        Dmai_err0("Destination buffer width must be greater than zero\n");
        return Dmai_EINVAL;
    }

    if (dstDim.height <= 0) {
        Dmai_err0("Destination buffer height must be greater than zero\n");
        return Dmai_EINVAL;
    }

    if ((srcDim.lineLength & 0x1F) != 0) {
        Dmai_err0("Source buffer pitch must be a multiple of 32 bytes\n");
        return Dmai_EINVAL;
    }

    if ((dstDim.lineLength & 0x1F) != 0) {
        Dmai_err0("Destination buffer pitch must be a multiple of 32 bytes\n");
        return Dmai_EINVAL;
    }


    /* Check for valid buffer scaling */
    hDif = srcDim.width  * 256 / dstDim.width;
    vDif = srcDim.height * 256 / dstDim.height;

    if (hDif < 32) {
        Dmai_err0("Horizontal up-scaling must not exceed 8x\n");
        return Dmai_EINVAL;
    }

    if (hDif > 4096) {
        Dmai_err0("Horizontal down-scaling must not exceed 1/16x\n");
        return Dmai_EINVAL;
    }

    if (vDif < 32) {
        Dmai_err0("Vertical up-scaling must not exceed 8x\n");
        return Dmai_EINVAL;
    }

    if (vDif > 4096) {
        Dmai_err0("Vertical down-scaling must not exceed 1/16x\n");
        return Dmai_EINVAL;
    }

    /* Set the driver default parameters and retrieve what was set */
    Dmai_clear(rsz_ss_config);
    rsz_chan_config.oper_mode = IMP_MODE_SINGLE_SHOT;
    rsz_chan_config.chain = 0;
    rsz_chan_config.len = 0;
    rsz_chan_config.config = NULL; /* to set defaults in driver */
    if (ioctl(hResize->fd, RSZ_S_CONFIG, &rsz_chan_config) < 0) {
        Dmai_err0("Error in setting default configuration for single shot mode\n");
        goto cleanup;
    }

    /* default configuration setting in Resizer successfull */
    Dmai_clear(rsz_ss_config);
    rsz_chan_config.oper_mode = IMP_MODE_SINGLE_SHOT;
    rsz_chan_config.chain = 0;
    rsz_chan_config.len = sizeof(struct rsz_single_shot_config);
    rsz_chan_config.config = &rsz_ss_config;

    if (ioctl(hResize->fd, RSZ_G_CONFIG, &rsz_chan_config) < 0) {
        Dmai_err0("Error in getting resizer channel configuration from driver\n");
        goto cleanup;
    }

    /* input params are set at the resizer */
    rsz_ss_config.input.image_width  = srcDim.width;
    rsz_ss_config.input.image_height = srcDim.height;
    rsz_ss_config.input.ppln = rsz_ss_config.input.image_width + 8;
    rsz_ss_config.input.lpfr = rsz_ss_config.input.image_height + 10;
    rsz_ss_config.input.pix_fmt = pixFormatConversion(BufferGfx_getColorSpace(hSrcBuf));
    rsz_ss_config.output1.pix_fmt = pixFormatConversion(BufferGfx_getColorSpace(hDstBuf));
    rsz_ss_config.output1.enable = 1;
    rsz_ss_config.output1.width = dstDim.width;
    rsz_ss_config.output1.height = dstDim.height;
    rsz_ss_config.output2.enable = 0;

    rsz_chan_config.oper_mode = IMP_MODE_SINGLE_SHOT;
    rsz_chan_config.chain = 0;
    rsz_chan_config.len = sizeof(struct rsz_single_shot_config);
    if (ioctl(hResize->fd, RSZ_S_CONFIG, &rsz_chan_config) < 0) {
        Dmai_err0("Error in setting default configuration for single shot mode\n");
        goto cleanup;
    }
    rsz_chan_config.oper_mode = IMP_MODE_SINGLE_SHOT;
    rsz_chan_config.chain = 0;
    rsz_chan_config.len = sizeof(struct rsz_single_shot_config);

    /* read again and verify */
    if (ioctl(hResize->fd, RSZ_G_CONFIG, &rsz_chan_config) < 0) {
        Dmai_err0("Error in getting configuration from driver\n");
        goto cleanup;
    }

    return Dmai_EOK;
    
cleanup:
    close(hResize->fd);
    hResize->fd = 0;    
    return Dmai_EFAIL;
#else
    Dmai_err0("not implemented\n");
    return Dmai_ENOTIMPL;
#endif
}
/******************************************************************************
 * Framecopy_accel_execute
 ******************************************************************************/
Int Framecopy_accel_config(Framecopy_Handle hFc,
                           Buffer_Handle hSrcBuf, Buffer_Handle hDstBuf)
{
#ifdef CONFIG_VDCE
    vdce_params_t params;
    BufferGfx_Dimensions srcDim;
    BufferGfx_Dimensions dstDim;
    Int width, height;

    /* Buffer needs to be graphics buffers */
    if (Buffer_getType(hSrcBuf) != Buffer_Type_GRAPHICS ||
        Buffer_getType(hDstBuf) != Buffer_Type_GRAPHICS) {

        Dmai_err0("Src and dst buffers need to be graphics buffers\n");
        return Dmai_EINVAL;
    }

    /* Sanity check buffer color space */
    if (BufferGfx_getColorSpace(hSrcBuf) !=
        BufferGfx_getColorSpace(hDstBuf)) {

        Dmai_err0("Src and dst buffers need to have same colorspace\n");
        return Dmai_EINVAL;
    }

    BufferGfx_getDimensions(hSrcBuf, &srcDim);
    BufferGfx_getDimensions(hDstBuf, &dstDim);

    /* Source and destination width must be even */
    if (dstDim.width % 2 || srcDim.width % 2) {
        Dmai_err2("Output (%d) and input width (%d) must be even\n",
                  dstDim.width, srcDim.width);
        return Dmai_EINVAL;
    }

    /* Pitches must be a multiple of 8 */
    if (dstDim.lineLength % 8 || srcDim.lineLength % 8) {
        Dmai_err2("Dst (%ld) and src (%ld) pitch must be a multiple of 8\n",
                  dstDim.lineLength, srcDim.lineLength);
        return Dmai_EINVAL;
    }

   /* Select the smallest resolution */
    width = srcDim.width < dstDim.width ? srcDim.width : dstDim.width;
    height = srcDim.height < dstDim.height ? srcDim.height : dstDim.height;

    Dmai_dbg2("Configuring resizer to copy image resolution %dx%d\n",
              width, height);

    params.vdce_mode = VDCE_OPERATION_RESIZING;

    if (ioctl(hFc->fd, VDCE_GET_DEFAULT, &params) < 0) {
        Dmai_err0("default params failed error.\n");
        return Dmai_EFAIL;
    }

    switch (BufferGfx_getColorSpace(hSrcBuf)) {
        case ColorSpace_YUV422PSEMI:
            params.vdce_mode_params.rsz_params.rsz_mode = VDCE_MODE_422;
            /* Speed up the conversion, note that this value hangs the resizer
             * for 420P color format 
             */
            params.common_params.prcs_unit_value = 256;
            break;
        case ColorSpace_YUV420PSEMI:
            params.vdce_mode_params.rsz_params.rsz_mode = VDCE_MODE_420;
            break;
        default:
            Dmai_err0("Colorspace format not supported\n");
            return Dmai_ENOTIMPL;
    }
 
    params.common_params.src_hsz_luminance = width;
    params.common_params.src_vsz_luminance = height;

    params.common_params.dst_hsz_luminance = width;
    params.common_params.dst_vsz_luminance = height;

    params.common_params.src_processing_mode = VDCE_PROGRESSIVE;
    params.common_params.src_mode = VDCE_FRAME_MODE;
    params.common_params.res_mode = VDCE_FRAME_MODE;

    /* call ioctl to set parameters */
    if (ioctl(hFc->fd, VDCE_SET_PARAMS, &params) < 0) {
        Dmai_err0("VDCE_SET_PARAMS failed \n");
        return Dmai_EFAIL;
    }

    return Dmai_EOK;
#else
    Dmai_err0("not implemented\n");
    return Dmai_ENOTIMPL;
#endif
}
/******************************************************************************
 * Display_v4l2_create
 ******************************************************************************/
Display_Handle Display_v4l2_create(BufTab_Handle hBufTab, Display_Attrs *attrs)
{
    struct v4l2_format         fmt;
    enum v4l2_buf_type         type;
    Display_Handle             hDisplay;
    Int32                      width, height, bytesperline;

    assert(attrs);

    /* delayStreamon not supported for this platform */
    if (attrs->delayStreamon == TRUE) {
        Dmai_err0("Support for delayed VIDIOC_STREAMON not implemented\n");
        return NULL;
    }

    /* Allocate space for state object */
    hDisplay = calloc(1, sizeof(Display_Object));

    if (hDisplay == NULL) {
        Dmai_err0("Failed to allocate space for Display Object\n");
        return NULL;
    }

    hDisplay->userAlloc = TRUE;

    /* Open video capture device */
    hDisplay->fd = open(attrs->displayDevice, O_RDWR, 0);

    if (hDisplay->fd == -1) {
        Dmai_err2("Cannot open %s (%s)\n",
                  attrs->displayDevice, strerror(errno));
        cleanup(hDisplay);
        return NULL;
    }

    /* Determine the video image dimensions */
    fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;

    if (ioctl(hDisplay->fd, VIDIOC_G_FMT, &fmt) == -1) {
        Dmai_err0("Failed to determine video display format\n");
        cleanup(hDisplay);
        return NULL;
    }

    Dmai_dbg3("Found video output size %dx%d pitch %d\n",
              fmt.fmt.pix.width, fmt.fmt.pix.height, fmt.fmt.pix.bytesperline);
    
    /* If video standard is set to auto then use current height and width */
    if (attrs->videoStd == VideoStd_AUTO) {
        width = fmt.fmt.pix.width;
        height = fmt.fmt.pix.height;
        bytesperline = fmt.fmt.pix.bytesperline;
    }
    else if (attrs->videoStd == -1) {
        width = attrs->width;
        height = attrs->height;
        bytesperline = width;
    }
    else {
        VideoStd_getResolution(attrs->videoStd, &width, &height);
        bytesperline = width;
    }

    fmt.fmt.pix.width = width;
    fmt.fmt.pix.height = height;
    fmt.fmt.pix.bytesperline = bytesperline;
    fmt.fmt.pix.sizeimage = bytesperline * height * 2;
    
    /* If colorspace is passed then use this colorspace */
    switch (attrs->colorSpace) {
        case ColorSpace_YUV422PSEMI: 
            fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_NV16;
            break;

        default:
            Dmai_err0("Output colorspace is not supported\n");
            cleanup(hDisplay);
            return NULL;
            break;            
    }

    Dmai_dbg3("Setting video output size %dx%d pitch %d\n",
              fmt.fmt.pix.width, fmt.fmt.pix.height, fmt.fmt.pix.bytesperline);
    
    if (ioctl(hDisplay->fd, VIDIOC_S_FMT, &fmt) == -1) {
        Dmai_err0("Failed to set video display format\n");
        cleanup(hDisplay);
        return NULL;
    }

    Dmai_dbg3("Current video output size %dx%d pitch %d\n",
              fmt.fmt.pix.width, fmt.fmt.pix.height, fmt.fmt.pix.bytesperline);

    /* Should the device driver allocate the display buffers? */
    if (hBufTab == NULL) {
        hDisplay->userAlloc = FALSE;

        if (_Dmai_v4l2DriverAlloc(hDisplay->fd,
                                  attrs->numBufs,
                                  V4L2_BUF_TYPE_VIDEO_OUTPUT,
                                  &hDisplay->bufDescs,
                                  &hBufTab,
                                  0, attrs->colorSpace) < 0) {
            Dmai_err1("Failed to allocate display driver buffers on %s\n",
                      attrs->displayDevice);
            cleanup(hDisplay);
            return NULL;
        }
    }
    else {
        Dmai_err0("User supplied buffers not supported\n");
        cleanup(hDisplay);
        return NULL;
    }

    /* Start the video streaming */
    type = V4L2_BUF_TYPE_VIDEO_OUTPUT;

    if (ioctl(hDisplay->fd, VIDIOC_STREAMON, &type) == -1) {
        Dmai_err2("VIDIOC_STREAMON failed on %s (%s)\n", attrs->displayDevice,
                                                         strerror(errno));
        cleanup(hDisplay);
        return NULL;
    }

    hDisplay->started = TRUE;
    hDisplay->hBufTab = hBufTab;
    hDisplay->displayStd = Display_Std_V4L2;

    return hDisplay;
}
Beispiel #4
0
/******************************************************************************
 * Sdec_create
 ******************************************************************************/
Sdec_Handle Sdec_create(Engine_Handle hEngine, Char *codecName,
                        SPHDEC_Params *params, SPHDEC_DynamicParams *dynParams)
{
    Sdec_Handle         hSd;
    SPHDEC_Handle       hDecode;
    SPHDEC_Status       decStatus;
    XDAS_Int32          status;

    if (hEngine == NULL || codecName == NULL ||
        params == NULL || dynParams == NULL) {
        Dmai_err0("Cannot pass null for engine, codec name, params or "
                  "dynamic params\n");
        return NULL;
    }

    /* Allocate space for the object */
    hSd = (Sdec_Handle)calloc(1, sizeof(Sdec_Object));

    if (hSd == NULL) {
        Dmai_err0("Failed to allocate space for Sdec Object\n");
        return NULL;
    }

    /* Create speech decoder */
    hDecode = SPHDEC_create(hEngine, codecName, params);

    if (hDecode == NULL) {
        Dmai_err0("Failed to create speech decoder\n");
        cleanup(hSd);
        return NULL;
    }

    Dmai_dbg1("Speech decoder instance of %s created\n", codecName);

    /* Set dynamic parameters */
    decStatus.size = sizeof(SPHDEC_Status);
    status = SPHDEC_control(hDecode, XDM_SETPARAMS, dynParams, &decStatus);

    if (status != SPHDEC_EOK) {
        Dmai_err1("XDM_SETPARAMS failed, status=%d\n", status);
        SPHDEC_delete(hDecode);
        cleanup(hSd);
        return NULL;
    }

    /* Get buffer information from video decoder */
    status = SPHDEC_control(hDecode, XDM_GETBUFINFO, dynParams,
                            &decStatus);

    if (status != SPHDEC_EOK) {
        Dmai_err0("XDM_GETBUFINFO control failed\n");
        SPHDEC_delete(hDecode);
        cleanup(hSd);
        return NULL;
    }

    Dmai_dbg2("Speech decoder requires buffer sizes in %u and out %u\n",
              (Uns) decStatus.bufInfo.minInBufSize[0],
              (Uns) decStatus.bufInfo.minInBufSize[1]);

    memcpy(hSd->minInBufSize,
           decStatus.bufInfo.minInBufSize, sizeof(hSd->minInBufSize));
    hSd->minNumInBufs = decStatus.bufInfo.minNumInBufs;
    memcpy(hSd->minOutBufSize,
           decStatus.bufInfo.minOutBufSize, sizeof(hSd->minOutBufSize));
    hSd->minNumOutBufs = decStatus.bufInfo.minNumOutBufs;

    hSd->hDecode = hDecode;

    return hSd;
}
/******************************************************************************
 * Framecopy_accel_execute
 ******************************************************************************/
Int Framecopy_accel_execute(Framecopy_Handle hFc,
                             Buffer_Handle hSrcBuf, Buffer_Handle hDstBuf)
{
#ifdef CONFIG_VDCE
    vdce_address_start_t params;
    BufferGfx_Dimensions srcDim;
    BufferGfx_Dimensions dstDim;
    UInt32 srcOffset, dstOffset;

    assert(hFc);
    assert(hSrcBuf);
    assert(hDstBuf);

    /* VDCE addresses must be a multiple of 8 */
    assert((((UInt32) Buffer_getUserPtr(hDstBuf)) & 0x7) == 0);
    assert((((UInt32) Buffer_getUserPtr(hSrcBuf)) & 0x7) == 0);

    /* Buffer sizes / 4 must be a multiple of 8 */
    assert(((Buffer_getSize(hSrcBuf) / 4) & 0x7) == 0);
    assert(((Buffer_getSize(hDstBuf) / 4) & 0x7) == 0);

    BufferGfx_getDimensions(hSrcBuf, &srcDim);
    BufferGfx_getDimensions(hDstBuf, &dstDim);

    assert(srcDim.x >= 0);
    assert(srcDim.y >= 0);
    assert(dstDim.x >= 0);
    assert(dstDim.y >= 0);
    assert((srcDim.x & 0x7) == 0);
    assert((dstDim.x & 0x7) == 0);

    srcOffset = srcDim.y * srcDim.lineLength + srcDim.x;
    dstOffset = dstDim.y * dstDim.lineLength + dstDim.x;

    params.buffers[VDCE_BUF_IN].index     = -1;
    params.buffers[VDCE_BUF_IN].buf_type  = VDCE_BUF_IN;
    params.buffers[VDCE_BUF_IN].virt_ptr  = ((Int32) Buffer_getUserPtr(hSrcBuf)+
                                                     srcOffset);
    params.buffers[VDCE_BUF_IN].size      = Buffer_getSize(hSrcBuf);

    params.buffers[VDCE_BUF_OUT].index    = -1;
    params.buffers[VDCE_BUF_OUT].buf_type = VDCE_BUF_OUT;
    params.buffers[VDCE_BUF_OUT].virt_ptr = ((Int32) Buffer_getUserPtr(hDstBuf)+
                                                     dstOffset);
    params.buffers[VDCE_BUF_OUT].size     = Buffer_getSize(hDstBuf);

    params.src_horz_pitch = srcDim.lineLength;
    params.res_horz_pitch = dstDim.lineLength;

    if (ioctl(hFc->fd, VDCE_START, &params) < 0) {
        Dmai_err0("Failed VDCE_START\n");
        return Dmai_EFAIL;
    }

    if (BufferGfx_getColorSpace(hDstBuf) == ColorSpace_YUV420PSEMI) {
        Buffer_setNumBytesUsed(hDstBuf, dstDim.width * dstDim.height * 3 / 2);
    }
    else {
        Buffer_setNumBytesUsed(hDstBuf, dstDim.width * dstDim.height * 2);
    }

    return Dmai_EOK;
#else
    Dmai_err0("not implemented\n");
    return Dmai_ENOTIMPL;
#endif
}
Beispiel #6
0
/******************************************************************************
 * _Dmai_v4l2DriverAlloc
 ******************************************************************************/
Int _Dmai_v4l2DriverAlloc(Int fd, Int numBufs, enum v4l2_buf_type type,
                          struct _VideoBufDesc **bufDescsPtr,
                          BufTab_Handle *hBufTabPtr, Int topOffset, 
                          ColorSpace_Type colorSpace)
{
    BufferGfx_Attrs             gfxAttrs = BufferGfx_Attrs_DEFAULT;
    struct v4l2_requestbuffers  req;
    struct v4l2_format          fmt;
    _VideoBufDesc              *bufDesc;
    Buffer_Handle               hBuf;
    Int                         bufIdx;
    Int8                       *virtPtr;

    Dmai_clear(fmt);
    fmt.type = type;

    if (ioctl(fd, VIDIOC_G_FMT, &fmt) == -1) {
        Dmai_err1("VIDIOC_G_FMT failed (%s)\n", strerror(errno));
        return Dmai_EFAIL;
    }

    Dmai_clear(req);
    req.count  = numBufs;
    req.type   = type;
    req.memory = V4L2_MEMORY_MMAP;

    /* Allocate buffers in the capture device driver */
    if (ioctl(fd, VIDIOC_REQBUFS, &req) == -1) {
        Dmai_err1("VIDIOC_REQBUFS failed (%s)\n", strerror(errno));
        return Dmai_ENOMEM;
    }

    if (req.count < numBufs || !req.count) {
        Dmai_err0("Insufficient device driver buffer memory\n");
        return Dmai_ENOMEM;
    }

    /* Allocate space for buffer descriptors */
    *bufDescsPtr = calloc(numBufs, sizeof(_VideoBufDesc));

    if (*bufDescsPtr == NULL) {
        Dmai_err0("Failed to allocate space for buffer descriptors\n");
        return Dmai_ENOMEM;
    }

    gfxAttrs.dim.width          = fmt.fmt.pix.width;
    gfxAttrs.dim.height         = fmt.fmt.pix.height;
    gfxAttrs.dim.lineLength     = fmt.fmt.pix.bytesperline;
    gfxAttrs.colorSpace         = colorSpace;
    gfxAttrs.bAttrs.reference   = TRUE;

    *hBufTabPtr = BufTab_create(numBufs, fmt.fmt.pix.sizeimage,
                                BufferGfx_getBufferAttrs(&gfxAttrs));

    if (*hBufTabPtr == NULL) {
        return Dmai_ENOMEM;
    }

    for (bufIdx = 0; bufIdx < numBufs; bufIdx++) {
        bufDesc = &(*bufDescsPtr)[bufIdx];

        /* Ask for information about the driver buffer */
        Dmai_clear(bufDesc->v4l2buf);
        bufDesc->v4l2buf.type   = type;
        bufDesc->v4l2buf.memory = V4L2_MEMORY_MMAP;
        bufDesc->v4l2buf.index  = bufIdx;

        if (ioctl(fd, VIDIOC_QUERYBUF, &bufDesc->v4l2buf) == -1) {
            Dmai_err1("Failed VIDIOC_QUERYBUF (%s)\n", strerror(errno));
            return Dmai_EFAIL;
        }

        /* Map the driver buffer to user space */
        virtPtr = mmap(NULL,
                       bufDesc->v4l2buf.length,
                       PROT_READ | PROT_WRITE,
                       MAP_SHARED,
                       fd,
                       bufDesc->v4l2buf.m.offset) + topOffset;

        if (virtPtr == MAP_FAILED) {
            Dmai_err1("Failed to mmap buffer (%s)\n", strerror(errno));
            return Dmai_EFAIL;
        }

        /* Initialize the Buffer with driver buffer information */
        hBuf = BufTab_getBuf(*hBufTabPtr, bufIdx);

        Buffer_setNumBytesUsed(hBuf, fmt.fmt.pix.bytesperline *
                                     fmt.fmt.pix.height);
        Buffer_setUseMask(hBuf, gfxAttrs.bAttrs.useMask);
        Buffer_setUserPtr(hBuf, virtPtr);

        /* Initialize buffer to black */
        _Dmai_blackFill(hBuf);

        Dmai_dbg3("Driver buffer %d mapped to %#x has physical address "
                  "%#lx\n", bufIdx, (Int) virtPtr, Buffer_getPhysicalPtr(hBuf));

        bufDesc->hBuf = hBuf;

        /* Queue buffer in device driver */
        if (ioctl(fd, VIDIOC_QBUF, &bufDesc->v4l2buf) == -1) {
            Dmai_err1("VIODIOC_QBUF failed (%s)\n", strerror(errno));
            return Dmai_EFAIL;
        }
    }

    return Dmai_EOK;
}
Beispiel #7
0
/******************************************************************************
 * Sound_alsa_create
 ******************************************************************************/
Sound_Handle Sound_alsa_create(Sound_Attrs *attrs)
{
    Sound_Handle hSound;
    Int status;
    snd_output_t *log;
    assert(attrs);

    hSound = calloc(1, sizeof(Sound_Object));

    if (hSound == NULL) {
        Dmai_err0("Failed to allocate space for Sound Object\n");
        return NULL;
    }

    hSound->soundStd = attrs->soundStd;
    hSound->sampleRate = attrs->sampleRate;
    hSound->channels = attrs->channels;
    hSound->bufSize  = attrs->bufSize;

    if (attrs->mode == Sound_Mode_INPUT ||
        attrs->mode == Sound_Mode_FULLDUPLEX) {

        status = snd_pcm_open(&hSound->rcIn, AUDIO_DEVICE,
                              SND_PCM_STREAM_CAPTURE, 0);

        if (status < 0) {
            Dmai_err2("Failed to open ALSA sound device for input %s (%s)\n",
                      AUDIO_DEVICE, snd_strerror(status));
            Sound_alsa_delete(hSound);
            return NULL;
        }

        /* Allocate a PCM SW and HW Param structure */
        status = snd_pcm_hw_params_malloc(&hSound->hwParamsIn);

        if (status < 0) {
            Dmai_err2("Failed to alloc hardware param structure on %s (%s)\n",
                      AUDIO_DEVICE, snd_strerror(status));
            Sound_alsa_delete(hSound);
            return NULL;
        }

        status = snd_pcm_sw_params_malloc(&hSound->swParamsIn);

        if (status < 0) {
            Dmai_err2("Failed to alloc software param structure on %s (%s)\n",
                      AUDIO_DEVICE, snd_strerror(status));
            Sound_alsa_delete(hSound);
            return NULL;
        }
    
        if (initHwParams(hSound->rcIn,hSound->hwParamsIn,attrs,hSound) < 0) {
            Sound_alsa_delete(hSound);
            return NULL;
        }

        if (initSwParams(hSound->rcIn,hSound->swParamsIn,hSound,1) < 0) {
            Sound_alsa_delete(hSound);
            return NULL;
        }
    }

    if (attrs->mode == Sound_Mode_OUTPUT ||
        attrs->mode == Sound_Mode_FULLDUPLEX) {

        status = snd_pcm_open(&hSound->rcOut, AUDIO_DEVICE,
                              SND_PCM_STREAM_PLAYBACK, 0);

        if (status < 0) {
            Dmai_err2("Failed to open ALSA sound device for output %s (%s)\n",
                      AUDIO_DEVICE, snd_strerror(status));
            Sound_alsa_delete(hSound);
            return NULL;
        }

        /* Allocate a PCM SW and HW Param structure */
        status = snd_pcm_hw_params_malloc(&hSound->hwParamsOut);

        if (status < 0) {
            Dmai_err2("Failed to alloc hardware param structure on %s (%s)\n",
                      AUDIO_DEVICE, snd_strerror(status));
            Sound_alsa_delete(hSound);
            return NULL;
        }

        status = snd_pcm_sw_params_malloc(&hSound->swParamsOut);

        if (status < 0) {
            Dmai_err2("Failed to alloc hardware param structure on %s (%s)\n",
                      AUDIO_DEVICE, snd_strerror(status));
            Sound_alsa_delete(hSound);
            return NULL;
        }

        if (initHwParams(hSound->rcOut,hSound->hwParamsOut,attrs,hSound) < 0) {
            Sound_alsa_delete(hSound);
            return NULL;
        }

        if (initSwParams(hSound->rcOut,hSound->swParamsOut,hSound,0) < 0) {
            Sound_alsa_delete(hSound);
            return NULL;
        }

        if (setMixerVolume (attrs) <0) {
            Sound_alsa_delete (hSound);
            return NULL;
        }
    }
#if 0
if (attrs->mode != Sound_Mode_OUTPUT) {
        if (attrs->soundInput == Sound_Input_MIC) {
            if(setMixerControl(RIGHT_LINE_CTRL_ELEM, 0) != Dmai_EOK) {
                Dmai_err0("Failed to configure Right_PGA_Mixer_Line1R_Switch\n");
                Sound_alsa_delete(hSound);
                return NULL;
            }
            if(setMixerControl(LEFT_LINE_CTRL_ELEM, 0) != Dmai_EOK) {
                Dmai_err0("Failed to configure Left_PGA_Mixer_Line1L_Switch\n");
                Sound_alsa_delete(hSound);
                return NULL;
            }
            if(setMixerControl(RIGHT_MIC_CTRL_ELEM, 1) != Dmai_EOK) {
                Dmai_err0("Failed to configure Right_PGA_Mixer_Mic3R_Switch\n");
                Sound_alsa_delete(hSound);
                return NULL;
            }
            if(setMixerControl(LEFT_MIC_CTRL_ELEM, 1) != Dmai_EOK) {
                Dmai_err0("Failed to configure Left_PGA_Mixer_Mic3L_Switch\n");
                Sound_alsa_delete(hSound);
                return NULL;
            }
        } else if (attrs->soundInput == Sound_Input_LINE) {
            if(setMixerControl(RIGHT_LINE_CTRL_ELEM, 1) != Dmai_EOK) {
                Dmai_err0("Failed to configure Right_PGA_Mixer_Line1R_Switch\n");
                Sound_alsa_delete(hSound);
                return NULL;
            }
            if(setMixerControl(LEFT_LINE_CTRL_ELEM, 1) != Dmai_EOK) {
                Dmai_err0("Failed to configure Left_PGA_Mixer_Line1L_Switch\n");
                Sound_alsa_delete(hSound);
                return NULL;
            }
            if(setMixerControl(RIGHT_MIC_CTRL_ELEM, 0) != Dmai_EOK) {
                Dmai_err0("Failed to configure Right_PGA_Mixer_Mic3R_Switch\n");
                Sound_alsa_delete(hSound);
                return NULL;
            }
            if(setMixerControl(LEFT_MIC_CTRL_ELEM, 0) != Dmai_EOK) {
                Dmai_err0("Failed to configure Left_PGA_Mixer_Mic3L_Switch\n");
                Sound_alsa_delete(hSound);
                return NULL;
            }
        }
    }
    snd_output_close(log);
#endif
    return hSound;
}
Beispiel #8
0
/******************************************************************************
 * _Dmai_v4l2UserAlloc
 ******************************************************************************/
Int _Dmai_v4l2UserAlloc(Int fd, Int numBufs, enum v4l2_buf_type type,
                        struct _VideoBufDesc **bufDescsPtr,
                        BufTab_Handle hBufTab, Int topOffset, 
                        ColorSpace_Type colorSpace, Int queueBuffers)
{
    struct v4l2_requestbuffers  req;
    struct v4l2_format          fmt;
    _VideoBufDesc              *bufDesc;
    Buffer_Handle               hBuf;
    Int                         bufIdx;

    Dmai_clear(fmt);
    fmt.type = type;

    /*
     * Tell the driver that we will use user allocated buffers, but don't
     * allocate any buffers in the driver (just the internal descriptors).
     */
    Dmai_clear(req);
    req.type   = type;
    req.count  = numBufs; 
    req.memory = V4L2_MEMORY_USERPTR;

    if (ioctl(fd, VIDIOC_REQBUFS, &req) == -1) {
        Dmai_err0("Could not allocate video display buffers\n");
        return Dmai_ENOMEM;
    }

    /* The driver may return less buffers than requested */
    if (req.count < numBufs || !req.count) {
        Dmai_err0("Insufficient device driver buffer memory\n");
        return Dmai_ENOMEM;
    }

    /* Allocate space for buffer descriptors */
    *bufDescsPtr = calloc(numBufs, sizeof(_VideoBufDesc));

    if (*bufDescsPtr == NULL) {
        Dmai_err0("Failed to allocate space for buffer descriptors\n");
        return Dmai_ENOMEM;
    }

    for (bufIdx = 0; bufIdx < numBufs; bufIdx++) {
        bufDesc = &(*bufDescsPtr)[bufIdx];
        hBuf = BufTab_getBuf(hBufTab, bufIdx);

        if (hBuf == NULL) {
            Dmai_err0("Failed to get buffer from BufTab for display\n");
            return Dmai_ENOMEM;
        }

        if (Buffer_getType(hBuf) != Buffer_Type_GRAPHICS) {
            Dmai_err0("Buffer supplied to Display not a Graphics buffer\n");
            return Dmai_EINVAL;
        }

        Dmai_clear(bufDesc->v4l2buf);
        bufDesc->v4l2buf.index     = bufIdx;
        bufDesc->v4l2buf.type      = type;
        bufDesc->v4l2buf.memory    = V4L2_MEMORY_USERPTR;
        bufDesc->v4l2buf.m.userptr = (UInt32) Buffer_getUserPtr(hBuf);
        bufDesc->v4l2buf.length    = Buffer_getSize(hBuf);
        bufDesc->hBuf              = hBuf;
        bufDesc->used              = (queueBuffers == FALSE) ? TRUE : FALSE;

        /* If queueBuffers is TRUE, initialize the buffers to black and queue
         * them into the driver.
         */
        if (queueBuffers == TRUE) {
            Buffer_setNumBytesUsed(hBuf, Buffer_getSize(hBuf));
            _Dmai_blackFill(hBuf);

            /* Queue buffer in device driver */
            if (ioctl(fd, VIDIOC_QBUF, &bufDesc->v4l2buf) == -1) {
                Dmai_err1("VIODIC_QBUF failed (%s)\n", strerror(errno));
                return Dmai_EFAIL;
            }
        }
    }

    return Dmai_EOK;
}
/******************************************************************************
 * Framecopy_resizer_accel_config
 ******************************************************************************/
Int Framecopy_resizer_accel_config(Framecopy_Handle hFc,
                           Buffer_Handle hSrcBuf, Buffer_Handle hDstBuf)
{
#if defined(CONFIG_VIDEO_OMAP34XX_ISP_RESIZER)
    struct v4l2_requestbuffers reqbuf;
    Int rszRate;
    BufferGfx_Dimensions srcDim, dstDim;
    struct rsz_params  params = {
        0,                              /* in_hsize (set at run time) */
        0,                              /* in_vsize (set at run time) */
        0,                              /* in_pitch (set at run time) */
        RSZ_INTYPE_YCBCR422_16BIT,      /* inptyp */
        0,                              /* vert_starting_pixel */
        0,                              /* horz_starting_pixel */
        0,                              /* cbilin */
        RSZ_PIX_FMT_UYVY,               /* pix_fmt */
        0,                              /* out_hsize (set at run time) */
        0,                              /* out_vsize (set at run time) */
        0,                              /* out_pitch (set at run time) */
        0,                              /* hstph */
        0,                              /* vstph */
        {                               /* hfilt_coeffs */
            256, 0, 0, 0, 256, 0, 0, 0, 256, 0, 0, 0, 256, 0, 0, 0,
            256, 0, 0, 0, 256, 0, 0, 0, 256, 0, 0, 0, 256, 0, 0, 0
        },
        {                               /* vfilt_coeffs */
            256, 0, 0, 0, 256, 0, 0, 0, 256, 0, 0, 0, 256, 0, 0, 0,
            256, 0, 0, 0, 256, 0, 0, 0, 256, 0, 0, 0, 256, 0, 0, 0
        },
        {                               /* yenh_params */
            0,                              /* type */
            0,                              /* gain */
            0,                              /* slop */
            0                               /* core */
        }
    };

    /* Pointers must be a multiple of 4096 bytes */
    assert((Buffer_getPhysicalPtr(hDstBuf) & 0xFFF) == 0);
    assert((Buffer_getPhysicalPtr(hSrcBuf) & 0xFFF) == 0);

    BufferGfx_getDimensions(hSrcBuf, &srcDim);
    BufferGfx_getDimensions(hDstBuf, &dstDim);

    Dmai_dbg2("Configuring resizer to copy image of resolution %dx%d\n",
              srcDim.width, srcDim.height);

    /* Source and destination pitch must be 32 bytes aligned */
    if (srcDim.lineLength % 32 || dstDim.lineLength % 32) {
        Dmai_err2("Src (%ld) and dst (%ld) must be aligned on 32 bytes\n",
                  srcDim.lineLength, dstDim.lineLength);
        return Dmai_EINVAL;
    }

    /* Set up the copy job */
    params.in_hsize            = srcDim.width;
    params.in_vsize            = srcDim.height;
    params.in_pitch            = srcDim.lineLength;
    params.out_hsize           = dstDim.width;
    params.out_vsize           = dstDim.height;
    params.out_pitch           = dstDim.lineLength;
    params.cbilin              = 0;
    params.pix_fmt             = RSZ_PIX_FMT_UYVY;
    params.vert_starting_pixel = 0;
    params.horz_starting_pixel = 0;
    params.inptyp              = RSZ_INTYPE_YCBCR422_16BIT;
    params.hstph               = 0;
    params.vstph               = 0;
    params.yenh_params.type    = 0;
    params.yenh_params.gain    = 0;
    params.yenh_params.slop    = 0;
    params.yenh_params.core    = 0;

    hFc->inSize  = srcDim.lineLength * params.in_vsize;
    hFc->outSize = dstDim.lineLength * params.out_vsize;

    if (ioctl(hFc->fd, RSZ_S_PARAM, &params) == -1) {
        Dmai_err0("Framecopy setting parameters failed.\n");
        return Dmai_EFAIL;
    }

    rszRate = 0x0;

    if (ioctl(hFc->fd, RSZ_S_EXP, &rszRate) == -1) {
        Dmai_err0("Framecopy setting read cycle failed.\n");
        return Dmai_EFAIL;
    }

    reqbuf.type     = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    reqbuf.memory   = V4L2_MEMORY_USERPTR;
    reqbuf.count    = 2;

    if (ioctl(hFc->fd, RSZ_REQBUF, &reqbuf) == -1) {
        Dmai_err0("Request buffer failed.\n");
        return Dmai_EFAIL;
    }

    return Dmai_EOK;
#else
    Dmai_err0("not implemented\n");
    return Dmai_ENOTIMPL;
#endif /* end CONFIG_VIDEO_OMAP34XX_ISP_RESIZER */
}
Beispiel #10
0
/******************************************************************************
 * Capture_detectVideoStd
 ******************************************************************************/
Int Capture_detectVideoStd(Capture_Handle hCapture, VideoStd_Type *videoStdPtr,
                           Capture_Attrs *attrs)
{
    v4l2_std_id             id;
    struct v4l2_input       input;
    Int                     index;
    Int                     fd;
    struct v4l2_standard    std;

    assert(videoStdPtr);
    assert(attrs);

    if (attrs->videoStd < 0 || attrs->videoStd > VideoStd_COUNT) {
        Dmai_err1("Invalid capture standard given (%d)\n", attrs->videoStd);
        return Dmai_EINVAL;
    }

    if (hCapture) {
        fd = hCapture->fd;
    }
    else {
        fd = open(attrs->captureDevice, O_RDWR, 0);

        if (fd == -1) {
            Dmai_err2("Cannot open %s (%s)\n", attrs->captureDevice,
                                               strerror(errno));
            return Dmai_EFAIL;
        }
    }

    /* Display available video input */
    Dmai_dbg0("Available video input:\n");
    for (index=0;; index++) {

        input.index = index;
        if (ioctl(fd, VIDIOC_ENUMINPUT, &input) < 0) {
            if (errno == EINVAL || errno == ENOTTY)
                break;
        }

        Dmai_dbg1(" name=%s\n", input.name);
    }

    /* Set video input */
    switch (attrs->videoInput) {

        case Capture_Input_SVIDEO:
                Dmai_dbg0("Setting video input to SVIDEO\n");
                index = 1;
                break;
        case Capture_Input_COMPOSITE:
                Dmai_dbg0("Setting video input to COMPOSITE\n");
                index = 0;
                break;
        default:
                Dmai_err0("Unknown video input\n");
                return Dmai_EFAIL;
                break;
    }
        
    if (ioctl(fd, VIDIOC_S_INPUT, &index) < 0) {
        Dmai_err0("Failed VIDIOC_S_INPUT\n");
        return Dmai_EFAIL;
    }
 
    /* Display available video standards */
    Dmai_dbg0("Available video standard:\n");
    for (index=0;; index++) {

        std.frameperiod.numerator = 1;
        std.frameperiod.denominator = 0;
        std.index = index;

        if (ioctl(fd, VIDIOC_ENUMSTD, &std) < 0) {
            if (errno == EINVAL || errno == ENOTTY)
                break;
        }
        Dmai_dbg3(" name=%s, fps=%d/%d\n", std.name, 
                    std.frameperiod.denominator, std.frameperiod.numerator);
    }

    /* Get current video standard */
    if (ioctl(fd, VIDIOC_G_STD, &id) < 0) {
        Dmai_err0("Failed VIDIOC_G_STD\n");
        return Dmai_EFAIL;
    }

    if (!hCapture) {
        close(fd);
    }

    if (id & V4L2_STD_NTSC) {
       *videoStdPtr = VideoStd_D1_NTSC;
        Dmai_dbg0("Found NTSC std input\n");
    }
    else if (id & V4L2_STD_PAL) {
        *videoStdPtr = VideoStd_D1_PAL;
        Dmai_dbg0("Found PAL std input\n");
    }
    else if (id & V4L2_STD_525_60) {
        *videoStdPtr = VideoStd_480P;
        Dmai_dbg0("Found 525_60 std input\n");
    }
    else if (id & V4L2_STD_625_50) {
        *videoStdPtr = VideoStd_576P;
        Dmai_dbg0("Found 625_50 std input\n");
    }
    else {
        Dmai_err1("Unknown video standard on capture device %s\n",
                  attrs->captureDevice);
        return Dmai_EFAIL; 
    }

    return Dmai_EOK;
}
Beispiel #11
0
/******************************************************************************
 * Capture_create
 ******************************************************************************/
Capture_Handle Capture_create(BufTab_Handle hBufTab, Capture_Attrs *attrs)
{
    struct v4l2_capability      cap;
    struct v4l2_cropcap         cropCap;
    struct v4l2_crop            crop;
    struct v4l2_format          fmt;
    enum v4l2_buf_type          type;
    Capture_Handle              hCapture;
    VideoStd_Type               videoStd;
    Int32                       width, height;
    Int32                       pixelformat;

    assert(attrs);
    memset(&fmt, 0x00, sizeof(struct v4l2_format));

    /* Allocate space for state object */
    hCapture = calloc(1, sizeof(Capture_Object));

    if (hCapture == NULL) {
        Dmai_err0("Failed to allocate space for Capture Object\n");
        return NULL;
    }

    /* User allocated buffers by default */
    hCapture->userAlloc = TRUE;

    /* Open video capture device */
    hCapture->fd = open(attrs->captureDevice, O_RDWR, 0);

    if (hCapture->fd == -1) {
        Dmai_err2("Cannot open %s (%s)\n", attrs->captureDevice,
                                           strerror(errno));
        cleanup(hCapture);
        return NULL;
    }

    /* See if an input is connected, and if so which standard */
    if (Capture_detectVideoStd(hCapture, &videoStd, attrs) < 0) {
        cleanup(hCapture);
        return NULL;
    }

    hCapture->videoStd = videoStd;

    if (VideoStd_getResolution(videoStd, &width, &height) < 0) {
        cleanup(hCapture);
        Dmai_err0("Failed to get resolution of capture video standard\n");
        return NULL;
    }

    /* Query for capture device capabilities */
    if (ioctl(hCapture->fd, VIDIOC_QUERYCAP, &cap) == -1) {
        cleanup(hCapture);
        if (errno == EINVAL) {
            Dmai_err1("%s is no V4L2 device\n", attrs->captureDevice);
            cleanup(hCapture);
            return NULL;
        }
        Dmai_err2("Failed VIDIOC_QUERYCAP on %s (%s)\n", attrs->captureDevice,
                                                       strerror(errno));
        cleanup(hCapture);
        return NULL;
    }

    if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {
        Dmai_err1("%s is not a video capture device\n", attrs->captureDevice);
        cleanup(hCapture);
        return NULL;
    }

    if (!(cap.capabilities & V4L2_CAP_STREAMING)) {
        Dmai_err1("%s does not support streaming i/o\n", attrs->captureDevice);
        cleanup(hCapture);
        return NULL;
    }

    /* Query for video input cropping capability */
    cropCap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    if (ioctl(hCapture->fd, VIDIOC_CROPCAP, &cropCap) == -1) {
        Dmai_err2("VIDIOC_CROPCAP failed on %s (%s)\n", attrs->captureDevice,
                                                        strerror(errno));
        cleanup(hCapture);
        return NULL;
    }

    Dmai_dbg4("Cropping window boundry left=%d, top=%d, width=%d, height=%d\n",
              cropCap.bounds.left, cropCap.bounds.top, cropCap.bounds.width, 
              cropCap.bounds.height);

    Dmai_dbg4("Default cropping rect left=%d, top=%d, width=%d, height=%d\n",
              cropCap.defrect.left, cropCap.defrect.top, cropCap.defrect.width, 
              cropCap.defrect.height);

    if (attrs->cropWidth > 0 && attrs->cropHeight > 0) {
        if (attrs->cropX & 0x1) {
            Dmai_err1("Crop width (%ld) needs to be even\n", attrs->cropX);
            cleanup(hCapture);
            return NULL;
        }

        crop.type     = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        crop.c.left   = attrs->cropX;
        crop.c.top    = attrs->cropY;
        crop.c.width  = attrs->cropWidth;
        crop.c.height = hCapture->topOffset ? attrs->cropHeight + 4 + 2 :
                                              attrs->cropHeight;

        Dmai_dbg4("Setting capture cropping at %dx%d size %dx%d\n",
                  crop.c.left, crop.c.top, crop.c.width, crop.c.height);

        /* Crop the image depending on requested image size */
        if (ioctl(hCapture->fd, VIDIOC_S_CROP, &crop) == -1) {
            Dmai_err2("VIDIOC_S_CROP failed on %s (%s)\n", attrs->captureDevice,
                                                           strerror(errno));
            cleanup(hCapture);
            return NULL;
        }
    
        width = crop.c.width;
        height = crop.c.height;
    }

    /* Query for video input format */
    fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    if (ioctl(hCapture->fd, VIDIOC_G_FMT, &fmt) == -1) {
        Dmai_err2("Failed VIDIOC_G_FMT on %s (%s)\n", attrs->captureDevice,
                                                      strerror(errno));
        cleanup(hCapture);
        return NULL;
    }

    fmt.fmt.pix.width        = width;
    fmt.fmt.pix.height       = height; 
    fmt.fmt.pix.field        = V4L2_FIELD_INTERLACED;
    fmt.type                 = V4L2_BUF_TYPE_VIDEO_CAPTURE;

    switch(attrs->colorSpace) {
        case ColorSpace_UYVY: 
            fmt.fmt.pix.pixelformat  = V4L2_PIX_FMT_UYVY;
            pixelformat = fmt.fmt.pix.pixelformat;
            break;
        default: 
            Dmai_err0("Dmai capture module does not support this colorSpace\n");
            cleanup(hCapture);
            return NULL;
    }

    if (ioctl(hCapture->fd, VIDIOC_S_FMT, &fmt) == -1) {
        Dmai_err2("Failed VIDIOC_S_FMT on %s (%s)\n", attrs->captureDevice,
                                                      strerror(errno));
        cleanup(hCapture);
        return NULL;
    }

    if ((fmt.fmt.pix.width != width)  || (fmt.fmt.pix.height != height)) {
        Dmai_err4("Failed to set resolution %d x %d (%d x %d)\n", width,
                    height, fmt.fmt.pix.width, fmt.fmt.pix.height);
        cleanup(hCapture);
        return NULL;
    }

    if (pixelformat != fmt.fmt.pix.pixelformat) {
        Dmai_err0("Failed to set pixelformat\n");
        cleanup(hCapture);
        return NULL;
    }

    Dmai_dbg3("Video input connected size %dx%d pitch %d\n",
              fmt.fmt.pix.width, fmt.fmt.pix.height, fmt.fmt.pix.bytesperline);


    if (hBufTab == NULL) {
        hCapture->userAlloc = FALSE;

        /* The driver allocates the buffers */
        if (_Dmai_v4l2DriverAlloc(hCapture->fd,
                                  attrs->numBufs,
                                  V4L2_BUF_TYPE_VIDEO_CAPTURE,
                                  &hCapture->bufDescs,
                                  &hBufTab,
                                  hCapture->topOffset,
                                  attrs->colorSpace) < 0) {
            Dmai_err1("Failed to allocate capture driver buffers on %s\n",
                      attrs->captureDevice);
            cleanup(hCapture);
            return NULL;
        }
    }
    else {
        /* Make the driver use the user supplied buffers */
        if (_Dmai_v4l2UserAlloc(hCapture->fd,
                                attrs->numBufs,
                                V4L2_BUF_TYPE_VIDEO_CAPTURE,
                                &hCapture->bufDescs,
                                hBufTab,
                                0, attrs->colorSpace) < 0) {
            Dmai_err1("Failed to intialize capture driver buffers on %s\n",
                      attrs->captureDevice);
            cleanup(hCapture);
            return NULL;
        }
    }

    hCapture->hBufTab = hBufTab;

    /* Start the video streaming */
    type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

    if (ioctl(hCapture->fd, VIDIOC_STREAMON, &type) == -1) {
        Dmai_err2("VIDIOC_STREAMON failed on %s (%s)\n", attrs->captureDevice,
                                                         strerror(errno));
        cleanup(hCapture);
        return NULL;
    }

    hCapture->started = TRUE;

    return hCapture;
}
/******************************************************************************
 * Display_fbdev_create
 ******************************************************************************/
Display_Handle Display_fbdev_create(BufTab_Handle hBufTab, Display_Attrs *attrs)
{
    BufferGfx_Attrs         gfxAttrs       = BufferGfx_Attrs_DEFAULT;
    struct fb_var_screeninfo varInfo;
    struct fb_fix_screeninfo fixInfo;
    Int                      displaySize;
    Int                      bufIdx;
    Int8                    *virtPtr;
    Int32                    physPtr;
    Int32                    height, width;
    Display_Handle           hDisplay;
    Buffer_Handle            hBuf;

    if (attrs == NULL) {
        Dmai_err0("Must supply valid attrs\n");
        return NULL;
    }

    if (hBufTab != NULL) {
        Dmai_err0("FBdev display does not accept user allocated buffers\n");
        return NULL;
    }

    hDisplay = calloc(1, sizeof(Display_Object));

    if (hDisplay == NULL) {
        Dmai_err0("Failed to allocate space for Display Object\n");
        return NULL;
    }

    /* Setup sysfs variable */
    /* Set up the sysfs variables before opening the display device */
    if (_SysFs_setup(attrs) < 0) {
        cleanup(hDisplay);
        return NULL;
    }

    /* Open video display device */
    hDisplay->fd = open(attrs->displayDevice, O_RDWR);

    if (hDisplay->fd == -1) {
        Dmai_err2("Failed to open fb device %s (%s)\n", attrs->displayDevice,
                                                        strerror(errno));
        cleanup(hDisplay);
        return NULL;
    }

    /* Get fixed screen info */
    if (ioctl(hDisplay->fd, FBIOGET_FSCREENINFO, &fixInfo) == -1) {
        Dmai_err2("Failed FBIOGET_FSCREENINFO on %s (%s)\n",
                  attrs->displayDevice, strerror(errno));
        cleanup(hDisplay);
        return NULL;
    }

    /* Get virtual screen info */
    if (ioctl(hDisplay->fd, FBIOGET_VSCREENINFO, &varInfo) == -1) {
        Dmai_err2("Failed FBIOGET_VSCREENINFO on %s (%s)\n",
                  attrs->displayDevice, strerror(errno));
        cleanup(hDisplay);
        return NULL;
    }

    Dmai_dbg5("Found width=%d height=%d, yres_virtual=%d,xres_virtual=%d,"
              " line_length=%d\n", varInfo.xres, varInfo.yres, 
                varInfo.yres_virtual,varInfo.xres_virtual, fixInfo.line_length);

    /* Save current virtual screen info. */
    memcpy(&hDisplay->origVarInfo, &varInfo, sizeof(struct fb_var_screeninfo));

    /* If video standard is set to auto then use current height and width */
    if (attrs->videoStd == VideoStd_AUTO) {
        width = varInfo.xres;
        height = varInfo.yres;
    }
    else {
        VideoStd_getResolution(attrs->videoStd, &width, &height);
    }

    if (attrs->width > 0) {
        if (attrs->width > varInfo.xres)
            width = varInfo.xres;
        else 
            width = attrs->width;	
    }

    if (attrs->height > 0) {
        if (attrs->height > varInfo.yres)
            height = varInfo.yres;
        else 
            height = attrs->height;	
    }

    varInfo.xoffset         = 0;
    varInfo.yoffset         = 0;
    varInfo.xres            = width;
    varInfo.yres            = height;
    varInfo.xres_virtual    = width;
    varInfo.yres_virtual    = varInfo.yres * attrs->numBufs;

    /* Set video display format */
    Dmai_dbg4("Setting width=%d height=%d, yres_virtual=%d,"
              " xres_virtual=%d\n", varInfo.xres, varInfo.yres, 
              varInfo.yres_virtual, varInfo.xres_virtual);

    if (ioctl(hDisplay->fd, FBIOPUT_VSCREENINFO, &varInfo) == -1) {
        Dmai_err2("Failed FBIOPUT_VSCREENINFO on %s (%s)\n",
                  attrs->displayDevice, strerror(errno));
        cleanup(hDisplay);
        return NULL;
    }

    if (ioctl(hDisplay->fd, FBIOGET_FSCREENINFO, &fixInfo) == -1) {
        Dmai_err2("Failed FBIOGET_FSCREENINFO on %s (%s)\n",
                  attrs->displayDevice, strerror(errno));
        cleanup(hDisplay);
        return NULL;
    }

    Dmai_dbg5("New width=%d, height=%d, yres_virtual=%d,xres_virtual=%d, "
              "line_length=%d\n", varInfo.xres, varInfo.yres, 
              varInfo.yres_virtual, varInfo.xres_virtual, fixInfo.line_length);

    gfxAttrs.dim.width          = varInfo.xres;
    gfxAttrs.colorSpace         = attrs->colorSpace;
    gfxAttrs.dim.height         = varInfo.yres;
    gfxAttrs.dim.lineLength     = fixInfo.line_length;
    gfxAttrs.bAttrs.reference   = TRUE;
    displaySize                 = fixInfo.line_length * varInfo.yres;

    hBufTab = BufTab_create(attrs->numBufs, displaySize,
                            BufferGfx_getBufferAttrs(&gfxAttrs));

    if (hBufTab == NULL) {
        Dmai_err0("Failed to allocate BufTab for display buffers\n");
        cleanup(hDisplay);
        return NULL;
    }

    hBuf = BufTab_getBuf(hBufTab, 0);

    Buffer_setNumBytesUsed(hBuf, varInfo.xres * varInfo.yres *
                                 varInfo.bits_per_pixel / 8);
    virtPtr = (Int8 *) mmap (NULL,
                             displaySize * attrs->numBufs,
                             PROT_READ | PROT_WRITE,
                             MAP_SHARED,
                             hDisplay->fd, 0);

    if (virtPtr == MAP_FAILED) {
        Dmai_err2("Failed mmap on %s (%s)\n", attrs->displayDevice,
                                              strerror(errno));
        cleanup(hDisplay);
        return NULL;
    }

    if (Buffer_setUserPtr(hBuf, virtPtr) < 0) {
        cleanup(hDisplay);
        return NULL;
    }

    _Dmai_blackFill(hBuf);

    Dmai_dbg3("Display buffer %d mapped to %#lx has physical address %#lx\n", 0,
              (Int32) virtPtr, physPtr);

    for (bufIdx=1; bufIdx < attrs->numBufs; bufIdx++) {
        hBuf = BufTab_getBuf(hBufTab, bufIdx);
        Buffer_setNumBytesUsed(hBuf, varInfo.xres * varInfo.yres *
                                     varInfo.bits_per_pixel / 8);

        virtPtr = virtPtr + displaySize;
        Buffer_setUserPtr(hBuf, virtPtr);
        _Dmai_blackFill(hBuf);

        Dmai_dbg3("Display buffer %d mapped to %#lx, physical address %#lx\n",
                  bufIdx, (unsigned long) virtPtr, physPtr);
    }

    hDisplay->hBufTab = hBufTab;
    hDisplay->displayIdx = 0;
    hDisplay->workingIdx = attrs->numBufs > 1 ? 1 : 0;
    hDisplay->displayStd = Display_Std_FBDEV;

    if (setDisplayBuffer(hDisplay, hDisplay->displayIdx) < 0) {
        cleanup(hDisplay);
        return NULL;
    }

    if (ioctl(hDisplay->fd, FBIOBLANK, 0)) {
        Dmai_err1("Error enabling %s\n", attrs->displayDevice);
        cleanup(hDisplay);
        return NULL;
    }

    return hDisplay;
}