소스 정리

main
cityhunter 8 months ago
parent 1709e4ad2f
commit 4ef17a44ef

@ -30,7 +30,35 @@
</component>
<component name="ChangeListManager">
<list default="true" id="c7060a21-3980-4f82-af16-7c494d5c734c" name="변경" comment="">
<change afterPath="$PROJECT_DIR$/gitsh.sh" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Makefile" beforeDir="false" afterPath="$PROJECT_DIR$/Makefile" afterDir="false" />
<change beforePath="$PROJECT_DIR$/gen/onvif.h" beforeDir="false" afterPath="$PROJECT_DIR$/gen/onvif.h" afterDir="false" />
<change beforePath="$PROJECT_DIR$/gen/soapC_001.cpp" beforeDir="false" afterPath="$PROJECT_DIR$/gen/soapC_001.cpp" afterDir="false" />
<change beforePath="$PROJECT_DIR$/gen/soapC_002.cpp" beforeDir="false" afterPath="$PROJECT_DIR$/gen/soapC_002.cpp" afterDir="false" />
<change beforePath="$PROJECT_DIR$/gen/soapC_003.cpp" beforeDir="false" afterPath="$PROJECT_DIR$/gen/soapC_003.cpp" afterDir="false" />
<change beforePath="$PROJECT_DIR$/gen/soapC_004.cpp" beforeDir="false" afterPath="$PROJECT_DIR$/gen/soapC_004.cpp" afterDir="false" />
<change beforePath="$PROJECT_DIR$/libonvif.a" beforeDir="false" afterPath="$PROJECT_DIR$/libonvif.a" afterDir="false" />
<change beforePath="$PROJECT_DIR$/libv4l2cpp/.gitignore" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/libv4l2cpp/CMakeLists.txt" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/libv4l2cpp/README.md" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/libv4l2cpp/UNLICENSE" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/libv4l2cpp/inc/V4l2Access.h" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/libv4l2cpp/inc/V4l2Capture.h" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/libv4l2cpp/inc/V4l2Device.h" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/libv4l2cpp/inc/V4l2MmapDevice.h" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/libv4l2cpp/inc/V4l2Output.h" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/libv4l2cpp/inc/V4l2ReadWriteDevice.h" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/libv4l2cpp/inc/logger.h" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/libv4l2cpp/main.cpp" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/libv4l2cpp/src/V4l2Access.cpp" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/libv4l2cpp/src/V4l2Capture.cpp" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/libv4l2cpp/src/V4l2Device.cpp" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/libv4l2cpp/src/V4l2MmapDevice.cpp" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/libv4l2cpp/src/V4l2Output.cpp" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/libv4l2cpp/src/V4l2ReadWriteDevice.cpp" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/libv4l2cpp/src/logger.cpp" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/onvif-server.exe" beforeDir="false" afterPath="$PROJECT_DIR$/onvif-server.exe" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/serverDevice.o" beforeDir="false" afterPath="$PROJECT_DIR$/src/serverDevice.o" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
@ -93,10 +121,13 @@
<component name="PropertiesComponent"><![CDATA[{
"keyToString": {
"Makefile 타깃.all.executor": "Run",
"Makefile 타깃.onvif-client.exe.executor": "Run",
"Makefile 타깃.onvif-server.exe.executor": "Run",
"ModuleVcsDetector.initialDetectionPerformed": "true",
"RunOnceActivity.RadMigrateCodeStyle": "true",
"RunOnceActivity.ShowReadmeOnStart": "true",
"RunOnceActivity.cidr.known.project.marker": "true",
"RunOnceActivity.git.unshallow": "true",
"RunOnceActivity.readMode.enableVisualFormatting": "true",
"SHELLCHECK.PATH": "/home/cityhunter/.local/share/JetBrains/CLion2025.1/Shell Script/shellcheck",
"cf.first.check.clang-format": "false",
@ -111,10 +142,10 @@
"vue.rearranger.settings.migration": "true"
}
}]]></component>
<component name="RunManager" selected="Makefile 타깃.all">
<configuration default="true" type="CLionExternalRunConfiguration" factoryName="Application" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true">
<component name="RunManager" selected="Makefile 타깃.onvif-server.exe">
<configuration name="all" type="CLionNativeAppRunConfigurationType" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="v4l2onvif" TARGET_NAME="all" CONFIG_NAME="all" version="1">
<method v="2">
<option name="CLION.EXTERNAL.BUILD" enabled="true" />
<option name="CLION.COMPOUND.BUILD" enabled="true" />
</method>
</configuration>
<configuration name="all" type="CLionNativeAppRunConfigurationType" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="v4l2onvif" TARGET_NAME="all" CONFIG_NAME="all" version="1">
@ -127,6 +158,16 @@
<option name="CLION.COMPOUND.BUILD" enabled="true" />
</method>
</configuration>
<configuration name="install" type="CLionNativeAppRunConfigurationType" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="v4l2onvif" TARGET_NAME="install" CONFIG_NAME="install" version="1">
<method v="2">
<option name="CLION.COMPOUND.BUILD" enabled="true" />
</method>
</configuration>
<configuration name="libclient.a" type="CLionNativeAppRunConfigurationType" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="v4l2onvif" TARGET_NAME="libclient.a" CONFIG_NAME="libclient.a" version="1">
<method v="2">
<option name="CLION.COMPOUND.BUILD" enabled="true" />
</method>
</configuration>
<configuration name="libclient.a" type="CLionNativeAppRunConfigurationType" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="v4l2onvif" TARGET_NAME="libclient.a" CONFIG_NAME="libclient.a" version="1">
<method v="2">
<option name="CLION.COMPOUND.BUILD" enabled="true" />
@ -137,6 +178,16 @@
<option name="CLION.COMPOUND.BUILD" enabled="true" />
</method>
</configuration>
<configuration name="liblibv4l2rtspserver.a" type="CLionNativeAppRunConfigurationType" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="v4l2onvif" TARGET_NAME="liblibv4l2rtspserver.a" CONFIG_NAME="liblibv4l2rtspserver.a" version="1">
<method v="2">
<option name="CLION.COMPOUND.BUILD" enabled="true" />
</method>
</configuration>
<configuration name="libonvif.a" type="CLionNativeAppRunConfigurationType" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="v4l2onvif" TARGET_NAME="libonvif.a" CONFIG_NAME="libonvif.a" version="1">
<method v="2">
<option name="CLION.COMPOUND.BUILD" enabled="true" />
</method>
</configuration>
<configuration name="libonvif.a" type="CLionNativeAppRunConfigurationType" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="v4l2onvif" TARGET_NAME="libonvif.a" CONFIG_NAME="libonvif.a" version="1">
<method v="2">
<option name="CLION.COMPOUND.BUILD" enabled="true" />
@ -147,6 +198,16 @@
<option name="CLION.COMPOUND.BUILD" enabled="true" />
</method>
</configuration>
<configuration name="libserver.a" type="CLionNativeAppRunConfigurationType" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="v4l2onvif" TARGET_NAME="libserver.a" CONFIG_NAME="libserver.a" version="1">
<method v="2">
<option name="CLION.COMPOUND.BUILD" enabled="true" />
</method>
</configuration>
<configuration name="libwsdd.a" type="CLionNativeAppRunConfigurationType" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="v4l2onvif" TARGET_NAME="libwsdd.a" CONFIG_NAME="libwsdd.a" version="1">
<method v="2">
<option name="CLION.COMPOUND.BUILD" enabled="true" />
</method>
</configuration>
<configuration name="libwsdd.a" type="CLionNativeAppRunConfigurationType" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="v4l2onvif" TARGET_NAME="libwsdd.a" CONFIG_NAME="libwsdd.a" version="1">
<method v="2">
<option name="CLION.COMPOUND.BUILD" enabled="true" />
@ -157,18 +218,59 @@
<option name="CLION.COMPOUND.BUILD" enabled="true" />
</method>
</configuration>
<configuration name="onvif-client.exe" type="CLionNativeAppRunConfigurationType" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="v4l2onvif" TARGET_NAME="onvif-client.exe" CONFIG_NAME="onvif-client.exe" version="1">
<method v="2">
<option name="CLION.COMPOUND.BUILD" enabled="true" />
</method>
</configuration>
<configuration name="onvif-server.exe" type="CLionNativeAppRunConfigurationType" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="v4l2onvif" TARGET_NAME="onvif-server.exe" CONFIG_NAME="onvif-server.exe" version="1">
<method v="2">
<option name="CLION.COMPOUND.BUILD" enabled="true" />
</method>
</configuration>
<configuration name="onvif-server.exe" type="CLionNativeAppRunConfigurationType" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="v4l2onvif" TARGET_NAME="onvif-server.exe" CONFIG_NAME="onvif-server.exe" version="1">
<method v="2">
<option name="CLION.COMPOUND.BUILD" enabled="true" />
</method>
</configuration>
<configuration default="true" type="CMakeRunConfiguration" factoryName="Application" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true">
<method v="2">
<option name="com.jetbrains.cidr.execution.CidrBuildBeforeRunTaskProvider$BuildBeforeRunTask" enabled="true" />
</method>
</configuration>
<configuration name="all" type="MAKEFILE_TARGET_RUN_CONFIGURATION" factoryName="Makefile" temporary="true">
<makefile filename="$PROJECT_DIR$/v4l2onvif/Makefile" target="all" workingDirectory="" arguments="">
<envs />
</makefile>
<method v="2" />
</configuration>
<configuration name="all" type="MAKEFILE_TARGET_RUN_CONFIGURATION" factoryName="Makefile" temporary="true">
<makefile filename="$PROJECT_DIR$/v4l2onvif/Makefile" target="all" workingDirectory="" arguments="">
<envs />
</makefile>
<method v="2" />
</configuration>
<configuration name="onvif-client.exe" type="MAKEFILE_TARGET_RUN_CONFIGURATION" factoryName="Makefile" temporary="true">
<makefile filename="$PROJECT_DIR$/Makefile" target="onvif-client.exe" workingDirectory="" arguments="">
<envs />
</makefile>
<method v="2" />
</configuration>
<configuration name="onvif-client.exe" type="MAKEFILE_TARGET_RUN_CONFIGURATION" factoryName="Makefile" temporary="true">
<makefile filename="$PROJECT_DIR$/Makefile" target="onvif-client.exe" workingDirectory="" arguments="">
<envs />
</makefile>
<method v="2" />
</configuration>
<configuration name="onvif-server.exe" type="MAKEFILE_TARGET_RUN_CONFIGURATION" factoryName="Makefile" temporary="true">
<makefile filename="$PROJECT_DIR$/Makefile" target="onvif-server.exe" workingDirectory="" arguments="">
<envs />
</makefile>
<method v="2" />
</configuration>
<list>
<item itemvalue="Makefile 타깃.onvif-server.exe" />
<item itemvalue="Makefile 타깃.onvif-client.exe" />
<item itemvalue="Makefile 타깃.all" />
<item itemvalue="네이티브 애플리케이션.all" />
<item itemvalue="네이티브 애플리케이션.install" />
@ -182,6 +284,8 @@
</list>
<recent_temporary>
<list>
<item itemvalue="Makefile 타깃.onvif-server.exe" />
<item itemvalue="Makefile 타깃.onvif-client.exe" />
<item itemvalue="Makefile 타깃.all" />
</list>
</recent_temporary>
@ -195,7 +299,8 @@
<updated>1745466803192</updated>
<workItem from="1745466811240" duration="64000" />
<workItem from="1745467023675" duration="173000" />
<workItem from="1745467243162" duration="6561000" />
<workItem from="1745467243162" duration="9543000" />
<workItem from="1745478005046" duration="3161000" />
</task>
<servers />
</component>
@ -207,7 +312,19 @@
<map>
<entry key="MAIN">
<value>
<State />
<State>
<option name="FILTERS">
<map>
<entry key="branch">
<value>
<list>
<option value="main" />
</list>
</value>
</entry>
</map>
</option>
</State>
</value>
</entry>
</map>

