status_t allocateAtomBuffer(AtomBuffer &aBuff, const AtomBuffer &formatDescriptor, Callbacks *aCallbacks)
    {
        LOG1("%s with these properties: (%dx%d)s:%d fourcc %s", __FUNCTION__,
                formatDescriptor.width, formatDescriptor.height,
                formatDescriptor.bpl, v4l2Fmt2Str(formatDescriptor.fourcc));
        status_t status = OK;
        aBuff.dataPtr = NULL;

        aCallbacks->allocateMemory(&aBuff, formatDescriptor.size);
        if (aBuff.buff == NULL) {
            LOGE("Failed to allocate AtomBuffer");
            return NO_MEMORY;
        }

        aBuff.width = formatDescriptor.width;
        aBuff.height = formatDescriptor.height;
        aBuff.bpl = formatDescriptor.bpl;
        aBuff.fourcc = formatDescriptor.fourcc;
        aBuff.size = formatDescriptor.size;
        aBuff.dataPtr = aBuff.buff->data;
        aBuff.shared = false;

        LOG1("@%s allocated heap buffer with pointer %p", __FUNCTION__, aBuff.dataPtr);
        return status;
    }
void ImageScaler::downScaleImage(void *src, void *dest,
    int dest_w, int dest_h, int dest_bpl,
    int src_w, int src_h, int src_bpl,
    int fourcc, int src_skip_lines_top, // number of lines that are skipped from src image start pointer
    int src_skip_lines_bottom) // number of lines that are skipped after reading src_h (should be set always to reach full image height)
{
    unsigned char *m_dest = (unsigned char *)dest;
    const unsigned char * m_src = (const unsigned char *)src;

    LOG1("%s: dest_w:%d, dest_h:%d, src_w:%d, src_h:%d, fourcc:%s 0x%x", __func__,
         dest_w, dest_h, src_w, src_h, v4l2Fmt2Str(fourcc), fourcc);

    switch (fourcc) {
        case V4L2_PIX_FMT_NV21:
        case V4L2_PIX_FMT_NV12: {
            if (dest_w == src_w && dest_h == src_h) {
                // trim only
                ImageScaler::trimNv12Image(m_dest, m_src,
                    dest_w, dest_h, dest_bpl,
                    src_w, src_h, src_bpl,
                    src_skip_lines_top, src_skip_lines_bottom);
            } else {
                // downscale & crop
                ImageScaler::downScaleAndCropNv12Image(m_dest, m_src,
                    dest_w, dest_h, dest_bpl,
                    src_w, src_h, src_bpl,
                    src_skip_lines_top, src_skip_lines_bottom);
            }
            break;
        }
        case V4L2_PIX_FMT_YUYV:
            // downscale
            ImageScaler::downScaleYUY2Image(m_dest, m_src,
                dest_w, dest_h, src_w, src_h);
            break;
        default: {
            ALOGE("no downscale support for fourcc = %s 0x%x", v4l2Fmt2Str(fourcc), fourcc);
            break;
        }
    }
}
/**
 * Update the current device node configuration (low-level)
 *
 * This called is allowed in the following states:
 * - OPEN
 * - CONFIGURED
 * - PREPARED
 *
 * This methods allows more detailed control of the format than the previous one
 * It updates the internal configuration used to check for discrepancies between
 * configuration and buffer pool properties
 *
 * \param aFormat:[IN] reference to the new v4l2_format .
 *
 *  \return NO_ERROR if everything went well
 *          INVALID_OPERATION if device is not in correct state (open)
 *          UNKNOW_ERROR if we get an error from the v4l2 ioctl's
 */
