5 * RAWV coding-scheme for low-latency loosless video streaming
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
24 * A scheme for transmitting progressive PAL/NTSC video over 1Gbps Ethernet
25 * LAN is presented. Loosless 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.
35 * - each frame is transmitted in series of independent fragments
36 * - each fragment carries header and payload
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,
48 * < - - - - - - w i d t h - - - - - - >
49 * +-----------------------------------+ ^
54 * frag_startline -->|-----------------------------------| h
58 * |-----------------------------------| h
64 * +-----------------------------------+ v
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 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
84 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
86 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
90 * Version of coding used. This specification describes coding for
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 * According to http://fourcc.org/yuv.php; recommended are YUYV, YUY2,
113 * UYVY, GREY, Y800 and Y8.
115 * Fragment Startline (frag_startline)
116 * Vertical position of this fragment's first line relative to frame top.
118 * Fragment Lines (frag_nlines)
119 * Number of lines in this fragment.
124 * 1. right after header go raw pixel data in specified-in-header pixel format.
125 * There should be data for at least
127 * frag_nlines * width (1)
131 * frag_nlines * width * pixsize(pixfmt) (2)
135 * 2. there could be more data than specified in (2). in such a case,
136 * trailer content is out of this specification scope.
139 * TODO talk about packet reordering
140 * TODO talk about packet loss
141 * TODO talk about needed bandwith for typical streams
142 * (PAL color, PAL mono, NTSC color, NTSC mono)
147 * [1] RFC3550 -- RTP: A Transport Protocol for Real-Time Applications
148 * [2] RFC3551 -- RTP Profile for Audio and Video Conferences with Minimal Control
149 * [3] RFC4175 -- RTP Payload Format for Uncompressed Video
150 * [4] IIDC 1394-based Digital Camera Specification Ver.1.32
157 * Copyright (C) 2010,2011 Kirill Smelkov <kirr@navytux.spb.ru>
158 * Copyright (C) 2011 Marine Bridge and Navigation Systems (http://mns.spb.ru/)
160 * This library is free software; you can redistribute it and/or
161 * modify it under the terms of the GNU Lesser General Public
162 * License as published by the Free Software Foundation; either
163 * version 2.1 of the License, or (at your option) any later version.
165 * This library is distributed in the hope that it will be useful,
166 * but WITHOUT ANY WARRANTY; without even the implied warranty of
167 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
168 * Lesser General Public License for more details.
170 * You should have received a copy of the GNU Lesser General Public
171 * License along with this library; if not, write to the Free Software
172 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
175 #include <asm/types.h>
176 #include <sys/types.h>
180 #include <arpa/inet.h>
190 /* XXX endiannes ? */
191 #define MKTAG32(a,b,c,d) (((__u32)(a)<<0)|((__u32)(b)<<8)|((__u32)(c)<<16)|((__u32)(d)<<24))
197 #pragma pack(push, 1)
202 __u8 __reserved_for_flags
;
205 #define NFRAME_MAX 0x10000
208 __u16 fragments_total
;
215 __u16 frag_startline
;
218 /* padding, so that the whole header is 32 bytes */
228 size_t length
; /* ~= height * bytesperline */
230 int width
, height
, bytesperline
;
237 /* if we know top/bottom fields are in wrong order in this frame
240 * -1 -- swap and shift one filed XXX write more
242 signed int interlace_tb_swapped
: 2;
245 struct FrameSubscription
{
246 void (*func
)(const Frame
*, void *);
249 bool operator== (const FrameSubscription
&rhs
)
251 return (func
== rhs
.func
) && (self
== rhs
.self
);
257 * Displays video frames to YUY2 overlay
261 View(int w
, int h
, bool upscale
, const char *title
);
264 /* whether to upscale frame on display.
266 * NOTE: only upscale is supported, not downscale
270 void display_frame(const Frame
*f
);
271 static void __display_frame(const Frame
*f
, void *self
);
274 SDL_Surface
*display
;
275 SDL_Overlay
*overlay
;
280 * Captures video frames from V4L2 source
284 VideoCapture(const char *dev_name
, int width
, int height
, int interlace_tb_swapped
=0, int queue_len
=4);
287 void start_capture();
290 void subscribe(void (*func
)(const Frame
*, void *), void *self
);
291 void unsubscribe(void (*func
)(const Frame
*, void *), void *self
);
300 vector
<Frame
> buffers
;
301 vector
<FrameSubscription
> subscribers
;
309 * Sends video frames to network
313 NetTx(const char *dest
, int port
, int mtu
);
316 void tx_frame(const Frame
*f
);
317 static void __tx_frame(const Frame
*f
, void *self
);
320 struct sockaddr_in tx_addr
;
326 * Receives video frames from network
330 NetRx(const char *listen_on
, int port
, int mtu
);
333 void subscribe(void (*func
)(const Frame
*, void *), void *self
);
334 void unsubscribe(void (*func
)(const Frame
*, void *), void *self
);
337 void __handle_recv(unsigned len
);
341 struct sockaddr_in rx_addr
;
344 vector
<FrameSubscription
> subscribers
;
347 vector
<__u8
> fragbuf
; // XXX align?
348 vector
<__u8
> framebuf
; // XXX align?
350 struct Frame f
; /* current frame */
352 /* current rx state */
353 __u16 nframe
, nfragment
, fragments_total
;
354 __u16 frag_received
; /* # of fragments received in current frame */
355 __u32 frag_dropped_total
; /* total # of dropped fragments */
359 /* XXX is this a good idea ? */
360 struct RawvError
: std::runtime_error
362 RawvError(const char *msg
);
363 ~RawvError() throw();
366 void die(const char *fmt
, ...);
367 void die_errno(const char *msg
);
368 void warn(const char *fmt
, ...);
369 void warn_errno(const char *msg
);