@ -3,7 +3,7 @@ PREFIX?=/usr
DESTDIR?=$(PREFIX)/bin
$(info PREFIX=$(PREFIX) SYSROOT=$(SYSROOT) DESTDIR=$(DESTDIR))
#VERSION=$(shell git describe --tags --always --dirty)
VERSION=$(shell git describe --tags --always --dirty)
$(info VERSION=$(VERSION))
GSOAP_PREFIX?=$(SYSROOT)/usr/local
@ -57,14 +57,14 @@ libonvif.a: $(ONVIF_SRC:%.cpp=%.o)
# ws-discovery
libwsdd.a:
# git submodule init ws-discovery
# git submodule update ws-discovery
git submodule init ws-discovery
git submodule update ws-discovery
make -C ws-discovery/gsoap libwsdd.a
cp ws-discovery/gsoap/libwsdd.a .
# v4l2rtsp
liblibv4l2rtspserver.a:
# git submodule update --recursive --init v4l2rtspserver
git submodule update --recursive --init v4l2rtspserver
cd v4l2rtspserver && cmake -DALSA=OFF -DCMAKE_CXX_COMPILER=$(CXX) -DCMAKE_C_COMPILER=$(CC) -DCMAKE_CXX_FLAGS=$(CMAKE_CXX_FLAGS) . && make libv4l2rtspserver
cp v4l2rtspserver/$@ .
@ -87,4 +87,4 @@ clean:
install:
mkdir -p $(DESTDIR)
install -D -m 0755 onvif-server.exe $(DESTDIR)
install -D -m 0755 onvif-client.exe $(DESTDIR)
install -D -m 0755 onvif-client.exe $(DESTDIR)