status_t V4L2VideoNode::setFormat(struct v4l2_format &aFormat)
{

    LOG1("@%s device = %s", __FUNCTION__, mName.string());
    int ret(0);

    if ((mState != DEVICE_OPEN) &&
        (mState != DEVICE_CONFIGURED) &&
        (mState != DEVICE_PREPARED) ){
        ALOGE("%s invalid device state %d",__FUNCTION__, mState);
        return INVALID_OPERATION;
    }


    LOG1("VIDIOC_S_FMT: width: %d, height: %d, bpl: %d, fourcc: %s, field: %d",
            aFormat.fmt.pix.width,
            aFormat.fmt.pix.height,
            aFormat.fmt.pix.bytesperline,
            v4l2Fmt2Str(aFormat.fmt.pix.pixelformat),
            aFormat.fmt.pix.field);
    ret = ioctl(mFd, VIDIOC_S_FMT, &aFormat);
    if (ret < 0) {
        ALOGE("VIDIOC_S_FMT failed: %s", strerror(errno));
        return UNKNOWN_ERROR;
    }

    // Update current configuration with the new one
    mFormatDescriptor.fourcc = aFormat.fmt.pix.pixelformat;
    mFormatDescriptor.width = aFormat.fmt.pix.width;
    mFormatDescriptor.height = aFormat.fmt.pix.height;
    mFormatDescriptor.bpl = aFormat.fmt.pix.bytesperline;
    // TODO: we should respect fmt.pix.sizeimage ensure its always
    //       page aligned with our types of allocations
    mFormatDescriptor.size = frameSize(mFormatDescriptor.fourcc,
                                       bytesToPixels(mFormatDescriptor.fourcc, mFormatDescriptor.bpl),
                                       mFormatDescriptor.height);
    LOG1("bpl: %d from ISP", mFormatDescriptor.bpl);

    mState = DEVICE_CONFIGURED;
    mSetBufferPool.clear();
    mSetBufferPool.setCapacity(MAX_V4L2_BUFFERS);
    return NO_ERROR;
}
/**
 * Update the current device node configuration (low-level)
 *
 * This called is allowed in the following states:
 * - OPEN
 * - CONFIGURED
 * - PREPARED
 *
 * This methods allows more detailed control of the format than the previous one
 * It updates the internal configuration used to check for discrepancies between
 * configuration and buffer pool properties
 *
 * \param aFormat:[IN] reference to the new v4l2_format .
 *
 *  \return NO_ERROR if everything went well
 *          INVALID_OPERATION if device is not in correct state (open)
 *          UNKNOW_ERROR if we get an error from the v4l2 ioctl's
 */
status_t V4L2VideoNode::setFormat(struct v4l2_format &aFormat)
{

    LOG1("@%s device = %s", __FUNCTION__, mName.string());
    int ret(0);

    if ((mState != DEVICE_OPEN) &&
        (mState != DEVICE_CONFIGURED) &&
        (mState != DEVICE_PREPARED) ){
        LOGE("%s invalid device state %d",__FUNCTION__, mState);
        return INVALID_OPERATION;
    }


    LOG1("VIDIOC_S_FMT: width: %d, height: %d, bpl: %d, fourcc: %s, field: %d",
         aFormat.fmt.pix.width,
         aFormat.fmt.pix.height,
         aFormat.fmt.pix.bytesperline,
         v4l2Fmt2Str(aFormat.fmt.pix.pixelformat),
         aFormat.fmt.pix.field);

    ret = pioctl(mFd, VIDIOC_S_FMT, &aFormat);
    if (ret < 0) {
        LOGE("VIDIOC_S_FMT failed: %s", strerror(errno));
        return UNKNOWN_ERROR;
    }

    // Update current configuration with the new one
    mConfig.originalFormat = mConfig.format = aFormat.fmt.pix.pixelformat;
    mConfig.width = aFormat.fmt.pix.width;
    mConfig.height = aFormat.fmt.pix.height;
    mConfig.stride = bytesToPixels(mConfig.format,aFormat.fmt.pix.bytesperline);
    mConfig.size = frameSize(mConfig.format, mConfig.stride, mConfig.height);

    if (mConfig.stride != mConfig.width)
        LOG1("stride: %d from ISP width: %d", mConfig.stride,mConfig.width);

    mState = DEVICE_CONFIGURED;
    mSetBufferPool.clear();
    return NO_ERROR;
}
Esempio n. 5
0
/**
 * RD Helper methods to dump a YUV file stored in an AtomBuffer to a file
 * This function can be used during investigations anywhere in the HAL
 * codebase
 *
 */
