Blame v4l2/v4l2_encode.cpp

Packit 1244b8
/*
Packit 1244b8
 * Copyright (C) 2014 Intel Corporation. All rights reserved.
Packit 1244b8
 *
Packit 1244b8
 * Licensed under the Apache License, Version 2.0 (the "License");
Packit 1244b8
 * you may not use this file except in compliance with the License.
Packit 1244b8
 * You may obtain a copy of the License at
Packit 1244b8
 *
Packit 1244b8
 *     http://www.apache.org/licenses/LICENSE-2.0
Packit 1244b8
 *
Packit 1244b8
 * Unless required by applicable law or agreed to in writing, software
Packit 1244b8
 * distributed under the License is distributed on an "AS IS" BASIS,
Packit 1244b8
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Packit 1244b8
 * See the License for the specific language governing permissions and
Packit 1244b8
 * limitations under the License.
Packit 1244b8
 */
Packit 1244b8
Packit 1244b8
#ifdef HAVE_CONFIG_H
Packit 1244b8
#include "config.h"
Packit 1244b8
#endif
Packit 1244b8
#include <linux/videodev2.h>
Packit 1244b8
#include <unistd.h>
Packit 1244b8
#include <errno.h>
Packit 1244b8
#include <stdlib.h>
Packit 1244b8
#include <sys/mman.h>
Packit 1244b8
Packit 1244b8
#include "v4l2_encode.h"
Packit 1244b8
#include "VideoEncoderHost.h"
Packit 1244b8
#include "common/log.h"
Packit 1244b8
Packit 1244b8
V4l2Encoder::V4l2Encoder()
Packit 1244b8
    : m_videoParamsChanged(false)
Packit 1244b8
    , m_maxOutputBufferSize(0)
Packit 1244b8
    , m_outputBufferSpace(NULL)
Packit 1244b8
    , m_separatedStreamHeader(false)
Packit 1244b8
    , m_requestStreamHeader(true)
Packit 1244b8
    , m_forceKeyFrame(false)