@ -1,8 +1,8 @@
#import "wsdd10.h"
#import "wsse.h"
/* gen/onvif.h
Generated by wsdl2h 2.8.138 from /home/cityhunter/CLionProjects/v4l2onvif/wsdl/b-2.xsd /home/cityhunter/CLionProjects/v4l2onvif/wsdl/bf-2.xsd /home/cityhunter/CLionProjects/v4l2onvif/wsdl/bw-2.wsdl /home/cityhunter/CLionProjects/v4l2onvif/wsdl/common.xsd /home/cityhunter/CLionProjects/v4l2onvif/wsdl/deviceio.wsdl /home/cityhunter/CLionProjects/v4l2onvif/wsdl/devicemgmt.wsdl /home/cityhunter/CLionProjects/v4l2onvif/wsdl/display.wsdl /home/cityhunter/CLionProjects/v4l2onvif/wsdl/event.wsdl /home/cityhunter/CLionProjects/v4l2onvif/wsdl/imaging.wsdl /home/cityhunter/CLionProjects/v4l2onvif/wsdl/include /home/cityhunter/CLionProjects/v4l2onvif/wsdl/media.wsdl /home/cityhunter/CLionProjects/v4l2onvif/wsdl/onvif.xsd /home/cityhunter/CLionProjects/v4l2onvif/wsdl/ptz.wsdl /home/cityhunter/CLionProjects/v4l2onvif/wsdl/r-2.xsd /home/cityhunter/CLionProjects/v4l2onvif/wsdl/receiver.wsdl /home/cityhunter/CLionProjects/v4l2onvif/wsdl/recording.wsdl /home/cityhunter/CLionProjects/v4l2onvif/wsdl/replay.wsdl /home/cityhunter/CLionProjects/v4l2onvif/wsdl/rw-2.wsdl /home/cityhunter/CLionProjects/v4l2onvif/wsdl/search.wsdl /home/cityhunter/CLionProjects/v4l2onvif/wsdl/t-1.xsd and typemap.dat
2025-04-24 04:46:34 GMT
Generated by wsdl2h 2.8.138 from wsdl/b-2.xsd wsdl/bf-2.xsd wsdl/bw-2.wsdl wsdl/common.xsd wsdl/deviceio.wsdl wsdl/devicemgmt.wsdl wsdl/display.wsdl wsdl/event.wsdl wsdl/imaging.wsdl wsdl/include wsdl/media.wsdl wsdl/onvif.xsd wsdl/ptz.wsdl wsdl/r-2.xsd wsdl/receiver.wsdl wsdl/recording.wsdl wsdl/replay.wsdl wsdl/rw-2.wsdl wsdl/search.wsdl wsdl/t-1.xsd and typemap.dat
2025-04-24 07:11:06 GMT
DO NOT INCLUDE THIS ANNOTATED FILE DIRECTLY IN YOUR PROJECT SOURCE CODE.
USE THE FILES GENERATED BY soapcpp2 FOR YOUR PROJECT'S SOURCE CODE.

@ -18,7 +18,7 @@ A commercial use license is available from Genivia Inc., contact@genivia.com
#include "soapH.h"
SOAP_SOURCE_STAMP("@(#) soapC_nnn.cpp ver 2.8.138 2025-04-24 04:46:35 GMT")
SOAP_SOURCE_STAMP("@(#) soapC_nnn.cpp ver 2.8.138 2025-04-24 07:11:07 GMT")
#ifndef WITH_NOGLOBAL

@ -18,7 +18,7 @@ A commercial use license is available from Genivia Inc., contact@genivia.com
#include "soapH.h"
SOAP_SOURCE_STAMP("@(#) soapC_nnn.cpp ver 2.8.138 2025-04-24 04:46:36 GMT")
SOAP_SOURCE_STAMP("@(#) soapC_nnn.cpp ver 2.8.138 2025-04-24 07:11:07 GMT")
void tt__DefoggingOptions::soap_default(struct soap *soap)

@ -18,7 +18,7 @@ A commercial use license is available from Genivia Inc., contact@genivia.com
#include "soapH.h"
SOAP_SOURCE_STAMP("@(#) soapC_nnn.cpp ver 2.8.138 2025-04-24 04:46:36 GMT")
SOAP_SOURCE_STAMP("@(#) soapC_nnn.cpp ver 2.8.138 2025-04-24 07:11:07 GMT")
SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_PointerTo_trt__SetAudioEncoderConfiguration(struct soap *soap, _trt__SetAudioEncoderConfiguration *const*a)

@ -18,7 +18,7 @@ A commercial use license is available from Genivia Inc., contact@genivia.com
#include "soapH.h"
SOAP_SOURCE_STAMP("@(#) soapC_nnn.cpp ver 2.8.138 2025-04-24 04:46:36 GMT")
SOAP_SOURCE_STAMP("@(#) soapC_nnn.cpp ver 2.8.138 2025-04-24 07:11:07 GMT")
SOAP_FMAC3 void SOAP_FMAC4 soap_default_std__vectorTemplateOf_wstop__TopicNamespaceType_Topic(struct soap *soap, std::vector<_wstop__TopicNamespaceType_Topic> *p)

Binary file not shown.

@ -1,7 +0,0 @@
src/*.o
*.a
*.cmake
CMakeCache.txt
CMakeFiles/
libv4l2cpptest
Makefile

@ -1,14 +0,0 @@
cmake_minimum_required(VERSION 3.5)
# set project name from current directory
get_filename_component(BASENAME ${CMAKE_CURRENT_LIST_DIR} NAME)
project(${BASENAME})
set (CMAKE_CXX_STANDARD 11)
aux_source_directory(src SRC_FILES)
add_library(${PROJECT_NAME} STATIC ${SRC_FILES})
target_include_directories(${PROJECT_NAME} PUBLIC "${CMAKE_CURRENT_LIST_DIR}/inc")
add_executable (${PROJECT_NAME}test main.cpp)
target_link_libraries (${PROJECT_NAME}test ${PROJECT_NAME})

@ -1,43 +0,0 @@
libv4l2cpp
====================
It is a C++ wrapper for V4L2
Dependencies
------------
- liblog4cpp5-dev (optional)
V4L2 Capture
-------------
- create a V4L2 Capture interface using MMAP interface:
V4L2DeviceParameters param("/dev/video0", V4L2_PIX_FMT_*, width, height, fps, IOTYPE_MMAP);
V4l2Capture* videoCapture = V4l2Capture::create(param);
- data are available :
timeval timeout;
bool isReadable = videoCapture->isReadable(&timeout);
- read data :
size_t nb = videoCapture->read(buffer, bufferSize);
V4L2 Output
-------------
- To create a V4L2 Output interface using MMAP interface:
V4L2DeviceParameters param("/dev/video0", V4L2_PIX_FMT_*, width, height, fps, IOTYPE_MMAP);
V4l2Output* videoOutput = V4l2Output::create(param);
- data could be written :
timeval timeout;
bool isWritable = videoOutput->isWritable(&timeout);
- write data :
size_t nb = videoOutput->write(buffer, bufferSize);

@ -1,24 +0,0 @@
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <http://unlicense.org>

@ -1,48 +0,0 @@
/* ---------------------------------------------------------------------------
** This software is in the public domain, furnished "as is", without technical
** support, and with no warranty, express or implied, as to its usefulness for
** any purpose.
**
** V4l2Access.h
**
** V4L2 wrapper
**
** -------------------------------------------------------------------------*/
#pragma once
#include "V4l2Device.h"
class V4l2Access
{
public:
explicit V4l2Access(V4l2Device* device);
virtual ~V4l2Access();
int getFd() { return m_device->getFd(); }
unsigned int getBufferSize() { return m_device->getBufferSize(); }
unsigned int getFormat() { return m_device->getFormat(); }
unsigned int getWidth() { return m_device->getWidth(); }
unsigned int getHeight() { return m_device->getHeight(); }
void queryFormat() { m_device->queryFormat(); }
int setFormat(unsigned int format, unsigned int width, unsigned int height) {
return m_device->setFormat(format, width, height);
}
int setFps(int fps) {
return m_device->setFps(fps);
}
int isReady() { return m_device->isReady(); }
int start() { return m_device->start(); }
int stop() { return m_device->stop(); }
private:
V4l2Access(const V4l2Access&);
V4l2Access & operator=(const V4l2Access&);
protected:
V4l2Device* m_device;
};

@ -1,33 +0,0 @@
/* ---------------------------------------------------------------------------
** This software is in the public domain, furnished "as is", without technical
** support, and with no warranty, express or implied, as to its usefulness for
** any purpose.
**
** V4l2Capture.h
**
** V4L2 Capture wrapper
**
** -------------------------------------------------------------------------*/
#pragma once
#include "V4l2Access.h"
// ---------------------------------
// V4L2 Capture
// ---------------------------------
class V4l2Capture : public V4l2Access
{
protected:
explicit V4l2Capture(V4l2Device* device);
public:
static V4l2Capture* create(const V4L2DeviceParameters & param);
virtual ~V4l2Capture();
size_t read(char* buffer, size_t bufferSize);
bool isReadable(timeval* tv);
};

