changeset d4e08e83f4fa in /z/repo/gem5
details: http://repo.gem5.org/gem5?cmd=changeset;node=d4e08e83f4fa
description:
        VNC: Add support for capturing frame buffer to file each time it is 
changed.

        When a change in the frame buffer from the VNC server is detected, the 
new
        frame is stored out to the m5out/frames_*/ directory.  Specifiy the flag
        "--frame-capture" when running configs/example/fs.py to enable this 
behavior.

diffstat:

 configs/example/fs.py     |   7 ++++++
 src/base/bitmap.cc        |  44 ++++++++++++++++++++++++++++---------
 src/base/bitmap.hh        |  15 ++++++++++++-
 src/base/vnc/VncServer.py |   1 +
 src/base/vnc/convert.cc   |  23 +++++++++++++++++--
 src/base/vnc/convert.hh   |  18 ++++++++++++---
 src/base/vnc/vncserver.cc |  54 +++++++++++++++++++++++++++++++++++++++++++++-
 src/base/vnc/vncserver.hh |  22 +++++++++++++++++++
 8 files changed, 163 insertions(+), 21 deletions(-)

diffs (truncated from 416 to 300 lines):

diff -r 3301137733cd -r d4e08e83f4fa configs/example/fs.py
--- a/configs/example/fs.py     Thu Dec 01 00:15:25 2011 -0800
+++ b/configs/example/fs.py     Thu Dec 01 00:15:26 2011 -0800
@@ -72,6 +72,10 @@
 # System options
 parser.add_option("--kernel", action="store", type="string")
 parser.add_option("--script", action="store", type="string")
+parser.add_option("--frame-capture", action="store_true",
+        help="Stores changed frame buffers from the VNC server to compressed "\
+        "files in the gem5 output directory")
+
 if buildEnv['TARGET_ISA'] == "arm":
     parser.add_option("--bare-metal", action="store_true",
                help="Provide the raw system without the linux specific bits")
@@ -205,4 +209,7 @@
 if options.timesync:
     root.time_sync_enable = True
 
+if options.frame_capture:
+    VncServer.frame_capture = True
+
 Simulation.run(options, root, test_sys, FutureClass)
diff -r 3301137733cd -r d4e08e83f4fa src/base/bitmap.cc
--- a/src/base/bitmap.cc        Thu Dec 01 00:15:25 2011 -0800
+++ b/src/base/bitmap.cc        Thu Dec 01 00:15:26 2011 -0800
@@ -36,6 +36,7 @@
  *
  * Authors: William Wang
  *          Ali Saidi
+ *          Chris Emmons
  */
 
 #include <cassert>
@@ -43,29 +44,50 @@
 #include "base/bitmap.hh"
 #include "base/misc.hh"
 
+const size_t Bitmap::sizeofHeaderBuffer = sizeof(Magic) + sizeof(Header) +
+                                        sizeof(Info);
+
 // bitmap class ctor
 Bitmap::Bitmap(VideoConvert::Mode _mode, uint16_t w, uint16_t h, uint8_t *d)
     : mode(_mode), height(h), width(w), data(d),
-    vc(mode, VideoConvert::rgb8888, width, height)
+    vc(mode, VideoConvert::rgb8888, width, height), headerBuffer(0)
 {
 }
 
+Bitmap::~Bitmap() {
+    if (headerBuffer)
+        delete [] headerBuffer;
+}
+
 void