Packit 1244b8
{
Packit 1244b8
    m_memoryMode[INPUT] = V4L2_MEMORY_USERPTR; // dma_buf hasn't been supported yet
Packit 1244b8
    m_pixelFormat[INPUT] = V4L2_PIX_FMT_YUV420M;
Packit 1244b8
    m_bufferPlaneCount[INPUT] = 3; // decided by m_pixelFormat[INPUT]
Packit 1244b8
    m_memoryMode[OUTPUT] = V4L2_MEMORY_MMAP;
Packit 1244b8
    m_pixelFormat[OUTPUT] = V4L2_PIX_FMT_H264;
Packit 1244b8
    m_bufferPlaneCount[OUTPUT] = 1;
Packit 1244b8
    m_maxBufferCount[INPUT] = 3;
Packit 1244b8
    m_maxBufferCount[OUTPUT] = 3;
Packit 1244b8
Packit 1244b8
    m_inputFrames.resize(m_maxBufferCount[INPUT]);
Packit 1244b8
    m_outputFrames.resize(m_maxBufferCount[OUTPUT]);
Packit 1244b8
}
Packit 1244b8
Packit 1244b8
bool V4l2Encoder::start()
Packit 1244b8
{
Packit 1244b8
    YamiStatus status = YAMI_SUCCESS;
Packit 1244b8
    ASSERT(m_encoder);
Packit 1244b8
Packit 1244b8
    VideoConfigAVCStreamFormat streamFormat;
Packit 1244b8
    streamFormat.size = sizeof(VideoConfigAVCStreamFormat);
Packit 1244b8
    streamFormat.streamFormat = AVC_STREAM_FORMAT_ANNEXB;
Packit 1244b8
    m_encoder->setParameters(VideoConfigTypeAVCStreamFormat, &streamFormat);
Packit 1244b8
Packit 1244b8
    if (m_svct) {
Packit 1244b8
        VideoTemporalLayers layers;
Packit 1244b8
        layers.numLayersMinus1 = 1; // It is two layers actually
Packit 1244b8
        layers.bitRate[0] = m_videoParams.rcParams.bitRate / 2;
Packit 1244b8
        layers.bitRate[1] = m_videoParams.rcParams.bitRate;
Packit 1244b8
Packit 1244b8
        m_videoParams.temporalLayers = layers;
Packit 1244b8
    }
Packit 1244b8
Packit 1244b8
    status = m_encoder->setParameters(VideoParamsTypeCommon, &m_videoParams);
Packit 1244b8
    ASSERT(status == YAMI_SUCCESS);
Packit 1244b8
Packit 1244b8
    NativeDisplay nativeDisplay;
Packit 1244b8
    nativeDisplay.type = NATIVE_DISPLAY_DRM;
Packit 1244b8
    nativeDisplay.handle = 0;
Packit 1244b8
Packit 1244b8
    m_encoder->setNativeDisplay(&nativeDisplay);
Packit 1244b8
Packit 1244b8
    status = m_encoder->start();
Packit 1244b8
    ASSERT(status == YAMI_SUCCESS);
Packit 1244b8
    status = m_encoder->getParameters(VideoParamsTypeCommon, &m_videoParams);
Packit 1244b8
    ASSERT(status == YAMI_SUCCESS);
Packit 1244b8
Packit 1244b8
    return true;
Packit 1244b8
}
Packit 1244b8
Packit 1244b8
bool V4l2Encoder::stop()
Packit 1244b8
{
Packit 1244b8
    YamiStatus encodeStatus = YAMI_SUCCESS;
Packit 1244b8
    if (m_encoder)
Packit 1244b8
        encodeStatus = m_encoder->stop();
Packit 1244b8
    return encodeStatus == YAMI_SUCCESS;
Packit 1244b8
}
Packit 1244b8
Packit 1244b8
Packit 1244b8
bool V4l2Encoder::UpdateVideoParameters(bool isInputThread)
Packit 1244b8
{
Packit 1244b8
    YamiStatus status = YAMI_SUCCESS;
Packit 1244b8
    AutoLock locker(m_videoParamsLock); // make sure the caller has released m_videoParamsLock
Packit 1244b8
Packit 1244b8
    if (!m_videoParamsChanged)
Packit 1244b8
        return true;
Packit 1244b8
Packit 1244b8
    if (isInputThread || !m_streamOn[INPUT]) {
Packit 1244b8
        status = m_encoder->setParameters(VideoParamsTypeCommon, &m_videoParams);
Packit 1244b8
        ASSERT(status == YAMI_SUCCESS);
Packit 1244b8
        m_videoParamsChanged = false;
Packit 1244b8
    }
Packit 1244b8
Packit 1244b8
    return status == YAMI_SUCCESS;
Packit 1244b8
}
Packit 1244b8
bool V4l2Encoder::inputPulse(uint32_t index)
Packit 1244b8
{
Packit 1244b8
    YamiStatus status = YAMI_SUCCESS;
Packit 1244b8
Packit 1244b8
    if(m_videoParamsChanged )
Packit 1244b8
        UpdateVideoParameters(true);
Packit 1244b8
Packit 1244b8
    DEBUG_FOURCC("m_inputFrames[index].fourcc: ", m_inputFrames[index].fourcc);
Packit 1244b8
    status = m_encoder->encode(&m_inputFrames[index]);
Packit 1244b8
    ASSERT(m_inputFrames[index].bufAvailable); // check it at a later time when yami does encode in async
Packit 1244b8
Packit 1244b8
    if (status != YAMI_SUCCESS)
Packit 1244b8
        return false;
Packit 1244b8
Packit 1244b8
    return true;
Packit 1244b8
}
Packit 1244b8
Packit 1244b8
bool V4l2Encoder::outputPulse(uint32_t &index)
Packit 1244b8
{
Packit 1244b8
    YamiStatus status = YAMI_SUCCESS;
Packit 1244b8
Packit 1244b8
    VideoEncOutputBuffer *outputBuffer = &(m_outputFrames[index]);
Packit 1244b8
    if (m_separatedStreamHeader) {
Packit 1244b8
        outputBuffer->format = OUTPUT_FRAME_DATA;
Packit 1244b8
        if (m_requestStreamHeader) {
Packit 1244b8
            outputBuffer->format = OUTPUT_CODEC_DATA;
Packit 1244b8
        }
Packit 1244b8
    } else
Packit 1244b8
        outputBuffer->format = OUTPUT_EVERYTHING;
Packit 1244b8
Packit 1244b8
    status = m_encoder->getOutput(outputBuffer, false);
Packit 1244b8
Packit 1244b8
    if (status != YAMI_SUCCESS)
Packit 1244b8
        return false;
Packit 1244b8
Packit 1244b8
    ASSERT(m_maxOutputBufferSize > 0); // update m_maxOutputBufferSize after VIDIOC_S_FMT
Packit 1244b8
    ASSERT(m_outputBufferSpace);
Packit 1244b8
    ASSERT(outputBuffer->dataSize <= m_maxOutputBufferSize);
Packit 1244b8
Packit 1244b8
    if (m_separatedStreamHeader) {
Packit 1244b8
        if (m_requestStreamHeader)
Packit 1244b8
            m_requestStreamHeader = false;
Packit 1244b8
    }
Packit 1244b8
Packit 1244b8
    return true;
Packit 1244b8
}
Packit 1244b8
Packit 1244b8
bool V4l2Encoder::acceptInputBuffer(struct v4l2_buffer *qbuf)
Packit 1244b8
{
Packit 1244b8
    uint32_t i;
Packit 1244b8
    VideoEncRawBuffer *inputBuffer = &(m_inputFrames[qbuf->index]);
Packit 1244b8
Packit 1244b8
    // XXX todo: add multiple planes support for yami
Packit 1244b8
    inputBuffer->data = reinterpret_cast<uint8_t*>(qbuf->m.planes[0].m.userptr);
Packit 1244b8
    inputBuffer->size = 0;
Packit 1244b8
    for (i=0; i<qbuf->length; i++) {
Packit 1244b8
       inputBuffer->size += qbuf->m.planes[i].bytesused;
Packit 1244b8
    }
Packit 1244b8
    inputBuffer->bufAvailable = false;
Packit 1244b8
    DEBUG("qbuf->index: %d, inputBuffer: %p, bufAvailable: %d", qbuf->index, inputBuffer, inputBuffer->bufAvailable);
Packit 1244b8
    inputBuffer->timeStamp = qbuf->timestamp.tv_sec * 1000000 + qbuf->timestamp.tv_usec; // XXX
Packit 1244b8
    if (m_forceKeyFrame) {
Packit 1244b8
        inputBuffer->forceKeyFrame = true;
Packit 1244b8
        m_forceKeyFrame = false;
Packit 1244b8
    }
Packit 1244b8
    switch(m_pixelFormat[INPUT]) {
Packit 1244b8
    case V4L2_PIX_FMT_NV12:
Packit 1244b8
        inputBuffer->fourcc = VA_FOURCC_NV12;
Packit 1244b8
        break;
Packit 1244b8
    case V4L2_PIX_FMT_YUV420M:
Packit 1244b8
        inputBuffer->fourcc = VA_FOURCC('I', '4', '2', '0');
Packit 1244b8
        break;
Packit 1244b8
    case V4L2_PIX_FMT_YUYV:
Packit 1244b8
        inputBuffer->fourcc = VA_FOURCC_YUY2;
Packit 1244b8
        break;
Packit 1244b8
    default:
Packit 1244b8
        ASSERT(0);
Packit 1244b8
        break;
Packit 1244b8
    }
Packit 1244b8
Packit 1244b8
    return true;
Packit 1244b8
}
Packit 1244b8
Packit 1244b8
bool V4l2Encoder::giveOutputBuffer(struct v4l2_buffer *dqbuf)
Packit 1244b8
{
Packit 1244b8
    ASSERT(dqbuf->index < m_maxBufferCount[OUTPUT]);
Packit 1244b8
    VideoEncOutputBuffer *outputBuffer = &(m_outputFrames[dqbuf->index]);
Packit 1244b8
    dqbuf->m.planes[0].bytesused = outputBuffer->dataSize;
Packit 1244b8
    dqbuf->bytesused = m_outputFrames[dqbuf->index].dataSize;
Packit 1244b8
    dqbuf->m.planes[0].m.mem_offset = 0;
Packit 1244b8
    ASSERT(m_maxOutputBufferSize > 0);
Packit 1244b8
    ASSERT(m_outputBufferSpace);
Packit 1244b8
    if (outputBuffer->flag & ENCODE_BUFFERFLAG_SYNCFRAME)
Packit 1244b8
        dqbuf->flags = V4L2_BUF_FLAG_KEYFRAME;
Packit 1244b8
Packit 1244b8
Packit 1244b8
    if (m_svct &&  (m_videoParams.temporalLayers.numLayersMinus1 > 0)
Packit 1244b8
            && (outputBuffer->temporalID == m_videoParams.temporalLayers.numLayersMinus1)) {
Packit 1244b8
        dqbuf->flags |= V4L2_BUF_FLAG_NON_REF;
Packit 1244b8
    }
Packit 1244b8
Packit 1244b8
    return true;
Packit 1244b8
}
Packit 1244b8
Packit 1244b8
int32_t V4l2Encoder::ioctl(int command, void* arg)
Packit 1244b8
{
Packit 1244b8
    YamiStatus encodeStatus = YAMI_SUCCESS;
Packit 1244b8
    int32_t ret = 0;
Packit 1244b8
Packit 1244b8
    DEBUG("fd: %d, ioctl command: %s", m_fd[0], IoctlCommandString(command));
Packit 1244b8
    switch (command) {
Packit 1244b8
    case VIDIOC_QBUF:
Packit 1244b8
    case VIDIOC_QUERYCAP:
Packit 1244b8
    case VIDIOC_STREAMON:
Packit 1244b8
    case VIDIOC_STREAMOFF:
Packit 1244b8
    case VIDIOC_REQBUFS:
Packit 1244b8
    case VIDIOC_DQBUF:
Packit 1244b8
        ret = V4l2CodecBase::ioctl(command, arg);
Packit 1244b8
        break;
Packit 1244b8
    case VIDIOC_QUERYBUF: {
Packit 1244b8
        struct v4l2_buffer *buffer = static_cast<struct v4l2_buffer*>(arg);
Packit 1244b8
        ASSERT (buffer->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
Packit 1244b8
        ASSERT(buffer->memory == V4L2_MEMORY_MMAP);
Packit 1244b8
        ASSERT(buffer->index < m_maxBufferCount[OUTPUT]);
Packit 1244b8
        ASSERT(buffer->length == m_bufferPlaneCount[OUTPUT]);
Packit 1244b8
        ASSERT(m_maxOutputBufferSize > 0);
Packit 1244b8
Packit 1244b8
        buffer->m.planes[0].length = m_maxOutputBufferSize;
Packit 1244b8
        buffer->m.planes[0].m.mem_offset = m_maxOutputBufferSize * buffer->index;
Packit 1244b8
    }
Packit 1244b8
    break;
Packit 1244b8
    case VIDIOC_S_EXT_CTRLS: {
Packit 1244b8
        uint32_t i;
Packit 1244b8
        struct v4l2_ext_controls *control = static_cast<struct v4l2_ext_controls *>(arg);
Packit 1244b8
        DEBUG("V4L2_CTRL_CLASS_MPEG: %d, control->ctrl_class: %d", V4L2_CTRL_CLASS_MPEG, control->ctrl_class);
Packit 1244b8
        if (control->ctrl_class == V4L2_CTRL_CLASS_MPEG) {
Packit 1244b8
            AutoLock locker(m_videoParamsLock);
Packit 1244b8
            struct v4l2_ext_control *ctrls = control->controls;
Packit 1244b8
            DEBUG("control->count: %d", control->count);
Packit 1244b8
            for (i=0; i<control->count; i++) {
Packit 1244b8
                DEBUG("VIDIOC_S_EXT_CTRLS:V4L2_CTRL_CLASS_MPEG:%d", ctrls->id);
Packit 1244b8
                switch (ctrls->id) {
Packit 1244b8
                    case V4L2_CID_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE:
Packit 1244b8
                        // ::EncodeTask
Packit 1244b8
                        ASSERT(ctrls->value == V4L2_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE_I_FRAME);
Packit 1244b8
                        m_forceKeyFrame = true;
Packit 1244b8
                        break;
Packit 1244b8
                    case V4L2_CID_MPEG_VIDEO_BITRATE: {
Packit 1244b8
                        // ::RequestEncodingParametersChangeTask
Packit 1244b8
                        m_videoParams.rcParams.bitRate = ctrls->value;
Packit 1244b8
                        m_videoParamsChanged = true;
Packit 1244b8
                    }
Packit 1244b8
                        break;
Packit 1244b8
                    case V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE:
Packit 1244b8
                        INFO("enable bitrate control");
Packit 1244b8
                        m_videoParams.rcMode = RATE_CONTROL_CBR;
Packit 1244b8
                        m_videoParamsChanged = true;
Packit 1244b8
                        break;
Packit 1244b8
                    case V4L2_CID_MPEG_VIDEO_HEADER_MODE:
Packit 1244b8
                        // Separate stream header so we can cache it and insert into the stream.
Packit 1244b8
                        if (ctrls->value == V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE)
Packit 1244b8
                            m_separatedStreamHeader = true;
Packit 1244b8
                        INFO("use separated stream header: %d", m_separatedStreamHeader);
Packit 1244b8
                        break;
Packit 1244b8
                    case V4L2_CID_MPEG_VIDEO_B_FRAMES:
Packit 1244b8
                    case V4L2_CID_MPEG_MFC51_VIDEO_RC_REACTION_COEFF:
Packit 1244b8
                    case V4L2_CID_MPEG_MFC51_VIDEO_RC_FIXED_TARGET_BIT:
Packit 1244b8
                    case V4L2_CID_MPEG_VIDEO_H264_MAX_QP:
Packit 1244b8
                    case V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE:
Packit 1244b8
                    case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
Packit 1244b8
                    case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
Packit 1244b8
                    default:
Packit 1244b8
                        break;
Packit 1244b8
                }
Packit 1244b8
                ctrls++;
Packit 1244b8
            }
Packit 1244b8
        }
Packit 1244b8
        UpdateVideoParameters();
Packit 1244b8
    }
Packit 1244b8
    break;
Packit 1244b8
    case VIDIOC_S_PARM: {
Packit 1244b8
        struct v4l2_streamparm *parms = static_cast<struct v4l2_streamparm *>(arg);
Packit 1244b8
        if (parms->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
Packit 1244b8
            AutoLock locker(m_videoParamsLock);
Packit 1244b8
            // ::RequestEncodingParametersChangeTask
Packit 1244b8
            m_videoParams.frameRate.frameRateNum = parms->parm.output.timeperframe.numerator;
Packit 1244b8
            m_videoParams.frameRate.frameRateDenom = parms->parm.output.timeperframe.denominator;
Packit 1244b8
            uint32_t framerate = m_videoParams.frameRate.frameRateNum/m_videoParams.frameRate.frameRateDenom;
Packit 1244b8
            if (framerate * 2 < m_videoParams.intraPeriod) {
Packit 1244b8
                m_videoParams.intraPeriod = framerate * 2;
Packit 1244b8
            }
Packit 1244b8
            m_videoParamsChanged = true;
Packit 1244b8
        }
Packit 1244b8
        UpdateVideoParameters();
Packit 1244b8
    }
Packit 1244b8
    break;
Packit 1244b8
    case VIDIOC_S_FMT: {
Packit 1244b8
        struct v4l2_format *format = static_cast<struct v4l2_format *>(arg);
Packit 1244b8
        ASSERT(!m_streamOn[INPUT] && !m_streamOn[OUTPUT]);
Packit 1244b8
        if (format->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
Packit 1244b8
            // ::SetOutputFormat
Packit 1244b8
            switch (format->fmt.pix_mp.pixelformat) {
Packit 1244b8
                case V4L2_PIX_FMT_H264: {
Packit 1244b8
                    m_encoder.reset(createVideoEncoder(YAMI_MIME_H264), releaseVideoEncoder);
Packit 1244b8
                    if (!m_encoder) {
Packit 1244b8
                        ret = -1;
Packit 1244b8
                        break;
Packit 1244b8
                    }
Packit 1244b8
                    m_videoParams.size = sizeof(m_videoParams);
Packit 1244b8
                    encodeStatus = m_encoder->getParameters(VideoParamsTypeCommon, &m_videoParams);
Packit 1244b8
                    ASSERT(encodeStatus == YAMI_SUCCESS);
Packit 1244b8
                    m_videoParams.profile = VAProfileH264Main;
Packit 1244b8
                    encodeStatus = m_encoder->setParameters(VideoParamsTypeCommon, &m_videoParams);
Packit 1244b8
                    ASSERT(encodeStatus == YAMI_SUCCESS);
Packit 1244b8
                }
Packit 1244b8
                break;
Packit 1244b8
                case V4L2_PIX_FMT_VP8:
Packit 1244b8
                default:
Packit 1244b8
                    ret = -1;
Packit 1244b8
                break;
Packit 1244b8
            }
Packit 1244b8
Packit 1244b8
        } else if (format->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
Packit 1244b8
            // ::NegotiateInputFormat
Packit 1244b8
            ASSERT(format->fmt.pix_mp.pixelformat == V4L2_PIX_FMT_YUV420M
Packit 1244b8
                || format->fmt.pix_mp.pixelformat == V4L2_PIX_FMT_YUYV
Packit 1244b8
                || format->fmt.pix_mp.pixelformat == V4L2_PIX_FMT_NV12);
Packit 1244b8
            m_pixelFormat[INPUT] = format->fmt.pix_mp.pixelformat;
Packit 1244b8
            switch (m_pixelFormat[INPUT]) {
Packit 1244b8
            case V4L2_PIX_FMT_YUV420M:
Packit 1244b8
                m_bufferPlaneCount[INPUT] = 3;
Packit 1244b8
                format->fmt.pix_mp.plane_fmt[0].bytesperline = m_videoParams.resolution.width;
Packit 1244b8
                format->fmt.pix_mp.plane_fmt[0].sizeimage = m_videoParams.resolution.width * m_videoParams.resolution.height;
Packit 1244b8
                format->fmt.pix_mp.plane_fmt[1].bytesperline = m_videoParams.resolution.width/2;
Packit 1244b8
                format->fmt.pix_mp.plane_fmt[1].sizeimage = m_videoParams.resolution.width * m_videoParams.resolution.height /4;
Packit 1244b8
                format->fmt.pix_mp.plane_fmt[2].bytesperline = m_videoParams.resolution.width/2;
Packit 1244b8
                format->fmt.pix_mp.plane_fmt[2].sizeimage = m_videoParams.resolution.width * m_videoParams.resolution.height /4;
Packit 1244b8
            break;
Packit 1244b8
            case V4L2_PIX_FMT_NV12:
Packit 1244b8
                m_bufferPlaneCount[INPUT] = 2;
Packit 1244b8
                format->fmt.pix_mp.plane_fmt[0].bytesperline = m_videoParams.resolution.width;
Packit 1244b8
                format->fmt.pix_mp.plane_fmt[0].sizeimage = m_videoParams.resolution.width * m_videoParams.resolution.height;
Packit 1244b8
                format->fmt.pix_mp.plane_fmt[1].bytesperline = m_videoParams.resolution.width;
Packit 1244b8
                format->fmt.pix_mp.plane_fmt[1].sizeimage = m_videoParams.resolution.width * m_videoParams.resolution.height /2;
Packit 1244b8
            break;
Packit 1244b8
            case V4L2_PIX_FMT_YUYV:
Packit 1244b8
                m_bufferPlaneCount[INPUT] = 1;
Packit 1244b8
                format->fmt.pix_mp.plane_fmt[0].bytesperline = m_videoParams.resolution.width * 2;
Packit 1244b8
                format->fmt.pix_mp.plane_fmt[0].sizeimage = m_videoParams.resolution.width * m_videoParams.resolution.height * 2;
Packit 1244b8
                break;
Packit 1244b8
            default:
Packit 1244b8
                ASSERT(0);
Packit 1244b8
                break;
Packit 1244b8
            }
Packit 1244b8
            ASSERT(m_encoder);
Packit 1244b8
            m_videoParams.resolution.width = format->fmt.pix_mp.width;
Packit 1244b8
            m_videoParams.resolution.height= format->fmt.pix_mp.height;
Packit 1244b8
            encodeStatus = m_encoder->setParameters(VideoParamsTypeCommon, &m_videoParams);
Packit 1244b8
            ASSERT(encodeStatus == YAMI_SUCCESS);
Packit 1244b8
            encodeStatus = m_encoder->getMaxOutSize(&m_maxOutputBufferSize);
Packit 1244b8
            ASSERT(encodeStatus == YAMI_SUCCESS);
Packit 1244b8
            INFO("resolution: %d x %d, m_maxOutputBufferSize: %d", m_videoParams.resolution.width,
Packit 1244b8
                m_videoParams.resolution.height, m_maxOutputBufferSize);
Packit 1244b8
        } else {
Packit 1244b8
            ret = -1;
Packit 1244b8
            ERROR("unknow type: %d of setting format VIDIOC_S_FMT", format->type);
Packit 1244b8
        }
Packit 1244b8
    }
Packit 1244b8
    break;
Packit 1244b8
    case VIDIOC_S_CROP: {
Packit 1244b8
        // ::SetFormats
Packit 1244b8
        //struct v4l2_crop *crop = static_cast<struct v4l2_crop *>(arg);
Packit 1244b8
        INFO("ignore crop for now (the difference between buffer size and real size)");
Packit 1244b8
    }
Packit 1244b8
    break;
Packit 1244b8
    default:
Packit 1244b8
        ret = -1;
Packit 1244b8
        ERROR("unknown ioctrl command: %d", command);
Packit 1244b8
    break;
Packit 1244b8
    }
Packit 1244b8
Packit 1244b8
    if (ret == -1 && errno != EAGAIN) {
Packit 1244b8
        ERROR("ioctl failed");
Packit 1244b8
        WARNING("ioctl command: %s failed", IoctlCommandString(command));
Packit 1244b8
    }
Packit 1244b8
Packit 1244b8
    return ret;
Packit 1244b8
}
Packit 1244b8
Packit 1244b8
Packit 1244b8
void* V4l2Encoder::mmap (void* addr, size_t length,
Packit 1244b8
                      int prot, int flags, unsigned int offset)
Packit 1244b8
{
Packit 1244b8
    uint32_t i;
Packit 1244b8
    ASSERT((prot == PROT_READ) | PROT_WRITE);
Packit 1244b8
    ASSERT(flags == MAP_SHARED);
Packit 1244b8
Packit 1244b8
    ASSERT(m_maxOutputBufferSize > 0);
Packit 1244b8
    ASSERT(length <= m_maxOutputBufferSize);
Packit 1244b8
    if (!m_outputBufferSpace) {
Packit 1244b8
        m_outputBufferSpace = static_cast<uint8_t*>(malloc(m_maxOutputBufferSize * m_maxBufferCount[OUTPUT]));
Packit 1244b8
        for (i=0; i
Packit 1244b8
            m_outputFrames[i].data = m_outputBufferSpace + m_maxOutputBufferSize*i;
Packit 1244b8
            m_outputFrames[i].bufferSize = m_maxOutputBufferSize;
Packit 1244b8
            m_outputFrames[i].format = OUTPUT_EVERYTHING;
Packit 1244b8
        }
Packit 1244b8
    }
Packit 1244b8
    ASSERT(m_outputBufferSpace);
Packit 1244b8
Packit 1244b8
    return m_outputBufferSpace + offset;
Packit 1244b8
}
Packit 1244b8