[CEF1] A simple multithreaded offscreen renderer example

Built a cool app using CEF that you'd like to share with the community? Talk about it here.

[CEF1] A simple multithreaded offscreen renderer example

Postby Sga » Thu Jun 14, 2012 7:23 am

Hi everybody, I present you a (really) simple example made with CEF1.

Features:
  • console application
  • BMP output
  • one CPP file only
Requirements:
  • boost::thread
  • CEF1 libs/includes
  • resources and binaries:
    • "locales" folder
    • chrome.pak"
    • icudt.dll
    • libcef.dll

Here the full example source code, feel free to use it and modify it.

Code: Select all
/// link to: libcef_dll_wrapper.lib libcef.lib
#define BOOST_ALL_DYN_LINK
#define _WIN32_WINNT 0x0500
#include <iomanip>
#include "windows.h"
#include "boost/thread.hpp"
#include "include/cef_app.h"
#include "include/cef_client.h"

class OffscreenClient : public CefClient,
   public CefDisplayHandler,
   public CefLifeSpanHandler,
   public CefRequestHandler,
   public CefRenderHandler
{
public:
   OffscreenClient();
   virtual ~OffscreenClient();

   virtual CefRefPtr<CefLifeSpanHandler> GetLifeSpanHandler() OVERRIDE {
      return this;
   }
   virtual CefRefPtr<CefRequestHandler> GetRequestHandler() OVERRIDE {
      return this;
   }
   virtual CefRefPtr<CefRenderHandler> GetRenderHandler() OVERRIDE {
      return this;
   }

   void SaveBrowserImage(CefRefPtr<CefBrowser> browser, const std::string &filename);

   virtual void OnPaint(CefRefPtr<CefBrowser> browser, PaintElementType type,
      const RectList& dirtyRects, const void* buffer) OVERRIDE;

   // CefLifeSpanHandler methods
   virtual void OnAfterCreated(CefRefPtr<CefBrowser> browser) OVERRIDE;
   virtual void OnBeforeClose(CefRefPtr<CefBrowser> browser) OVERRIDE;

   CefRefPtr<CefBrowser> GetBrowser()
   {
      return m_browser;
   }

private:
   // The child browser window
   CefRefPtr<CefBrowser> m_browser;

   // Include the default reference counting implementation.
   IMPLEMENT_REFCOUNTING(OffscreenClient);
   // Include the default locking implementation.
   IMPLEMENT_LOCKING(OffscreenClient);
};

OffscreenClient::OffscreenClient()
{
}

OffscreenClient::~OffscreenClient()
{
}

void OffscreenClient::OnAfterCreated(CefRefPtr<CefBrowser> browser)
{
   AutoLock lock_scope(this);

   // keep browser reference
   m_browser = browser;
}

void OffscreenClient::OnBeforeClose(CefRefPtr<CefBrowser> browser)
{
   AutoLock lock_scope(this);

   // Free the browser pointer so that the browser can be destroyed
   m_browser = NULL;

   // quit message loop
   CefQuitMessageLoop();
}

void OffscreenClient::OnPaint(CefRefPtr<CefBrowser> browser, PaintElementType type, const RectList& dirtyRects, const void* buffer)
{
   static int s = 1;
   std::ostringstream oss;
   oss << std::setw(4) << std::setfill('0') << s++ << ".bmp";
   SaveBrowserImage(browser, oss.str());
}

