/usr/include/libindi/stream/streammanager.h is in libindi-dev 1.7.1-0ubuntu1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 | /*
Copyright (C) 2015 by Jasem Mutlaq <mutlaqja@ikarustech.com>
Copyright (C) 2014 by geehalel <geehalel@gmail.com>
Stream Recorder
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#pragma once
#include "indidevapi.h"
#include "recorder/recordermanager.h"
#include "encoder/encodermanager.h"
#include <string>
#include <map>
#include <sys/time.h>
#include <stdint.h>
/**
* \class StreamManager
\brief Class to provide video streaming and recording functionality.
INDI::CCD can utilize this class to add streaming and recording functionality to the driver.
Transfer of the video stream is done via the same BLOB property \e CCD1 used for transfer of image data to the client. Therefore,
it is not possible to transmit image data and video stream at the same time. Two formats are accepted for video streaming:
+ Grayscale 8bit frame that represents intensity/lumienance.
+ Color 24bit RGB frame.
Use setPixelFormat() and setSize() before uploading the stream data. 16bit frames are only supported in some recorders. You can send
16bit frames, but they will be downscaled to 8bit when necessary for streaming and recording purposes. Base classes must implement
startStreaming() and stopStreaming() functions. When a frame is ready, use uploadStream() to send the data to active encoders and recorders.
It is highly recommended to implement the streaming functionality in a dedicated thread.
\section Encoders
Encoders are responsible for encoding the frame and transmitting it to the client. The CCD1 BLOB format is set to the desired format.
Default encoding format is RAW (format = ".stream").
Currently, two encoders are supported:
1. RAW Encoder: Frame is sent as is (lossless). If compression is enabled, the frame is compressed with zlib. Uncompressed format is ".stream"
and compressed format is ".stream.z"
2. MJPEG Encoder: Frame is encoded to a JPEG image before being transmitted. Format is ".stream_jpg"
\section Recorders
Recorders are responsible for recording the video stream to a file. The recording file directory and name can be set via the RECORD_FILE
property which is composed of RECORD_FILE_DIR and RECORD_FILE_NAME elements. You can specify a record directory name together with a file name.
You may use special character sequences to generate dynamic names:
* _D_ is replaced with the date ('YYYY-MM-DD')
* _H_ is replaced with the time ('hh-mm-ss')
* _T_ is replaced with a timestamp
* _F_ is replaced with the filter name currently in use (see Snoop Devices in Options tab)
Currently, two recorders are supported:
1. SER recorder: Saves video streams along with timestamps in <a href=http://www.grischa-hahn.homepage.t-online.de/astro/ser/">SER format</a>.
2. OGV recorder: Saves video streams in libtheora OGV files. INDI must be compiled with the optional OGG Theora support for this functionality to be
available. Frame rate is estimated from the average FPS.
\section Subframing
By default, the full image width and height are used for transmitting the data. Subframing is possible by updating the CCD_STREAM_FRAME
property. All values set in this property must be set in BINNED coordinates, unlike the CCD_FRAME which is set in UNBINNED coordinates.
\example Check CCD Simulator, V4L2 CCD, and ZWO ASI drivers for example implementations.
\author Jasem Mutlaq
\author Jean-Luc Geehalel
*/
namespace INDI
{
class CCD;
class StreamManager
{
public:
enum
{
RECORD_ON,
RECORD_TIME,
RECORD_FRAME,
RECORD_OFF
};
StreamManager(CCD *mainCCD);
virtual ~StreamManager();
virtual void ISGetProperties(const char *dev);
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n);
virtual bool ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n);
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n);
virtual bool initProperties();
virtual bool updateProperties();
virtual bool saveConfigItems(FILE *fp);
/**
* @brief newFrame CCD drivers call this function when a new frame is received. It is then streamed, or recorded, or both according to the settings in the streamer.
*/
void newFrame(const uint8_t *buffer, uint32_t nbytes);
/**
* @brief setStream Enables (starts) or disables (stops) streaming.
* @param enable True to enable, false to disable
* @return True if operation is successful, false otherwise.
*/
bool setStream(bool enable);
RecorderInterface *getRecorder() { return recorder; }
bool isDirectRecording() { return direct_record; }
bool isStreaming() { return m_isStreaming; }
bool isRecording() { return m_isRecording; }
bool isBusy() { return (isStreaming() || isRecording()); }
uint8_t getTargetFPS() { return static_cast<uint8_t>(StreamOptionsN[OPTION_TARGET_FPS].value); }
uint8_t *getDownscaleBuffer() { return downscaleBuffer; }
uint32_t getDownscaleBufferSize() { return downscaleBufferSize; }
const char *getDeviceName();
void setSize(uint16_t width, uint16_t height);
bool setPixelFormat(INDI_PIXEL_FORMAT pixelFormat, uint8_t pixelDepth=8);
void getStreamFrame(uint16_t *x, uint16_t *y, uint16_t *w, uint16_t *h);
bool close();
protected:
CCD *currentCCD = nullptr;
private:
/* Utility for record file */
int mkpath(std::string s, mode_t mode);
std::string expand(std::string fname, const std::map<std::string, std::string> &patterns);
bool startRecording();
bool stopRecording();
/**
* @brief uploadStream Upload frame to client using the selected encoder
* @param buffer pointer to frame image buffer
* @param nbytes size of frame in bytes
* @return True if frame is encoded and sent to client, false otherwise.
*/
bool uploadStream(const uint8_t *buffer, uint32_t nbytes);
/**
* @brief recordStream Calls the backend recorder to record a single frame.
* @param deltams time in milliseconds since last frame
*/
bool recordStream(const uint8_t *buffer, uint32_t nbytes, double deltams);
/* Stream switch */
ISwitch StreamS[2];
ISwitchVectorProperty StreamSP;
/* Record switch */
ISwitch RecordStreamS[4];
ISwitchVectorProperty RecordStreamSP;
/* Record File Info */
IText RecordFileT[2] {};
ITextVectorProperty RecordFileTP;
/* Streaming Options */
INumber StreamOptionsN[2];
INumberVectorProperty StreamOptionsNP;
enum { OPTION_TARGET_FPS, OPTION_RATE_DIVISOR};
/* Measured FPS */
INumber FpsN[2];
INumberVectorProperty FpsNP;
enum { FPS_INSTANT, FPS_AVERAGE };
/* Record Options */
INumber RecordOptionsN[2];
INumberVectorProperty RecordOptionsNP;
// Stream Frame
INumberVectorProperty StreamFrameNP;
INumber StreamFrameN[4];
/* BLOBs */
IBLOBVectorProperty *imageBP;
IBLOB *imageB;
// Encoder Selector. It's static now but should this implemented as plugin interface?
ISwitch EncoderS[2];
ISwitchVectorProperty EncoderSP;
enum { ENCODER_RAW, ENCODER_MJPEG };
// Recorder Selector. Static but should be implmeneted as a dynamic plugin interface
ISwitch RecorderS[2];
ISwitchVectorProperty RecorderSP;
enum { RECORDER_RAW, RECORDER_OGV };
bool m_isStreaming;
bool m_isRecording;
int streamframeCount;
int recordframeCount;
double recordDuration;
// Recorder
RecorderManager *recorderManager = nullptr;
RecorderInterface *recorder = nullptr;
bool direct_record;
std::string recordfiledir, recordfilename; /* in case we should move it */
// Encoders
EncoderManager *encoderManager = nullptr;
EncoderInterface *encoder = nullptr;
// Measure FPS
// timer_t fpstimer;
// struct itimerspec tframe1, tframe2;
// use bsd timers
struct itimerval tframe1, tframe2;
double mssum, framecountsec;
INDI_PIXEL_FORMAT m_PixelFormat;
uint8_t m_PixelDepth;
uint16_t rawWidth=0, rawHeight=0;
// Downscale buffer for streaming
uint8_t *downscaleBuffer = nullptr;
uint32_t downscaleBufferSize=0;
};
}
|