Esempio n. 1
0
bool V4l2Encoder::inputPulse(int32_t index)
{
    Encode_Status status = ENCODE_SUCCESS;

    if(m_videoParamsChanged )
        UpdateVideoParameters(true);

    status = m_encoder->encode(&m_inputFrames[index]);

    if (status != ENCODE_SUCCESS)
        return false;

    ASSERT(m_inputFrames[index].bufAvailable); // check it at a later time when yami does encode in async
    return true;
}
Esempio n. 2
0
bool V4l2Encoder::inputPulse(uint32_t index)
{
    Encode_Status status = ENCODE_SUCCESS;

    if(m_videoParamsChanged )
        UpdateVideoParameters(true);

#if ANDROID
    if (m_memoryType == VIDEO_DATA_MEMORY_TYPE_ANDROID_NATIVE_BUFFER) {
        status = m_encoder->encode(m_videoFrames[index]);
    }
    else
#endif
    {
        DEBUG_FOURCC("m_inputFrames[index].fourcc: ", m_inputFrames[index].fourcc);
        status = m_encoder->encode(&m_inputFrames[index]);
        ASSERT(m_inputFrames[index].bufAvailable); // check it at a later time when yami does encode in async
    }

    if (status != ENCODE_SUCCESS)
        return false;

    return true;
}
Esempio n. 3
0
int32_t V4l2Encoder::ioctl(int command, void* arg)
{
    Encode_Status encodeStatus = ENCODE_SUCCESS;
    int32_t ret = 0;

    DEBUG("fd: %d, ioctl command: %s", m_fd[0], IoctlCommandString(command));
    switch (command) {
    case VIDIOC_QUERYCAP:
    case VIDIOC_STREAMON:
    case VIDIOC_STREAMOFF:
    case VIDIOC_REQBUFS:
    case VIDIOC_QBUF:
    case VIDIOC_DQBUF:
        ret = V4l2CodecBase::ioctl(command, arg);
        break;
    case VIDIOC_QUERYBUF: {
        struct v4l2_buffer *buffer = static_cast<struct v4l2_buffer*>(arg);
        ASSERT (buffer->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
        ASSERT(buffer->memory == V4L2_MEMORY_MMAP);
        ASSERT(buffer->index>=0 && buffer->index<m_maxBufferCount[OUTPUT]);
        ASSERT(buffer->length == m_bufferPlaneCount[OUTPUT]);
        ASSERT(m_maxOutputBufferSize > 0);

        buffer->m.planes[0].length = m_maxOutputBufferSize;
        buffer->m.planes[0].m.mem_offset = m_maxOutputBufferSize * buffer->index;
    }
    break;
    case VIDIOC_S_EXT_CTRLS: {
        int i;
        struct v4l2_ext_controls *control = static_cast<struct v4l2_ext_controls *>(arg);
        DEBUG("V4L2_CTRL_CLASS_MPEG: %d, control->ctrl_class: %d", V4L2_CTRL_CLASS_MPEG, control->ctrl_class);
        if (control->ctrl_class == V4L2_CTRL_CLASS_MPEG) {
            AutoLock locker(m_videoParamsLock);
            struct v4l2_ext_control *ctrls = control->controls;
            DEBUG("control->count: %d", control->count);
            for (i=0; i<control->count; i++) {
                DEBUG("VIDIOC_S_EXT_CTRLS:V4L2_CTRL_CLASS_MPEG:%d", ctrls->id);
                switch (ctrls->id) {
                    case V4L2_CID_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE:
                        // ::EncodeTask
                        ASSERT(ctrls->value == V4L2_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE_I_FRAME);
                        m_forceKeyFrame = true;
                        break;
                    case V4L2_CID_MPEG_VIDEO_BITRATE: {
                        // ::RequestEncodingParametersChangeTask
                        m_videoParams.rcParams.bitRate = ctrls->value;
                        m_videoParamsChanged = true;
                    }
                        break;
                    case V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE:
                        INFO("enable bitrate control");
                        m_videoParams.rcMode = RATE_CONTROL_CBR;
                        m_videoParamsChanged = true;
                        break;
                    case V4L2_CID_MPEG_VIDEO_HEADER_MODE:
                        // Separate stream header so we can cache it and insert into the stream.
                        if (ctrls->value == V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE)
                            m_separatedStreamHeader = true;
                        INFO("use separated stream header: %d", m_separatedStreamHeader);
                        break;
                    case V4L2_CID_MPEG_VIDEO_B_FRAMES:
                    case V4L2_CID_MPEG_MFC51_VIDEO_RC_REACTION_COEFF:
                    case V4L2_CID_MPEG_MFC51_VIDEO_RC_FIXED_TARGET_BIT:
                    case V4L2_CID_MPEG_VIDEO_H264_MAX_QP:
                    case V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE:
                    case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
                    case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
                    default:
                        break;
                }
                ctrls++;
            }
        }
        UpdateVideoParameters();
    }
    break;
    case VIDIOC_S_PARM: {
        struct v4l2_streamparm *parms = static_cast<struct v4l2_streamparm *>(arg);
        if (parms->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
            AutoLock locker(m_videoParamsLock);
            // ::RequestEncodingParametersChangeTask
            m_videoParams.frameRate.frameRateNum = parms->parm.output.timeperframe.denominator;
            m_videoParams.frameRate.frameRateDenom = parms->parm.output.timeperframe.numerator;
            int framerate = m_videoParams.frameRate.frameRateNum/m_videoParams.frameRate.frameRateDenom;
            if (framerate * 2 < m_videoParams.intraPeriod) {
                m_videoParams.intraPeriod = framerate * 2;
            }
            m_videoParamsChanged = true;
        }
        UpdateVideoParameters();
    }
    break;
    case VIDIOC_S_FMT: {
        struct v4l2_format *format = static_cast<struct v4l2_format *>(arg);
        ASSERT(!m_streamOn[INPUT] && !m_streamOn[OUTPUT]);
        if (format->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
            // ::SetOutputFormat
            switch (format->fmt.pix_mp.pixelformat) {
                case V4L2_PIX_FMT_H264: {
                    m_encoder.reset(createVideoEncoder("video/h264"), releaseVideoEncoder);
                    m_videoParams.size = sizeof(m_videoParams);
                    encodeStatus = m_encoder->getParameters(VideoParamsTypeCommon, &m_videoParams);
                    ASSERT(encodeStatus == ENCODE_SUCCESS);
                    m_videoParams.profile = VAProfileH264Main;
                    encodeStatus = m_encoder->setParameters(VideoParamsTypeCommon, &m_videoParams);
                    ASSERT(encodeStatus == ENCODE_SUCCESS);
                }
                break;
                case V4L2_PIX_FMT_VP8:
                default:
                    ret = -1;
                break;
            }

        } else if (format->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
            // ::NegotiateInputFormat
            ASSERT(format->fmt.pix_mp.pixelformat == V4L2_PIX_FMT_YUV420M || format->fmt.pix_mp.pixelformat == V4L2_PIX_FMT_YUYV);
            m_pixelFormat[INPUT] = format->fmt.pix_mp.pixelformat;
            switch (m_pixelFormat[INPUT]) {
            case V4L2_PIX_FMT_YUV420M:
                m_bufferPlaneCount[INPUT] = 3;
            break;
            case V4L2_PIX_FMT_YUYV:
                m_bufferPlaneCount[INPUT] = 1;
                break;
            default:
                ASSERT(0);
                break;
            }
            ASSERT(m_encoder);
            m_videoParams.resolution.width = format->fmt.pix_mp.width;
            m_videoParams.resolution.height= format->fmt.pix_mp.height;
            encodeStatus = m_encoder->setParameters(VideoParamsTypeCommon, &m_videoParams);
            ASSERT(encodeStatus == ENCODE_SUCCESS);
            encodeStatus = m_encoder->getMaxOutSize(&m_maxOutputBufferSize);
            ASSERT(encodeStatus == ENCODE_SUCCESS);
            INFO("resolution: %d x %d, m_maxOutputBufferSize: %d", m_videoParams.resolution.width,
                m_videoParams.resolution.height, m_maxOutputBufferSize);
            format->fmt.pix_mp.plane_fmt[0].bytesperline = m_videoParams.resolution.width;
            format->fmt.pix_mp.plane_fmt[0].sizeimage = m_videoParams.resolution.width * m_videoParams.resolution.height;
            format->fmt.pix_mp.plane_fmt[1].bytesperline = m_videoParams.resolution.width/2;
            format->fmt.pix_mp.plane_fmt[1].sizeimage = m_videoParams.resolution.width * m_videoParams.resolution.height /4;
            format->fmt.pix_mp.plane_fmt[2].bytesperline = m_videoParams.resolution.width/2;
            format->fmt.pix_mp.plane_fmt[2].sizeimage = m_videoParams.resolution.width * m_videoParams.resolution.height /4;
        } else {
            ret = -1;
            ERROR("unknow type: %d of setting format VIDIOC_S_FMT", format->type);
        }
    }
    break;
    case VIDIOC_S_CROP: {
        // ::SetFormats
        struct v4l2_crop *crop = static_cast<struct v4l2_crop *>(arg);
        INFO("ignore crop for now (the difference between buffer size and real size)");
    }
    break;
    default:
        ret = -1;
        ERROR("unknown ioctrl command: %d", command);
    break;
    }

    if (ret == -1 && errno != EAGAIN) {
        ERROR("ioctl failed");
        WARNING("ioctl command: %s failed", IoctlCommandString(command));
    }

    return ret;
}