[mmap] partial revert of 8cef8db4 to disable using mmap file reader
[videoplayer.git] / main.cpp
blob09420d034b9eb87e9037852f01b1216ce7791103
1 /* ***** BEGIN LICENSE BLOCK *****
3 * The MIT License
5 * Copyright (c) 2008 BBC Research
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
25 * ***** END LICENSE BLOCK ***** */
27 #include "mainwindow.h"
29 #ifdef Q_OS_LINUX
30 #include "X11/Xlib.h"
31 #endif
33 #include <QApplication>
35 #include <string>
36 using namespace std;
38 #include <iostream>
39 #include <boost/program_options.hpp>
40 namespace po = boost::program_options;
42 #include "readerInterface.h"
43 #include "yuvReader.h"
44 #include "yuvReaderMmap.h"
45 #ifdef HAVE_DIRAC
46 #include "diracReader.h"
47 #endif
49 #include "frameQueue.h"
50 #include "videoTransport.h"
51 #ifdef Q_OS_LINUX
52 #include "QShuttlePro.h"
53 #endif
55 #ifdef Q_OS_UNIX
56 #include "QConsoleInput.h"
57 #endif
59 #include "GLvideo_params.h"
61 #include "config.h"
63 struct Transport_params {
64 bool looping;
65 QString fileName;
66 QString fileType;
67 bool quit_at_end;
68 bool forceFileType;
69 int videoWidth;
70 int videoHeight;
73 void
74 usage()
76 printf("\nOpenGL accelerated YUV video player.");
77 printf("\n");
78 printf("\nUsage: progname -<flag1> [<flag1_val>] ... <input>");
79 printf("\n");
80 printf("\nSupported file formats:");
81 printf("\n");
82 printf("\n .i420 4:2:0 YUV 8 bit planar");
83 printf("\n .yv12 4:2:0 YVU 8 bit planar");
84 printf("\n .420p 4:2:0 YUV 8 bit planar");
85 printf("\n .422p 4:2:2 YUV 8 bit planar");
86 printf("\n .444p 4:4:4 YUV 8 bit planar");
87 printf("\n .uyvy 4:2:2 YUV 8 bit packed");
88 printf("\n .v210 4:2:2 YUV 10 bit packed");
89 printf("\n .v216 4:2:2 YUV 16 bit packed");
90 printf("\n .16p0 4:2:0 YUV 16 bit planar");
91 printf("\n .16p2 4:2:2 YUV 16 bit planar");
92 printf("\n .16p4 4:4:4 YUV 16 bit planar");
93 printf("\n");
95 printf("\nKeypress Action");
96 printf("\n======== ======");
97 printf("\no Toggle OSD state");
98 printf("\nf Toggle full screen mode");
99 printf("\nm Switch to output levels from user flags out-range and out-black");
100 printf("\nn Switch to video output levels, out-range=240 out-black=16");
101 printf("\nb Switch to computer output levels, out-range=256, out-black=0");
102 printf("\nEsc Return from full screen mode to windowed");
103 printf("\na Toggle aspect ratio lock");
104 printf("\nd Toggle deinterlacing of an interlaced source");
105 printf("\nSpace Play/Pause");
106 printf("\ns Stop");
107 printf("\n1,2,3,4,5,6,7 Play forward at 1,2,5,10,20,50,100x");
108 printf("\nCTRL + 1,2,3,4,5,6,7 Play backward at 1,2,5,10,20,50,100x");
109 printf("\n> Jog one frame forward when paused");
110 printf("\n< Jog one frame backward when paused");
111 printf("\ny Toggle display of luma on/off");
112 printf("\nc Toggle display of chroma on/off");
113 printf("\nh Switch to HDTV colour matrix kr=0.2126 kg=0.7152 kb=0.0722");
114 printf("\nj Switch to SDTV colour matrix kr=0.2990 kg=0.5870 kb=0.1140");
115 printf("\nk Switch to colour matrix kr, kg, kb from user flags");
116 printf("\nq Quit");
117 printf("\n");
118 printf("\n");
121 bool
122 parseCommandLine(int argc, char **argv, GLvideo_params& vp, Transport_params& tp, Qt_params& qt)
124 bool allParsed = true; //default to command line parsing succeeding
125 int cols = 81;
127 if (getenv("COLUMNS"))
128 cols = atoi(getenv("COLUMNS"));
130 try {
131 // Declare the supported options.
132 po::options_description desc("Allowed options type default description\n"
133 "=============== ==== ======= ===========", cols);
134 desc.add_options()
135 ("width,w", po::value(&tp.videoWidth), "int 1920 Width of video luma component")
136 ("height,h", po::value(&tp.videoHeight), "int 1080 Height of video luma component")
137 ("repeats,r", po::value(&vp.frame_repeats), "int 0 Frame is repeated r extra times")
138 ("loop,l", po::value(&tp.looping), "int 1 Number of times to loop video (1=inf)")
139 ("quit,q", po::bool_switch(&tp.quit_at_end), "int 0 Exit at end of video file (implies loop=0)")
140 ("interlace,i", po::bool_switch(&vp.interlaced_source), " Source is interlaced")
141 ("deinterlace,d", po::bool_switch(&vp.deinterlace), " Enable Deinterlacer (requires -i)")
142 ("yrange", po::value(&vp.input_luma_range), "int 220 Range of input luma (white-black+1)")
143 ("yblack", po::value(&vp.input_luma_blacklevel), "int 16 Blacklevel of input luma")
144 ("cblack", po::value(&vp.input_chroma_blacklevel), "int 16 Blacklevel of input chroma")
145 ("out-range", po::value(&vp.output_range), "int 220 Range of R'G'B' output (white-black+1)")
146 ("out-black", po::value(&vp.output_blacklevel), "int 16 Blacklevel of R'G'B' output")
147 ("ymult", po::value(&vp.luminance_mul), "float 1.0 User luma multipler")
148 ("cmult", po::value(&vp.chrominance_mul), "float 1.0 User chroma multiplier")
149 ("yoffset2", po::value(&vp.luminance_offset2), "float 0.0 User luma offset2")
150 ("coffset2", po::value(&vp.chrominance_offset2), "float 0.0 User chroma offset2")
151 ("matrixkr", po::value(&vp.matrix_Kr), "float 0.2126 Luma coefficient Kr")
152 ("matrixkg", po::value(&vp.matrix_Kg), "float 0.7152 Luma coefficient Kg")
153 ("matrixkb", po::value(&vp.matrix_Kb), "float 0.0722 Luma coefficient Kb\n"
154 " ITU-R BT709/BT1361, SMPTE274M/296M")
155 ("sdmatrix,s", " As '-kr 0.299 -kg 0.587 -kb 0.114'\n"
156 " ITU-R BT601/BT470, SMPTE170M/293M")
157 #if WITH_OSD
158 ("fontfile", po::value<string>(), "string TrueType font file for OSD")
159 ("osdscale", po::value(&vp.osd_scale), "float 1.0 OSD size scaling factor")
160 ("osdbackalpha", po::value(&vp.osd_back_alpha),"float 0.7 Transparency for OSD background")
161 ("osdtextalpha", po::value(&vp.osd_text_alpha),"float 0.5 Transparency for OSD text")
162 ("osdstate", po::value(&vp.osd_bot), "int 0 OSD initial state")
163 ("caption", po::value<string>(), "string OSD Caption text")
164 #endif
165 ("filetype,t", po::value<string>(), "string Force file type\n"
166 " [i420|yv12|uyvy|v210|v216]")
167 ("full,f", po::bool_switch(&qt.start_fullscreen)," Start in full screen mode")
168 ("hidemouse", po::bool_switch(&qt.hidemouse), " Never show the mouse pointer")
169 ("video", " Video file to play")
170 ("help", " Show usage information");
172 //file filename is a 'positional option' that we give the name 'video' to
173 po::positional_options_description p;
174 p.add("video", -1);
176 po::variables_map vm;
177 po::store(po::command_line_parser(argc, argv). options(desc).positional(p).run(), vm);
178 po::notify(vm);
180 if (vm.count("help")) {
181 usage();
182 std::cout << desc << std::endl;
183 exit(0);
186 if (vm.count("sd")) {
187 SetLumaCoeffsRec601(vp);
190 if (vm.count("matrixkr") || vm.count("matrixkg") || vm.count("matrixkb")) {
191 if (vp.matrix_Kr + vp.matrix_Kg + vp.matrix_Kb < 1.0)
192 printf("Warning, luma coefficients do not sum to unity\n");
195 #ifdef WITH_OSD
196 if (vm.count("fontfile")) {
197 string tmp = vm["fontfile"].as<string>();
198 vp.font_file = tmp.data();
200 //check OSD font file exists
201 QFileInfo fi(vp.font_file);
202 if(fi.exists() == false) {
203 printf("Cannot find OSD font file %s\n", vp.font_file.toLatin1().data());
204 allParsed = false;
206 else {
207 if(fi.isReadable() == false) {
208 printf("Cannot read OSD font file %s\n", vp.font_file.toLatin1().data());
209 allParsed = false;
214 if(vm.count("caption")) {
215 string tmp = vm["caption"].as<string>();
216 vp.caption = tmp.data();
218 #endif
220 QString known_extensions("i420 yv12 420p 422p 444p uyvy v216 v210 16p4 16p2 16p0");
221 #ifdef HAVE_DIRAC
222 known_extensions.append(" drc");
223 #endif
225 if (vm.count("filetype")) {
226 string tmp = vm["filetype"].as<string>();
227 tp.fileType = tmp.data();
229 if(known_extensions.contains(tp.fileType.toLower(), Qt::CaseInsensitive))
230 tp.forceFileType=true;
231 else {
232 printf("Unknown file type %s\n", tp.fileType.toLatin1().data());
233 allParsed = false;
238 if (vm.count("video") == 0) {
239 printf("No file to play!\n");
240 allParsed = false;
242 else {
243 string tmp = vm["video"].as<string>();
244 tp.fileName = tmp.data();
246 QFileInfo fi(tp.fileName);
248 if(fi.exists()) {
249 if(tp.forceFileType == false) {
250 //file extension must be one we know about
251 if(known_extensions.contains(fi.suffix().toLower(), Qt::CaseInsensitive) == false) {
252 printf("Do not know how to play file with extension %s\n", fi.suffix().toLatin1().data());
253 printf("Please specify file format with the -t flag\n");
254 allParsed = false;
256 else {
257 //the file type has not been forced, and it is an allowed file type
258 tp.fileType = fi.suffix().toLower();
262 else {
263 printf("File %s does not exist\n", tp.fileName.toLatin1().data());
264 allParsed = false;
268 catch(exception& e)
270 printf("Command line error : ");
271 cout << e.what() << "\n";
272 allParsed = false;
275 return allParsed;
278 int main(int argc, char **argv)
280 #ifdef Q_OS_LINUX
281 XInitThreads();
282 #endif
284 struct GLvideo_params vr_params;
285 /* some defaults in the abscence of any settings */
286 vr_params.frame_repeats = 1;
287 vr_params.caption = "hello world";
288 vr_params.osd_scale = 1.;
289 vr_params.osd_back_alpha = 0.7;
290 vr_params.osd_text_alpha = 0.5;
291 vr_params.osd_perf = false;
292 vr_params.osd_bot = OSD_NONE;
293 vr_params.osd_valid = false;
294 vr_params.font_file = DEFAULT_FONTFILE;
295 vr_params.input_luma_range = 220;
296 vr_params.input_luma_blacklevel = 16;
297 vr_params.input_chroma_blacklevel = 128;
298 vr_params.output_blacklevel = 16;
299 vr_params.output_range = 220;
300 vr_params.luminance_mul = 1.;
301 vr_params.chrominance_mul = 1.;
302 vr_params.luminance_offset2 = 0.;
303 vr_params.chrominance_offset2 = 0.;
304 vr_params.interlaced_source = false;
305 vr_params.deinterlace = false;
306 vr_params.matrix_valid = false;
307 SetLumaCoeffsRec709(vr_params);
308 vr_params.aspect_ratio_lock = true;
309 vr_params.show_luma = true;
310 vr_params.show_chroma = true;
312 struct Transport_params t_params;
313 t_params.looping = true;
314 t_params.quit_at_end = false;
315 t_params.forceFileType = false;
316 t_params.videoWidth = 1920;
317 t_params.videoHeight = 1080;
319 struct Qt_params qt_params;
320 qt_params.hidemouse = false;
321 qt_params.start_fullscreen = false;
323 /* QApplication will munge argc/argv, needs to be called before
324 * parseCommandLine. Eg, useful for X11's -display :0 convention */
325 QApplication app(argc, argv);
327 //override settings with command line
328 if (parseCommandLine(argc, argv, vr_params, t_params, qt_params) == false) {
329 return -1;
332 //object containing a seperate thread that manages the lists of frames to be displayed
333 FrameQueue* frameQueue = new FrameQueue();
335 //object that generates frames to be inserted into the frame queue
336 ReaderInterface* reader = NULL;
337 #ifdef HAVE_DIRAC
338 //make dirac reader if required
339 if(t_params.fileType.toLower() == "drc") {
340 DiracReader *r = new DiracReader( *frameQueue );
342 r->setFileName(t_params.fileName);
343 reader = r;
344 r->start(QThread::LowestPriority);
346 #endif
348 //default to YUV reader
349 if (reader == NULL) {
350 #if 0
351 YUVReaderMmap *r = new YUVReaderMmap( *frameQueue );
352 #else
353 YUVReader *r = new YUVReader( *frameQueue );
354 #endif
355 //YUV reader parameters
356 r->setVideoWidth(t_params.videoWidth);
357 r->setVideoHeight(t_params.videoHeight);
358 r->setForceFileType(t_params.forceFileType);
359 r->setFileType(t_params.fileType);
360 r->setFileName(t_params.fileName);
362 reader = r;
365 frameQueue->setReader(reader);
367 //object controlling the video playback 'transport'
368 VideoTransport* vt = new VideoTransport(frameQueue);
370 frameQueue->start();
372 MainWindow* window = new MainWindow(vr_params, qt_params, vt);
374 #ifdef Q_OS_LINUX
375 //shuttlePro jog dial - linux only native support at the moment
376 QShuttlePro* shuttle = new QShuttlePro();
378 //shuttlepro jog wheel
379 QObject::connect(shuttle, SIGNAL(jogForward()), vt, SLOT(transportJogFwd()));
380 QObject::connect(shuttle, SIGNAL(jogBackward()), vt, SLOT(transportJogRev()));
382 //shuttlepro shuttle dial
383 QObject::connect(shuttle, SIGNAL(shuttleRight7()), vt, SLOT(transportFwd100()));
384 QObject::connect(shuttle, SIGNAL(shuttleRight6()), vt, SLOT(transportFwd50()));
385 QObject::connect(shuttle, SIGNAL(shuttleRight5()), vt, SLOT(transportFwd20()));
386 QObject::connect(shuttle, SIGNAL(shuttleRight4()), vt, SLOT(transportFwd10()));
387 QObject::connect(shuttle, SIGNAL(shuttleRight3()), vt, SLOT(transportFwd5()));
388 QObject::connect(shuttle, SIGNAL(shuttleRight2()), vt, SLOT(transportFwd2()));
389 QObject::connect(shuttle, SIGNAL(shuttleRight1()), vt, SLOT(transportFwd1()));
391 QObject::connect(shuttle, SIGNAL(shuttleLeft7()), vt, SLOT(transportRev100()));
392 QObject::connect(shuttle, SIGNAL(shuttleLeft6()), vt, SLOT(transportRev50()));
393 QObject::connect(shuttle, SIGNAL(shuttleLeft5()), vt, SLOT(transportRev20()));
394 QObject::connect(shuttle, SIGNAL(shuttleLeft4()), vt, SLOT(transportRev10()));
395 QObject::connect(shuttle, SIGNAL(shuttleLeft3()), vt, SLOT(transportRev5()));
396 QObject::connect(shuttle, SIGNAL(shuttleLeft2()), vt, SLOT(transportRev2()));
397 QObject::connect(shuttle, SIGNAL(shuttleLeft1()), vt, SLOT(transportRev1()));
398 QObject::connect(shuttle, SIGNAL(shuttleCenter()), vt, SLOT(transportStop()));
400 //shuttlepro buttons
401 QObject::connect(shuttle, SIGNAL(key267Pressed()), vt, SLOT(transportPlayPause()));
402 QObject::connect(shuttle, SIGNAL(key265Pressed()), vt, SLOT(transportFwd1()));
403 QObject::connect(shuttle, SIGNAL(key259Pressed()), window, SLOT(toggleFullScreen()));
404 QObject::connect(shuttle, SIGNAL(key256Pressed()), window, SLOT(toggleOSD()));
405 QObject::connect(shuttle, SIGNAL(key257Pressed()), window, SLOT(toggleAspectLock()));
407 //this is what the IngexPlayer also does
408 //key 269, press=previous mark, hold=start of file
409 //key 270, press=next mark, hold=end of file
410 //key 257, cycle displayed timecode type
411 //key 258, press=lock controls, hold=unlock controls
412 #endif
414 #ifdef Q_OS_UNIX
415 QConsoleInput tty(window);
416 #endif
418 if (t_params.quit_at_end) {
419 QObject::connect(vt, SIGNAL(endOfFile()), &app, SLOT(quit()));
420 t_params.looping = false;
422 vt->setLooping(t_params.looping);
424 window->show();
425 /* app.exec will run until the mainwindow terminates */
426 app.exec();
428 #ifdef Q_OS_LINUX
429 if(shuttle) {
430 shuttle->stop();
431 shuttle->wait();
433 #endif
435 delete window;
436 delete frameQueue;
438 return 0;