This repository has been archived on 2024-05-02. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
ar_basalt/thirdparty/Pangolin/include/pangolin/video/video.h
2022-04-05 11:42:28 +03:00

262 lines
11 KiB
C++

/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* 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 OR COPYRIGHT
* HOLDERS 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.
*/
#pragma once
// Pangolin video supports various cameras and file formats through
// different 3rd party libraries.
//
// Video URI's take the following form:
// scheme:[param1=value1,param2=value2,...]//device
//
// scheme = file | files | pango | shmem | dc1394 | uvc | v4l | openni2 |
// openni | depthsense | pleora | teli | mjpeg | test |
// thread | convert | debayer | split | join | shift | mirror | unpack
//
// file/files - read one or more streams from image file(s) / video
// e.g. "files://~/data/dataset/img_*.jpg"
// e.g. "files://~/data/dataset/img_[left,right]_*.pgm"
// e.g. "files:///home/user/sequence/foo%03d.jpeg"
//
// e.g. "file:[fmt=GRAY8,size=640x480]///home/user/raw_image.bin"
// e.g. "file:[realtime=1]///home/user/video/movie.pango"
// e.g. "file:[stream=1]///home/user/video/movie.avi"
//
// dc1394 - capture video through a firewire camera
// e.g. "dc1394:[fmt=RGB24,size=640x480,fps=30,iso=400,dma=10]//0"
// e.g. "dc1394:[fmt=FORMAT7_1,size=640x480,pos=2+2,iso=400,dma=10]//0"
// e.g. "dc1394:[fmt=FORMAT7_3,deinterlace=1]//0"
//
// v4l - capture video from a Video4Linux (USB) camera (normally YUVY422 format)
// method=mmap|read|userptr
// e.g. "v4l:///dev/video0"
// e.g. "v4l[method=mmap]:///dev/video0"
//
// openni2 - capture video / depth from OpenNI2 SDK (Kinect / Xtrion etc)
// imgN=grey|rgb|ir|ir8|ir24|depth|reg_depth
// e.g. "openni2://'
// e.g. "openni2:[img1=rgb,img2=depth,coloursync=true]//"
// e.g. "openni2:[img1=depth,close=closerange,holefilter=true]//"
// e.g. "openni2:[size=320x240,fps=60,img1=ir]//"
//
// openni - capture video / depth from OpenNI 1.0 SDK (Kinect / Xtrion etc)
// Sensor modes containing '8' will truncate to 8-bits.
// Sensor modes containing '+' explicitly enable IR illuminator
// imgN=rgb|ir|ir8|ir+|ir8+|depth|reg_depth
// autoexposure=true|false
// e.g. "openni://'
// e.g. "openni:[img1=rgb,img2=depth]//"
// e.g. "openni:[size=320x240,fps=60,img1=ir]//"
//
// depthsense - capture video / depth from DepthSense SDK.
// DepthSenseViewer can be used to alter capture settings.
// imgN=depth|rgb
// sizeN=QVGA|320x240|...
// fpsN=25|30|60|...
// e.g. "depthsense://"
// e.g. "depthsense:[img1=depth,img2=rgb]//"
//
// pleora - USB 3 vision cameras accepts any option in the same format reported by eBUSPlayer
// e.g. for lightwise cameras: "pleora:[size=512x256,pos=712x512,sn=00000274,ExposureTime=10000,PixelFormat=Mono12p,AcquisitionMode=SingleFrame,TriggerSource=Line0,TriggerMode=On]//"
// e.g. for toshiba cameras: "pleora:[size=512x256,pos=712x512,sn=0300056,PixelSize=Bpp12,ExposureTime=10000,ImageFormatSelector=Format1,BinningHorizontal=2,BinningVertical=2]//"
// e.g. toshiba alternated "pleora:[UserSetSelector=UserSet1,ExposureTime=10000,PixelSize=Bpp12,Width=1400,OffsetX=0,Height=1800,OffsetY=124,LineSelector=Line1,LineSource=ExposureActive,LineSelector=Line2,LineSource=Off,LineModeAll=6,LineInverterAll=6,UserSetSave=Execute,
// UserSetSelector=UserSet2,PixelSize=Bpp12,Width=1400,OffsetX=1048,Height=1800,OffsetY=124,ExposureTime=10000,LineSelector=Line1,LineSource=Off,LineSelector=Line2,LineSource=ExposureActive,LineModeAll=6,LineInverterAll=6,UserSetSave=Execute,
// SequentialShutterIndex=1,SequentialShutterEntry=1,SequentialShutterIndex=2,SequentialShutterEntry=2,SequentialShutterTerminateAt=2,SequentialShutterEnable=On,,AcquisitionFrameRateControl=Manual,AcquisitionFrameRate=70]//"
//
// thread - thread that continuously pulls from the child streams so that data in, unpacking, debayering etc can be decoupled from the main application thread
// e.g. thread://pleora://
// e.g. thread://unpack://pleora:[PixelFormat=Mono12p]//
//
// convert - use FFMPEG to convert between video pixel formats
// e.g. "convert:[fmt=RGB24]//v4l:///dev/video0"
// e.g. "convert:[fmt=GRAY8]//v4l:///dev/video0"
//
// mjpeg - capture from (possibly networked) motion jpeg stream using FFMPEG
// e.g. "mjpeg://http://127.0.0.1/?action=stream"
//
// debayer - debayer an input video stream
// e.g. "debayer:[tile="BGGR",method="downsample"]//v4l:///dev/video0
//
// split - split an input video into a one or more streams based on Region of Interest / memory specification
// roiN=X+Y+WxH
// memN=Offset:WxH:PitchBytes:Format
// e.g. "split:[roi1=0+0+640x480,roi2=640+0+640x480]//files:///home/user/sequence/foo%03d.jpeg"
// e.g. "split:[mem1=307200:640x480:1280:GRAY8,roi2=640+0+640x480]//files:///home/user/sequence/foo%03d.jpeg"
// e.g. "split:[stream1=2,stream2=1]//pango://video.pango"
//
// truncate - select a subregion of a video based on start and end (last index+1) index
// e.g. Generate 30 random frames: "truncate:[end=30]//test://"
// e.g. "truncate:[begin=100,end=120]"
//
// join - join streams
// e.g. "join:[sync_tolerance_us=100, sync_continuously=true]//{pleora:[sn=00000274]//}{pleora:[sn=00000275]//}"
//
// test - output test video sequence
// e.g. "test://"
// e.g. "test:[size=640x480,fmt=RGB24]//"
#include <pangolin/utils/uri.h>
#include <pangolin/video/video_exception.h>
#include <pangolin/video/video_interface.h>
#include <pangolin/video/video_output_interface.h>
namespace pangolin
{
//! Open Video Interface from string specification (as described in this files header)
PANGOLIN_EXPORT
std::unique_ptr<VideoInterface> OpenVideo(const std::string& uri);
//! Open Video Interface from Uri specification
PANGOLIN_EXPORT
std::unique_ptr<VideoInterface> OpenVideo(const Uri& uri);
//! Open VideoOutput Interface from string specification (as described in this files header)
PANGOLIN_EXPORT
std::unique_ptr<VideoOutputInterface> OpenVideoOutput(const std::string& str_uri);
//! Open VideoOutput Interface from Uri specification
PANGOLIN_EXPORT
std::unique_ptr<VideoOutputInterface> OpenVideoOutput(const Uri& uri);
//! Create vector of matching interfaces either through direct cast or filter interface.
template<typename T>
std::vector<T*> FindMatchingVideoInterfaces( VideoInterface& video )
{
std::vector<T*> matches;
T* vid = dynamic_cast<T*>(&video);
if(vid) {
matches.push_back(vid);
}
VideoFilterInterface* vidf = dynamic_cast<VideoFilterInterface*>(&video);
if(vidf) {
std::vector<T*> fmatches = vidf->FindMatchingStreams<T>();
matches.insert(matches.begin(), fmatches.begin(), fmatches.end());
}
return matches;
}
template<typename T>
T* FindFirstMatchingVideoInterface( VideoInterface& video )
{
T* vid = dynamic_cast<T*>(&video);
if(vid) {
return vid;
}
VideoFilterInterface* vidf = dynamic_cast<VideoFilterInterface*>(&video);
if(vidf) {
std::vector<T*> fmatches = vidf->FindMatchingStreams<T>();
if(fmatches.size()) {
return fmatches[0];
}
}
return 0;
}
inline
picojson::value GetVideoFrameProperties(VideoInterface* video)
{
VideoPropertiesInterface* pi = dynamic_cast<VideoPropertiesInterface*>(video);
VideoFilterInterface* fi = dynamic_cast<VideoFilterInterface*>(video);
if(pi) {
return pi->FrameProperties();
}else if(fi){
if(fi->InputStreams().size() == 1) {
return GetVideoFrameProperties(fi->InputStreams()[0]);
}else if(fi->InputStreams().size() > 0){
picojson::value streams;
for(size_t i=0; i< fi->InputStreams().size(); ++i) {
const picojson::value dev_props = GetVideoFrameProperties(fi->InputStreams()[i]);
if(dev_props.contains("streams")) {
const picojson::value& dev_streams = dev_props["streams"];
for(size_t j=0; j < dev_streams.size(); ++j) {
streams.push_back(dev_streams[j]);
}
}else{
streams.push_back(dev_props);
}
}
if(streams.size() > 1) {
picojson::value json = streams[0];
json["streams"] = streams;
return json;
}else{
return streams[0];
}
}
}
return picojson::value();
}
inline
picojson::value GetVideoDeviceProperties(VideoInterface* video)
{
VideoPropertiesInterface* pi = dynamic_cast<VideoPropertiesInterface*>(video);
VideoFilterInterface* fi = dynamic_cast<VideoFilterInterface*>(video);
if(pi) {
return pi->DeviceProperties();
}else if(fi){
if(fi->InputStreams().size() == 1) {
return GetVideoDeviceProperties(fi->InputStreams()[0]);
}else if(fi->InputStreams().size() > 0){
picojson::value streams;
for(size_t i=0; i< fi->InputStreams().size(); ++i) {
const picojson::value dev_props = GetVideoDeviceProperties(fi->InputStreams()[i]);
if(dev_props.contains("streams")) {
const picojson::value& dev_streams = dev_props["streams"];
for(size_t j=0; j < dev_streams.size(); ++j) {
streams.push_back(dev_streams[j]);
}
}else{
streams.push_back(dev_props);
}
}
if(streams.size() > 1) {
picojson::value json = streams[0];
json["streams"] = streams;
return json;
}else{
return streams[0];
}
}
}
return picojson::value();
}
}