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
}
// 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 {
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()) {
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 */
}
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;
#include "draw_thread.h"
#include "qt_gldraw.h"
+#include "qt_glutil_gl2_0.h"
#include "agar_logger.h"
#include "menu_disk.h"
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)));
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");
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");
#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;
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;
}
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;
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;
+}
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;
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
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();
//#include "emu.h"
+#include <QOpenGLFramebufferObject>
+#include <QOpenGLFramebufferObject>
+#include <QColor>
+
#include "qt_gldraw.h"
#include "agar_logger.h"
#include "qt_glutil_gl2_0.h"
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()
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);
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)
class EMU;
class QEvent;
class GLDrawClass;
+class QOpenGLFramebufferObject;
+class QOpenGLFramebufferObjectFormat;
class GLDraw_2_0 : public QObject
{
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];
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();
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
#include <QObject>
#include <QString>
+#include <QImage>
#include <SDL.h>
#include "osd_base.h"
int get_screen_width(void);
int get_screen_height(void);
int get_vm_buttons_code(int num);
+
public:
OSD();
~OSD();
int get_window_mode_height(int mode);
QString get_vm_config_name(void);
double vm_frame_rate(void);
-
};
QT_END_NAMESPACE
#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)
class VM;
class FIFO;
class CSP_KeyTables;
+class USING_FLAGS;
QT_BEGIN_NAMESPACE
class OSD_BASE : public QThread
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;
int mouse_oldy;
Qt::CursorShape mouse_shape;
+ QImage background_image;
+ QImage button_images[N_MAX_BUTTONS];
+ QImage rec_image_buffer;
+
// printer
// screen
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;
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];
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 *);
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
#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)
{
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;
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)
{
locked_vm = false;
}
+
+
+
void OSD::set_draw_thread(DrawThreadClass *handler)
{
this->moveToThread(handler);