open source

This commit is contained in:
lvfulong
2020-11-11 16:17:13 +08:00
parent 4d989f3ecb
commit bc4ca748de
2441 changed files with 623057 additions and 2 deletions
@@ -0,0 +1,113 @@
#ifndef __JsVideo_h__
#define __JsVideo_h__
#include "../../JSInterface/JSInterface.h"
#include <JSObjBase.h>
#include <map>
#include <set>
#include <string>
#include "VideoCache.h"
#include <Image/JCVideo.h>
namespace laya
{
//#define SHOW_NOT_IMPLEMENT_LOG
#ifdef SHOW_NOT_IMPLEMENT_LOG
#define NOT_IMPLEMENT() do { LOGW("%s is not implemented", __FUNCTION__); } while(false);
#define NOT_IMPLEMENT_RET(value) do { LOGW("%s is not implemented", __FUNCTION__); } while(false); return value;
#else
#define NOT_IMPLEMENT()
#define NOT_IMPLEMENT_RET(value) return value;
#endif
class JSVideo : public JsObjBase, public JSObjNode
{
public:
static JsObjClassInfo JSCLSINFO;
static void exportJS();
JSVideo();
~JSVideo();
void AddEvent(const char* evtName);
void RemoveEvent(const char* evtName);
void _setDispatchEventFunc(JSValueAsParam emitFunc);
void Load();
void Play();
void Pause();
void Stop();
bool CanPlayType(const char* type);
void SetAutoplay(bool val);
bool GetAutoplay();
void SetX(double val);
double GetX();
void SetY(double val);
double GetY();
bool GetPaused();
bool GetLoop();
void SetLoop(bool value);
const char* GetSrc();
void SetSrc(const char* url);
double GetVideoWidth();
double GetVideoHeight();
double GetWidth();
void SetWidth(double val);
double GetHeight();
void SetHeight(double val);
double GetCurrentTime();
void SetCurrentTime(double val);
double GetDuration();
double GetVolume();
void SetVolume(double val);
void CallHandle(const char* evtName);
int32_t GetReadyState();
int getImageID();
void _releaseHandler();
private:
void Init();
void Dispose();
void LoadInternal(const std::string& path);
void LoadUrlOnDownloadEnd();
void DispatchEvtToJS(const std::string path);
private:
static int ms_handleIdx;
static std::set<std::string> ms_supportFormat;
VideoCache m_videoCache;
std::map<std::string, int> m_evtMap;
JsObjHandle m_dispatchHandle;
std::string m_src;
bool m_isDownloadWaitLoad;
bool m_isDownloadWaitPlay;
IVideoHandler* m_pVideoHandler; /// !! released it by JCVideo
JCVideo* m_pJCVideo;
int m_nID;
};
};
#endif
@@ -0,0 +1,248 @@
#ifdef ANDROID
#include "../../../CToJavaBridge.h"
#include "JSVideo.h"
namespace laya
{
static const char* s_className = "layaair/game/browser/LayaVideoPlayer";
std::set<std::string> JSVideo::ms_supportFormat = {
"video/mp4",
"video/ogg",
};
struct AndroidVideoHandler : public IVideoHandler
{
AndroidVideoHandler()
{
obj = nullptr;
}
virtual ~AndroidVideoHandler()
{
}
virtual bool isFrameUpdated()
{
bool ret = false;
if (obj == nullptr)
return ret ;
CToJavaBridge::GetInstance()->callObjRetMethod(obj, s_className, "isFrameAvailable", &ret);
return ret;
}
virtual void updateBitmapData(BitmapData* bitmapData)
{
if (obj == nullptr)
{
return;
}
int64_t ptr = reinterpret_cast<int64_t>(bitmapData);
// LOGI("[Debug][Video] ptr is %ld", ptr);
CToJavaBridge::GetInstance()->callObjVoidMethod(obj, s_className, "updateBitmap", ptr);
}
jobject obj;
};
static jobject& GetObj(IVideoHandler* videoHandler)
{
AndroidVideoHandler* pHandler = static_cast<AndroidVideoHandler*>(videoHandler);
return pHandler->obj;
}
static void EmptyObj(IVideoHandler* videoHandler)
{
AndroidVideoHandler* pHandler = static_cast<AndroidVideoHandler*>(videoHandler);
pHandler->obj = nullptr;
}
JSVideo::JSVideo()
{
Init();
// LOGI("[Debug][Video] call JSVideo");
AdjustAmountOfExternalAllocatedMemory(sizeof(JSVideo));
JCMemorySurvey::GetInstance()->newClass("JSVideo", sizeof(JSVideo), this);
m_pVideoHandler = new AndroidVideoHandler();
CToJavaBridge::GetInstance()->newObject(&(GetObj(m_pVideoHandler)), s_className, reinterpret_cast<intptr_t>(this));
m_pJCVideo->setVideoHandler(m_pVideoHandler);
// LOGI("[Debug][Video] create obj id is %d", GetObj(m_pVideoHandler));
}
JSVideo::~JSVideo()
{
Dispose();
JCMemorySurvey::GetInstance()->releaseClass("JSVideo", this);
}
void JSVideo::_releaseHandler()
{
CToJavaBridge::GetInstance()->disposeObject(GetObj(m_pVideoHandler), s_className, "Dispose");
EmptyObj(m_pVideoHandler);
}
void JSVideo::LoadInternal(const std::string& path)
{
// LOGI("%s", path.c_str());
// LOGI("[Debug][Video]call Load: obj id is %d", GetObj(m_pVideoHandler));
CToJavaBridge::GetInstance()->callObjVoidMethod(GetObj(m_pVideoHandler), s_className, "Load", path.c_str());
}
void JSVideo::Play()
{
if (m_isDownloadWaitLoad)
{
m_isDownloadWaitPlay = true;
return;
}
m_isDownloadWaitPlay = false;
CToJavaBridge::GetInstance()->callObjVoidMethod(GetObj(m_pVideoHandler), s_className, "Play");
}
void JSVideo::Pause()
{
m_isDownloadWaitPlay = false;
CToJavaBridge::GetInstance()->callObjVoidMethod(GetObj(m_pVideoHandler), s_className, "Pause");
}
void JSVideo::Stop()
{
}
bool JSVideo::GetPaused()
{
bool ret = false;
CToJavaBridge::GetInstance()->callObjRetMethod(GetObj(m_pVideoHandler), s_className, "IsPaused", &ret);
return ret;
}
bool JSVideo::GetLoop()
{
bool ret = false;
CToJavaBridge::GetInstance()->callObjRetMethod(GetObj(m_pVideoHandler), s_className, "IsLoop", &ret);
return ret;
}
void JSVideo::SetLoop(bool value)
{
CToJavaBridge::GetInstance()->callObjVoidMethod(GetObj(m_pVideoHandler), s_className, "SetLoop", value);
}
void JSVideo::SetAutoplay(bool value)
{
CToJavaBridge::GetInstance()->callObjVoidMethod(GetObj(m_pVideoHandler), s_className, "SetAutoplay", value);
}
bool JSVideo::GetAutoplay()
{
bool ret = false;
CToJavaBridge::GetInstance()->callObjRetMethod(GetObj(m_pVideoHandler), s_className, "IsAutoplay", &ret);
return ret;
}
void JSVideo::SetX(double val)
{
CToJavaBridge::GetInstance()->callObjVoidMethod(GetObj(m_pVideoHandler), s_className, "setX", (int)val);
}
double JSVideo::GetX()
{
return 0;
}
void JSVideo::SetY(double val)
{
CToJavaBridge::GetInstance()->callObjVoidMethod(GetObj(m_pVideoHandler), s_className, "setY", (int)val);
}
double JSVideo::GetY()
{
return 0;
}
double JSVideo::GetVideoWidth()
{
int ret = 0;
CToJavaBridge::GetInstance()->callObjRetMethod(GetObj(m_pVideoHandler), s_className, "getVideoWidth", &ret);
return (double)ret;
}
double JSVideo::GetVideoHeight()
{
int ret = 0;
CToJavaBridge::GetInstance()->callObjRetMethod(GetObj(m_pVideoHandler), s_className, "getVideoHeight", &ret);
return (double)ret;
}
double JSVideo::GetWidth()
{
return 0;
}
void JSVideo::SetWidth(double val)
{
CToJavaBridge::GetInstance()->callObjVoidMethod(GetObj(m_pVideoHandler), s_className, "setWidth", (int)val);
}
double JSVideo::GetHeight()
{
return 0;
}
void JSVideo::SetHeight(double val)
{
CToJavaBridge::GetInstance()->callObjVoidMethod(GetObj(m_pVideoHandler), s_className, "setHeight", (int)val);
}
double JSVideo::GetCurrentTime()
{
int ret = 0;
CToJavaBridge::GetInstance()->callObjRetMethod(GetObj(m_pVideoHandler), s_className, "getCurrentTime", &ret);
//LOGI("[Debug][Video] CurrentTime %d", ret);
return (double)(ret * 0.001);
}
/// \param [in] val - the unit is seconds
void JSVideo::SetCurrentTime(double val)
{
CToJavaBridge::GetInstance()->callObjVoidMethod(GetObj(m_pVideoHandler), s_className, "setCurrentTime", (int)(val * 1000));
}
double JSVideo::GetDuration()
{
int ret = 0;
CToJavaBridge::GetInstance()->callObjRetMethod(GetObj(m_pVideoHandler), s_className, "getDuration", &ret);
//LOGI("[Debug][Video] Duration %d", ret);
return (double)(ret * 0.001);
}
double JSVideo::GetVolume()
{
int ret = 0;
CToJavaBridge::GetInstance()->callObjRetMethod(GetObj(m_pVideoHandler), s_className, "getVolume", &ret);
return (double)ret;
}
void JSVideo::SetVolume(double val)
{
CToJavaBridge::GetInstance()->callObjVoidMethod(GetObj(m_pVideoHandler), s_className, "setVolume", val);
}
int32_t JSVideo::GetReadyState()
{
int32_t ret = 0;
CToJavaBridge::GetInstance()->callObjRetMethod(GetObj(m_pVideoHandler), s_className, "GetReadyState", &ret);
return ret;
}
};
#endif // ANDROID
@@ -0,0 +1,173 @@
#include "JSVideo.h"
#include "../../../JCScriptRuntime.h"
#include "../../../JCConch.h"
#include "../../../JCSystemConfig.h"
#include <LayaGL/JCLayaGLDispatch.h>
namespace laya
{
int JSVideo::ms_handleIdx = 0;
void JSVideo::Init()
{
m_pJCVideo = new JCVideo();
m_nID = JCConch::s_pConchRender->m_pImageManager->getImageID();
// LOGI("[Debug][Video] ID is %d", m_nID);
m_pJCVideo->setManager(JCConch::s_pConchRender->m_pFileResManager, JCConch::s_pConchRender->m_pImageManager);
m_isDownloadWaitLoad = false;
m_isDownloadWaitPlay = false;
m_src = "";
if (g_kSystemConfig.m_nThreadMODE == THREAD_MODE_DOUBLE)
{
JCScriptRuntime::s_JSRT->flushSharedCmdBuffer();
JCCommandEncoderBuffer* pCmd = JCScriptRuntime::s_JSRT->m_pRenderCmd;
pCmd->append(LAYA_CREATE_IMAGE_ON_RENDER_THREAD);
pCmd->append(m_nID);
pCmd->append((intptr_t)(m_pJCVideo));
}
else
{
JCConch::s_pConchRender->m_pImageManager->setImage(m_nID, m_pJCVideo);
}
}
void JSVideo::Dispose()
{
JCCommandEncoderBuffer* pCmd = JCScriptRuntime::s_JSRT->m_pGCCmd;
pCmd->append(LAYA_DELETE_IMAGE_ON_RENDER_THREAD);
pCmd->append(m_nID);
}
void JSVideo::Load()
{
if (m_videoCache.IsDownloaded(m_src.c_str()))
{
m_isDownloadWaitPlay = false;
const std::string localPath = m_videoCache.GetCacheFilePath(m_src.c_str());
LoadInternal(localPath);
m_videoCache.CancelDownload();
}
else
{
m_isDownloadWaitPlay = true;
m_videoCache.DownloadFile(m_src.c_str());
m_videoCache.OnLastFileDownloaded(std::bind(&JSVideo::LoadUrlOnDownloadEnd, this));
}
}
bool JSVideo::CanPlayType(const char* type)
{
auto it = ms_supportFormat.find(type);
return it != ms_supportFormat.end();
}
const char* JSVideo::GetSrc()
{
return m_src.c_str();
}
void JSVideo::SetSrc(const char* url)
{
m_src = url;
Load();
}
int JSVideo::getImageID()
{
return m_nID;
}
void JSVideo::AddEvent(const char* evtName)
{
auto it = m_evtMap.find(evtName);
if (it == m_evtMap.end())
m_evtMap.insert(std::make_pair(evtName, 1));
else
it->second++;
}
void JSVideo::RemoveEvent(const char* evtName)
{
auto it = m_evtMap.find(evtName);
if (it != m_evtMap.end())
{
it->second--;
if (it->second == 0)
m_evtMap.erase(it);
}
}
void JSVideo::_setDispatchEventFunc(JSValueAsParam emitFunc)
{
m_dispatchHandle.set(0, this, emitFunc);
}
void JSVideo::CallHandle(const char* evtName)
{
std::string evt(evtName);
// LOGI("[Debug][Video]Call handle %s", evtName);
auto it = m_evtMap.find(evtName);
if (it != m_evtMap.end())
{
if(JCScriptRuntime::s_JSRT)
{
JCScriptRuntime::s_JSRT->m_pScriptThread->post(std::bind(&JSVideo::DispatchEvtToJS, this, evt));
}
}
}
void JSVideo::DispatchEvtToJS(const std::string evtName)
{
m_dispatchHandle.Call(evtName.c_str());
}
void JSVideo::LoadUrlOnDownloadEnd()
{
Load();
if (!m_isDownloadWaitLoad && m_isDownloadWaitPlay)
{
Play();
}
}
ADDJSCLSINFO(JSVideo, JSObjNode);
void JSVideo::exportJS()
{
JSP_CLASS("ConchVideo", JSVideo);
JSP_REG_CONSTRUCTOR(JSVideo);
JSP_ADD_METHOD("load", JSVideo::Load);
JSP_ADD_METHOD("play", JSVideo::Play);
JSP_ADD_METHOD("pause", JSVideo::Pause);
JSP_ADD_METHOD("stop", JSVideo::Stop);
JSP_ADD_METHOD("addEvent", JSVideo::AddEvent);
JSP_ADD_METHOD("removeEvent", JSVideo::RemoveEvent);
JSP_ADD_METHOD("_setDispatchEventFunc", JSVideo::_setDispatchEventFunc);
JSP_ADD_METHOD("_releaseHandler", JSVideo::_releaseHandler);
JSP_ADD_METHOD("canPlayType", JSVideo::CanPlayType);
JSP_ADD_PROPERTY_RO(paused, JSVideo, GetPaused);
JSP_ADD_PROPERTY(loop, JSVideo, GetLoop, SetLoop);
JSP_ADD_PROPERTY(x, JSVideo, GetX, SetX);
JSP_ADD_PROPERTY(y, JSVideo, GetY, SetY);
JSP_ADD_PROPERTY_RO(videoWidth, JSVideo, GetVideoWidth);
JSP_ADD_PROPERTY_RO(videoHeight, JSVideo, GetVideoHeight);
JSP_ADD_PROPERTY_RO(readyState, JSVideo, GetReadyState);
JSP_ADD_PROPERTY_RO(conchImgId, JSVideo, getImageID);
JSP_ADD_PROPERTY(autoplay, JSVideo, GetAutoplay, SetAutoplay);
JSP_ADD_PROPERTY(width, JSVideo, GetWidth, SetWidth);
JSP_ADD_PROPERTY(height, JSVideo, GetHeight, SetHeight);
JSP_ADD_PROPERTY(currentTime, JSVideo, GetCurrentTime, SetCurrentTime);
JSP_ADD_PROPERTY_RO(duration, JSVideo, GetDuration);
JSP_ADD_PROPERTY(src, JSVideo, GetSrc, SetSrc);
JSP_ADD_PROPERTY(currentSrc, JSVideo, GetSrc, SetSrc);
JSP_ADD_PROPERTY(volume, JSVideo, GetVolume, SetVolume);
JSP_INSTALL_CLASS("ConchVideo", JSVideo);
}
}
@@ -0,0 +1,252 @@
//
// JSVideo_IOSImpl.cpp
// conchRuntime
//
// Created by LayaBox on 2018/11/2.
// Copyright © 2018 LayaBox. All rights reserved.
//
#ifdef __APPLE__
#include "JSVideo.h"
#include "../../../CToObjectC.h"
namespace laya {
std::set<std::string> JSVideo::ms_supportFormat = {
"video/mp4",
};
struct IOSVideoHandler : public IVideoHandler
{
IOSVideoHandler()
{
obj = nullptr;
}
virtual ~IOSVideoHandler()
{
}
virtual bool isFrameUpdated()
{
if(!obj)
return false;
bool ret = false;
CToObjectVideoPlayerIsFrameUpdate(obj, &ret);
return ret;
}
virtual void updateBitmapData(BitmapData* bitmapData)
{
if(obj == nullptr)
return;
CToObjectVideoPlayerGetBitmap(obj, bitmapData);
}
void* obj;
};
static inline void* GetObj(IVideoHandler* videoHandler)
{
IOSVideoHandler* pHandler = static_cast<IOSVideoHandler*>(videoHandler);
return pHandler->obj;
}
static inline void** GetObjPtr(IVideoHandler* videoHandler)
{
IOSVideoHandler* pHandler = static_cast<IOSVideoHandler*>(videoHandler);
return &pHandler->obj;
}
static inline void EmptyObj(IVideoHandler* videoHandler)
{
IOSVideoHandler* pHandler = static_cast<IOSVideoHandler*>(videoHandler);
pHandler->obj = nullptr;
}
JSVideo::JSVideo()
{
Init();
AdjustAmountOfExternalAllocatedMemory(sizeof(JSVideo));
JCMemorySurvey::GetInstance()->newClass("JSVideo", sizeof(JSVideo), this);
m_pVideoHandler = new IOSVideoHandler(); // released it by JCVideo in render thread
CToObjectNewVideoPlayer(GetObjPtr(m_pVideoHandler), std::bind(&JSVideo::CallHandle, this, std::placeholders::_1));
m_pJCVideo->setVideoHandler(m_pVideoHandler);
}
JSVideo::~JSVideo()
{
Dispose();
JCMemorySurvey::GetInstance()->releaseClass("JSVideo", this);
}
void JSVideo::_releaseHandler()
{
CToObjectDisposeVideoPlayer(GetObj(m_pVideoHandler));
EmptyObj(m_pVideoHandler);
}
void JSVideo::LoadInternal(const std::string& path)
{
CToObjectVideoPlayerLoad(GetObj(m_pVideoHandler), path.c_str());
}
void JSVideo::Play()
{
if(m_isDownloadWaitLoad)
{
m_isDownloadWaitPlay = true;
return;
}
m_isDownloadWaitPlay = false;
CToObjectVideoPlayerPlay(GetObj(m_pVideoHandler));
}
void JSVideo::Pause()
{
m_isDownloadWaitPlay = false;
CToObjectVideoPlayerPause(GetObj(m_pVideoHandler));
}
void JSVideo::Stop()
{
NOT_IMPLEMENT();
}
bool JSVideo::GetPaused()
{
bool ret = false;
CToObjectVideoPlayerGetPaused(GetObj(m_pVideoHandler), &ret);
return ret;
}
bool JSVideo::GetLoop()
{
bool ret = false;
CToObjectVideoPlayerGetLoop(GetObj(m_pVideoHandler), &ret);
return ret;
}
void JSVideo::SetLoop(bool value)
{
CToObjectVideoPlayerSetLoop(GetObj(m_pVideoHandler), value);
}
void JSVideo::SetX(double val)
{
CToObjectVideoPlayerSetX(GetObj(m_pVideoHandler), val);
}
double JSVideo::GetX()
{
NOT_IMPLEMENT_RET(0);
}
void JSVideo::SetY(double val)
{
CToObjectVideoPlayerSetY(GetObj(m_pVideoHandler), val);
}
double JSVideo::GetY()
{
NOT_IMPLEMENT_RET(0);
}
double JSVideo::GetVideoWidth()
{
double ret = 0;
CToObjectVideoPlayerGetVideoWidth(GetObj(m_pVideoHandler), &ret);
return ret;
}
double JSVideo::GetVideoHeight()
{
double ret = 0;
CToObjectVideoPlayerGetVideoHeight(GetObj(m_pVideoHandler), &ret);
return ret;
}
double JSVideo::GetWidth()
{
double ret = 0;
CToObjectVideoPlayerGetWidth(GetObj(m_pVideoHandler), &ret);
return ret;
}
void JSVideo::SetWidth(double val)
{
CToObjectVideoPlayerSetWidth(GetObj(m_pVideoHandler), val);
}
double JSVideo::GetHeight()
{
double ret = 0;
CToObjectVideoPlayerGetHeight(GetObj(m_pVideoHandler), &ret);
return ret;
}
void JSVideo::SetHeight(double val)
{
CToObjectVideoPlayerSetHeight(GetObj(m_pVideoHandler), val);
}
double JSVideo::GetCurrentTime()
{
double ret = 0;
CToObjectVideoPlayerGetCurrentTime(GetObj(m_pVideoHandler), &ret);
return ret;
}
void JSVideo::SetCurrentTime(double val)
{
CToObjectVideoPlayerSetCurrentTime(GetObj(m_pVideoHandler), val);
}
double JSVideo::GetDuration()
{
double ret = 0;
CToObjectVideoPlayerGetDuration(GetObj(m_pVideoHandler), &ret);
return ret;
}
double JSVideo::GetVolume()
{
double ret = 0;
CToObjectVideoPlayerGetVolume(GetObj(m_pVideoHandler), &ret);
return ret;
}
void JSVideo::SetVolume(double val)
{
CToObjectVideoPlayerSetVolume(GetObj(m_pVideoHandler), val);
}
int32_t JSVideo::GetReadyState()
{
int32_t ret = 0;
CToObjectVideoPlayerGetReadyState(GetObj(m_pVideoHandler), &ret);
return ret;
}
void JSVideo::SetAutoplay(bool val)
{
CToObjectVideoPlayerSetAutoplay(GetObj(m_pVideoHandler), val);
}
bool JSVideo::GetAutoplay()
{
bool ret = false;
CToObjectVideoPlayerGetAutoplay(GetObj(m_pVideoHandler), &ret);
return ret;
}
};
#endif
@@ -0,0 +1,191 @@
#include "JSVideo.h"
#if (!defined ANDROID) && (!defined __APPLE__)
namespace laya
{
std::set<std::string> JSVideo::ms_supportFormat = {
//"video/mp4",
//"video/ogg",
//"video/webm"
};
class Win32VideoHandler final : public IVideoHandler
{
public:
Win32VideoHandler()
{
}
virtual ~Win32VideoHandler()
{
}
virtual bool isFrameUpdated()
{
NOT_IMPLEMENT_RET(false);
}
virtual void updateBitmapData(BitmapData* bitmapData)
{
NOT_IMPLEMENT();
}
};
JSVideo::JSVideo()
{
Init();
AdjustAmountOfExternalAllocatedMemory(sizeof(JSVideo));
JCMemorySurvey::GetInstance()->newClass("JSVideo", sizeof(JSVideo), this);
m_pVideoHandler = new Win32VideoHandler;
m_pJCVideo->setVideoHandler(m_pVideoHandler);
}
JSVideo::~JSVideo()
{
Dispose();
JCMemorySurvey::GetInstance()->releaseClass("JSVideo", this);
}
void JSVideo::_releaseHandler()
{
}
void JSVideo::LoadInternal(const std::string& path)
{
LOGI("%s", path.c_str());
CallHandle("loadedmetadata");
}
void JSVideo::Play()
{
NOT_IMPLEMENT();
}
void JSVideo::Pause()
{
NOT_IMPLEMENT();
}
void JSVideo::Stop()
{
NOT_IMPLEMENT();
}
bool JSVideo::GetPaused()
{
NOT_IMPLEMENT_RET(true);
}
bool JSVideo::GetLoop()
{
NOT_IMPLEMENT_RET(false);
}
void JSVideo::SetLoop(bool value)
{
NOT_IMPLEMENT();
}
void JSVideo::SetAutoplay(bool value)
{
NOT_IMPLEMENT();
}
bool JSVideo::GetAutoplay()
{
NOT_IMPLEMENT_RET(false);
}
double JSVideo::GetVideoWidth()
{
NOT_IMPLEMENT_RET(0);
}
double JSVideo::GetVideoHeight()
{
NOT_IMPLEMENT_RET(0);
}
double JSVideo::GetWidth()
{
NOT_IMPLEMENT_RET(0);
}
void JSVideo::SetWidth(double val)
{
NOT_IMPLEMENT();
}
double JSVideo::GetHeight()
{
NOT_IMPLEMENT_RET(0);
}
void JSVideo::SetHeight(double val)
{
}
double JSVideo::GetCurrentTime()
{
NOT_IMPLEMENT_RET(0);
}
void JSVideo::SetCurrentTime(double val)
{
NOT_IMPLEMENT();
}
double JSVideo::GetDuration()
{
NOT_IMPLEMENT_RET(0);
}
double JSVideo::GetVolume()
{
NOT_IMPLEMENT_RET(0);
}
void JSVideo::SetVolume(double val)
{
NOT_IMPLEMENT();
}
void JSVideo::SetX(double val)
{
NOT_IMPLEMENT();
}
double JSVideo::GetX()
{
NOT_IMPLEMENT_RET(0);
}
void JSVideo::SetY(double val)
{
NOT_IMPLEMENT();
}
double JSVideo::GetY()
{
NOT_IMPLEMENT_RET(0);
}
int32_t JSVideo::GetReadyState()
{
NOT_IMPLEMENT_RET(1);
}
};
#endif
@@ -0,0 +1,183 @@
#include "VideoCache.h"
#include <downloadMgr/JCDownloadMgr.h>
#include <resource/JCFileResManager.h>
#include "../../../JCScriptRuntime.h"
#include <fileSystem/JCFileSystem.h>
#include <downloadCache/JCServerFileCache.h>
namespace laya
{
enum UrlProtocol {
File,
Http,
Https,
Unknown,
};
struct UrlPair
{
const char* name;
UrlProtocol protocol;
};
static UrlProtocol GetUrlProtocol(const std::string& url)
{
static UrlPair urlPairs[] =
{
{ "file://", UrlProtocol::File },
{ "http://", UrlProtocol::Http },
{ "https://", UrlProtocol::Https },
};
static const int urlPairNum = 3;
for (int i = 0; i < urlPairNum; i++)
{
int pos = url.find_first_of(urlPairs[i].name);
if (pos != std::string::npos)
return urlPairs->protocol;
}
return UrlProtocol::Unknown;
}
std::map<std::string, std::string> VideoCache::ms_cachePathMap = std::map<std::string, std::string>();
VideoCache::VideoCache()
{
m_isDownloading = false;
m_onLastFileDownloaded = nullptr;
m_callbackRef.reset(new int(1));
}
bool VideoCache::IsDownloaded(const std::string& url)
{
auto it = ms_cachePathMap.find(url);
if (it == ms_cachePathMap.end())
return false;
const std::string& filePathUrl = it->second;
auto protocol = GetUrlProtocol(url);
if (protocol != UrlProtocol::File)
return true;
int pos = filePathUrl.find_first_of("://");
const std::string& filePath = filePathUrl.substr(pos + 3);
if (!fs::exists(filePath))
{
ms_cachePathMap.erase(it);
return false;
}
return true;
}
const std::string& VideoCache::GetCacheFilePath(const std::string& url)
{
auto it = ms_cachePathMap.find(url);
if (it == ms_cachePathMap.end())
return "";
else
return it->second;
}
void VideoCache::DownloadFile(const std::string& url)
{
if (IsDownloaded(url))
return;
if (m_isDownloading)
{
m_pendingUrls.push(url);
return;
}
m_isDownloading = true;
m_curDownloadUrl = url;
laya::JCFileRes* res = JCScriptRuntime::s_JSRT->m_pFileResMgr->getRes(m_curDownloadUrl);
std::weak_ptr<int> cbref(m_callbackRef);
res->setOnReadyCB(std::bind(&VideoCache::onDownloaded, this, std::placeholders::_1, cbref));
res->setOnErrorCB(std::bind(&VideoCache::onDownloadErr, this, std::placeholders::_1, std::placeholders::_2, cbref));
}
void VideoCache::CancelDownload()
{
m_onLastFileDownloaded = nullptr;
std::queue<std::string> empty;
m_pendingUrls.swap(empty);
}
void VideoCache::OnLastFileDownloaded(std::function<void()> callback)
{
m_onLastFileDownloaded = callback;
}
bool VideoCache::onDownloaded(void* p_pRes, std::weak_ptr<int> callbackref)
{
if (!callbackref.lock()) return false;
laya::JCResStateDispatcher* pRes = (laya::JCResStateDispatcher*)p_pRes;
laya::JCFileRes* pFileRes = (laya::JCFileRes*)pRes;
if (pFileRes->m_pBuffer.get() == NULL || pFileRes->m_nLength == 0)
{
return false;
}
JCBuffer p_buf;
p_buf.m_pPtr = pFileRes->m_pBuffer.get();
p_buf.m_nLen = pFileRes->m_nLength;
std::map<std::string, std::string>::iterator iter = ms_cachePathMap.find(m_curDownloadUrl);
std::string localFilePath;
std::string localFilePathUrl;
if (iter != ms_cachePathMap.end())
{
localFilePath = iter->second;
}
else
{
int p1 = m_curDownloadUrl.rfind('/');
int p2 = m_curDownloadUrl.rfind('\\');
int pos = std::max<int>(p1, p2);
std::string mediaFile = m_curDownloadUrl.substr(pos + 1, m_curDownloadUrl.length());
//去掉?后面的,因为可能增加版本号
int p3 = mediaFile.rfind('?');
char* sT = (char*)(mediaFile.c_str());
if (p3 != -1)
{
sT[p3] = 0;
}
unsigned int hash = JCCachedFileSys::hashRaw(m_curDownloadUrl.c_str());
char tmpBuf[32];
sprintf(tmpBuf, "%x_", hash);
localFilePath = JCScriptRuntime::s_JSRT->m_pFileResMgr->m_pFileCache->getAppPath() + "/" + tmpBuf + mediaFile;
writeFileSync(localFilePath.c_str(), p_buf);
localFilePathUrl = "file://" + localFilePath;
ms_cachePathMap[m_curDownloadUrl] = localFilePathUrl;
}
if (m_pendingUrls.size() > 0)
{
const std::string nextUrl = m_pendingUrls.front();
m_pendingUrls.pop();
DownloadFile(nextUrl);
}
else if(m_onLastFileDownloaded)
{
m_onLastFileDownloaded();
m_onLastFileDownloaded = nullptr;
}
return true;
}
bool VideoCache::onDownloadErr(void* p_pRes, int p_nErrCode, std::weak_ptr<int> callbackref)
{
if (!callbackref.lock())return false;
return true;
}
}
@@ -0,0 +1,36 @@
#pragma once
#include <string>
#include <map>
#include <queue>
#include <memory>
#include <functional>
namespace laya
{
class VideoCache
{
public:
VideoCache();
~VideoCache() {}
bool IsDownloaded(const std::string& url);
const std::string& GetCacheFilePath(const std::string& url);
void DownloadFile(const std::string& url);
void OnLastFileDownloaded(std::function<void()> callback);
void CancelDownload();
private:
bool onDownloaded(void* p_pRes, std::weak_ptr<int> callbackref);
bool onDownloadErr(void* p_pRes, int p_nErrCode, std::weak_ptr<int> callbackref);
private:
static std::map<std::string, std::string> ms_cachePathMap;
std::function<void()> m_onLastFileDownloaded;
std::shared_ptr<int> m_callbackRef;
std::queue<std::string> m_pendingUrls;
std::string m_curDownloadUrl;
bool m_isDownloading;
};
};