void OffscreenClient::SaveBrowserImage(CefRefPtr<CefBrowser> browser, const std::string &filename)
{
   // Retrieve the image size.
   int width, height;
   if (!browser->GetSize(PET_VIEW, width, height))
      return;

   void* bits;

   // Populate the bitmap info header.
   BITMAPINFOHEADER info;
   info.biSize = sizeof(BITMAPINFOHEADER);
   info.biWidth = width;
   info.biHeight = -height;  // minus means top-down bitmap
   info.biPlanes = 1;
   info.biBitCount = 32;
   info.biCompression = BI_RGB;  // no compression
   info.biSizeImage = 0;
   info.biXPelsPerMeter = 1;
   info.biYPelsPerMeter = 1;
   info.biClrUsed = 0;
   info.biClrImportant = 0;

   // Create the bitmap and retrieve the bit buffer.
   HDC screen_dc = GetDC(NULL);
   HBITMAP bitmap = CreateDIBSection(screen_dc, reinterpret_cast<BITMAPINFO*>(&info), DIB_RGB_COLORS, &bits, NULL, 0);
   ReleaseDC(NULL, screen_dc);

   // Read the image into the bit buffer.
   if (bitmap == NULL)
      return;

   if (!browser->GetImage(PET_VIEW, width, height, bits))
      return;

   // Populate the bitmap file header.
   BITMAPFILEHEADER file;
   file.bfType = 0x4d42;
   file.bfSize = sizeof(BITMAPFILEHEADER);
   file.bfReserved1 = 0;
   file.bfReserved2 = 0;
   file.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);

   // Write the bitmap to file.
   HANDLE file_handle = CreateFile(filename.c_str(), GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
   if (file_handle != INVALID_HANDLE_VALUE)
   {
      DWORD bytes_written = 0;
      WriteFile(file_handle, &file, sizeof(file), &bytes_written, 0);
      WriteFile(file_handle, &info, sizeof(info), &bytes_written, 0);
      WriteFile(file_handle, bits, width * height * 4, &bytes_written, 0);
      CloseHandle(file_handle);
   }

   DeleteObject(bitmap);
}

void browser_thread(CefRefPtr<OffscreenClient> &client)
{
   // handle of current console
   HWND hWnd = GetConsoleWindow();

   // use this as the UI/main thread
   CefSettings settings;
   settings.multi_threaded_message_loop = false;

   // initialize CEF
   CefInitialize(settings, CefRefPtr<CefApp>());

   // set as offscreen renderer
   CefWindowInfo info;
   info.SetAsOffScreen(hWnd);

   client = new OffscreenClient();
   CefBrowserSettings browserSettings;

   // synchronous/blocking call
   CefBrowser::CreateBrowserSync(info, static_cast<CefRefPtr<CefClient>>(client), "http://www.google.com", browserSettings);

   // set default browser size
   client->GetBrowser()->SetSize(PET_VIEW, 800, 600);
   CefRunMessageLoop();

   // destroy client (it will call ~OffscreenClient())
   client = NULL;

   // shut down CEF
   CefShutdown();
}

int main()
{
   CefRefPtr<OffscreenClient> offscreenClient;

   // create browser in another thread
   boost::thread thread = boost::thread(browser_thread, boost::ref(offscreenClient));

   // wait for client creation
   while (!offscreenClient)
      Sleep(100);

   // wait for browser to be ready
   while (!offscreenClient->GetBrowser())
      Sleep(100);

   // wait for current URL (www.google.com) to show
   Sleep(4000);

   // load another URL
   offscreenClient->GetBrowser()->GetMainFrame()->LoadURL("www.youtube.com");
   Sleep(4000);

   // change window size
   offscreenClient->GetBrowser()->SetSize(PET_VIEW, 1024, 768);
   Sleep(4000);

   // close browser
   offscreenClient->GetBrowser()->CloseBrowser();

   // wait for thread to complete
   thread.join();

   return 0;
}
Sga
Techie
 
Posts: 11
Joined: Wed Jun 13, 2012 9:51 am

Re: [CEF1] A simple multithreaded offscreen renderer example

Postby tuma » Mon Jul 23, 2012 4:40 am

Is there equivalent example for MAC platform?
- tumapathy
tuma
Techie
 
Posts: 37
Joined: Fri May 11, 2012 3:26 am

Re: [CEF1] A simple multithreaded offscreen renderer example

Postby Sga » Mon Jul 23, 2012 4:48 am

I'm sorry but I do not have a Mac available for programming...
Sga
Techie
 
Posts: 11
Joined: Wed Jun 13, 2012 9:51 am

Re: [CEF1] A simple multithreaded offscreen renderer example

Postby Sachin » Mon Aug 27, 2012 5:25 am