@ -1,124 +0,0 @@
/* ---------------------------------------------------------------------------
** This software is in the public domain, furnished "as is", without technical
** support, and with no warranty, express or implied, as to its usefulness for
** any purpose.
**
** V4l2Device.h
**
** V4L2 wrapper
**
** -------------------------------------------------------------------------*/
#pragma once
#include <string>
#include <list>
#include <linux/videodev2.h>
#include <fcntl.h>
#ifndef V4L2_PIX_FMT_VP8
#define V4L2_PIX_FMT_VP8 v4l2_fourcc('V', 'P', '8', '0')
#endif
#ifndef V4L2_PIX_FMT_VP9
#define V4L2_PIX_FMT_VP9 v4l2_fourcc('V', 'P', '9', '0')
#endif
#ifndef V4L2_PIX_FMT_HEVC
#define V4L2_PIX_FMT_HEVC v4l2_fourcc('H', 'E', 'V', 'C')
#endif
enum V4l2IoType
{
IOTYPE_READWRITE,
IOTYPE_MMAP
};
// ---------------------------------
// V4L2 Device parameters
// ---------------------------------
struct V4L2DeviceParameters
{
V4L2DeviceParameters(const char* devname, const std::list<unsigned int> & formatList, unsigned int width, unsigned int height, int fps, V4l2IoType ioType = IOTYPE_MMAP, int openFlags = O_RDWR | O_NONBLOCK) :
m_devName(devname), m_formatList(formatList), m_width(width), m_height(height), m_fps(fps), m_iotype(ioType), m_openFlags(openFlags) {}
V4L2DeviceParameters(const char* devname, unsigned int format, unsigned int width, unsigned int height, int fps, V4l2IoType ioType = IOTYPE_MMAP, int openFlags = O_RDWR | O_NONBLOCK) :
m_devName(devname), m_width(width), m_height(height), m_fps(fps), m_iotype(ioType), m_openFlags(openFlags) {
if (format) {
m_formatList.push_back(format);
}
}
std::string m_devName;
std::list<unsigned int> m_formatList;
unsigned int m_width;
unsigned int m_height;
int m_fps;
V4l2IoType m_iotype;
int m_verbose;
int m_openFlags;
};
// ---------------------------------
// V4L2 Device
// ---------------------------------
class V4l2Device
{
friend class V4l2Capture;
friend class V4l2Output;
protected:
void close();
int initdevice(const char *dev_name, unsigned int mandatoryCapabilities);
int checkCapabilities(int fd, unsigned int mandatoryCapabilities);
int configureFormat(int fd);
int configureFormat(int fd, unsigned int format, unsigned int width, unsigned int height);
int configureParam(int fd, int fps);
virtual bool init(unsigned int mandatoryCapabilities);
virtual size_t writeInternal(char*, size_t) { return -1; }
virtual bool startPartialWrite() { return false; }
virtual size_t writePartialInternal(char*, size_t) { return -1; }
virtual bool endPartialWrite() { return false; }
virtual size_t readInternal(char*, size_t) { return -1; }
public:
V4l2Device(const V4L2DeviceParameters& params, v4l2_buf_type deviceType);
virtual ~V4l2Device();
virtual bool isReady() { return (m_fd != -1); }
virtual bool start() { return true; }
virtual bool stop() { return true; }
unsigned int getBufferSize() { return m_bufferSize; }
unsigned int getFormat() { return m_format; }
unsigned int getWidth() { return m_width; }
unsigned int getHeight() { return m_height; }
int getFd() { return m_fd; }
void queryFormat();
int setFormat(unsigned int format, unsigned int width, unsigned int height) {
return this->configureFormat(m_fd, format, width, height);
}
int setFps(int fps) {
return this->configureParam(m_fd, fps);
}
static std::string fourcc(unsigned int format);
static unsigned int fourcc(const char* format);
protected:
V4L2DeviceParameters m_params;
int m_fd;
v4l2_buf_type m_deviceType;
unsigned int m_bufferSize;
unsigned int m_format;
unsigned int m_width;
unsigned int m_height;
struct v4l2_buffer m_partialWriteBuf;
bool m_partialWriteInProgress;
};

@ -1,48 +0,0 @@
/* ---------------------------------------------------------------------------
** This software is in the public domain, furnished "as is", without technical
** support, and with no warranty, express or implied, as to its usefulness for
** any purpose.
**
** V4l2MmapDevice.h
**
** V4L2 source using mmap API
**
** -------------------------------------------------------------------------*/
#pragma once
#include "V4l2Device.h"
#define V4L2MMAP_NBBUFFER 10
class V4l2MmapDevice : public V4l2Device
{
protected:
size_t writeInternal(char* buffer, size_t bufferSize);
bool startPartialWrite();
size_t writePartialInternal(char*, size_t);
bool endPartialWrite();
size_t readInternal(char* buffer, size_t bufferSize);
public:
V4l2MmapDevice(const V4L2DeviceParameters & params, v4l2_buf_type deviceType);
virtual ~V4l2MmapDevice();
virtual bool init(unsigned int mandatoryCapabilities);
virtual bool isReady() { return ((m_fd != -1)&& (n_buffers != 0)); }
virtual bool start();
virtual bool stop();
protected:
unsigned int n_buffers;
struct buffer
{
void * start;
size_t length;
};
buffer m_buffer[V4L2MMAP_NBBUFFER];
};

@ -1,35 +0,0 @@
/* ---------------------------------------------------------------------------
** This software is in the public domain, furnished "as is", without technical
** support, and with no warranty, express or implied, as to its usefulness for
** any purpose.
**
** V4l2Output.h
**
** V4L2 Output wrapper
**
** -------------------------------------------------------------------------*/
#pragma once
#include "V4l2Access.h"
// ---------------------------------
// V4L2 Output
// ---------------------------------
class V4l2Output : public V4l2Access
{
protected:
explicit V4l2Output(V4l2Device* device);
public:
static V4l2Output* create(const V4L2DeviceParameters & param);
virtual ~V4l2Output();
size_t write(char* buffer, size_t bufferSize);
bool isWritable(timeval* tv);
bool startPartialWrite();
size_t writePartial(char* buffer, size_t bufferSize);
bool endPartialWrite();
};

@ -1,29 +0,0 @@
/* ---------------------------------------------------------------------------
** This software is in the public domain, furnished "as is", without technical
** support, and with no warranty, express or implied, as to its usefulness for
** any purpose.
**
** V4l2ReadWriteDevice.h
**
** V4L2 source using read/write API
**
** -------------------------------------------------------------------------*/
#pragma once
#include "V4l2Device.h"
class V4l2ReadWriteDevice : public V4l2Device
{
protected:
virtual size_t writeInternal(char* buffer, size_t bufferSize);
virtual size_t readInternal(char* buffer, size_t bufferSize);
public:
V4l2ReadWriteDevice(const V4L2DeviceParameters& params, v4l2_buf_type deviceType);
};

