| /**************************************************************************** |
| * 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; |
| } |
| |
| if (codec->output.fdesc.pixelformat != |
| codec->output.format.fmt.pix.pixelformat) |
| { |
| ret = -EINVAL; |
| 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; |
| } |
| |
| if (codec->capture.fdesc.pixelformat != |
| codec->capture.format.fmt.pix.pixelformat) |
| { |
| ret = -EINVAL; |
| goto err1; |
| } |
| |
| 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; |
| } |