OSDN Git Service

[Qt][MOVIE_SAVER] Record correct screen with one-board-computer, with background...
authorK.Ohta <whatisthis.sowhat@gmail.com>
Mon, 6 Jun 2016 16:54:36 +0000 (01:54 +0900)
committerK.Ohta <whatisthis.sowhat@gmail.com>
Mon, 6 Jun 2016 16:54:36 +0000 (01:54 +0900)
15 files changed:
source/src/qt/avio/movie_saver.cpp
source/src/qt/avio/movie_saver.h
source/src/qt/avio/movie_saver_audio.cpp
source/src/qt/avio/movie_saver_video.cpp
source/src/qt/common/emu_thread.cpp
source/src/qt/common/qt_utils.cpp
source/src/qt/gui/draw_thread.cpp
source/src/qt/gui/draw_thread.h
source/src/qt/gui/qt_gldraw.h
source/src/qt/gui/qt_glutil_gl2_0.cpp
source/src/qt/gui/qt_glutil_gl2_0.h
source/src/qt/osd.h
source/src/qt/osd_base.h
source/src/qt/osd_screen.cpp
source/src/qt/osd_wrapper.cpp

index 5fda0c8..8bd9d0c 100644 (file)
@@ -117,7 +117,7 @@ void MOVIE_SAVER::enqueue_video(QImage *p)
        if(p == NULL) return;
        uint32_t *pq;
        QImage *pp = new QImage(*p);
-       //AGAR_DebugLog(AGAR_LOG_DEBUG, "Movie: Enqueue video data %d bytes", p->byteCount());
+       //AGAR_DebugLog(AGAR_LOG_DEBUG, "Movie: Enqueue video data %d bytes %dx%d", pp->byteCount(), pp->width(), pp->height());
        video_data_queue.enqueue(pp);
 #endif   
 }