-Bitmap::write(std::ostream *bmp)
+Bitmap::write(std::ostream *bmp) const
 {
     assert(data);
 
-    // For further information see: 
http://en.wikipedia.org/wiki/BMP_file_format
-    Magic  magic = {{'B','M'}};
-    Header header = {sizeof(VideoConvert::Rgb8888) * width * height , 0, 0, 
54};
-    Info   info = {sizeof(Info), width, height, 1,
-                   sizeof(VideoConvert::Rgb8888) * 8, 0,
-                   sizeof(VideoConvert::Rgb8888) * width * height, 1, 1, 0, 0};
+    // header is always the same for a bitmap object; compute the info once per
+    //   bitmap object
+    if (!headerBuffer) {
+        // For further information see:
+        //   http://en.wikipedia.org/wiki/BMP_file_format
+        Magic magic = {{'B','M'}};
+        Header header = {sizeof(VideoConvert::Rgb8888) * width * height,
+                                0, 0, 54};
+        Info info = {sizeof(Info), width, height, 1,
+                    sizeof(VideoConvert::Rgb8888) * 8, 0,
+                    sizeof(VideoConvert::Rgb8888) * width * height, 1, 1, 0, 
0};
 
-    bmp->write(reinterpret_cast<char*>(&magic),  sizeof(magic));
-    bmp->write(reinterpret_cast<char*>(&header), sizeof(header));
-    bmp->write(reinterpret_cast<char*>(&info),   sizeof(info));
+        char *p = headerBuffer = new char[sizeofHeaderBuffer];
+        memcpy(p, &magic, sizeof(Magic));
+        p += sizeof(Magic);
+        memcpy(p, &header, sizeof(Header));
+        p += sizeof(Header);
+        memcpy(p, &info,   sizeof(Info));
+    }
 
+    // 1.  write the header
+    bmp->write(headerBuffer, sizeofHeaderBuffer);
+
+    // 2.  write the bitmap data
     uint8_t *tmp = vc.convert(data);
     uint32_t *tmp32 = (uint32_t*)tmp;
 
diff -r 3301137733cd -r d4e08e83f4fa src/base/bitmap.hh
--- a/src/base/bitmap.hh        Thu Dec 01 00:15:25 2011 -0800
+++ b/src/base/bitmap.hh        Thu Dec 01 00:15:26 2011 -0800
@@ -36,6 +36,7 @@
  *
  * Authors: William Wang
  *          Ali Saidi
+ *          Chris Emmons
  */
 #ifndef __BASE_BITMAP_HH__
 #define __BASE_BITMAP_HH__
@@ -62,6 +63,9 @@
      */
     Bitmap(VideoConvert::Mode mode, uint16_t w, uint16_t h, uint8_t *d);
 
+    /** Destructor */
+    ~Bitmap();
+
     /** Provide the converter with the data that should be output. It will be
      * converted into rgb8888 and write out when write() is called.
      * @param d the data
@@ -71,7 +75,13 @@
     /** Write the provided data into the fstream provided
      * @param bmp stream to write to
      */
-    void write(std::ostream *bmp);
+    void write(std::ostream *bmp) const;
+
+    /** Gets a hash over the bitmap for quick comparisons to other bitmaps.
+     * @return hash of the bitmap
+     */
+    uint64_t getHash() const { return vc.getHash(data); }
+
 
   private:
     VideoConvert::Mode mode;
@@ -81,6 +91,9 @@
 
     VideoConvert vc;
 
+    mutable char *headerBuffer;
+    static const size_t sizeofHeaderBuffer;
+
     struct Magic
     {
         unsigned char magic_number[2];
diff -r 3301137733cd -r d4e08e83f4fa src/base/vnc/VncServer.py
--- a/src/base/vnc/VncServer.py Thu Dec 01 00:15:25 2011 -0800
+++ b/src/base/vnc/VncServer.py Thu Dec 01 00:15:26 2011 -0800
@@ -43,3 +43,4 @@
     type = 'VncServer'
     port = Param.TcpPort(5900, "listen port")
     number = Param.Int(0, "vnc client number")
+    frame_capture = Param.Bool(False, "capture changed frames to files")
diff -r 3301137733cd -r d4e08e83f4fa src/base/vnc/convert.cc
--- a/src/base/vnc/convert.cc   Thu Dec 01 00:15:25 2011 -0800
+++ b/src/base/vnc/convert.cc   Thu Dec 01 00:15:26 2011 -0800
@@ -67,7 +67,7 @@
 }
 
 uint8_t*
-VideoConvert::convert(uint8_t *fb)
+VideoConvert::convert(const uint8_t *fb) const
 {
     switch (inputMode) {
       case bgr565:
@@ -82,7 +82,7 @@
 }
 
 uint8_t*
-VideoConvert::m565rgb8888(uint8_t *fb, bool bgr)
+VideoConvert::m565rgb8888(const uint8_t *fb, bool bgr) const
 {
     uint8_t *out = new uint8_t[area() * sizeof(uint32_t)];
     uint32_t *out32 = (uint32_t*)out;
@@ -113,7 +113,7 @@
 
 
 uint8_t*
-VideoConvert::bgr8888rgb8888(uint8_t *fb)
+VideoConvert::bgr8888rgb8888(const uint8_t *fb) const
 {
     uint8_t *out = new uint8_t[area() * sizeof(uint32_t)];
     uint32_t *out32 = (uint32_t*)out;
@@ -136,4 +136,21 @@
 
     return out;
 }
+/*
+uint64_t
+VideoConvert::getHash(const uint8_t *fb) const
+{
+    const uint8_t *fb_e = fb + area();
 
+    uint64_t hash = 1;
+    while (fb < fb_e - 8) {
+        hash += *((const uint64_t*)fb);
+        fb += 8;
+    }
+
+    while (fb < fb_e) {
+        hash += *(fb++);
+    }
+
+    return hash;
+}*/
diff -r 3301137733cd -r d4e08e83f4fa src/base/vnc/convert.hh
--- a/src/base/vnc/convert.hh   Thu Dec 01 00:15:25 2011 -0800
+++ b/src/base/vnc/convert.hh   Thu Dec 01 00:15:26 2011 -0800
@@ -44,6 +44,7 @@
 #ifndef __BASE_VNC_CONVERT_HH__
 #define __BASE_VNC_CONVERT_HH__
 
+#include <zlib.h>
 #include "base/bitunion.hh"
 
 class VideoConvert
@@ -107,12 +108,21 @@
      * @param fb the frame buffer to convert
      * @return the converted data (user must free)
      */
-    uint8_t* convert(uint8_t *fb);
+    uint8_t* convert(const uint8_t *fb) const;
 
     /** Return the number of pixels that this buffer specifies
      * @return number of pixels
      */
-    int area() { return width * height; }
+    int area() const { return width * height; }
+
+    /**
+     * Returns a hash on the raw data.
+     *
+     * @return hash of the buffer
+     */
+    inline uint64_t getHash(const uint8_t *fb) const {
+        return adler32(0UL, fb, width * height);
+    }
 
   private:
 
@@ -121,7 +131,7 @@
      * @param fb the data to convert
      * @return converted data
      */
-    uint8_t* bgr8888rgb8888(uint8_t *fb);
+    uint8_t* bgr8888rgb8888(const uint8_t *fb) const;
 
     /**
      * Convert a bgr565 or rgb565 input to rgb8888.
@@ -129,7 +139,7 @@
      * @param bgr true if the input data is bgr565
      * @return converted data
      */
-    uint8_t* m565rgb8888(uint8_t *fb, bool bgr);
+    uint8_t* m565rgb8888(const uint8_t *fb, bool bgr) const;
 
     Mode inputMode;
     Mode outputMode;
diff -r 3301137733cd -r d4e08e83f4fa src/base/vnc/vncserver.cc
--- a/src/base/vnc/vncserver.cc Thu Dec 01 00:15:25 2011 -0800
+++ b/src/base/vnc/vncserver.cc Thu Dec 01 00:15:26 2011 -0800
@@ -43,7 +43,10 @@
  */
 
 #include <sys/ioctl.h>
+#include <sys/stat.h>
 #include <sys/termios.h>
+#include <sys/types.h>
+#include <fcntl.h>
 #include <poll.h>
 #include <unistd.h>
 
@@ -52,11 +55,14 @@
 
 #include "base/vnc/vncserver.hh"
 #include "base/atomicio.hh"
+#include "base/bitmap.hh"
 #include "base/misc.hh"
+#include "base/output.hh"
 #include "base/socket.hh"
 #include "base/trace.hh"
 #include "debug/VNC.hh"
 #include "sim/byteswap.hh"
+#include "sim/core.hh"
 
 using namespace std;
 
@@ -98,14 +104,14 @@
     : SimObject(p), listenEvent(NULL), dataEvent(NULL), number(p->number),
       dataFd(-1), _videoWidth(1), _videoHeight(1), clientRfb(0), 
keyboard(NULL),
       mouse(NULL), sendUpdate(false), videoMode(VideoConvert::UnknownMode),
-      vc(NULL)
+      vc(NULL), captureEnabled(p->frame_capture), captureCurrentFrame(0),
+      captureLastHash(0), captureBitmap(0)
 {
     if (p->port)
         listen(p->port);
 
     curState = WaitForProtocolVersion;
 
-
     // currently we only support this one pixel format
     // unpacked 32bit rgb (rgb888 + 8 bits of nothing/alpha)
     // keep it around for telling the client and making
_______________________________________________
gem5-dev mailing list
[email protected]
http://m5sim.org/mailman/listinfo/gem5-dev

Reply via email to