
Figure 1
UML class diagram showing how connections to supported devices are created and maintained in GIFT-Grab. The VideoSourceFactory singleton creates on demand a polymorphic IVideoSource object that serves as the interface for acquiring video frames from a supported device. The diagram shows three of the derived classes which implement this interface. The choice of the IVideoSource type depends on the connection request.

Figure 2
UML class diagram showing the observer design pattern hierarchy for video sources and targets in GIFT-Grab. Every IVideoSource is also an IObservable, to which IObservers can be attached. Each time a new VideoFrame becomes available, the IObservable notifies all its IObservers by calling the update method. Similarly, each IVideoTarget is an IObservers, with its update method automatically calling the append method (i.e. appending that particular frame to the file).

Figure 3
UML sequence diagram showing how the visitor design pattern [14] is used for realising the observer pattern with an IVideoSource implementor that does not inherently support callbacks: The BroadcastDaemon visitor queries the VideoSourceOpenCV object in regular intervals for a new VideoFrame. Once obtained, the new VideoFrame is propagated to all attached observers by calling notify.

Figure 4
UML class diagram representing the video target hierarchy in GIFT-Grab. Two implementors of the IVideoTarget interface are shown: VideoTargetOpenCV and VideoTargetFFmpeg classes which are used for encoding video frames and saving them to video files. Similar to the case of VideoSourceFactory, the VideoTargetFactory singleton creates on demand a polymorphic IVideoTarget object. However contrary to the case of VideoSourceFactory, the ownership of the created IVideoTarget object passes to the caller, i.e. the caller is responsible for destroying it to free up memory at the end of its lifetime.
Table 1
Recorded maximum CPU load (as percentage) and maximum system memory used (in gigabytes) while recording each of the datasets shown in figure 5. Note that these are system-wide measurements to give an idea of the system load during the benchmarking process.
| GeForce GTX TITAN X | GeForce GTX 980 Ti | ||
|---|---|---|---|
| I420 frames | HD: | 14.3%, 5.7 GB | 14.3%, 5.7 GB |
| Full HD: | 14.7%, 5.7 GB | 17.2%, 5.7 GB | |
| 4K: | 67.7%, 6.3 GB | 75.8%, 6.3 GB | |
| BGRA frames | HD: | 18.5%, 3.8 GB | 15.6%, 3.8 GB |
| Full HD: | 50.0%, 4.8 GB | 16.7%, 4.8 GB | |
| 4K: | 52.9%, 11.0 GB | 55.2%, 11.0 GB |

Figure 5
Wall-clock execution times in milliseconds for encoding 100 video frames of three different resolutions on two GPUs and subsequently writing them to a video file. Each column is for one GPU. The upper row shows execution times when I420 frames are fed into the file writer, i.e. no colour space conversion before encoding. The lower row shows the case when BGRA frames are fed into the file writer, i.e. BGRA-to-I420 conversion performed before encoding. The darker shade in each graph shows the region within the time limits that would allow for processing 60 fps. The lighter shade in the lower row shows the respective region for 30 fps (but not 60 fps). The numbers in parantheses in the figure legends indicate the maximum GPU memory allocated at a time for each dataset.
Table 2
Encoding times in milliseconds for the excluded first frame (initialisation) in each of the datasets shown in figure 5.
| GeForce GTX TITAN X | GeForce GTX 980 Ti | ||
|---|---|---|---|
| I420 frames | HD: | 486 msec | 451 msec |
| Full HD: | 495 msec | 412 msec | |
| 4K: | 754 msec | 731 msec | |
| BGRA frames | HD: | 509 msec | 441 msec |
| Full HD: | 505 msec | 452 msec | |
| 4K: | 798 msec | 736 msec |