int CameraDump::dumpAtom2File(const AtomBuffer *b, const char *name)
{
    int bytes = 0;

    ALOGE("Dumping %s resolution (%dx%d) format %s",name,b->width, b->height,v4l2Fmt2Str(b->fourcc));

    FILE *fd = fopen(name, "wb+");

    if(fd == NULL) {
        ALOGE("%s could not open dump file ",__FUNCTION__);
        return -1;
    }

    bytes = fwrite(b->dataPtr, 1, b->size, fd);
    if (bytes != b->size) {
        ALOGE("ERROR DUMPING %s written %d size %d",name, bytes, b->size);
    }

    fclose(fd);
    return 0;
}
/**
 * setBufferPool
 * updates the set buffer pool with externally allocated memory
 *
 * The device has to be at least in CONFIGURED state but once configured
 * it the buffer pool can be reset in PREPARED state.
 *
 * This pool will become active after calling start()
 * \param pool: array of void* where the memory is available
 * \param poolSize: amount of buffers in the pool
 * \param formatDescriptor: description of the properties of the buffers
 *                   it should match the configuration passed during setFormat
 * \param cached: boolean to detect whether the buffers are cached or not
 *                A cached buffer in this context means that the buffer
 *                memory may be accessed through some system caches, and
 *                the V4L2 driver must do cache invalidation in case
 *                the image data source is not updating system caches
 *                in hardware.
 *                When false (not cached), V4L2 driver can assume no cache
 *                invalidation/flushes are needed for this buffer.
 */
status_t V4L2VideoNode::setBufferPool(void **pool, int poolSize,
                                     AtomBuffer *formatDescriptor, bool cached)
{
    LOG1("@%s: device = %s", __FUNCTION__, mName.string());
    struct v4l2_buffer_info vinfo;
    CLEAR(vinfo);
    uint32_t cacheflags = V4L2_BUF_FLAG_NO_CACHE_INVALIDATE |
                          V4L2_BUF_FLAG_NO_CACHE_CLEAN;

    if ((mState != DEVICE_CONFIGURED) && (mState != DEVICE_PREPARED)) {
        ALOGE("%s:Invalid operation, device %s not configured (state = %d)",
                __FUNCTION__, mName.string(), mState);
        return INVALID_OPERATION;
    }

    if (pool == NULL || formatDescriptor == NULL) {
        ALOGE("Invalid parameters, pool %p frameInfo %p",pool, formatDescriptor);
        return BAD_TYPE;
    }

    /**
     * check that the configuration of these buffers matches what we have already
     * told the driver.
     */
    if ((formatDescriptor->width != mFormatDescriptor.width) ||
        (formatDescriptor->height != mFormatDescriptor.height) ||
        (formatDescriptor->bpl != mFormatDescriptor.bpl) ||
        (formatDescriptor->fourcc != mFormatDescriptor.fourcc) ) {
        ALOGE("Pool configuration does not match device configuration: (%dx%d) s:%d f:%s Pool is: (%dx%d) s:%d f:%s ",
                mFormatDescriptor.width, mFormatDescriptor.height, mFormatDescriptor.bpl, v4l2Fmt2Str(mFormatDescriptor.fourcc),
                formatDescriptor->width, formatDescriptor->height, formatDescriptor->bpl, v4l2Fmt2Str(formatDescriptor->fourcc));
        return BAD_VALUE;
    }

    mSetBufferPool.clear();
    mSetBufferPool.setCapacity(MAX_V4L2_BUFFERS);

    for (int i = 0; i < poolSize; i++) {
        vinfo.data = pool[i];
        vinfo.width = formatDescriptor->width;
        vinfo.height = formatDescriptor->height;
        vinfo.format = formatDescriptor->fourcc;
        vinfo.length = formatDescriptor->size;
        if (cached)
           vinfo.cache_flags = 0;
       else
           vinfo.cache_flags = cacheflags;

        mSetBufferPool.push(vinfo);
    }

    mState = DEVICE_PREPARED;
    return NO_ERROR;
}