I tried to use your simple example but while building I got the following linker errors.

Error 1 error LNK2019: unresolved external symbol "void __cdecl CefQuitMessageLoop(void)" (?CefQuitMessageLoop@@YAXXZ) referenced in function "public: virtual void __thiscall OffscreenClient::OnBeforeClose(class CefRefPtr<class CefBrowser>)" (?OnBeforeClose@OffscreenClient@@UAEXV?$CefRefPtr@VCefBrowser@@@@@Z) main.obj cef
Error 2 error LNK2019: unresolved external symbol __imp__DeleteObject@4 referenced in function "public: void __thiscall OffscreenClient::SaveBrowserImage(class CefRefPtr<class CefBrowser>,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)" (?SaveBrowserImage@OffscreenClient@@QAEXV?$CefRefPtr@VCefBrowser@@@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z) main.obj cef
Error 3 error LNK2019: unresolved external symbol __imp__ReleaseDC@8 referenced in function "public: void __thiscall OffscreenClient::SaveBrowserImage(class CefRefPtr<class CefBrowser>,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)" (?SaveBrowserImage@OffscreenClient@@QAEXV?$CefRefPtr@VCefBrowser@@@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z) main.obj cef

and few more.

I am linking libcef.lib and libcef_dll_wrapper.lib and doing all what you said but can't get away with these errors.
Can you please tell me what I am doing wrong?
Sachin
Newbie
 
Posts: 2
Joined: Mon Aug 27, 2012 5:18 am

Re: [CEF1] A simple multithreaded offscreen renderer example

Postby Sga » Mon Aug 27, 2012 10:25 am

I do not have my CEF working environment right now, so I have to guess.
Linker errors may be caused by a mismatch between your libcef_dll_wrapper.lib and your environment.
You may have to download the wrapper source and build the lib from scratch.
Sga
Techie
 
Posts: 11
Joined: Wed Jun 13, 2012 9:51 am

Re: [CEF1] A simple multithreaded offscreen renderer example

Postby Sachin » Tue Aug 28, 2012 2:54 am

I am now able to get away with those linker errors, but following new errors came up

Warning 1 Command line warning D9035 : option 'Wp64' has been deprecated and will be removed in a future release cl cefclient
Error 2 error LNK2005: "public: __thiscall std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >::~basic_string<char,struct std::char_traits<char>,class std::allocator<char> >(void)" (??1?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@XZ) already defined in libcef_dll_wrapper.lib(v8handler_cpptoc.obj) msvcprtd.lib cefclient
Error 3 error LNK2005: "public: __thiscall std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >(char const *)" (??0?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@PBD@Z) already defined in libcef_dll_wrapper.lib(v8handler_cpptoc.obj) msvcprtd.lib cefclient
Error 4 error LNK2005: "public: char const * __thiscall std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >::c_str(void)const " (?c_str@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QBEPBDXZ) already defined in libcef_dll_wrapper.lib(v8handler_cpptoc.obj) msvcprtd.lib cefclient
Error 5 error LNK2019: unresolved external symbol _WinMain@16 referenced in function ___tmainCRTStartup MSVCRTD.lib cefclient
Error 6 fatal error LNK1120: 1 unresolved externals c:\Users\sachjain\Documents\cef\Debug\cefclient.exe 1 cefclient

I guess, some problem with project settings.
Can you please tell me what's going wrong here?

Thanks for help.
Sachin
Newbie
 
Posts: 2
Joined: Mon Aug 27, 2012 5:18 am

Re: [CEF1] A simple multithreaded offscreen renderer example

Postby Sga » Tue Aug 28, 2012 3:35 am

You need to rebuild the libcef_dll_wrapper project to match your settings, follow the "dynamic linking section" here:

http://code.google.com/p/chromiumembedd ... eLibraries

Also, this topic may help:

http://magpcss.org/ceforum/viewtopic.ph ... ned+#p1808
Sga
Techie
 
Posts: 11
Joined: Wed Jun 13, 2012 9:51 am


Return to Apps Discussion

Who is online

Users browsing this forum: No registered users and 23 guests