open source
This commit is contained in:
@@ -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;
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user