Cosmetics
[rawv.git] / rawv.h
blob546f1a7a551e3fb50527008fcc479cb93e39d8b7
1 #ifndef _RAWV_H_
2 #define _RAWV_H_
4 /*
5 * RAWV - low-latency lossless video streaming over 1Gbps Ethernet
6 * Copyright (C) 2010 Kirill Smelkov <kirr@navytux.spb.ru>
8 * You may use and redistribute this work under the Creative Commons
9 * Attribution-Share Alike (CC-BY-SA) 3.0. You are free to Share (to copy,
10 * distribute, display, and perform the work) and to Remix (to make derivative
11 * works), under the following conditions:
13 * 1. Attribution. You must attribute the work in the manner specified by the
14 * author or licensor (but not in any way that suggests that they endorse you
15 * or your use of the work).
16 * 2. Share Alike. If you alter, transform, or build upon this work, you may
17 * distribute the resulting work only under the same, similar or a compatible
18 * license.
21 * Abstract
22 * --------
24 * A scheme for transmitting progressive PAL/NTSC video over 1Gbps Ethernet
25 * LAN is presented. Lossless coding, low end-to-end latencies (under 100ms in
26 * non-specialized test setup) and packet loss tolerance make this scheme
27 * applicable for specialized tasks in medical, industrial and military
28 * environments. Development effort for both software and hardware
29 * implementations is shown to be low because of design simplicity.
32 * Coding
33 * ------
35 * - each frame is transmitted in series of independent fragments
36 * - each fragment carries header and payload
37 * - header:
39 * 1. special 4-byte magic identifying this coding method,
40 * 2. version of coding subvariant and fragment flags,
41 * 3. fragment's frame sequence number,
42 * 4. fragment sequence number and number of fragments in the whole frame,
43 * 5. width, height and pixel format of its frame,
44 * 6. fragment startline and number of lines in this fragment,
45 * 7. padding;
48 * < - - - - - - w i d t h - - - - - - >
49 * +-----------------------------------+ ^
50 * | | |
51 * | | |
52 * | | |
53 * | |
54 * frag_startline -->|-----------------------------------| h
55 * | ' | e
56 * | ' frag_nlines | i
57 * | ' | g
58 * |-----------------------------------| h
59 * | | t
60 * | |
61 * | | |
62 * | | |
63 * | | |
64 * +-----------------------------------+ v
68 * 0 1 2 3
69 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
70 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
71 * 0 | 0x52 ('R') | 0x41 ('A') | 0x57 ('W') | 0x56 ('V') |
72 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
73 * 32 | Version | Flags | Frame Number |
74 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
75 * 64 | Fragment Number | Fragments Total |
76 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
77 * 96 | Frame Width | Frame Height |
78 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
79 * 128 | Pixel Format |
80 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
81 * 160 | Fragment Startline | Fragment Lines |
82 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
83 * 192 | Reserved |
84 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
85 * 224 | Reserved |
86 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
89 * Version
90 * Version of coding used. This specification describes coding for
91 * version 0x01.
93 * Flags
94 * This field is currently reserved to be 0x00.
96 * Frame Number (nframe)
97 * Sequence number of this fragment's frame.
99 * Fragment Number (nfragment)
100 * Sequence number of this fragment. Starts from 0 for each new frame.
102 * Fragments Total (fragments_total)
103 * Total number of fragments in current frame.
105 * Frame Width (width)
106 * Frame width in pixels.
108 * Frame Height (height)
109 * Frame height in pixels.
111 * Pixel Format (pixfmt)
112 * 4 characters denoting payload pixel format according to
113 * http://fourcc.org/yuv.php; recommended are YUYV, YUY2, UYVY, GREY,
114 * Y800 and Y8.
116 * Fragment Startline (frag_startline)
117 * Vertical position of this fragment's first line relative to frame top.
119 * Fragment Lines (frag_nlines)
120 * Number of lines in this fragment.
123 * all integer fields are carried in network byte order, that is, most
124 * significant byte (octet) first.
127 * - payload:
129 * 1. right after header go raw pixel data in specified-in-header pixel format.
130 * There should be data for at least
132 * frag_nlines * width (1)
134 * pixels, which is
136 * frag_nlines * width * pixsize(pixfmt) (2)
138 * bytes.
140 * 2. there could be more data than specified in (2). in such a case,
141 * trailer content is out of this specification scope.
144 * TODO talk about packet reordering
145 * TODO talk about packet loss
146 * TODO talk about needed bandwidth for typical streams
147 * (PAL color, PAL mono, NTSC color, NTSC mono)
150 * References:
152 * [1] RFC3550 -- RTP: A Transport Protocol for Real-Time Applications
153 * [2] RFC3551 -- RTP Profile for Audio and Video Conferences with Minimal Control
154 * [3] RFC4175 -- RTP Payload Format for Uncompressed Video
155 * [4] IIDC 1394-based Digital Camera Specification Ver.1.32
156 * [5] MPEG-TS (?)
161 * RAWV library
162 * Copyright (C) 2010,2011,2012 Kirill Smelkov <kirr@navytux.spb.ru>
163 * Copyright (C) 2011 Marine Bridge and Navigation Systems (http://mns.spb.ru/)
165 * This library is free software; you can redistribute it and/or
166 * modify it under the terms of the GNU Lesser General Public
167 * License as published by the Free Software Foundation; either
168 * version 2.1 of the License, or (at your option) any later version.
170 * This library is distributed in the hope that it will be useful,
171 * but WITHOUT ANY WARRANTY; without even the implied warranty of
172 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
173 * Lesser General Public License for more details.
175 * You should have received a copy of the GNU Lesser General Public
176 * License along with this library; if not, write to the Free Software
177 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
180 #include <asm/types.h>
181 #include <sys/types.h>
182 #include <stdexcept>
184 #include <vector>
185 #include <arpa/inet.h>
186 #include <endian.h>
188 struct SDL_Surface;
189 struct SDL_Overlay;
191 namespace rawv {
193 using std::vector;
196 /* compose 4-characters tag to a 32-bit integer
198 * The mapping is so that host native in-memory representation of resulting
199 * integer always repeats characters in originally specified order. e.g.
201 * MKTAG32('R','A','W','V') -> 0x56574152 (= "RAWV") LE
202 * -> 0x52415756 (= "RAWV") BE
204 * that is integer is in native order, by character go in network byte-order
205 * _always_.
207 #define MKTAG32_LE(a,b,c,d) (((__u32)(a)<< 0)|((__u32)(b)<< 8)|((__u32)(c)<<16)|((__u32)(d)<<24))
208 #define MKTAG32_BE(a,b,c,d) (((__u32)(a)<<24)|((__u32)(b)<<16)|((__u32)(c)<< 8)|((__u32)(d)<< 0))
210 #if __BYTE_ORDER != __BIG_ENDIAN
211 # define MKTAG32 MKTAG32_LE
212 #else
213 # define MKTAG32 MKTAG32_BE
214 #endif
218 * RAWV packet header
220 * all fields go in network byteorder on the wire(*)
222 #pragma pack(push, 1)
223 struct rawv_header {
224 __u32 magic; /* (*) fourcc -- _characters_ go in network byteorder */
226 __u8 version;
227 __u8 __reserved_for_flags;
228 __u16 nframe;
230 __u16 nfragment;
231 __u16 fragments_total;
233 __u16 width;
234 __u16 height;
236 __u32 pixfmt; /* (*) fourcc -- _characters_ go in network byteorder */
238 __u16 frag_startline;
239 __u16 frag_nlines;
241 /* padding, so that the whole header is 32 bytes */
242 __u32 __reserved[2];
244 #pragma pack(pop)
247 * One video frame
249 struct Frame {
250 __u8 *start;
251 size_t length; /* ~= height * bytesperline */
253 int width, height, bytesperline;
254 __u32 pixfmt_4cc; /* characters go in network byteorder */
255 __u32 sequence;
256 // XXX timestamp ?
258 /* flags */
260 /* if we know top/bottom fields are in wrong order in this frame
262 * +1 -- swap fields
263 * -1 -- swap and shift one filed XXX write more
265 signed int interlace_tb_swapped : 2;
270 * Interfaces for video sink and source
272 struct IVideoSink {
273 /* Source will query framebuffer from one of subscribed sinks, and if ok,
274 * will put video frame directly into it. Otherwise source will use it's own
275 * frame buffer.
277 * ->v_query_framebuf() should read
279 * f->pixfmt_4cc,
280 * f->width,
281 * f->height
283 * to see whether it is possible to provide a buffer for requested
284 * parameters, and if yes, have to set
286 * f->start,
287 * f->length,
288 * f->bytesperline
290 * and return true.
292 * buffer should be valid until one next ->v_on_frame() call, after which
293 * buffer ownership returns back to sink.
294 * XXX interaction with v_unsubscribe()
296 virtual bool v_query_framebuf(Frame *f) = 0;
298 /* Source will notify sink when new frame is available via this method */
299 virtual void v_on_frame(const Frame *f) = 0;
302 virtual ~IVideoSink();
306 struct IVideoSource {
307 virtual void v_start_capture() = 0;
308 virtual void v_stop_capture() = 0;
310 virtual void v_subscribe(IVideoSink *) = 0;
311 virtual void v_unsubscribe(IVideoSink *) = 0;
313 virtual ~IVideoSource();
317 /* convenience class for IVideoSource implementers */
318 struct VideoSource : IVideoSource {
319 void v_subscribe(IVideoSink *);
320 void v_unsubscribe(IVideoSink *);
323 vector<IVideoSink *> v_subscribers;
324 IVideoSink *vs_sinkbuf; /* sink which provided framebuf */
326 /* go through subscribers & notify them */
327 void notify_v_subscribers(const Frame *f);
329 /* query sinks for video framebuffer for f's frame-metric.
331 * see IVideoSink->v_query_framebuf() for details.
333 bool query_sink_framebuf(Frame *f);
336 VideoSource();
337 ~VideoSource();
343 * Displays video frames to YUY2 overlay
345 struct View : IVideoSink
347 View(int w, int h, bool upscale, const char *title);
348 ~View();
350 /* whether to upscale frame on display.
352 * NOTE: only upscale is supported, not downscale
354 bool upscale;
356 /* IVideoSink */
357 bool v_query_framebuf(Frame *f);
358 void v_on_frame(const Frame *f);
361 SDL_Surface *display;
362 SDL_Overlay *overlay;
367 * Captures video frames from V4L2 source
369 struct VideoCapture : VideoSource
371 VideoCapture(const char *dev_name, int width, int height, int interlace_tb_swapped=0, int queue_len=4);
372 ~VideoCapture();
374 /* IVideoSource */
375 void v_start_capture();
376 void v_stop_capture();
379 // XXX naming
380 int read_frame();
384 int fd;
386 vector<Frame> buffers;
388 bool vcapture_on;
394 * Sends video frames to network
396 struct NetTx : IVideoSink
398 NetTx(const char *dest, int port, int mtu);
399 ~NetTx();
401 /* IVideoSink */
402 bool v_query_framebuf(Frame *f);
403 void v_on_frame(const Frame *f);
405 int sk;
406 struct sockaddr_in tx_addr;
407 int mtu;
412 * Receives video frames from network
414 struct NetRx : VideoSource
416 NetRx(const char *listen_on, int port, int mtu);
417 ~NetRx();
419 /* IVideoSource */
420 void v_start_capture();
421 void v_stop_capture();
423 int handle_recv();
424 void __handle_recv(unsigned len);
427 int sk;
428 struct sockaddr_in rx_addr;
429 int mtu;
431 void flush_frame();
433 vector<__u8> fragbuf; // XXX align?
434 vector<__u8> framebuf; // XXX align?
436 struct Frame f; /* current frame */
438 /* current rx state */
439 __u16 nframe, nfragment, fragments_total;
440 __u16 frag_received; /* # of fragments received in current frame */
441 __u32 frag_dropped_total; /* total # of dropped fragments */
445 /* XXX is this a good idea ? */
446 struct RawvError : std::runtime_error
448 RawvError(const char *msg);
449 ~RawvError() throw();
452 void die(const char *fmt, ...);
453 void die_errno(const char *msg);
454 void warn(const char *fmt, ...);
455 void warn_errno(const char *msg);
457 } /* rawv:: */
459 #endif