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; }
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; }
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; }