@ -1,112 +0,0 @@
/* ---------------------------------------------------------------------------
** This software is in the public domain, furnished "as is", without technical
** support, and with no warranty, express or implied, as to its usefulness for
** any purpose.
**
** logger.h
**
** -------------------------------------------------------------------------*/
#pragma once
#include <unistd.h>
#include <cstring>
#define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
#ifdef HAVE_LOG4CPP
#include "log4cpp/Category.hh"
#include "log4cpp/FileAppender.hh"
#include "log4cpp/PatternLayout.hh"
#define LOG(__level) log4cpp::Category::getRoot() << log4cpp::Priority::__level << __FILENAME__ << ":" << __LINE__ << "\n\t"
inline int getLogLevel() {
log4cpp::Category &log = log4cpp::Category::getRoot();
return log.getPriority();
}
inline void setLogLevel(int verbose) {
log4cpp::Category &log = log4cpp::Category::getRoot();
switch (verbose)
{
case 2: log.setPriority(log4cpp::Priority::DEBUG); break;
case 1: log.setPriority(log4cpp::Priority::INFO); break;
default: log.setPriority(log4cpp::Priority::NOTICE); break;
}
}
inline void initLogger(int verbose)
{
// initialize log4cpp
log4cpp::Category &log = log4cpp::Category::getRoot();
log4cpp::Appender *app = new log4cpp::FileAppender("root", fileno(stdout));
if (app)
{
log4cpp::PatternLayout *plt = new log4cpp::PatternLayout();
if (plt)
{
plt->setConversionPattern("%d [%-6p] - %m%n");
app->setLayout(plt);
}
log.addAppender(app);
}
setLogLevel(verbose);
LOG(INFO) << "level:" << log4cpp::Priority::getPriorityName(log.getPriority());
}
#else
typedef enum {EMERG = 0,
FATAL = 0,
ALERT = 100,
CRIT = 200,
ERROR = 300,
WARN = 400,
NOTICE = 500,
INFO = 600,
DEBUG = 700,
NOTSET = 800
} PriorityLevel;
#include <iostream>
#include <iomanip>
#include <sstream>
extern int LogLevel;
inline std::string getLevel(const char* level) {
std::stringstream ss;
ss << "[" << level << "]";
return ss.str();
}
inline std::string getFilename(const char* filename, int line) {
std::stringstream ss;
ss << "(" << filename << ":" << line << ")";
return ss.str();
}
#define LOG(__level) if (__level<=LogLevel) std::cout << "\n" << std::setw(8) << std::left << getLevel(#__level) << " " << std::setw(30) << std::left << getFilename(__FILENAME__, __LINE__) << "\t"
inline int getLogLevel() {
return LogLevel;
}
inline void setLogLevel(int verbose) {
switch (verbose)
{
case 2: LogLevel=DEBUG; break;
case 1: LogLevel=INFO; break;
default: LogLevel=NOTICE; break;
}
}
inline void initLogger(int verbose)
{
setLogLevel(verbose);
std::cout << "log level:" << LogLevel << std::endl;
}
#endif

@ -1,130 +0,0 @@
/* ---------------------------------------------------------------------------
** This software is in the public domain, furnished "as is", without technical
** support, and with no warranty, express or implied, as to its usefulness for
** any purpose.
**
** main.cpp
**
** test V4L2 capture device
**
** -------------------------------------------------------------------------*/
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <signal.h>
#include "logger.h"
#include "V4l2Capture.h"
int stop=0;
/* ---------------------------------------------------------------------------
** SIGINT handler
** -------------------------------------------------------------------------*/
void sighandler(int)
{
printf("SIGINT\n");
stop =1;
}
/* ---------------------------------------------------------------------------
** main
** -------------------------------------------------------------------------*/
int main(int argc, char* argv[])
{
int verbose = 0;
const char *in_devname = "/dev/video0";
V4l2IoType ioTypeIn = IOTYPE_MMAP;
int format = 0;
int width = 0;
int height = 0;
int fps = 0;
int framecount = 0;
int c = 0;
while ((c = getopt (argc, argv, "x:hv:" "G:f:r")) != -1)
{
switch (c)
{
case 'v': verbose = 1; if (optarg && *optarg=='v') verbose++; break;
case 'r': ioTypeIn = IOTYPE_READWRITE ; break;
case 'G': sscanf(optarg,"%dx%dx%d", &width, &height, &fps) ; break;
case 'f': format = V4l2Device::fourcc(optarg) ; break;
case 'x': sscanf(optarg,"%d", &framecount) ; break;
case 'h':
{
std::cout << argv[0] << " [-v[v]] [-G <width>x<height>x<fps>] [-f format] [device] [-r]" << std::endl;
std::cout << "\t -G <width>x<height>x<fps> : set capture resolution" << std::endl;
std::cout << "\t -v : verbose " << std::endl;
std::cout << "\t -vv : very verbose " << std::endl;
std::cout << "\t -r : V4L2 capture using read interface (default use memory mapped buffers)" << std::endl;
std::cout << "\t -x <count> : read <count> frames and save them in current dir." << std::endl;
std::cout << "\t device : V4L2 capture device (default "<< in_devname << ")" << std::endl;
exit(0);
}
}
}
if (optind<argc)
{
in_devname = argv[optind];
optind++;
}
// initialize log4cpp
initLogger(verbose);
// init V4L2 capture interface
V4L2DeviceParameters param(in_devname, format, width, height, fps, ioTypeIn);
V4l2Capture* videoCapture = V4l2Capture::create(param);
if (videoCapture == NULL)
{
LOG(WARN) << "Cannot reading from V4L2 capture interface for device:" << in_devname;
}
else
{
timeval tv;
LOG(NOTICE) << "Start reading from " << in_devname;
signal(SIGINT,sighandler);
while (!stop)
{
tv.tv_sec=1;
tv.tv_usec=0;
int ret = videoCapture->isReadable(&tv);
if (ret == 1)
{
char buffer[videoCapture->getBufferSize()];
int rsize = videoCapture->read(buffer, sizeof(buffer));
if (rsize == -1)
{
LOG(NOTICE) << "stop " << strerror(errno);
stop=1;
}
else
{
LOG(NOTICE) << "size:" << rsize;
static int stop_count = 0;
if(framecount and stop_count < framecount){
std::string filename = "Frame" + std::to_string(stop_count) + '.' + V4l2Device::fourcc(videoCapture->getFormat());
stop_count++;
FILE *fp = fopen(filename.c_str(), "wb");
fwrite(buffer, 1, rsize, fp);
fclose(fp);
LOG(NOTICE) << "saved:\t" << filename;
}
}
}
else if (ret == -1)
{
LOG(NOTICE) << "stop " << strerror(errno);
stop=1;
}
}
delete videoCapture;
}
return 0;
}

@ -1,20 +0,0 @@
/* ---------------------------------------------------------------------------
** This software is in the public domain, furnished "as is", without technical
** support, and with no warranty, express or implied, as to its usefulness for
** any purpose.
**
** V4l2Access.cpp
**
** V4L2 wrapper
**
** -------------------------------------------------------------------------*/
#include "V4l2Access.h"
V4l2Access::V4l2Access(V4l2Device* device) : m_device(device) {
}
V4l2Access::~V4l2Access() {
delete m_device;
}

