-
Notifications
You must be signed in to change notification settings - Fork 290
/
videoOutput.h
334 lines (294 loc) · 14.3 KB
/
videoOutput.h
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
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
/*
* Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved.
*
* 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.
*/
#ifndef __VIDEO_OUTPUT_H_
#define __VIDEO_OUTPUT_H_
#include "videoOptions.h"
#include "imageFormat.h"
#include "commandLine.h"
#include <vector>
/**
* Standard command-line options able to be passed to videoOutput::Create()
* @ingroup video
*/
#define VIDEO_OUTPUT_USAGE_STRING "videoOutput arguments: \n" \
" output resource URI of the output stream, for example:\n" \
" * file://my_image.jpg (image file)\n" \
" * file://my_video.mp4 (video file)\n" \
" * file://my_directory/ (directory of images)\n" \
" * rtp://<remote-ip>:1234 (RTP stream)\n" \
" * rtsp://@:8554/my_stream (RTSP stream)\n" \
" * webrtc://@:1234/my_stream (WebRTC stream)\n" \
" * display://0 (OpenGL window)\n" \
" --output-codec=CODEC desired codec for compressed output streams:\n" \
" * h264 (default), h265\n" \
" * vp8, vp9\n" \
" * mpeg2, mpeg4\n" \
" * mjpeg\n" \
" --output-encoder=TYPE the encoder engine to use, one of these:\n" \
" * cpu\n" \
" * omx (aarch64/JetPack4 only)\n" \
" * v4l2 (aarch64/JetPack5 only)\n" \
" --output-save=FILE path to a video file for saving the compressed stream\n" \
" to disk, in addition to the primary output above\n" \
" --bitrate=BITRATE desired target VBR bitrate for compressed streams,\n" \
" in bits per second. The default is 4000000 (4 Mbps)\n" \
" --stun-server=URL WebRTC connection STUN server (set to 'disabled' for LAN)\n" \
" --headless don't create a default OpenGL GUI window\n\n"
/**
* The videoOutput API is for rendering and transmitting frames to video input devices such as display windows,
* broadcasting RTP network streams to remote hosts over UDP/IP, and saving videos/images/directories to disk.
*
* videoOutput interfaces are implemented by glDisplay, gstEncoder, and imageWriter.
* The specific implementation is selected at runtime based on the type of resource URI.
* An instance can have multiple sub-streams, for example simultaneously outputting to
* a display and encoded video on disk or RTP stream.
*
* videoOutput supports the following protocols and resource URI's:
*
* - `display://0` for rendering to display using OpenGL, where `0` corresponds to the display number.
* By default, an OpenGL window will be created, unless the `--headless` command line option is used.
*
* - `rtp://<remote-host>:1234` to broadcast a compressed RTP stream to a remote host, where you should
* substitute `<remote-host>` with the remote host's IP address or hostname, and `1234` is the port.
*
* - `rtsp://@:8554/my_stream` to serve a compressed RTSP stream at the specified port and stream path.
* RTSP clients can connect to the stream at the specified path. Using this will create a RTSP server
* that can handle multiple videoOutput streams on the same port but with different paths
* (e.g. `rtsp://<hostname>:8554/my_stream_1`, `rtsp://<hostname>:8554/my_stream_2`, ect)
*
* - `webrtc://@:1234/my_stream` to serve a compressed WebRTC stream at the specified port and path
* that browsers can connect to and view. Users will be able to navigate their browser to
* `http://<hostname>:1234/my_stream` and view a rudimentary video player that plays the stream.
* More advanced web front-ends can be created by using standard client-side Javascript WebRTC APIs.
*
* - `file:///home/user/my_video.mp4` for saving videos, images, and directories of images to disk.
* You can leave off the `file://` protocol identifier and it will be deduced from the path.
* It can be a relative or absolute path. You can output a sequence of images using a path of
* the form `my_dir/image_%i.jpg` (where `%i` can include printf-style modifiers like `%03i`).
* The `%i` will be replaced with the image number in the sequence. If just a directory is
* specified, then by default it will create a sequence of the form `%i.jpg` in that directory.
* Supported video formats for saving include MKV, MP4, AVI, and FLV. Supported codecs for
* encoding include H.264, H.265, VP8, VP9, and MJPEG. Supported image formats for saving
* include JPG, PNG, TGA, and BMP.
*
* @see URI for info about resource URI formats.
* @see videoOptions for additional options and command-line arguments.
* @ingroup video
*/
class videoOutput
{
public:
/**
* Create videoOutput interface from a videoOptions struct that's already been filled out.
* It's expected that the supplied videoOptions already contain a valid resource URI.
*/
static videoOutput* Create( const videoOptions& options );
/**
* Create videoOutput interface by parsing command line arguments, including the resource URI.
* @param positionArg indicates the positional argument number in the command line of
* the resource URI (or `-1` if a positional argument isn't used).
* @see videoOptions for valid command-line arguments to be parsed.
* @see the documentation above and the URI struct for more info about resource URI's.
*/
static videoOutput* Create( const int argc, char** argv, int positionArg=-1 );
/**
* Create videoOutput interface by parsing command line arguments, including the resource URI.
* @param positionArg indicates the positional argument number in the command line of
* the resource URI (or `-1` if a positional argument isn't used).
* @see videoOptions for valid command-line arguments to be parsed.
* @see the documentation above and the URI struct for more info about resource URI's.
*/
static videoOutput* Create( const commandLine& cmdLine, int positionArg=-1 );
/**
* Create videoOutput interface from a resource URI string and optional videoOptions.
* @see the documentation above and the URI struct for more info about resource URI's.
*/
static videoOutput* Create( const char* URI, const videoOptions& options=videoOptions() );
/**
* Create videoOutput interface from a resource URI string and parsing command line arguments.
* @param positionArg indicates the positional argument number in the command line of
* the resource URI (or `-1` if a positional argument isn't used).
* @see videoOptions for valid command-line arguments to be parsed.
* @see the documentation above and the URI struct for more info about resource URI's.
*/
static videoOutput* Create( const char* URI, const commandLine& cmdLine, int positionArg=-1, const videoOptions& options=videoOptions() );
/**
* Create videoOutput interface from a resource URI string and parsing command line arguments.
* @param positionArg indicates the positional argument number in the command line of
* the resource URI (or `-1` if a positional argument isn't used).
* @see videoOptions for valid command-line arguments to be parsed.
* @see the documentation above and the URI struct for more info about resource URI's.
*/
static videoOutput* Create( const char* URI, const int argc, char** argv, int positionArg=-1, const videoOptions& options=videoOptions() );
/**
* Create videoOutput interface that acts as a NULL output and does nothing with incoming frames.
* CreateNullOutput() can be used when there are no other outputs created and programs expect one to run.
*/
static videoOutput* CreateNullOutput();
/**
* Destroy interface and release all resources.
*/
virtual ~videoOutput();
/**
* Usage string for command line arguments to Create()
*/
static inline const char* Usage() { return VIDEO_OUTPUT_USAGE_STRING; }
/**
* Render and output the next frame to the stream.
* The image formats supported by this templated version of Render() include the following:
*
* - uchar3 (`IMAGE_RGB8`)
* - uchar4 (`IMAGE_RGBA8`)
* - float3 (`IMAGE_RGB32F`)
* - float4 (`IMAGE_RGBA32F`)
*
* The image format will automatically be deduced from these types. If other types are used
* with this overload, a static compile-time error will be asserted.
*
* @param image CUDA pointer containing the image to output.
* @param width width of the image, in pixels.
* @param height height of the image, in pixels.
* @param stream the optional CUDA stream to queue operations on.
*
* @returns `true` on success, `false` on error.
*/
template<typename T> bool Render( T* image, uint32_t width, uint32_t height, cudaStream_t stream=0 ) { return Render((void**)image, width, height, imageFormatFromType<T>(), stream); }
/**
* Render and output the next frame to the stream.
*
* The image formats supported by Render() are `IMAGE_RGB8` (uchar3), `IMAGE_RGBA8` (uchar4),
* `IMAGE_RGB32F` (float3), and `IMAGE_RGBA32F` (float4). @see imageFormat for more info.
*
* @param image CUDA pointer containing the image to output.
* @param width width of the image, in pixels.
* @param height height of the image, in pixels.
* @param format format of the image (@see imageFormat)
* @param stream the optional CUDA stream to queue operations on.
*
* @returns `true` on success, `false` on error.
*/
virtual bool Render( void* image, uint32_t width, uint32_t height, imageFormat format, cudaStream_t stream=0 );
/**
* Begin streaming the device.
* After Open() is called, frames from the device can begin to be rendered.
*
* Open() is not stricly necessary to call, if you call one of the Render()
* functions they will first check to make sure that the stream is opened,
* and if not they will open it automatically for you.
*
* @returns `true` on success, `false` if an error occurred opening the stream.
*/
virtual bool Open();
/**
* Stop streaming the device.
*
* @note Close() is automatically called by the videoOutput destructor when
* it gets deleted, so you do not explicitly need to call Close() before
* exiting the program if you delete your videoSource object.
*/
virtual void Close();
/**
* Check if the device is actively streaming or not.
*
* @returns `true` if the device is streaming (open), or `false` if it's closed
* or has reached EOS (End Of Stream).
*/
inline bool IsStreaming() const { return mStreaming; }
/**
* Return the width of the stream, in pixels.
*/
inline uint32_t GetWidth() const { return mOptions.width; }
/**
* Return the height of the stream, in pixels.
*/
inline uint32_t GetHeight() const { return mOptions.height; }
/**
* Return the framerate, in Hz or FPS.
*/
inline float GetFrameRate() const { return mOptions.frameRate; }
/**
* Return the number of frames output.
*/
inline uint64_t GetFrameCount() const { return mOptions.frameCount; }
/**
* Return the resource URI of the stream.
*/
inline const URI& GetResource() const { return mOptions.resource; }
/**
* Return the videoOptions of the stream.
*/
inline const videoOptions& GetOptions() const { return mOptions; }
/**
* Add an output sub-stream. When a frame is rendered
* to this stream, it will be rendered to each sub-stream.
*/
inline void AddOutput( videoOutput* output ) { if(output != NULL) mOutputs.push_back(output); }
/**
* Return the number of sub-streams.
*/
inline uint32_t GetNumOutputs() const { return mOutputs.size(); }
/**
* Return a sub-stream.
*/
inline videoOutput* GetOutput( uint32_t index ) const { return mOutputs[index]; }
/**
* Set a status string (i.e. status bar text on display window).
* Other types of interfaces may ignore the status text.
*/
virtual void SetStatus( const char* str );
/**
* Return the interface type of the stream.
* This could be one of the following values:
*
* - glDisplay::Type
* - gstEncoder::Type
* - imageWriter::Type
*/
virtual inline uint32_t GetType() const { return 0; }
/**
* Check if this stream is of a particular type.
* @see GetType() for possible values.
*/
inline bool IsType( uint32_t type ) const { return (type == GetType()); }
/**
* Check if a this stream is of a particular type.
* Can be used with glDisplay, gstEncoder, and imageWriter. For example:
*
* if( stream->IsType<glDisplay>() )
* glDisplay* display = (glDisplay*)stream; // safe to cast
*/
template<typename T> bool IsType() const { return IsType(T::Type); }
/**
* Convert this stream's class type to string.
*/
inline const char* TypeToStr() const { return TypeToStr(GetType()); }
/**
* Convert a class type to a string.
*/
static const char* TypeToStr( uint32_t type );
protected:
videoOutput( const videoOptions& options );
bool mStreaming;
videoOptions mOptions;
std::vector<videoOutput*> mOutputs;
};
#endif