1 module dcv.example.video; 2 3 /** 4 * Video streaming example using dcv library. 5 */ 6 7 import std.stdio; 8 import std.datetime : StopWatch; 9 import core.stdc.stdlib; 10 11 import dcv.io.image; 12 import dcv.imgproc.color; 13 import dcv.core.utils; 14 import dcv.io.video; 15 import dcv.plot.figure; 16 17 void main(string[] args) 18 { 19 if (args.length == 2 && args[1] == "-h") 20 { 21 printHelp(); 22 return; 23 } 24 25 //////////// Open the video stream //////////////// 26 27 InputStream inStream = new InputStream; 28 29 string path; // path to the video 30 InputStreamType type; // type of the stream (file or live) 31 32 if (!parseArgs(args, path, type)) 33 { 34 writeln("Error occurred while parsing arguments.\n\n"); 35 printHelp(); 36 return; 37 } 38 39 try 40 { 41 // Open the example video 42 inStream.open(path, type); 43 } 44 catch 45 { 46 writeln("Cannot open input video stream"); 47 exit(-1); 48 } 49 50 // Check if video has been opened correctly 51 if (!inStream.isOpen) 52 { 53 writeln("Cannot open input video stream"); 54 exit(-1); 55 } 56 57 //////////// Read video frames ////////////////// 58 59 Image frame; // frame image buffer, where each next frame of the video is stored. 60 61 // read the frame rate, if info is available. 62 double fps = inStream.frameRate ? inStream.frameRate : 30.0; 63 // calculate frame wait time in miliseconds - if video is live, set to minimal value. 64 double waitFrame = (type == InputStreamType.LIVE) ? 1.0 : 1000.0 / fps; 65 66 StopWatch s; 67 s.start; 68 69 // Read each next frame of the video in the loop. 70 while (inStream.readFrame(frame)) 71 { 72 import std.algorithm.comparison : max; 73 74 s.reset; 75 76 // If video frame pixel format is YUV, convert the data to RGB, then show it on screen 77 if (frame.format == ImageFormat.IF_YUV) 78 frame.sliced.yuv2rgb!ubyte.imshow(path); 79 else 80 frame.imshow(path); 81 82 // Compensate fps wait for lost time on color conversion. 83 int wait = max(1, cast(int)waitFrame - cast(int)s.peek.msecs); 84 85 // If user presses escape key, stop the streaming. 86 if (waitKey(wait) == KEY_ESCAPE) 87 break; 88 89 /* 90 Ask if figure with given name is visible. 91 92 Normally, you can close the figure window by pressing the 'x' button. 93 That way, figure closes, and visible property will return false. 94 So, if user presses the 'x' button, normal behavior would be to break the 95 streaming loop. 96 */ 97 if (!figure(path).visible) 98 break; 99 } 100 101 } 102 103 void printHelp() 104 { 105 writeln(` 106 DCV Video Streaming Example. 107 108 Run example program without arguments, to load and show the example video file centaur_1.mpg. 109 110 If multiple parameters are given, then parameters are considered to be: 111 112 1 - video stream mode (-f for file, -l for webcam or live mode); 113 2 - video stream name (for file mode it is the path to the file, for webcam it is the name of the stream, e.g. /dev/video0); 114 115 Examples: 116 ./video -l /dev/video0 117 ./video -f ../data/centaur_1.mpg 118 119 Tip: 120 To run the example program in best performance, compile with one of the following configurations 121 dub build --compiler=ldc2 --build=release 122 dub build --compiler=dmd --build=release-nobounds 123 `); 124 } 125 126 bool parseArgs(in string[] args, out string path, out InputStreamType type) 127 { 128 if (args.length == 1) 129 return true; 130 else if (args.length != 3) 131 return false; 132 133 type = InputStreamType.FILE; 134 135 switch (args[1]) 136 { 137 case "-file": 138 case "-f": 139 type = InputStreamType.FILE; 140 break; 141 case "-live": 142 case "-l": 143 type = InputStreamType.LIVE; 144 break; 145 default: 146 writeln("Invalid input type argument: ", args[2]); 147 exit(-1); 148 } 149 150 path = args[2]; 151 152 return true; 153 }