index fd08cf3..fb5435f 100644 (file)
@@ -28,12 +28,10 @@ extern "C" {
 
 // Copy from FFMPEG-3.0.2; doc/example/muxing.c .
 
-#define STREAM_DURATION   10.0
-#define STREAM_FRAME_RATE 25 /* 25 images/s */
 #define STREAM_PIX_FMT    AV_PIX_FMT_YUV420P /* default pix_fmt */
 
-#define SCALE_FLAGS SWS_BICUBIC
-//#define SCALE_FLAGS SWS_BILINEAR
+//#define SCALE_FLAGS SWS_BICUBLIN
+#define SCALE_FLAGS SWS_POINT
 
 // a wrapper around a single output AVStream
 typedef struct OutputStream {
index 8c24602..8b9a94f 100644 (file)
@@ -121,10 +121,6 @@ void *MOVIE_SAVER::get_audio_frame()
     int j, i, v;
     int16_t *q = (int16_t*)frame->data[0];
        int offset = 0;
-    /* check if we want to generate more frames */
-    //if (av_compare_ts(ost->next_pts, ost->st->codec->time_base,
-    //                  STREAM_DURATION, (AVRational){ 1, 1 }) >= 0)
-    //    return NULL;
        for(j = 0; j < frame->nb_samples; j++) {
                if(audio_remain <= 0) {
                        while(audio_data_queue.isEmpty()) {
index 71c2f43..0480194 100644 (file)
@@ -135,11 +135,6 @@ void *MOVIE_SAVER::get_video_frame(void)
        OutputStream *ost = &video_st;
     AVCodecContext *c = ost->st->codec;
 
-    /* check if we want to generate more frames */
-    //if (av_compare_ts(ost->next_pts, ost->st->codec->time_base,
-    //                  STREAM_DURATION, (AVRational){ 1, 1 }) >= 0)
-    //    return (void *)NULL;
-
     //if (c->pix_fmt != AV_PIX_FMT_YUV420P) {
         /* as we only generate a YUV420P picture, we must convert it
          * to the codec pixel format if needed */
index f13da44..744a54b 100644 (file)
@@ -1345,7 +1345,6 @@ void EmuThreadClass::doWork(const QString &params)
                        }
                        prev_skip = now_skip;
                        //printf("p_emu::RUN Frames = %d SKIP=%d Interval = %d NextTime = %d\n", run_frames, now_skip, interval, next_time);
-      
                        if(next_time > tick_timer.elapsed()) {
                                //  update window if enough time
                                draw_timing = false;
index e134a4b..39a671d 100644 (file)
@@ -29,6 +29,7 @@
 #include "draw_thread.h"
 
 #include "qt_gldraw.h"
+#include "qt_glutil_gl2_0.h"
 #include "agar_logger.h"
 
 #include "menu_disk.h"
@@ -277,8 +278,10 @@ void Ui_MainWindow::LaunchEmuThread(void)
        QImageReader *reader = new QImageReader(":/background.png");
        QImage *result = new QImage(reader->read()); // this acts as a default if the size is not matched
        glv->updateBitmap(result);
+       emu->get_osd()->upload_bitmap(result);
        delete result;
        delete reader;
+       emu->get_osd()->set_buttons();
 #endif
        AGAR_DebugLog(AGAR_LOG_DEBUG, "DrawThread : Start.");
        connect(hDrawEmu, SIGNAL(sig_draw_frames(int)), hRunEmu, SLOT(print_framerate(int)));
@@ -310,7 +313,9 @@ void Ui_MainWindow::LaunchEmuThread(void)
                        this, SLOT(resize_statusbar(int, int)));
        connect(hRunEmu, SIGNAL(sig_resize_uibar(int, int)),
                        this, SLOT(resize_statusbar(int, int)));
-       
+
+       connect(emu->get_osd(), SIGNAL(sig_req_encueue_video(int, int, int)),
+                       hDrawEmu, SLOT(do_req_encueue_video(int, int, int)));
        connect(hRunEmu, SIGNAL(sig_finished()), glv, SLOT(releaseKeyCode(void)));
        connect(hRunEmu, SIGNAL(sig_finished()), this, SLOT(delete_emu_thread()));
        objNameStr = QString("EmuDrawThread");
@@ -335,6 +340,7 @@ void Ui_MainWindow::LaunchEmuThread(void)
    
        connect(emu->get_osd(), SIGNAL(sig_enqueue_audio(int16_t*, int)), hSaveMovieThread, SLOT(enqueue_audio(int16_t *, int)));
        connect(emu->get_osd(), SIGNAL(sig_enqueue_video(QImage *)), hSaveMovieThread, SLOT(enqueue_video(QImage *)));
+       connect(glv->extfunc, SIGNAL(sig_push_image_to_movie(QImage *)), hSaveMovieThread, SLOT(enqueue_video(QImage *)));
        connect(this, SIGNAL(sig_quit_movie_thread()), hSaveMovieThread, SLOT(do_exit()));
 
        objNameStr = QString("EmuMovieThread");
index 47c9334..1e03359 100644 (file)
@@ -22,6 +22,7 @@
 #include "agar_logger.h"
 #include "mainwidget_base.h"
 #include "draw_thread.h"
+#include "qt_glutil_gl2_0.h"
 
 DrawThreadClass::DrawThreadClass(EMU *p, OSD *o, QObject *parent) : QThread(parent) {
        MainWindow = (Ui_MainWindowBase *)parent;
@@ -35,6 +36,11 @@ DrawThreadClass::DrawThreadClass(EMU *p, OSD *o, QObject *parent) : QThread(pare
        do_change_refresh_rate(screen->refreshRate());
        connect(screen, SIGNAL(refreshRateChanged(qreal)), this, SLOT(do_change_refresh_rate(qreal)));
        connect(this, SIGNAL(sig_update_screen(bitmap_t *)), glv, SLOT(update_screen(bitmap_t *)));
+       connect(this, SIGNAL(sig_push_frames_to_avio(int, int, int)), glv->extfunc, SLOT(paintGL_OffScreen(int, int, int)));
+       rec_frame_width = 640;
+       rec_frame_height = 480;
+       rec_frame_count = -1;
+
        bDrawReq = false;
 }
 
@@ -78,6 +84,11 @@ void DrawThreadClass::doWork(const QString &param)
                                emit sig_update_screen(draw_screen_buffer);
                        }
                }
+               if(rec_frame_count > 0) {
+                       emit sig_push_frames_to_avio(rec_frame_count,
+                                                                                rec_frame_width, rec_frame_height);
+                       rec_frame_count = -1;
+               }
                if(wait_count < 1.0f) {
                        msleep(1);
                        wait_count = wait_count + wait_refresh - 1.0f;
@@ -104,3 +115,9 @@ void DrawThreadClass::do_update_screen(bitmap_t *p)
        bDrawReq = true;
 }
        
+void DrawThreadClass::do_req_encueue_video(int count, int width, int height)
+{
+       rec_frame_width = width;
+       rec_frame_height = height;
+       rec_frame_count = count;
+}
index c9823f0..2a7b8d4 100644 (file)
@@ -35,6 +35,10 @@ class DrawThreadClass : public QThread {
        qreal wait_refresh;
        qreal wait_count;
        int wait_factor;
+       int rec_frame_count;
+       int rec_frame_width;
+       int rec_frame_height;
+       
  protected:
        QScreen *screen;
        int draw_frames;
@@ -53,11 +57,13 @@ public slots:
        void doDraw(bool flag);
        void do_change_refresh_rate(qreal rate);
        void do_update_screen(bitmap_t *p);
+       void do_req_encueue_video(int count, int width, int height);
 signals:
        int sig_draw_frames(int);
        int message_changed(QString);
        int sig_update_screen(bitmap_t *);
        int sig_draw_timing(bool);
+       int sig_push_frames_to_avio(int, int, int);
 };
 
 QT_END_NAMESPACE
index 7bac274..2fe109d 100644 (file)
@@ -64,13 +64,13 @@ class GLDrawClass: public QGLWidget
        QString filename_screen_pixmap;
        bool save_pixmap_req;
        void SaveToPixmap(void);
-       GLDraw_2_0 *extfunc;
        CSP_KeyTables *key_table;
 
 public:
        GLDrawClass(QWidget *parent = 0);
        ~GLDrawClass();
-
+       GLDraw_2_0 *extfunc;
+       
        QSize minimumSizeHint() const;
        QSize sizeHint() const;
        QSize getCanvasSize();
index 77f6977..fc4c6e1 100644 (file)
@@ -9,6 +9,10 @@
 
 //#include "emu.h"
 
+#include <QOpenGLFramebufferObject>
+#include <QOpenGLFramebufferObject>
+#include <QColor>
+
 #include "qt_gldraw.h"
 #include "agar_logger.h"
 #include "qt_glutil_gl2_0.h"
@@ -79,6 +83,13 @@ GLDraw_2_0::GLDraw_2_0(GLDrawClass *parent, EMU *emu) : QObject(parent)
        horiz_pixels = using_flags->get_screen_width();
        screen_width = 1.0;
        screen_height = 1.0;
+
+       offscreen_frame_buffer = NULL;
+       offscreen_frame_buffer_format = NULL;
+       rec_count = 0;
+       rec_width  = using_flags->get_screen_width();
+       rec_height = using_flags->get_screen_height();
+
 }
 
 GLDraw_2_0::~GLDraw_2_0()
@@ -648,7 +659,7 @@ void GLDraw_2_0::drawMain(QOpenGLShaderProgram *prg,
        if(texid != 0) {
                extfunc->glEnable(GL_TEXTURE_2D);
 
-               extfunc->glViewport(0, 0, p_wid->width(), p_wid->height());
+               //extfunc->glViewport(0, 0, p_wid->width(), p_wid->height());
                extfunc->glOrtho(-1.0f, 1.0f, -1.0f, 1.0f, -1.0, 1.0);
                extfunc->glBindTexture(GL_TEXTURE_2D, texid);
 
@@ -865,25 +876,36 @@ void GLDraw_2_0::resizeGL(int width, int height)
 void GLDraw_2_0::paintGL(void)
 {
        int i;
-       if(!crt_flag && !redraw_required) return;
-       if(p_emu != NULL) {
-               crt_flag = false;
-       }
-       redraw_required = false;
-       extfunc->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-       extfunc->glEnable(GL_DEPTH_TEST);
-       extfunc->glDisable(GL_BLEND);
-       if(using_flags->is_use_one_board_computer()) drawBitmapTexture();
-       drawButtons();
-       /*
-        * VRAMの表示:テクスチャ貼った四角形
-        */
-       drawScreenTexture();
-       extfunc->glDisable(GL_BLEND);
-       if(!using_flags->is_use_one_board_computer() && (using_flags->get_max_button() <= 0)) {
-               drawGrids();
+       if(crt_flag || redraw_required) { //return;
+               if(p_emu != NULL) {
+                       crt_flag = false;
+               }
+               redraw_required = false;
+               extfunc->glViewport(0, 0, p_wid->width(), p_wid->height());
+               extfunc->glOrtho(-1.0f, 1.0f, -1.0f, 1.0f, -1.0, 1.0);
+               
+               extfunc->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+               extfunc->glEnable(GL_DEPTH_TEST);
+               extfunc->glDisable(GL_BLEND);
+               if(using_flags->is_use_one_board_computer()) drawBitmapTexture();
+               drawButtons();
+               /*
+                * VRAMの表示:テクスチャ貼った四角形
+                */
+               drawScreenTexture();
+               extfunc->glDisable(GL_BLEND);
+               if(!using_flags->is_use_one_board_computer() && (using_flags->get_max_button() <= 0)) {
+                       drawGrids();
+               }
+               extfunc->glFlush();
        }
-       extfunc->glFlush();
+}
+
+void GLDraw_2_0::paintGL_OffScreen(int count, int w, int h)
+{
+       rec_count += count;
+       rec_width  = w;
+       rec_height = h;
 }
 
 void GLDraw_2_0::do_set_screen_multiply(float mul)
index 503a83b..57f1a33 100644 (file)
@@ -47,6 +47,8 @@ typedef struct {
 class EMU;
 class QEvent;
 class GLDrawClass;
+class QOpenGLFramebufferObject;
+class QOpenGLFramebufferObjectFormat;
 
 class GLDraw_2_0 : public QObject
 {
@@ -73,6 +75,10 @@ protected:
        int screen_texture_height;
        int screen_texture_height_old;
 
+       int rec_count;
+       int rec_width;
+       int rec_height;
+
        QOpenGLFunctions_2_0 *extfunc;
        VertexTexCoord_t vertexFormat[4];
        
@@ -121,7 +127,10 @@ protected:
        void drawBitmapTexture(void);
        bool crt_flag;
        bool redraw_required;
-       
+
+       QOpenGLFramebufferObject *offscreen_frame_buffer;
+       QOpenGLFramebufferObjectFormat *offscreen_frame_buffer_format;
+       QImage offscreen_image;
 public:
        GLDraw_2_0(GLDrawClass *parent, EMU *emu = 0);
        ~GLDraw_2_0();
@@ -161,5 +170,9 @@ public slots:
        void doSetGridsHorizonal(int lines, bool force);
        void doSetGridsVertical(int pixels, bool force);
        void updateBitmap(QImage *);
+       void paintGL_OffScreen(int count, int w, int h);
+
+signals:
+       int sig_push_image_to_movie(QImage *);
 };
 #endif // _QT_COMMON_GLUTIL_2_0_H
index 573e1a9..34b91cd 100644 (file)
@@ -13,6 +13,7 @@
 
 #include <QObject>
 #include <QString>
+#include <QImage>
 
 #include <SDL.h>
 #include "osd_base.h"
@@ -53,6 +54,7 @@ protected:
        int get_screen_width(void);
        int get_screen_height(void);
        int get_vm_buttons_code(int num);
+
 public:
        OSD();
        ~OSD();
@@ -72,7 +74,6 @@ public:
        int get_window_mode_height(int mode);
        QString get_vm_config_name(void);
        double vm_frame_rate(void);
-
 };
 QT_END_NAMESPACE
 
index ab8021f..5444012 100644 (file)
@@ -38,6 +38,7 @@
 #define SOCKET_BUFFER_MAX 0x100000
 #include "osd_types.h"
 
+#define N_MAX_BUTTONS 128
 
 #define WM_RESIZE  (WM_USER + 1)
 #define WM_SOCKET0 (WM_USER + 2)
@@ -61,6 +62,7 @@ class EMU;
 class VM;
 class FIFO;
 class CSP_KeyTables;
+class USING_FLAGS;
 
 QT_BEGIN_NAMESPACE
 class OSD_BASE : public QThread
@@ -71,11 +73,10 @@ protected:
        QSemaphore *VMSemaphore;
        QSemaphore *DebugSemaphore;
        sdl_snddata_t snddata;
-//private:
+
        _TCHAR app_path[_MAX_PATH];
        QElapsedTimer osd_timer;
        bool locked_vm;
-       
        // console
        FILE *hStdIn, *hStdOut;
        QString console_cmd_str;
@@ -113,6 +114,10 @@ protected:
        int mouse_oldy;
        Qt::CursorShape mouse_shape;
        
+       QImage background_image;
+       QImage button_images[N_MAX_BUTTONS];
+       QImage rec_image_buffer;
+       
        // printer
        
        // screen
@@ -143,14 +148,9 @@ protected:
        double rec_video_run_frames;
        double rec_video_frames;
        
-       //LPBITMAPINFO lpDibRec;
-       //PAVIFILE pAVIFile;
-       //PAVISTREAM pAVIStream;
-       //PAVISTREAM pAVICompressed;
-       //AVICOMPRESSOPTIONS AVIOpts;
        uint64_t dwAVIFileSize;
        uint64_t lAVIFrames;
-       //HANDLE hVideoThread;
+
        rec_video_thread_param_t rec_video_thread_param;
        
        bool first_draw_screen;
@@ -190,23 +190,6 @@ protected:
        void initialize_video();
        void release_video();
        
-       //IGraphBuilder *pGraphBuilder;
-       //IBaseFilter *pVideoBaseFilter;
-       //IBaseFilter *pCaptureBaseFilter;
-       //ICaptureGraphBuilder2 *pCaptureGraphBuilder2;
-       //ISampleGrabber *pVideoSampleGrabber;
-       //IBaseFilter *pSoundBaseFilter;
-       //ISampleGrabber *pSoundSampleGrabber;
-       //CMySampleGrabberCB *pSoundCallBack;
-       //IMediaControl *pMediaControl;
-       //IMediaSeeking *pMediaSeeking;
-       //IMediaPosition *pMediaPosition;
-       //IVideoWindow *pVideoWindow;
-       //IBasicVideo *pBasicVideo;
-       //IBasicAudio *pBasicAudio;
-       //bool bTimeFormatFrame;
-       //bool bVerticalReversed;
-       
        bitmap_t dshow_screen_buffer;
        int direct_show_width, direct_show_height;
        bool direct_show_mute[2];
@@ -437,7 +420,8 @@ public slots:
        void close_debugger_console();
        void do_close_debugger_thread();
        void do_assign_js_setting(int jsnum, int axis_idx, int assigned_value);
-       
+       void upload_bitmap(QImage *p);
+       void set_buttons();
 signals:
        int sig_update_screen(bitmap_t *);
        int sig_save_screen(const char *);
@@ -450,6 +434,7 @@ signals:
        int sig_movie_set_width(int);
        int sig_movie_set_height(int);
        int sig_debugger_finished();
+       int sig_req_encueue_video(int, int, int);
 };
 QT_END_NAMESPACE
 
index 896d1c9..4a5fbc4 100644 (file)
 
 #include "qt_gldraw.h"
 #include "osd.h"
+#include "menu_flags.h"
 
 #define REC_VIDEO_SUCCESS      1
 #define REC_VIDEO_FULL         2
 #define REC_VIDEO_ERROR                3
 
-
+extern USING_FLAGS *using_flags;
 
 void OSD_BASE::set_host_window_size(int window_width, int window_height, bool window_mode)
 {
@@ -239,6 +240,69 @@ void OSD_BASE::add_extra_frames(int extra_frames)
        rec_video_run_frames += extra_frames;
 }
 
+
+void OSD_BASE::upload_bitmap(QImage *p)
+{
+       if(!using_flags->is_use_one_board_computer()) return;
+       if(p != NULL) {
+               background_image = QImage(*p);
+               rec_image_buffer = QImage(*p);
+       }
+}
+
+void OSD_BASE::set_buttons()
+{
+       if(!using_flags->is_use_one_board_computer()) return;
+       
+       int i;
+       QImage *img;
+       QPainter *painter;
+       QColor col;
+       QRect rect;
+       QPen *pen;
+       QFont font = QFont(QString::fromUtf8("Sans"));
+       col.setRgb(0, 0, 0, 255);
+       pen = new QPen(col);
+       
+       button_desc_t *vm_buttons_d = using_flags->get_vm_buttons();
+       if(vm_buttons_d != NULL) {
+               for(i = 0; i < using_flags->get_max_button(); i++) {
+                       button_images[i] = QImage(vm_buttons_d[i].width, vm_buttons_d[i].height, QImage::Format_RGB32);
+                       img = &(button_images[i]);
+                       painter = new QPainter(img);
+                       painter->setRenderHint(QPainter::Antialiasing, true);
+                       col.setRgb(255, 255, 255, 255);
+                       if(strlen(vm_buttons_d[i].caption) <= 3) {
+                               font.setPixelSize(vm_buttons_d[i].width / 2); 
+                       } else {
+                               font.setPixelSize(vm_buttons_d[i].width / 4); 
+                       }
+                       painter->fillRect(0, 0, vm_buttons_d[i].width, vm_buttons_d[i].height, col);
+                       painter->setFont(font);
+                       //painter->setPen(pen);
+                       rect.setWidth(vm_buttons_d[i].width);
+                       rect.setHeight(vm_buttons_d[i].height);
+                       rect.setX(0);
+                       rect.setY(0);
+                       painter->drawText(rect, Qt::AlignCenter, QString::fromUtf8(vm_buttons_d[i].caption));
+                       delete painter;
+               }
+       }
+       delete pen;
+
+       QRgb pixel;
+       if(vm_buttons_d != NULL) {
+               for(int ii = 0; ii < using_flags->get_max_button(); ii++) {
+                       for(int yy = 0; yy < button_images[ii].height(); yy++) {
+                               for(int xx = 0; xx < button_images[ii].width(); xx++) {
+                                       pixel = button_images[ii].pixel(xx, yy);
+                                       background_image.setPixel(xx + vm_buttons_d[ii].x, yy + vm_buttons_d[ii].y, pixel);
+                               }
+                       }
+               }
+       }
+}
+
 int OSD_BASE::add_video_frames()
 {
        static double frames = 0;
@@ -260,26 +324,50 @@ int OSD_BASE::add_video_frames()
                        frames = vm_frame_rate() / rec_video_fps;
                }
        }
+
        while(rec_video_run_frames > 0) {
                rec_video_run_frames -= frames;
                rec_video_frames += frames;
                counter++;
        }
-       if(counter != 0) {
+
+       if(using_flags->is_use_one_board_computer()) {
                int size = vm_screen_buffer.pImage.byteCount();
                int i = counter;
-               // Rescaling
-               //QByteArray video_result(vm_screen_buffer.pImage.constBits(), size);
+               rec_image_buffer = QImage(background_image);
                QImage *video_result = &(vm_screen_buffer.pImage);
+               QRgb pixel;
+               for(int yy = 0; yy < video_result->height(); yy++) {
+                       for(int xx = 0; xx < video_result->width(); xx++) {
+                               pixel = video_result->pixel(xx, yy);
+                               pixel |= 0xff000000;
+                               if(pixel != 0xff000000) {
+                                       rec_image_buffer.setPixel(xx, yy, pixel);
+                               }
+                       }
+               }
                while(i > 0) {
                        // Enqueue to frame.
-                       emit sig_enqueue_video(video_result);
+                       emit sig_enqueue_video(&rec_image_buffer);
                        i--;
                }
+       } else {
+               if(counter != 0) {
+                       int size = vm_screen_buffer.pImage.byteCount();
+                       int i = counter;
+                       // Rescaling
+                       QImage *video_result = &(vm_screen_buffer.pImage);
+                       while(i > 0) {
+                               // Enqueue to frame.
+                               emit sig_enqueue_video(video_result);
+                               i--;
+                       }
+               }
        }
        return counter;
 }
 
+
 //#ifdef USE_PRINTER
 void OSD_BASE::create_bitmap(bitmap_t *bitmap, int width, int height)
 {
index f78d30c..7428b85 100644 (file)
@@ -274,6 +274,9 @@ void OSD::force_unlock_vm(void)
        locked_vm = false;
 }
 
+
+
+
 void OSD::set_draw_thread(DrawThreadClass *handler)
 {
        this->moveToThread(handler);