@ -1,90 +0,0 @@
/* ---------------------------------------------------------------------------
** This software is in the public domain, furnished "as is", without technical
** support, and with no warranty, express or implied, as to its usefulness for
** any purpose.
**
** V4l2Capture.cpp
**
** V4L2 wrapper
**
** -------------------------------------------------------------------------*/
// libv4l2
#include <linux/videodev2.h>
// project
#include "logger.h"
#include "V4l2Capture.h"
#include "V4l2MmapDevice.h"
#include "V4l2ReadWriteDevice.h"
// -----------------------------------------
// create video capture interface
// -----------------------------------------
V4l2Capture* V4l2Capture::create(const V4L2DeviceParameters & param)
{
V4l2Capture* videoCapture = NULL;
V4l2Device* videoDevice = NULL;
int caps = V4L2_CAP_VIDEO_CAPTURE;
switch (param.m_iotype)
{
case IOTYPE_MMAP:
videoDevice = new V4l2MmapDevice(param, V4L2_BUF_TYPE_VIDEO_CAPTURE);
caps |= V4L2_CAP_STREAMING;
break;
case IOTYPE_READWRITE:
videoDevice = new V4l2ReadWriteDevice(param, V4L2_BUF_TYPE_VIDEO_CAPTURE);
caps |= V4L2_CAP_READWRITE;
break;
}
if (videoDevice && !videoDevice->init(caps))
{
delete videoDevice;
videoDevice=NULL;
}
if (videoDevice)
{
videoCapture = new V4l2Capture(videoDevice);
}
return videoCapture;
}
// -----------------------------------------
// constructor
// -----------------------------------------
V4l2Capture::V4l2Capture(V4l2Device* device) : V4l2Access(device)
{
}
// -----------------------------------------
// destructor
// -----------------------------------------
V4l2Capture::~V4l2Capture()
{
}
// -----------------------------------------
// check readability
// -----------------------------------------
bool V4l2Capture::isReadable(timeval* tv)
{
int fd = m_device->getFd();
fd_set fdset;
FD_ZERO(&fdset);
FD_SET(fd, &fdset);
return (select(fd+1, &fdset, NULL, NULL, tv) == 1);
}
// -----------------------------------------
// read from V4l2Device
// -----------------------------------------
size_t V4l2Capture::read(char* buffer, size_t bufferSize)
{
return m_device->readInternal(buffer, bufferSize);
}

