OSDN Git Service

[MOVIE_LOADER] Fix scaling factor.Displaying video as correct width and height.
[csp-qt/common_source_project-fm7.git] / source / src / qt / osd_screen.cpp
1 /*
2         Skelton for retropc emulator
3
4         Author : K.Ohta <whatisthis.sowhat _at_ gmail.com>
5         Date   : 2015.11.30-
6
7         [ Qt screen ]
8 */
9
10 #include <QImage>
11 #include <QPainter>
12 #include <QColor>
13 #include <QPen>
14 #include <QPoint>
15 #include <QTextCodec>
16 #include <QDateTime>
17 #include <QImageReader>
18 #include <QMutexLocker>
19
20 #include "qt_gldraw.h"
21 #include "osd_base.h"
22 #include "menu_flags.h"
23 //#include "csp_logger.h"
24
25 #define REC_VIDEO_SUCCESS       1
26 #define REC_VIDEO_FULL          2
27 #define REC_VIDEO_ERROR         3
28
29 //extern USING_FLAGS *using_flags;
30
31 void OSD_BASE::set_host_window_size(int window_width, int window_height, bool window_mode)
32 {
33         if(window_width != -1) {
34                 host_window_width = window_width;
35         }
36         if(window_height != -1) {
37                 host_window_height = window_height;
38         }
39         host_window_mode = window_mode;
40         
41         first_draw_screen = false;
42         first_invalidate = true;
43 }
44
45 void OSD_BASE::set_vm_screen_lines(int lines)
46 {
47         emit sig_resize_vm_lines(lines);
48 }
49
50 void OSD_BASE::set_vm_screen_size(int screen_width, int screen_height, int window_width, int window_height, int window_width_aspect, int window_height_aspect)
51 {
52         if(vm_screen_width != screen_width || vm_screen_height != screen_height) {
53                 if(window_width == -1) {
54                         window_width = screen_width;
55                 }
56                 if(window_height == -1) {
57                         window_height = screen_height;
58                 }
59                 if(window_width_aspect == -1) {
60                         window_width_aspect = window_width;
61                 }
62                 if(window_height_aspect == -1) {
63                         window_height_aspect = window_height;
64                 }
65                 vm_screen_width = screen_width;
66                 vm_screen_height = screen_height;
67                 vm_window_width = window_width;
68                 vm_window_height = window_height;
69                 vm_window_width_aspect = window_width_aspect;
70                 vm_window_height_aspect = window_height_aspect;
71                 
72                 // change the window size
73                 //emit sig_movie_set_width(screen_width);
74                 //emit sig_movie_set_height(screen_height);
75                 emit sig_resize_vm_screen(&(vm_screen_buffer.pImage), screen_width, screen_height);
76         }
77 }
78
79
80 scrntype_t* OSD_BASE::get_vm_screen_buffer(int y)
81 {
82         return get_buffer(&vm_screen_buffer, y);
83 }
84
85 scrntype_t* OSD_BASE::get_buffer(bitmap_t *p, int y)
86 {
87         if((y >= p->pImage.height()) || (y < 0) || (y >= p->height)) {
88                 return NULL;
89         }
90         return (scrntype_t *)p->pImage.scanLine(y);
91 }
92
93 int OSD_BASE::draw_screen()
94 {
95         // draw screen
96         QMutexLocker Locker_S(screen_mutex);
97         //QMutexLocker Locker_VM(vm_mutex);
98         if(vm_screen_buffer.width != vm_screen_width || vm_screen_buffer.height != vm_screen_height) {
99                 //emit sig_movie_set_width(vm_screen_width);
100                 //emit sig_movie_set_height(vm_screen_height);
101                 initialize_screen_buffer(&vm_screen_buffer, vm_screen_width, vm_screen_height, 0);
102         }
103         this->vm_draw_screen();
104         // screen size was changed in vm->draw_screen()
105         if(vm_screen_buffer.width != vm_screen_width || vm_screen_buffer.height != vm_screen_height) {
106                 return 0;
107         }
108         draw_screen_buffer = &vm_screen_buffer;
109         
110         // calculate screen size
111         // invalidate window
112         emit sig_update_screen(draw_screen_buffer);
113
114         first_draw_screen = self_invalidate = true;
115         
116         // record avi file
117         if(now_record_video) {
118                 add_video_frames();
119         }
120         return 1;
121 }
122
123 int OSD_BASE::no_draw_screen()
124 {
125         if(now_record_video) {
126                 add_video_frames();
127         }
128         return 1;
129 }
130
131 void OSD_BASE::do_draw(bool flag)
132 {
133         int frames;
134 #if defined(USE_MOVIE_PLAYER) || defined(USE_VIDEO_CAPTURE)
135         do_decode_movie(1);
136 #endif
137         if(flag) {
138                 frames = draw_screen();
139         } else {
140                 frames = no_draw_screen();
141         }
142         emit sig_draw_frames(frames);
143 }
144
145 void OSD_BASE::update_screen()
146 {
147         // UpdateScreen
148         // -> qt_gldraw.cpp , qt_glutil.cpp and qt_glevents.cpp within src/qt/common/ .
149         first_invalidate = self_invalidate = false;
150 }
151
152 void OSD_BASE::initialize_screen_buffer(bitmap_t *buffer, int width, int height, int mode)
153 {
154         release_screen_buffer(buffer);
155         buffer->width = width;
156         buffer->height = height;
157         if((width > buffer->pImage.width()) || (height > buffer->pImage.height())) {
158                 QColor col(0, 0, 0, 255);
159                 buffer->pImage = QImage(width, height, QImage::Format_ARGB32);
160                 buffer->pImage.fill(col);
161         }
162         printf("%dx%d NULL=%d\n", buffer->pImage.width(), buffer->pImage.height(), buffer->pImage.isNull() ? 1 : 0);
163         QColor fillcolor;
164         fillcolor.setRgb(0, 0, 0, 255);
165         buffer->pImage.fill(fillcolor);
166         //emit sig_movie_set_width(width);
167         //emit sig_movie_set_height(height);
168         emit sig_resize_vm_screen(&(buffer->pImage), width, height);
169 }
170
171 void OSD_BASE::release_screen_buffer(bitmap_t *buffer)
172 {
173         if(!(buffer->width == 0 && buffer->height == 0)) {
174                 //if(buffer->hPainter == NULL) delete buffer->hPainter;
175         }
176         buffer->width = 0;
177         buffer->height = 0;
178         //memset(buffer, 0, sizeof(bitmap_t));
179 }
180
181
182 void OSD_BASE::rotate_screen_buffer(bitmap_t *source, bitmap_t *dest)
183 {
184 }
185
186 void OSD_BASE::stretch_screen_buffer(bitmap_t *source, bitmap_t *dest)
187 {
188 }
189
190 void OSD_BASE::capture_screen()
191 {
192         // create file name
193         char file_name[_MAX_PATH];
194         memset(file_name, 0x00, sizeof(file_name));
195         create_date_file_name((_TCHAR *)file_name, _MAX_PATH, _T("png"));
196         emit sig_save_screen((const char *)file_name); 
197         // create bitmap
198 }
199
200 bool OSD_BASE::start_record_video(int fps)
201 {
202         if(fps > 0) {
203                 rec_video_fps = fps;
204                 rec_video_fps_nsec = (int)(1.0e9 / (double)fps);
205                 rec_video_nsec = 0;
206         }
207
208         QDateTime nowTime = QDateTime::currentDateTime();
209         QString tmps = nowTime.toString(QString::fromUtf8("yyyy-MM-dd_hh-mm-ss.zzz."));
210         QString path = QString::fromUtf8("Saved_Movie_") + tmps + QString::fromUtf8("mp4");
211         //QString path = QString::fromUtf8("Saved_Movie_") + tmps + QString::fromUtf8("mkv");
212         path = QString::fromLocal8Bit((const char *)this->get_app_path()) + path;
213         int rate = this->get_sound_rate();
214
215         emit sig_save_as_movie(path, fps, rate);
216         now_record_video = true;
217         return true;
218 }
219
220 void OSD_BASE::do_start_record_video()
221 {
222         now_record_video = true;
223 }       
224
225 void OSD_BASE::stop_record_video()
226 {
227         now_record_video = false;
228         //rec_video_nsec = 0;
229         emit sig_stop_saving_movie();
230 }
231
232 void OSD_BASE::restart_record_video()
233 {
234         bool tmp = now_record_video;
235         stop_record_video();
236         if(tmp) {
237                 start_record_video(-1);
238         }
239 }
240
241 void OSD_BASE::add_extra_frames(int extra_frames)
242 {
243         //rec_video_run_frames += extra_frames;
244         rec_video_nsec += ((int)(1.0e9 / vm_frame_rate()) * extra_frames);
245         if(rec_video_nsec < 0) rec_video_nsec = 0;
246         //emit sig_send_wxita_frames(extra_frames);
247 }
248
249
250 void OSD_BASE::upload_bitmap(QImage *p)
251 {
252         if(!using_flags->is_use_one_board_computer()) return;
253         if(p != NULL) {
254                 background_image = QImage(*p);
255                 rec_image_buffer = QImage(*p);
256         }
257 }
258
259 void OSD_BASE::set_buttons()
260 {
261         if(!using_flags->is_use_one_board_computer()) return;
262         
263         button_desc_t *vm_buttons_d = using_flags->get_vm_buttons();
264         if(vm_buttons_d != NULL) {
265                 for(int i = 0; i < using_flags->get_max_button(); i++) {
266                         QString tmps;
267                         tmps = QString::asprintf(":/button%02d.png", i);
268                         QImageReader *reader = new QImageReader(tmps);
269                         QImage *result = new QImage(reader->read());
270                         QImage pic;
271                         if(result != NULL) {
272                                 if(!result->isNull()) {
273                                         pic = result->convertToFormat(QImage::Format_ARGB32);
274                                 } else {
275                                         pic = QImage(10, 10, QImage::Format_RGBA8888);
276                                         pic.fill(QColor(0,0,0,0));
277                                 }
278                                 delete result;
279                         }else {
280                                 pic = QImage(10, 10, QImage::Format_RGBA8888);
281                                 pic.fill(QColor(0,0,0,0));
282                         }
283                         button_images[i] = pic;
284                 }
285         }
286
287         QRgb pixel;
288         if(vm_buttons_d != NULL) {
289                 for(int ii = 0; ii < using_flags->get_max_button(); ii++) {
290                         int ww = button_images[ii].width();
291                         int hh = button_images[ii].height();
292                         for(int yy = 0; yy < hh; yy++) {
293                                 for(int xx = 0; xx < ww; xx++) {
294                                         pixel = button_images[ii].pixel(xx, yy);
295                                         int xxx = vm_buttons_d[ii].x + xx;
296                                         int yyy = vm_buttons_d[ii].y + yy;
297                                         background_image.setPixel(xxx, yyy, pixel);
298                                 }
299                         }
300                 }
301         }
302
303 }
304
305 int OSD_BASE::add_video_frames()
306 {
307         //static double frames = 0;
308         //static int prev_video_fps = -1;
309         int counter = 0;
310         //static double prev_vm_fps = -1;
311         double vm_fps = vm_frame_rate();
312         int delta_ns = (int)(1.0e9 / vm_fps);
313         //if(rec_video_fps_nsec >= delta_ns) {
314         if(delta_ns == rec_video_fps_nsec) {
315                 rec_video_nsec += delta_ns;
316                 if(rec_video_nsec > (rec_video_fps_nsec * 2)) {
317                         rec_video_nsec -= rec_video_fps_nsec;
318                 } else if(rec_video_nsec < (rec_video_fps_nsec * -2)) {
319                         rec_video_nsec += rec_video_fps_nsec;
320                 }
321                 while(rec_video_nsec > rec_video_fps_nsec) {
322                         rec_video_nsec -= rec_video_fps_nsec;
323                         counter++;
324                 }
325         } else { // Will branch whether rec_video_fps_nsec >= delta_ns ?
326                 rec_video_nsec += delta_ns;
327                 if(rec_video_nsec > (rec_video_fps_nsec * 2)) {
328                         rec_video_nsec -= rec_video_fps_nsec;
329                 } else if(rec_video_nsec < (rec_video_fps_nsec * -2)) {
330                         rec_video_nsec += rec_video_fps_nsec;
331                 }
332                 while(rec_video_nsec >= rec_video_fps_nsec) {
333                         rec_video_nsec -= rec_video_fps_nsec;
334                         counter++;
335                 }
336         }
337         
338         if(using_flags->is_use_one_board_computer()) {
339                 //int size = vm_screen_buffer.pImage.byteCount();
340                 int i = counter;
341                 rec_image_buffer = QImage(background_image);
342                 QImage *video_result = &(vm_screen_buffer.pImage);
343                 QRgb pixel;
344                 int ww = video_result->width();
345                 int hh = video_result->height();
346                 //printf("%d x %d\n", ww, hh);
347                 for(int yy = 0; yy < hh; yy++) {
348                         for(int xx = 0; xx < ww; xx++) {
349                                 pixel = video_result->pixel(xx, yy);
350 #if defined(__LITTLE_ENDIAN__)
351                                 pixel |= 0xff000000;
352                                 if(pixel != 0xff000000) {
353                                         rec_image_buffer.setPixel(xx, yy, pixel);
354                                 }
355 #else
356                                 pixel |= 0x000000ff;
357                                 if(pixel != 0x000000ff) {
358                                         rec_image_buffer.setPixel(xx, yy, pixel);
359                                 }
360 #endif                          
361                         }
362                 }
363                 if(i > 0) {
364                         // Enqueue to frame.
365                         emit sig_enqueue_video(i, background_image.width(), background_image.height(), &rec_image_buffer);
366                         //i--;
367                 }
368         } else {
369                 //int size = vm_screen_buffer.pImage.byteCount();
370                 int i = counter;
371                 QImage video_result = QImage(vm_screen_buffer.pImage);
372                 // Rescaling
373                 if(i > 0) {
374                         // Enqueue to frame.
375                         emit sig_enqueue_video(i, vm_screen_width, vm_screen_height, &video_result);
376                         //i--;
377                 }
378                 debug_log(CSP_LOG_DEBUG2, CSP_LOG_TYPE_SCREEN,  "Push Video %d frames\n", counter);
379         }
380         return counter;
381 }
382
383
384 //#ifdef USE_PRINTER
385 void OSD_BASE::create_bitmap(bitmap_t *bitmap, int width, int height)
386 {
387         QRect rect;
388         QColor col = QColor(0, 0, 0, 255);
389         initialize_screen_buffer(bitmap, width, height, 0); // HALFTONE
390         bitmap->hPainter.begin(&(bitmap->pImage));
391         bitmap->hPainter.fillRect(0, 0, width, height, col);
392         bitmap->hPainter.end();
393         debug_log(CSP_LOG_DEBUG, CSP_LOG_TYPE_PRINTER, "Create bitmap: %08x %d x %d", bitmap, width, height);
394 }
395
396 void OSD_BASE::release_bitmap(bitmap_t *bitmap)
397 {
398         release_screen_buffer(bitmap);
399         debug_log(CSP_LOG_DEBUG, CSP_LOG_TYPE_PRINTER, "Release bitmap: %08x", bitmap);
400 }
401
402 void OSD_BASE::create_font(font_t *font, const _TCHAR *family, int width, int height, int rotate, bool bold, bool italic)
403 {
404         QString fontName;
405         fontName = QString::fromUtf8((const char *)family);
406         if(fontName == QString::fromUtf8("Gothic")) {
407                 fontName = QString::fromUtf8("Sans Serif");
408         } else if(fontName == QString::fromUtf8("Mincho")) {
409                 fontName = QString::fromUtf8("Serif");
410         } else {
411                 //fontName = QString::fromUtf8("Sans Serif");
412                 fontName = QString::fromUtf8((const char *)family);
413         }
414         font->hFont = QFont(fontName);
415         font->hFont.setPixelSize(height);
416         //font->hFont.setFixedPitch(true);
417         font->hFont.setItalic(italic);
418         font->hFont.setBold(bold);      
419         QFontMetrics metric(font->hFont);
420         font->hFont.setStretch((width * 10000) / (metric.width("F") * 100));
421         font->rotate = rotate;
422         font->init_flag = true;
423         //debug_log(CSP_LOG_DEBUG, CSP_LOG_TYPE_PRINTER, "Create Font: Family=%s WIDTH=%d HEIGHT=%d",fontName.toUtf8().constData(), width, height);
424         // Qt uses substitution font if not found.
425 }
426
427 void OSD_BASE::release_font(font_t *font)
428 {
429         //debug_log(CSP_LOG_DEBUG, CSP_LOG_TYPE_PRINTER, "Release Font");
430 }
431
432 void OSD_BASE::create_pen(pen_t *pen, int width, uint8_t r, uint8_t g, uint8_t b)
433 {
434         pen->r = r;
435         pen->g = g;
436         pen->b = b;
437         pen->width = width;
438         pen->hPen = QPen(Qt::SolidLine);
439         QColor color = QColor(r, g, b, 255);
440         pen->hPen.setColor(color);
441         pen->hPen.setWidth(width);
442         //debug_log(CSP_LOG_DEBUG, CSP_LOG_TYPE_PRINTER, "Create PEN %08x to width=%d (RGB)=(%d,%d,%d)\n", pen, width, r, g, b);
443 }
444
445 void OSD_BASE::release_pen(pen_t *pen)
446 {
447         //debug_log(CSP_LOG_DEBUG, CSP_LOG_TYPE_PRINTER, "Release Pen %08x", pen);
448 }
449
450 void OSD_BASE::clear_bitmap(bitmap_t *bitmap, uint8_t r, uint8_t g, uint8_t b)
451 {
452         //lock_vm();
453         //debug_log(CSP_LOG_DEBUG, CSP_LOG_TYPE_PRINTER, "Clear bitmap %08x", bitmap);
454         draw_rectangle_to_bitmap(bitmap, 0, 0, bitmap->width, bitmap->height, r, g, b);
455         //unlock_vm();
456 }
457
458 int OSD_BASE::get_text_width(bitmap_t *bitmap, font_t *font, const char *text)
459 {
460         QFontMetrics fm(font->hFont);
461         QTextCodec *codec = QTextCodec::codecForName("Shift-JIS");
462         QString s = codec->toUnicode(text);
463         return fm.width(s);
464 }
465
466 void OSD_BASE::draw_text_to_bitmap(bitmap_t *bitmap, font_t *font, int x, int y, const _TCHAR *text, uint8_t r, uint8_t g, uint8_t b)
467 {
468         QColor col(r, g, b, 255);
469         QPoint loc = QPoint(x, y);
470         
471         QTextCodec *codec = QTextCodec::codecForName("Shift-JIS");
472         QString str = codec->toUnicode((char *)text);
473         bitmap->hPainter.begin(&(bitmap->pImage));
474         //bitmap->hPainter.setBackgroundMode(Qt::OpaqueMode);
475         bitmap->hPainter.setPen(col);
476         bitmap->hPainter.rotate((qreal)font->rotate);
477
478         bitmap->hPainter.setFont(font->hFont);
479         bitmap->hPainter.drawText(loc, str);
480         bitmap->hPainter.end();
481         //debug_log(CSP_LOG_DEBUG, CSP_LOG_TYPE_PRINTER, "Draw Text to BITMAP %08x : (%d,%d) %s : Color(%d,%d,%d)", bitmap, x, y, str.toUtf8().constData(), r, g, b);
482 }
483
484 void OSD_BASE::draw_line_to_bitmap(bitmap_t *bitmap, pen_t *pen, int sx, int sy, int ex, int ey)
485 {
486         QLine line(sx, sy, ex, ey);
487         bitmap->hPainter.begin(&(bitmap->pImage));
488         //bitmap->hPainter.setBackgroundMode(Qt::TransparentMode);
489         bitmap->hPainter.setPen(pen->hPen);
490         bitmap->hPainter.drawLine(line);
491         bitmap->hPainter.end();
492         //debug_log(CSP_LOG_DEBUG, CSP_LOG_TYPE_PRINTER, "Draw Line from (%d,%d) to (%d,%d) to BITMAP %08x", sx, sy, ex, ey, bitmap);
493 }
494
495 void OSD_BASE::draw_point_to_bitmap(bitmap_t *bitmap, int x, int y, uint8_t r, uint8_t g, uint8_t b)
496 {
497         QPoint point(x, y);
498         QColor d_col(r, g, b);
499         QPen d_pen(d_col);
500         bitmap->hPainter.begin(&(bitmap->pImage));
501         //bitmap->hPainter.setBackgroundMode(Qt::OpaqueMode);
502         bitmap->hPainter.setPen(d_pen);
503         bitmap->hPainter.drawPoint(point);
504         bitmap->hPainter.end();
505         //debug_log(CSP_LOG_DEBUG, CSP_LOG_TYPE_PRINTER, "Draw Point to BITMAP %08x :(%d,%d) Color=(%d,%d,%d)", bitmap, x, y, r, g, b);
506 }
507
508 void OSD_BASE::draw_rectangle_to_bitmap(bitmap_t *bitmap, int x, int y, int width, int height, uint8_t r, uint8_t g, uint8_t b)
509 {
510         QColor d_col(r, g, b, 255);
511         QBrush d_brush(d_col);
512         bitmap->hPainter.begin(&(bitmap->pImage));
513         //bitmap->hPainter.setBackgroundMode(Qt::OpaqueMode);
514         bitmap->hPainter.fillRect(x, y, width, height, d_brush);
515         bitmap->hPainter.end();
516         //debug_log(CSP_LOG_DEBUG, CSP_LOG_TYPE_PRINTER, "Draw Rect BITMAP %08x :from (%d,%d) size=(%d,%d) Color=(%d,%d,%d)", bitmap, x, y, width, height, r, g, b);
517 }
518
519 void OSD_BASE::stretch_bitmap(bitmap_t *dest, int dest_x, int dest_y, int dest_width, int dest_height, bitmap_t *source, int source_x, int source_y, int source_width, int source_height)
520 {
521         QRect src_r(source_x, source_y, source_width, source_height);
522         QRect dest_r(dest_x, dest_y, dest_width, dest_height);
523         dest->hPainter.begin(&(dest->pImage));
524         //dest->hPainter.setBackgroundMode(Qt::OpaqueMode);
525         dest->hPainter.drawImage(dest_r, source->pImage, src_r);
526         dest->hPainter.end();
527         //debug_log(CSP_LOG_DEBUG, CSP_LOG_TYPE_PRINTER, "Scale (%d,%d, %d, %d) to (%d,%d, %d, %d)", source_x, source_y, source_width, source_height,
528         //           dest_x, dest_y, dest_width, dest_height);
529 }
530 //#endif
531
532
533 void OSD_BASE::write_bitmap_to_file(bitmap_t *bitmap, const _TCHAR *file_path)
534 {
535         int comp_quality = 0;
536         bitmap->pImage.save(QString::fromUtf8((const char *)file_path), "PNG", comp_quality);
537         debug_log(CSP_LOG_DEBUG, CSP_LOG_TYPE_PRINTER, "Save (print outed) bitmap %08x to %s", bitmap, file_path);
538 }
539
540 int OSD_BASE::get_vm_window_width()
541 {
542         return vm_window_width;
543 }
544
545 int OSD_BASE::get_vm_window_height()
546 {
547         return vm_window_height;
548 }
549
550 int OSD_BASE::get_vm_window_width_aspect()
551 {
552         return vm_window_width_aspect;
553 }
554
555 int OSD_BASE::get_vm_window_height_aspect()
556 {
557         return vm_window_height_aspect;
558 }
559
560 void OSD_BASE::reload_bitmap()
561 {
562         first_invalidate = true;
563 }
564