Merge pull request #12776 from fusijie/refine_capture

CaptureScreen save in thread.
This commit is contained in:
子龙山人 2015-07-10 17:03:18 +08:00
commit 3adecedcee
1 changed files with 54 additions and 15 deletions

View File

@ -28,6 +28,7 @@ THE SOFTWARE.
#include <stdlib.h> #include <stdlib.h>
#include "base/CCDirector.h" #include "base/CCDirector.h"
#include "base/CCAsyncTaskPool.h"
#include "renderer/CCCustomCommand.h" #include "renderer/CCCustomCommand.h"
#include "renderer/CCRenderer.h" #include "renderer/CCRenderer.h"
#include "platform/CCImage.h" #include "platform/CCImage.h"
@ -49,22 +50,39 @@ int ccNextPOT(int x)
namespace utils namespace utils
{ {
/** /**
* Capture screen implementation, don't use it directly. * Capture screen implementation, don't use it directly.
*/ */
void onCaptureScreen(const std::function<void(bool, const std::string&)>& afterCaptured, const std::string& filename) void onCaptureScreen(const std::function<void(bool, const std::string&)>& afterCaptured, const std::string& filename)
{ {
static bool startedCapture = false;
if (startedCapture)
{
CCLOG("Screen capture is already working");
if (afterCaptured)
{
afterCaptured(false, filename);
}
return;
}
else
{
startedCapture = true;
}
auto glView = Director::getInstance()->getOpenGLView(); auto glView = Director::getInstance()->getOpenGLView();
auto frameSize = glView->getFrameSize(); auto frameSize = glView->getFrameSize();
#if (CC_TARGET_PLATFORM == CC_PLATFORM_MAC) || (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32) || (CC_TARGET_PLATFORM == CC_PLATFORM_LINUX) #if (CC_TARGET_PLATFORM == CC_PLATFORM_MAC) || (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32) || (CC_TARGET_PLATFORM == CC_PLATFORM_LINUX)
frameSize = frameSize * glView->getFrameZoomFactor() * glView->getRetinaFactor(); frameSize = frameSize * glView->getFrameZoomFactor() * glView->getRetinaFactor();
#endif #endif
int width = static_cast<int>(frameSize.width); int width = static_cast<int>(frameSize.width);
int height = static_cast<int>(frameSize.height); int height = static_cast<int>(frameSize.height);
bool succeed = false; bool succeed = false;
std::string outputFile = ""; std::string outputFile = "";
do do
{ {
std::shared_ptr<GLubyte> buffer(new GLubyte[width * height * 4], [](GLubyte* p){ CC_SAFE_DELETE_ARRAY(p); }); std::shared_ptr<GLubyte> buffer(new GLubyte[width * height * 4], [](GLubyte* p){ CC_SAFE_DELETE_ARRAY(p); });
@ -72,10 +90,10 @@ void onCaptureScreen(const std::function<void(bool, const std::string&)>& afterC
{ {
break; break;
} }
glPixelStorei(GL_PACK_ALIGNMENT, 1); glPixelStorei(GL_PACK_ALIGNMENT, 1);
glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buffer.get()); glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buffer.get());
std::shared_ptr<GLubyte> flippedBuffer(new GLubyte[width * height * 4], [](GLubyte* p) { CC_SAFE_DELETE_ARRAY(p); }); std::shared_ptr<GLubyte> flippedBuffer(new GLubyte[width * height * 4], [](GLubyte* p) { CC_SAFE_DELETE_ARRAY(p); });
if (!flippedBuffer) if (!flippedBuffer)
{ {
@ -87,7 +105,7 @@ void onCaptureScreen(const std::function<void(bool, const std::string&)>& afterC
memcpy(flippedBuffer.get() + (height - row - 1) * width * 4, buffer.get() + row * width * 4, width * 4); memcpy(flippedBuffer.get() + (height - row - 1) * width * 4, buffer.get() + row * width * 4, width * 4);
} }
std::shared_ptr<Image> image(new Image); Image* image = new (std::nothrow) Image;
if (image) if (image)
{ {
image->initWithRawData(flippedBuffer.get(), width * height * 4, width, height, 8); image->initWithRawData(flippedBuffer.get(), width * height * 4, width, height, 8);
@ -100,15 +118,36 @@ void onCaptureScreen(const std::function<void(bool, const std::string&)>& afterC
CCASSERT(filename.find("/") == std::string::npos, "The existence of a relative path is not guaranteed!"); CCASSERT(filename.find("/") == std::string::npos, "The existence of a relative path is not guaranteed!");
outputFile = FileUtils::getInstance()->getWritablePath() + filename; outputFile = FileUtils::getInstance()->getWritablePath() + filename;
} }
succeed = image->saveToFile(outputFile);
// Save image in AsyncTaskPool::TaskType::TASK_IO thread, and call afterCaptured in mainThread
static bool succeedSaveToFile = false;
std::function<void(void*)> mainThread = [afterCaptured, outputFile](void* param)
{
if (afterCaptured)
{
afterCaptured(succeedSaveToFile, outputFile);
}
startedCapture = false;
};
AsyncTaskPool::getInstance()->enqueue(AsyncTaskPool::TaskType::TASK_IO, mainThread, (void*)NULL, [image, outputFile]()
{
succeedSaveToFile = image->saveToFile(outputFile);
delete image;
});
} }
}while(0); else
{
if (afterCaptured) CCLOG("Malloc Image memory failed!");
{ if (afterCaptured)
afterCaptured(succeed, outputFile); {
} afterCaptured(succeed, outputFile);
}
startedCapture = false;
}
} while (0);
} }
/* /*
* Capture screen interface * Capture screen interface
*/ */