@ -1,253 +0,0 @@
/* ---------------------------------------------------------------------------
** This software is in the public domain, furnished "as is", without technical
** support, and with no warranty, express or implied, as to its usefulness for
** any purpose.
**
** V4l2Device.cpp
**
** -------------------------------------------------------------------------*/
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
// libv4l2
#include <linux/videodev2.h>
#include "logger.h"
#include "V4l2Device.h"
std::string V4l2Device::fourcc(unsigned int format) {
char formatArray[] = { (char)(format&0xff), (char)((format>>8)&0xff), (char)((format>>16)&0xff), (char)((format>>24)&0xff), 0 };
return std::string(formatArray, strlen(formatArray));
}
unsigned int V4l2Device::fourcc(const char* format) {
char fourcc[4];
memset(&fourcc, 0, sizeof(fourcc));
if (format != NULL)
{
strncpy(fourcc, format, 4);
}
return v4l2_fourcc(fourcc[0], fourcc[1], fourcc[2], fourcc[3]);
}
// -----------------------------------------
// V4L2Device
// -----------------------------------------
V4l2Device::V4l2Device(const V4L2DeviceParameters& params, v4l2_buf_type deviceType) : m_params(params), m_fd(-1), m_deviceType(deviceType), m_bufferSize(0), m_format(0)
{
}
V4l2Device::~V4l2Device()
{
this->close();
}
void V4l2Device::close()
{
if (m_fd != -1)
::close(m_fd);
m_fd = -1;
}
// query current format
void V4l2Device::queryFormat()
{
struct v4l2_format fmt;
memset(&fmt,0,sizeof(fmt));
fmt.type = m_deviceType;
if (0 == ioctl(m_fd,VIDIOC_G_FMT,&fmt))
{
m_format = fmt.fmt.pix.pixelformat;
m_width = fmt.fmt.pix.width;
m_height = fmt.fmt.pix.height;
m_bufferSize = fmt.fmt.pix.sizeimage;
LOG(DEBUG) << m_params.m_devName << ":" << fourcc(m_format) << " size:" << m_width << "x" << m_height << " bufferSize:" << m_bufferSize;
}
}
// intialize the V4L2 connection
bool V4l2Device::init(unsigned int mandatoryCapabilities)
{
struct stat sb;
if ( (stat(m_params.m_devName.c_str(), &sb)==0) && ((sb.st_mode & S_IFMT) == S_IFCHR) )
{
if (initdevice(m_params.m_devName.c_str(), mandatoryCapabilities) == -1)
{
LOG(ERROR) << "Cannot init device:" << m_params.m_devName;
}
}
else
{
// open a normal file
m_fd = open(m_params.m_devName.c_str(), O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU);
}
return (m_fd!=-1);
}
// intialize the V4L2 device
int V4l2Device::initdevice(const char *dev_name, unsigned int mandatoryCapabilities)
{
m_fd = open(dev_name, m_params.m_openFlags);
if (m_fd < 0)
{
LOG(ERROR) << "Cannot open device:" << m_params.m_devName << " " << strerror(errno);
this->close();
return -1;
}
if (checkCapabilities(m_fd,mandatoryCapabilities) !=0)
{
this->close();
return -1;
}
if (configureFormat(m_fd) !=0)
{
this->close();
return -1;
}
if (configureParam(m_fd, m_params.m_fps) !=0)
{
this->close();
return -1;
}
return m_fd;
}
// check needed V4L2 capabilities
int V4l2Device::checkCapabilities(int fd, unsigned int mandatoryCapabilities)
{
struct v4l2_capability cap;
memset(&(cap), 0, sizeof(cap));
if (-1 == ioctl(fd, VIDIOC_QUERYCAP, &cap))
{
LOG(ERROR) << "Cannot get capabilities for device:" << m_params.m_devName << " " << strerror(errno);
return -1;
}
LOG(INFO) << "driver:" << cap.driver << " capabilities:" << std::hex << cap.capabilities << " mandatory:" << mandatoryCapabilities << std::dec;
if ((cap.capabilities & V4L2_CAP_VIDEO_OUTPUT)) LOG(DEBUG) << m_params.m_devName << " support output";
if ((cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) LOG(DEBUG) << m_params.m_devName << " support capture";
if ((cap.capabilities & V4L2_CAP_READWRITE)) LOG(DEBUG) << m_params.m_devName << " support read/write";
if ((cap.capabilities & V4L2_CAP_STREAMING)) LOG(DEBUG) << m_params.m_devName << " support streaming";
if ((cap.capabilities & V4L2_CAP_TIMEPERFRAME)) LOG(DEBUG) << m_params.m_devName << " support timeperframe";
if ( (cap.capabilities & mandatoryCapabilities) != mandatoryCapabilities )
{
LOG(ERROR) << "Mandatory capability not available for device:" << m_params.m_devName;
return -1;
}
return 0;
}
// configure capture format
int V4l2Device::configureFormat(int fd)
{
// get current configuration
this->queryFormat();
unsigned int width = m_width;
unsigned int height = m_height;
if (m_params.m_width != 0) {
width= m_params.m_width;
}
if (m_params.m_height != 0) {
height= m_params.m_height;
}
if ( (m_params.m_formatList.size()==0) && (m_format != 0) ) {
m_params.m_formatList.push_back(m_format);
}
// try to set format, widht, height
std::list<unsigned int>::iterator it;
for (it = m_params.m_formatList.begin(); it != m_params.m_formatList.end(); ++it) {
unsigned int format = *it;
if (this->configureFormat(fd, format, width, height)==0) {
// format has been set
// get the format again because calling SET-FMT return a bad buffersize using v4l2loopback
this->queryFormat();
return 0;
}
}
return -1;
}
// configure capture format
int V4l2Device::configureFormat(int fd, unsigned int format, unsigned int width, unsigned int height)
{
struct v4l2_format fmt;
memset(&(fmt), 0, sizeof(fmt));
fmt.type = m_deviceType;
if (ioctl(m_fd,VIDIOC_G_FMT,&fmt) == -1)
{
LOG(ERROR) << m_params.m_devName << ": Cannot get format " << strerror(errno);
return -1;
}
if (width != 0) {
fmt.fmt.pix.width = width;
}
if (height != 0) {
fmt.fmt.pix.height = height;
}
if (format != 0) {
fmt.fmt.pix.pixelformat = format;
}
if (ioctl(fd, VIDIOC_S_FMT, &fmt) == -1)
{
LOG(ERROR) << m_params.m_devName << ": Cannot set format:" << fourcc(format) << " " << strerror(errno);
return -1;
}
if (fmt.fmt.pix.pixelformat != format)
{
LOG(ERROR) << m_params.m_devName << ": Cannot set pixelformat to:" << fourcc(format) << " format is:" << fourcc(fmt.fmt.pix.pixelformat);
return -1;
}
if ((fmt.fmt.pix.width != width) || (fmt.fmt.pix.height != height))
{
LOG(WARN) << m_params.m_devName << ": Cannot set size to:" << width << "x" << height << " size is:" << fmt.fmt.pix.width << "x" << fmt.fmt.pix.height;
}
m_format = fmt.fmt.pix.pixelformat;
m_width = fmt.fmt.pix.width;
m_height = fmt.fmt.pix.height;
m_bufferSize = fmt.fmt.pix.sizeimage;
LOG(INFO) << m_params.m_devName << ":" << fourcc(m_format) << " size:" << m_width << "x" << m_height << " bufferSize:" << m_bufferSize;
return 0;
}
// configure capture FPS
int V4l2Device::configureParam(int fd, int fps)
{
if (fps!=0)
{
struct v4l2_streamparm param;
memset(&(param), 0, sizeof(param));
param.type = m_deviceType;
param.parm.capture.timeperframe.numerator = 1;
param.parm.capture.timeperframe.denominator = fps;
if (ioctl(fd, VIDIOC_S_PARM, &param) == -1)
{
LOG(WARN) << "Cannot set param for device:" << m_params.m_devName << " " << strerror(errno);
}
LOG(INFO) << "fps:" << param.parm.capture.timeperframe.numerator << "/" << param.parm.capture.timeperframe.denominator;
LOG(INFO) << "nbBuffer:" << param.parm.capture.readbuffers;
}
return 0;
}

@ -1,311 +0,0 @@
/* ---------------------------------------------------------------------------
** This software is in the public domain, furnished "as is", without technical
** support, and with no warranty, express or implied, as to its usefulness for
** any purpose.
**
** V4l2MmapDevice.cpp
**
** V4L2 source using mmap API
**
** -------------------------------------------------------------------------*/
#include <string.h>
#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
// libv4l2
#include <linux/videodev2.h>
// project
#include "logger.h"
#include "V4l2MmapDevice.h"
V4l2MmapDevice::V4l2MmapDevice(const V4L2DeviceParameters & params, v4l2_buf_type deviceType) : V4l2Device(params, deviceType), n_buffers(0)
{
memset(&m_buffer, 0, sizeof(m_buffer));
}
bool V4l2MmapDevice::init(unsigned int mandatoryCapabilities)
{
bool ret = V4l2Device::init(mandatoryCapabilities);
if (ret)
{
ret = this->start();
}
return ret;
}
V4l2MmapDevice::~V4l2MmapDevice()
{
this->stop();
}
bool V4l2MmapDevice::start()
{
LOG(INFO) << "Device " << m_params.m_devName;
bool success = true;
struct v4l2_requestbuffers req;
memset (&req, 0, sizeof(req));
req.count = V4L2MMAP_NBBUFFER;
req.type = m_deviceType;
req.memory = V4L2_MEMORY_MMAP;
if (-1 == ioctl(m_fd, VIDIOC_REQBUFS, &req))
{
if (EINVAL == errno)
{
LOG(ERROR) << "Device " << m_params.m_devName << " does not support memory mapping";
success = false;
}
else
{
perror("VIDIOC_REQBUFS");
success = false;
}
}
else
{
LOG(INFO) << "Device " << m_params.m_devName << " nb buffer:" << req.count;
// allocate buffers
memset(&m_buffer,0, sizeof(m_buffer));
for (n_buffers = 0; n_buffers < req.count; ++n_buffers)
{
struct v4l2_buffer buf;
memset (&buf, 0, sizeof(buf));
buf.type = m_deviceType;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = n_buffers;
if (-1 == ioctl(m_fd, VIDIOC_QUERYBUF, &buf))
{
perror("VIDIOC_QUERYBUF");
success = false;
}
else
{
LOG(INFO) << "Device " << m_params.m_devName << " buffer idx:" << n_buffers << " size:" << buf.length << " offset:" << buf.m.offset;
m_buffer[n_buffers].length = buf.length;
if (!m_buffer[n_buffers].length) {
m_buffer[n_buffers].length = buf.bytesused;
}
m_buffer[n_buffers].start = mmap ( NULL /* start anywhere */,
m_buffer[n_buffers].length,
PROT_READ | PROT_WRITE /* required */,
MAP_SHARED /* recommended */,
m_fd,
buf.m.offset);
if (MAP_FAILED == m_buffer[n_buffers].start)
{
perror("mmap");
success = false;
}
}
}
// queue buffers
for (unsigned int i = 0; i < n_buffers; ++i)
{
struct v4l2_buffer buf;
memset (&buf, 0, sizeof(buf));
buf.type = m_deviceType;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = i;
if (-1 == ioctl(m_fd, VIDIOC_QBUF, &buf))
{
perror("VIDIOC_QBUF");
success = false;
}
}
// start stream
int type = m_deviceType;
if (-1 == ioctl(m_fd, VIDIOC_STREAMON, &type))
{
perror("VIDIOC_STREAMON");
success = false;
}
}
return success;
}
bool V4l2MmapDevice::stop()
{
LOG(INFO) << "Device " << m_params.m_devName;
bool success = true;
int type = m_deviceType;
if (-1 == ioctl(m_fd, VIDIOC_STREAMOFF, &type))
{
perror("VIDIOC_STREAMOFF");
success = false;
}
for (unsigned int i = 0; i < n_buffers; ++i)
{
if (-1 == munmap (m_buffer[i].start, m_buffer[i].length))
{
perror("munmap");
success = false;
}
}
// free buffers
struct v4l2_requestbuffers req;
memset (&req, 0, sizeof(req));
req.count = 0;
req.type = m_deviceType;
req.memory = V4L2_MEMORY_MMAP;
if (-1 == ioctl(m_fd, VIDIOC_REQBUFS, &req))
{
perror("VIDIOC_REQBUFS");
success = false;
}
n_buffers = 0;
return success;
}
size_t V4l2MmapDevice::readInternal(char* buffer, size_t bufferSize)
{
size_t size = 0;
if (n_buffers > 0)
{
struct v4l2_buffer buf;
memset (&buf, 0, sizeof(buf));
buf.type = m_deviceType;
buf.memory = V4L2_MEMORY_MMAP;
if (-1 == ioctl(m_fd, VIDIOC_DQBUF, &buf))
{
if (errno == EAGAIN) {
size = 0;
} else {
perror("VIDIOC_DQBUF");
size = -1;
}
}
else if (buf.index < n_buffers)
{
size = buf.bytesused;
if (size > bufferSize)
{
size = bufferSize;
LOG(WARN) << "Device " << m_params.m_devName << " buffer truncated available:" << bufferSize << " needed:" << buf.bytesused;
}
memcpy(buffer, m_buffer[buf.index].start, size);
if (-1 == ioctl(m_fd, VIDIOC_QBUF, &buf))
{
perror("VIDIOC_QBUF");
size = -1;
}
}
}
return size;
}
size_t V4l2MmapDevice::writeInternal(char* buffer, size_t bufferSize)
{
size_t size = 0;
if (n_buffers > 0)
{
struct v4l2_buffer buf;
memset (&buf, 0, sizeof(buf));
buf.type = m_deviceType;
buf.memory = V4L2_MEMORY_MMAP;
if (-1 == ioctl(m_fd, VIDIOC_DQBUF, &buf))
{
perror("VIDIOC_DQBUF");
size = -1;
}
else if (buf.index < n_buffers)
{
size = bufferSize;
if (size > buf.length)
{
LOG(WARN) << "Device " << m_params.m_devName << " buffer truncated available:" << buf.length << " needed:" << size;
size = buf.length;
}
memcpy(m_buffer[buf.index].start, buffer, size);
buf.bytesused = size;
if (-1 == ioctl(m_fd, VIDIOC_QBUF, &buf))
{
perror("VIDIOC_QBUF");
size = -1;
}
}
}
return size;
}
bool V4l2MmapDevice::startPartialWrite()
{
if (n_buffers <= 0)
return false;
if (m_partialWriteInProgress)
return false;
memset(&m_partialWriteBuf, 0, sizeof(m_partialWriteBuf));
m_partialWriteBuf.type = m_deviceType;
m_partialWriteBuf.memory = V4L2_MEMORY_MMAP;
if (-1 == ioctl(m_fd, VIDIOC_DQBUF, &m_partialWriteBuf))
{
perror("VIDIOC_DQBUF");
return false;
}
m_partialWriteBuf.bytesused = 0;
m_partialWriteInProgress = true;
return true;
}
size_t V4l2MmapDevice::writePartialInternal(char* buffer, size_t bufferSize)
{
size_t new_size = 0;
size_t size = 0;
if ((n_buffers > 0) && m_partialWriteInProgress)
{
if (m_partialWriteBuf.index < n_buffers)
{
new_size = m_partialWriteBuf.bytesused + bufferSize;
if (new_size > m_partialWriteBuf.length)
{
LOG(WARN) << "Device " << m_params.m_devName << " buffer truncated available:" << m_partialWriteBuf.length << " needed:" << new_size;
new_size = m_partialWriteBuf.length;
}
size = new_size - m_partialWriteBuf.bytesused;
memcpy(&((char *)m_buffer[m_partialWriteBuf.index].start)[m_partialWriteBuf.bytesused], buffer, size);
m_partialWriteBuf.bytesused += size;
}
}
return size;
}
bool V4l2MmapDevice::endPartialWrite()
{
if (!m_partialWriteInProgress)
return false;
if (n_buffers <= 0)
{
m_partialWriteInProgress = false; // abort partial write
return true;
}
if (-1 == ioctl(m_fd, VIDIOC_QBUF, &m_partialWriteBuf))
{
perror("VIDIOC_QBUF");
m_partialWriteInProgress = false; // abort partial write
return true;
}
m_partialWriteInProgress = false;
return true;
}

@ -1,106 +0,0 @@
/* ---------------------------------------------------------------------------
** This software is in the public domain, furnished "as is", without technical
** support, and with no warranty, express or implied, as to its usefulness for
** any purpose.
**
** V4l2Output.cpp
**
** V4L2 wrapper
**
** -------------------------------------------------------------------------*/
#include <string.h>
// libv4l2
#include <linux/videodev2.h>
// project
#include "logger.h"
#include "V4l2Output.h"
#include "V4l2MmapDevice.h"
#include "V4l2ReadWriteDevice.h"
// -----------------------------------------
// create video output interface
// -----------------------------------------
V4l2Output* V4l2Output::create(const V4L2DeviceParameters & param)
{
V4l2Output* videoOutput = NULL;
V4l2Device* videoDevice = NULL;
int caps = V4L2_CAP_VIDEO_OUTPUT;
switch (param.m_iotype)
{
case IOTYPE_MMAP:
videoDevice = new V4l2MmapDevice(param, V4L2_BUF_TYPE_VIDEO_OUTPUT);
caps |= V4L2_CAP_STREAMING;
break;
case IOTYPE_READWRITE:
videoDevice = new V4l2ReadWriteDevice(param, V4L2_BUF_TYPE_VIDEO_OUTPUT);
caps |= V4L2_CAP_READWRITE;
break;
}
if (videoDevice && !videoDevice->init(caps))
{
delete videoDevice;
videoDevice=NULL;
}
if (videoDevice)
{
videoOutput = new V4l2Output(videoDevice);
}
return videoOutput;
}
// -----------------------------------------
// constructor
// -----------------------------------------
V4l2Output::V4l2Output(V4l2Device* device) : V4l2Access(device)
{
}
// -----------------------------------------
// destructor
// -----------------------------------------
V4l2Output::~V4l2Output()
{
}
// -----------------------------------------
// check writability
// -----------------------------------------
bool V4l2Output::isWritable(timeval* tv)
{
int fd = m_device->getFd();
fd_set fdset;
FD_ZERO(&fdset);
FD_SET(fd, &fdset);
return (select(fd+1, NULL, &fdset, NULL, tv) == 1);
}
// -----------------------------------------
// write to V4l2Device
// -----------------------------------------
size_t V4l2Output::write(char* buffer, size_t bufferSize)
{
return m_device->writeInternal(buffer, bufferSize);
}
bool V4l2Output::startPartialWrite()
{
return m_device->startPartialWrite();
}
size_t V4l2Output::writePartial(char* buffer, size_t bufferSize)
{
return m_device->writePartialInternal(buffer, bufferSize);
}
bool V4l2Output::endPartialWrite()
{
return m_device->endPartialWrite();
}

@ -1,29 +0,0 @@
/* ---------------------------------------------------------------------------
** This software is in the public domain, furnished "as is", without technical
** support, and with no warranty, express or implied, as to its usefulness for
** any purpose.
**
** V4l2ReadWriteDevice.cpp
**
** V4L2 source using read/write API
**
** -------------------------------------------------------------------------*/
#include <unistd.h>
#include "V4l2ReadWriteDevice.h"
V4l2ReadWriteDevice::V4l2ReadWriteDevice(const V4L2DeviceParameters& params, v4l2_buf_type deviceType) : V4l2Device(params, deviceType) {
}
size_t V4l2ReadWriteDevice::writeInternal(char* buffer, size_t bufferSize) {
return ::write(m_fd, buffer, bufferSize);
}
size_t V4l2ReadWriteDevice::readInternal(char* buffer, size_t bufferSize) {
return ::read(m_fd, buffer, bufferSize);
}

@ -1,14 +0,0 @@
/* ---------------------------------------------------------------------------
** This software is in the public domain, furnished "as is", without technical
** support, and with no warranty, express or implied, as to its usefulness for
** any purpose.
**
** logger.cpp
**
** -------------------------------------------------------------------------*/
#include "logger.h"
#ifndef HAVE_LOG4CPP
int LogLevel=NOTICE;
#endif

Binary file not shown.

Binary file not shown.
Loading…
Cancel
Save