nuttx-apps/system/nxcodec/nxcodec.c
yangsen5 524caec5a0 nxcodec: Modify the logic of judging the correctness of the incoming pixformat
Signed-off-by: yangsen5 <yangsen5@xiaomi.com>
2024-09-13 12:33:45 +08:00

246 lines
5.9 KiB
C

/****************************************************************************
* apps/system/nxcodec/nxcodec.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <sys/ioctl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include "nxcodec.h"
/****************************************************************************
* Private Functions
****************************************************************************/
static inline bool nxcodec_splane_video(FAR struct v4l2_capability *cap)
{
return (cap->capabilities & V4L2_CAP_VIDEO_M2M) ||
((cap->capabilities & V4L2_CAP_STREAMING) &&
(cap->capabilities & (V4L2_CAP_VIDEO_OUTPUT |
V4L2_CAP_VIDEO_CAPTURE)));
}
static inline bool nxcodec_mplane_video(FAR struct v4l2_capability *cap)
{
return (cap->capabilities & V4L2_CAP_VIDEO_M2M_MPLANE) ||
((cap->capabilities & V4L2_CAP_STREAMING) &&
(cap->capabilities & (V4L2_CAP_VIDEO_OUTPUT_MPLANE |
V4L2_CAP_VIDEO_CAPTURE_MPLANE)));
}
static int nxcodec_prepare_contexts(FAR nxcodec_t *codec)
{
struct v4l2_capability cap;
int ret;
memset(&cap, 0, sizeof(cap));
ret = ioctl(codec->fd, VIDIOC_QUERYCAP, &cap);
if (ret < 0)
{
return -errno;
}
if (nxcodec_mplane_video(&cap))
{
codec->capture.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
codec->output.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
return 0;
}
if (nxcodec_splane_video(&cap))
{
codec->capture.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
codec->output.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
return 0;
}
return -EINVAL;
}
/****************************************************************************
* Public Functions
****************************************************************************/
int nxcodec_init(FAR nxcodec_t *codec)
{
int ret;
codec->fd = open(codec->devname, O_RDWR | O_NONBLOCK);
if (codec->fd < 0)
{
return -errno;
}
ret = nxcodec_prepare_contexts(codec);
if (ret < 0)
{
goto err0;
}
ret = nxcodec_context_get_format(&codec->output);
if (ret < 0)
{
printf("v4l2 output format not supported\n");
goto err0;
}
ret = nxcodec_context_get_format(&codec->capture);
if (ret < 0)
{
printf("v4l2 capture format not supported\n");
goto err0;
}
codec->output.format.type = codec->output.type;
ret = nxcodec_context_set_format(&codec->output);
if (ret < 0)
{
printf("can't set v4l2 output format\n");
goto err0;
}
codec->output.fd = open(codec->output.filename, O_RDONLY);
if (codec->output.fd < 0)
{
printf("Failed to open output file %s \n", codec->output.filename);
ret = -errno;
goto err0;
}
codec->capture.format.type = codec->capture.type;
ret = nxcodec_context_set_format(&codec->capture);
if (ret < 0)
{
printf("can't to set v4l2 capture format\n");
goto err1;
}
codec->capture.fd = open(codec->capture.filename,
O_WRONLY | O_CREAT, 0644);
if (codec->capture.fd < 0)
{
printf("Failed to open input file %s \n", codec->capture.filename);
ret = -errno;
goto err1;
}
return 0;
err1:
close(codec->output.fd);
err0:
close(codec->fd);
return ret;
}
int nxcodec_start(FAR nxcodec_t *codec)
{
int ret;
ret = nxcodec_context_init(&codec->output);
if (ret < 0)
{
printf("can't request output buffers\n");
return ret;
}
ret = nxcodec_context_set_status(&codec->output, VIDIOC_STREAMON);
if (ret < 0)
{
printf("set output VIDIOC_STREAMON failed\n");
goto err0;
}
ret = nxcodec_context_init(&codec->capture);
if (ret < 0)
{
printf("can't request capture buffers\n");
goto err0;
}
ret = nxcodec_context_set_status(&codec->capture, VIDIOC_STREAMON);
if (ret < 0)
{
printf("set capture VIDIOC_STREAMON failed\n");
goto err1;
}
ret = nxcodec_context_enqueue_frame(&codec->output);
if (ret < 0 && ret != -EAGAIN)
{
goto err1;
}
return 0;
err1:
nxcodec_context_uninit(&codec->capture);
err0:
nxcodec_context_uninit(&codec->output);
return ret;
}
int nxcodec_stop(FAR nxcodec_t *codec)
{
int ret;
if (!codec)
{
return 0;
}
nxcodec_context_uninit(&codec->output);
ret = nxcodec_context_set_status(&codec->output, VIDIOC_STREAMOFF);
if (ret < 0)
{
printf("set output VIDIOC_STREAMOFF failed\n");
return ret;
}
nxcodec_context_uninit(&codec->capture);
ret = nxcodec_context_set_status(&codec->capture, VIDIOC_STREAMOFF);
if (ret < 0)
{
printf("set capture VIDIOC_STREAMOFF failed\n");
return ret;
}
return 0;
}
int nxcodec_uninit(FAR nxcodec_t *codec)
{
close(codec->capture.fd);
close(codec->output.fd);
close(codec->fd);
return 0;
}