mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-09-03 14:10:33 +03:00
Compare commits
10 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
3f53006c35 | ||
|
f9b30c0db3 | ||
|
a5278fc126 | ||
|
74413ca7d3 | ||
|
98e6c6d17b | ||
|
9491df8c1b | ||
|
d325cb7f57 | ||
|
24ee60ffd7 | ||
|
cea8d5c1ab | ||
|
fc867b96a5 |
@@ -1,7 +1,7 @@
|
||||
FoundationClasses TKernel TKMath
|
||||
ModelingData TKG2d TKG3d TKGeomBase TKBRep
|
||||
ModelingAlgorithms TKGeomAlgo TKTopAlgo TKPrim TKBO TKBool TKHLR TKFillet TKOffset TKFeat TKMesh TKXMesh TKShHealing
|
||||
Visualization TKService TKV3d TKOpenGl TKMeshVS TKIVtk TKD3DHost TKVulkan
|
||||
Visualization TKService TKV3d TKOpenGl TKMeshVS TKIVtk TKD3DHost
|
||||
ApplicationFramework TKCDF TKLCAF TKCAF TKBinL TKXmlL TKBin TKXml TKStdL TKStd TKTObj TKBinTObj TKXmlTObj TKVCAF
|
||||
DataExchange TKXSBase TKSTEPBase TKSTEPAttr TKSTEP209 TKSTEP TKIGES TKXCAF TKXDEIGES TKXDESTEP TKSTL TKVRML TKXmlXCAF TKBinXCAF
|
||||
Draw TKDraw TKTopTest TKViewerTest TKXSDRAW TKDCAF TKXDEDRAW TKTObjDRAW TKQADraw TKIVtkDraw DRAWEXE
|
||||
|
@@ -203,10 +203,10 @@ n Aspect
|
||||
n DsgPrs
|
||||
n Graphic3d
|
||||
n Image
|
||||
n Media
|
||||
n MeshVS
|
||||
n OpenGl
|
||||
n D3DHost
|
||||
n Vulkan
|
||||
n Prs3d
|
||||
n PrsMgr
|
||||
n Select3D
|
||||
@@ -224,7 +224,6 @@ r Shaders
|
||||
t TKMeshVS
|
||||
t TKOpenGl
|
||||
t TKD3DHost
|
||||
t TKVulkan
|
||||
t TKService
|
||||
t TKV3d
|
||||
n BinTObjDrivers
|
||||
|
@@ -58,9 +58,6 @@ if (USE_TCL)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Vulkan
|
||||
set (CSF_vulkan "vulkan-1")
|
||||
|
||||
if (WIN32)
|
||||
set (CSF_advapi32 "advapi32.lib")
|
||||
set (CSF_gdi32 "gdi32.lib")
|
||||
@@ -68,6 +65,7 @@ if (WIN32)
|
||||
set (CSF_shell32 "shell32.lib")
|
||||
set (CSF_wsock32 "wsock32.lib")
|
||||
set (CSF_psapi "psapi.lib")
|
||||
set (CSF_winmm "winmm.lib")
|
||||
set (CSF_d3d9 "D3D9.lib")
|
||||
if ("${CMAKE_SYSTEM_NAME}" STREQUAL "WindowsStore" OR USE_GLES2)
|
||||
set (CSF_OpenGlLibs "libEGL libGLESv2")
|
||||
|
@@ -1349,8 +1349,6 @@ proc osutils:csfList { theOS theCsfLibsMap theCsfFrmsMap } {
|
||||
set aLibsMap(CSF_LIBLZMA) "liblzma"
|
||||
}
|
||||
|
||||
set aLibsMap(CSF_vulkan) "vulkan-1"
|
||||
|
||||
if { "$theOS" == "wnt" } {
|
||||
# WinAPI libraries
|
||||
set aLibsMap(CSF_kernel32) "kernel32"
|
||||
@@ -1361,6 +1359,7 @@ proc osutils:csfList { theOS theCsfLibsMap theCsfFrmsMap } {
|
||||
set aLibsMap(CSF_opengl32) "opengl32"
|
||||
set aLibsMap(CSF_wsock32) "wsock32"
|
||||
set aLibsMap(CSF_netapi32) "netapi32"
|
||||
set aLibsMap(CSF_winmm) "winmm"
|
||||
set aLibsMap(CSF_OpenGlLibs) "opengl32"
|
||||
if { "$::HAVE_GLES2" == "true" } {
|
||||
set aLibsMap(CSF_OpenGlLibs) "libEGL libGLESv2"
|
||||
|
@@ -53,8 +53,11 @@ android {
|
||||
|
||||
# Define output folder depending on compiler name
|
||||
MY_BITNESS = 32
|
||||
|
||||
equals(QMAKE_TARGET.arch, x86_64) | equals(QMAKE_HOST.arch, x86_64) { MY_BITNESS = 64 }
|
||||
equals(ANDROID_TARGET_ARCH, arm64-v8a) { MY_BITNESS = 64 }
|
||||
has64Target = $$find(QMAKE_TARGET.arch, "x64")
|
||||
count(has64Target, 1) { MY_BITNESS = 64 }
|
||||
|
||||
MY_PLATFORM = platform
|
||||
CONFIG(iphonesimulator, iphoneos|iphonesimulator) { MY_PLATFORM = iphonesimulator
|
||||
@@ -89,11 +92,24 @@ android-g++ {
|
||||
} else:win32-msvc2017 {
|
||||
MY_COMPILER = vc14
|
||||
MY_VC_VER = 14
|
||||
} else:win32-msvc {
|
||||
MY_COMPILER = vc14
|
||||
MY_VC_VER = 14
|
||||
aMsvcVer = $$(VisualStudioVersion)
|
||||
equals(aMsvcVer, 14.0){
|
||||
# VS2015, vc140
|
||||
} else:equals(aMsvcVer, 15.0){
|
||||
# VS2015, vc141
|
||||
} else:equals(aMsvcVer, 16.0){
|
||||
# VS2019, vc142
|
||||
} else {
|
||||
warning (Unknown msvc version. "$$MY_COMPILER" is used)
|
||||
}
|
||||
} else {
|
||||
warning (Unknown compiler. "$$MY_COMPILER" is used)
|
||||
}
|
||||
MY_PLATFORM_AND_COMPILER = $$MY_PLATFORM/$$MY_COMPILER
|
||||
#message (The platform is "$$MY_PLATFORM"; bitness is "$$MY_BITNESS"; compiler is "$$MY_COMPILER")
|
||||
#warning (The platform is "$$MY_PLATFORM"; bitness is "$$MY_BITNESS"; compiler is "$$MY_COMPILER")
|
||||
|
||||
CONFIG(debug, debug|release) { MY_BUILDTYPE = d }
|
||||
|
||||
|
@@ -168,7 +168,7 @@ void AIS_Animation::StartTimer (const Standard_Real theStartPts,
|
||||
{
|
||||
if (myTimer.IsNull())
|
||||
{
|
||||
myTimer = new AIS_AnimationTimer();
|
||||
myTimer = new Media_Timer();
|
||||
}
|
||||
myTimer->Stop();
|
||||
myTimer->Seek (theStartPts);
|
||||
|
@@ -191,7 +191,7 @@ protected:
|
||||
|
||||
protected:
|
||||
|
||||
Handle(AIS_AnimationTimer) myTimer;
|
||||
Handle(Media_Timer) myTimer;
|
||||
|
||||
TCollection_AsciiString myName; //!< animation name
|
||||
NCollection_Sequence<Handle(AIS_Animation)>
|
||||
|
@@ -15,60 +15,7 @@
|
||||
#ifndef _AIS_AnimationTimer_HeaderFile
|
||||
#define _AIS_AnimationTimer_HeaderFile
|
||||
|
||||
#include <OSD_Timer.hxx>
|
||||
#include <Standard_Transient.hxx>
|
||||
#include <Standard_Type.hxx>
|
||||
|
||||
//! Auxiliary class defining the animation timer.
|
||||
class AIS_AnimationTimer : public Standard_Transient
|
||||
{
|
||||
DEFINE_STANDARD_RTTIEXT(AIS_AnimationTimer, Standard_Transient)
|
||||
public:
|
||||
|
||||
//! Empty constructor.
|
||||
AIS_AnimationTimer() : myTimerFrom (0.0), myTimerSpeed (1.0) {}
|
||||
|
||||
//! Return elapsed time in seconds.
|
||||
Standard_Real ElapsedTime() const
|
||||
{
|
||||
return myTimerFrom + myTimer.ElapsedTime() * myTimerSpeed;
|
||||
}
|
||||
|
||||
//! Return playback speed coefficient (1.0 means normal speed).
|
||||
Standard_Real PlaybackSpeed() const { return myTimerSpeed; }
|
||||
|
||||
//! Setup playback speed coefficient.
|
||||
Standard_EXPORT void SetPlaybackSpeed (const Standard_Real theSpeed);
|
||||
|
||||
//! Return true if timer has been started.
|
||||
Standard_Boolean IsStarted() const
|
||||
{
|
||||
return myTimer.IsStarted();
|
||||
}
|
||||
|
||||
//! Start the timer.
|
||||
void Start()
|
||||
{
|
||||
myTimer.Start();
|
||||
}
|
||||
|
||||
//! Pause the timer.
|
||||
Standard_EXPORT void Pause();
|
||||
|
||||
//! Stop the timer.
|
||||
Standard_EXPORT void Stop();
|
||||
|
||||
//! Seek the timer to specified position.
|
||||
Standard_EXPORT void Seek (const Standard_Real theTime);
|
||||
|
||||
protected:
|
||||
|
||||
OSD_Timer myTimer;
|
||||
Standard_Real myTimerFrom;
|
||||
Standard_Real myTimerSpeed;
|
||||
|
||||
};
|
||||
|
||||
DEFINE_STANDARD_HANDLE(AIS_AnimationTimer, Standard_Transient)
|
||||
#include <Media_Timer.hxx>
|
||||
typedef Media_Timer AIS_AnimationTimer;
|
||||
|
||||
#endif // _AIS_AnimationTimer_HeaderFile
|
||||
|
250
src/AIS/AIS_MediaPlayer.cxx
Normal file
250
src/AIS/AIS_MediaPlayer.cxx
Normal file
@@ -0,0 +1,250 @@
|
||||
// Created by: Kirill GAVRILOV
|
||||
// Copyright (c) 2019 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#include <AIS_MediaPlayer.hxx>
|
||||
|
||||
#include <AIS_InteractiveContext.hxx>
|
||||
#include <Media_PlayerContext.hxx>
|
||||
#include <Message.hxx>
|
||||
#include <Message_Messenger.hxx>
|
||||
#include <Graphic3d_ArrayOfTriangles.hxx>
|
||||
#include <Graphic3d_MediaTexture.hxx>
|
||||
#include <SelectMgr_EntityOwner.hxx>
|
||||
#include <Select3D_SensitivePrimitiveArray.hxx>
|
||||
#include <V3d_Viewer.hxx>
|
||||
|
||||
IMPLEMENT_STANDARD_RTTIEXT(AIS_MediaPlayer, AIS_InteractiveObject)
|
||||
|
||||
//! Create an array of triangles defining a rectangle.
|
||||
static Handle(Graphic3d_ArrayOfTriangles) createRectangleArray (const Graphic3d_Vec2i& theLower,
|
||||
const Graphic3d_Vec2i& theUpper,
|
||||
Graphic3d_ArrayFlags theFlags)
|
||||
{
|
||||
Handle(Graphic3d_ArrayOfTriangles) aRectTris = new Graphic3d_ArrayOfTriangles (4, 6, theFlags);
|
||||
aRectTris->AddVertex (gp_Pnt (theLower.x(), theLower.y(), 0.0), gp_Pnt2d (0.0, 1.0));
|
||||
aRectTris->AddVertex (gp_Pnt (theLower.x(), theUpper.y(), 0.0), gp_Pnt2d (0.0, 0.0));
|
||||
aRectTris->AddVertex (gp_Pnt (theUpper.x(), theUpper.y(), 0.0), gp_Pnt2d (1.0, 0.0));
|
||||
aRectTris->AddVertex (gp_Pnt (theUpper.x(), theLower.y(), 0.0), gp_Pnt2d (1.0, 1.0));
|
||||
aRectTris->AddEdges (1, 2, 3);
|
||||
aRectTris->AddEdges (1, 3, 4);
|
||||
return aRectTris;
|
||||
}
|
||||
|
||||
//================================================================
|
||||
// Function : AIS_MediaPlayer
|
||||
// Purpose :
|
||||
//================================================================
|
||||
AIS_MediaPlayer::AIS_MediaPlayer()
|
||||
: myFramePair (new Graphic3d_MediaTextureSet()),
|
||||
myFrameSize (1, 1),
|
||||
myToClosePlayer (false)
|
||||
{
|
||||
SetTransformPersistence (new Graphic3d_TransformPers (Graphic3d_TMF_2d, Aspect_TOTP_LEFT_LOWER));
|
||||
SetZLayer (Graphic3d_ZLayerId_TopOSD);
|
||||
SetInfiniteState (true);
|
||||
|
||||
Graphic3d_MaterialAspect aMat;
|
||||
myFrameAspect = new Graphic3d_AspectFillArea3d (Aspect_IS_SOLID, Quantity_NOC_WHITE, Quantity_NOC_BLACK, Aspect_TOL_SOLID, 1.0f, aMat, aMat);
|
||||
myFrameAspect->SetShadingModel (Graphic3d_TOSM_UNLIT);
|
||||
myFrameAspect->SetTextureMapOn (true);
|
||||
myFrameAspect->SetTextureSet (myFramePair);
|
||||
}
|
||||
|
||||
//================================================================
|
||||
// Function : ~AIS_MediaPlayer
|
||||
// Purpose :
|
||||
//================================================================
|
||||
AIS_MediaPlayer::~AIS_MediaPlayer()
|
||||
{
|
||||
// stop threads
|
||||
myFramePair.Nullify();
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : OpenInput
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void AIS_MediaPlayer::OpenInput (const TCollection_AsciiString& thePath,
|
||||
Standard_Boolean theToWait)
|
||||
{
|
||||
if (myFramePair->PlayerContext().IsNull()
|
||||
&& thePath.IsEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
myFramePair->OpenInput (thePath, theToWait);
|
||||
SynchronizeAspects();
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : PresentFrame
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
bool AIS_MediaPlayer::PresentFrame (const Graphic3d_Vec2i& theLeftCorner,
|
||||
const Graphic3d_Vec2i& theMaxSize)
|
||||
{
|
||||
if (myToClosePlayer)
|
||||
{
|
||||
myToClosePlayer = false;
|
||||
if (!HasInteractiveContext())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!myFramePair->PlayerContext().IsNull())
|
||||
{
|
||||
myFramePair->PlayerContext()->Pause();
|
||||
}
|
||||
|
||||
Handle(AIS_InteractiveContext) aCtx = GetContext();
|
||||
Handle(AIS_InteractiveObject) aThis = this;
|
||||
aCtx->Remove (aThis, false);
|
||||
aCtx->CurrentViewer()->Invalidate();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (myFramePair->PlayerContext().IsNull())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool toRedraw = myFramePair->SwapFrames();
|
||||
toRedraw = updateSize (theLeftCorner, theMaxSize) || toRedraw;
|
||||
if (toRedraw)
|
||||
{
|
||||
myFrameAspect->SetShaderProgram (myFramePair->ShaderProgram());
|
||||
SynchronizeAspects();
|
||||
}
|
||||
return toRedraw;
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : updateSize
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
bool AIS_MediaPlayer::updateSize (const Graphic3d_Vec2i& theLeftCorner,
|
||||
const Graphic3d_Vec2i& theMaxSize)
|
||||
{
|
||||
const Graphic3d_Vec2i aFrameSize = myFramePair->FrameSize();
|
||||
Graphic3d_Vec2i aNewPos = theLeftCorner;
|
||||
Graphic3d_Vec2i aNewSize = myFrameSize;
|
||||
if (aFrameSize.x() > 0
|
||||
&& aFrameSize.y() > 0)
|
||||
{
|
||||
const double anAspect = double(theMaxSize.x()) / double(theMaxSize.y());
|
||||
const double aFitAspect = double(aFrameSize.x()) / double(aFrameSize.y());
|
||||
aNewSize = aFrameSize;
|
||||
if (aFitAspect >= anAspect)
|
||||
{
|
||||
aNewSize.y() = int(double(aFrameSize.x()) / aFitAspect);
|
||||
}
|
||||
else
|
||||
{
|
||||
aNewSize.x() = int(double(aFrameSize.y()) * aFitAspect);
|
||||
}
|
||||
|
||||
for (int aCoord = 0; aCoord < 2; ++aCoord)
|
||||
{
|
||||
if (aNewSize[aCoord] > theMaxSize[aCoord])
|
||||
{
|
||||
const double aScale = double(theMaxSize[aCoord]) / double(aNewSize[aCoord]);
|
||||
aNewSize.x() = int(double(aNewSize.x()) * aScale);
|
||||
aNewSize.y() = int(double(aNewSize.y()) * aScale);
|
||||
}
|
||||
}
|
||||
|
||||
aNewPos = theLeftCorner + theMaxSize / 2 - aNewSize / 2;
|
||||
}
|
||||
else if (myFrameSize.x() < 2
|
||||
|| myFrameSize.y() < 2)
|
||||
{
|
||||
aNewSize = theMaxSize;
|
||||
}
|
||||
|
||||
if (myFrameSize == aNewSize
|
||||
&& myFrameBottomLeft == aNewPos)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
myFrameSize = aNewSize;
|
||||
myFrameBottomLeft = aNewPos;
|
||||
if (HasInteractiveContext())
|
||||
{
|
||||
SetToUpdate();
|
||||
GetContext()->Redisplay (this, false);
|
||||
GetContext()->CurrentViewer()->Invalidate();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : PlayPause
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void AIS_MediaPlayer::PlayPause()
|
||||
{
|
||||
if (myFramePair->PlayerContext().IsNull())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Standard_Real aProgress = 0.0, aDuration = 0.0;
|
||||
bool isPaused = false;
|
||||
myFramePair->PlayerContext()->PlayPause (isPaused, aProgress, aDuration);
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : Compute
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void AIS_MediaPlayer::Compute (const Handle(PrsMgr_PresentationManager3d)& ,
|
||||
const Handle(Prs3d_Presentation)& thePrs,
|
||||
const Standard_Integer theMode)
|
||||
{
|
||||
thePrs->SetInfiniteState (IsInfinite());
|
||||
if (theMode != 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// main frame
|
||||
{
|
||||
Handle(Graphic3d_ArrayOfTriangles) aTris = createRectangleArray (myFrameBottomLeft, myFrameBottomLeft + myFrameSize, Graphic3d_ArrayFlags_VertexTexel);
|
||||
Handle(Graphic3d_Group) aMainGroup = thePrs->NewGroup();
|
||||
aMainGroup->SetGroupPrimitivesAspect (myFrameAspect);
|
||||
aMainGroup->AddPrimitiveArray (aTris);
|
||||
}
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : ComputeSelection
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void AIS_MediaPlayer::ComputeSelection (const Handle(SelectMgr_Selection)& theSel,
|
||||
const Standard_Integer theMode)
|
||||
{
|
||||
if (theMode != 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Handle(Graphic3d_ArrayOfTriangles) aTris = createRectangleArray (myFrameBottomLeft, myFrameBottomLeft + myFrameSize, Graphic3d_ArrayFlags_None);
|
||||
|
||||
Handle(SelectMgr_EntityOwner) anOwner = new SelectMgr_EntityOwner (this, 5);
|
||||
Handle(Select3D_SensitivePrimitiveArray) aSens = new Select3D_SensitivePrimitiveArray (anOwner);
|
||||
aSens->InitTriangulation (aTris->Attributes(), aTris->Indices(), TopLoc_Location());
|
||||
theSel->Add (aSens);
|
||||
}
|
96
src/AIS/AIS_MediaPlayer.hxx
Normal file
96
src/AIS/AIS_MediaPlayer.hxx
Normal file
@@ -0,0 +1,96 @@
|
||||
// Created by: Kirill GAVRILOV
|
||||
// Copyright (c) 2019 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _AIS_MediaPlayer_HeaderFile
|
||||
#define _AIS_MediaPlayer_HeaderFile
|
||||
|
||||
#include <AIS_InteractiveObject.hxx>
|
||||
#include <Graphic3d_MediaTextureSet.hxx>
|
||||
|
||||
class Media_PlayerContext;
|
||||
|
||||
//! Presentation for video playback.
|
||||
class AIS_MediaPlayer : public AIS_InteractiveObject
|
||||
{
|
||||
DEFINE_STANDARD_RTTIEXT(AIS_MediaPlayer, AIS_InteractiveObject)
|
||||
public:
|
||||
|
||||
//! Empty constructor.
|
||||
Standard_EXPORT AIS_MediaPlayer();
|
||||
|
||||
//! Destructor.
|
||||
Standard_EXPORT virtual ~AIS_MediaPlayer();
|
||||
|
||||
//! Setup callback to be called on queue progress (e.g. when new frame should be displayed).
|
||||
void SetCallback (Graphic3d_MediaTextureSet::CallbackOnUpdate_t theCallbackFunction, void* theCallbackUserPtr)
|
||||
{
|
||||
myFramePair->SetCallback (theCallbackFunction, theCallbackUserPtr);
|
||||
}
|
||||
|
||||
//! Open specified file.
|
||||
Standard_EXPORT void OpenInput (const TCollection_AsciiString& thePath,
|
||||
Standard_Boolean theToWait);
|
||||
|
||||
//! Display new frame.
|
||||
Standard_EXPORT bool PresentFrame (const Graphic3d_Vec2i& theLeftCorner,
|
||||
const Graphic3d_Vec2i& theMaxSize);
|
||||
|
||||
//! Return player context.
|
||||
const Handle(Media_PlayerContext)& PlayerContext() const { return myFramePair->PlayerContext(); }
|
||||
|
||||
//! Switch playback state.
|
||||
Standard_EXPORT void PlayPause();
|
||||
|
||||
//! Schedule player to be closed.
|
||||
void SetClosePlayer()
|
||||
{
|
||||
myToClosePlayer = true;
|
||||
myFramePair->Notify();
|
||||
}
|
||||
|
||||
//! Return duration.
|
||||
double Duration() const { return myFramePair->Duration(); }
|
||||
|
||||
//! @name AIS_InteractiveObject interface
|
||||
protected:
|
||||
|
||||
//! Accept only display mode 0.
|
||||
virtual Standard_Boolean AcceptDisplayMode (const Standard_Integer theMode) const Standard_OVERRIDE { return theMode == 0; }
|
||||
|
||||
//! Compute presentation.
|
||||
Standard_EXPORT virtual void Compute (const Handle(PrsMgr_PresentationManager3d)& thePrsMgr,
|
||||
const Handle(Prs3d_Presentation)& thePrs,
|
||||
const Standard_Integer theMode) Standard_OVERRIDE;
|
||||
|
||||
//! Compute selection
|
||||
Standard_EXPORT virtual void ComputeSelection (const Handle(SelectMgr_Selection)& theSel,
|
||||
const Standard_Integer theMode) Standard_OVERRIDE;
|
||||
|
||||
protected:
|
||||
|
||||
//! Update frame size.
|
||||
Standard_EXPORT bool updateSize (const Graphic3d_Vec2i& theLeftCorner,
|
||||
const Graphic3d_Vec2i& theMaxSize);
|
||||
|
||||
protected:
|
||||
|
||||
Handle(Graphic3d_MediaTextureSet) myFramePair;
|
||||
Handle(Graphic3d_AspectFillArea3d) myFrameAspect;
|
||||
Graphic3d_Vec2i myFrameBottomLeft;
|
||||
Graphic3d_Vec2i myFrameSize;
|
||||
bool myToClosePlayer;
|
||||
|
||||
};
|
||||
|
||||
#endif // _AIS_MediaPlayer_HeaderFile
|
@@ -2,7 +2,6 @@ AIS.cxx
|
||||
AIS.hxx
|
||||
AIS_Animation.cxx
|
||||
AIS_Animation.hxx
|
||||
AIS_AnimationTimer.cxx
|
||||
AIS_AnimationTimer.hxx
|
||||
AIS_AnimationCamera.cxx
|
||||
AIS_AnimationCamera.hxx
|
||||
@@ -105,6 +104,8 @@ AIS_MapIteratorOfMapOfInteractive.hxx
|
||||
AIS_MapOfInteractive.hxx
|
||||
AIS_MaxRadiusDimension.cxx
|
||||
AIS_MaxRadiusDimension.hxx
|
||||
AIS_MediaPlayer.cxx
|
||||
AIS_MediaPlayer.hxx
|
||||
AIS_MidPointRelation.cxx
|
||||
AIS_MidPointRelation.hxx
|
||||
AIS_MidPointRelation.lxx
|
||||
|
@@ -116,33 +116,13 @@ class BOPAlgo_PairOfShapeBoolean : public BOPAlgo_Algo {
|
||||
Handle(IntTools_Context) myContext;
|
||||
};
|
||||
//
|
||||
typedef NCollection_Vector<BOPAlgo_PairOfShapeBoolean> \
|
||||
BOPAlgo_VectorOfPairOfShapeBoolean;
|
||||
//
|
||||
typedef BOPTools_ContextFunctor
|
||||
<BOPAlgo_PairOfShapeBoolean,
|
||||
BOPAlgo_VectorOfPairOfShapeBoolean,
|
||||
Handle(IntTools_Context),
|
||||
IntTools_Context> BOPAlgo_BuilderSDFaceFunctor;
|
||||
//
|
||||
typedef BOPTools_ContextCnt
|
||||
<BOPAlgo_BuilderSDFaceFunctor,
|
||||
BOPAlgo_VectorOfPairOfShapeBoolean,
|
||||
Handle(IntTools_Context)> BOPAlgo_BuilderSDFaceCnt;
|
||||
//
|
||||
typedef NCollection_Vector<BOPAlgo_PairOfShapeBoolean> BOPAlgo_VectorOfPairOfShapeBoolean;
|
||||
|
||||
//=======================================================================
|
||||
// BuilderFace
|
||||
//
|
||||
typedef NCollection_Vector<BOPAlgo_BuilderFace> BOPAlgo_VectorOfBuilderFace;
|
||||
//
|
||||
typedef BOPTools_Functor
|
||||
<BOPAlgo_BuilderFace,
|
||||
BOPAlgo_VectorOfBuilderFace> BOPAlgo_BuilderFaceFunctor;
|
||||
//
|
||||
typedef BOPTools_Cnt
|
||||
<BOPAlgo_BuilderFaceFunctor,
|
||||
BOPAlgo_VectorOfBuilderFace> BOPAlgo_BuilderFaceCnt;
|
||||
//
|
||||
|
||||
//=======================================================================
|
||||
//class : BOPAlgo_VFI
|
||||
//purpose :
|
||||
@@ -205,18 +185,7 @@ class BOPAlgo_VFI : public BOPAlgo_Algo {
|
||||
};
|
||||
//
|
||||
typedef NCollection_Vector<BOPAlgo_VFI> BOPAlgo_VectorOfVFI;
|
||||
//
|
||||
typedef BOPTools_ContextFunctor
|
||||
<BOPAlgo_VFI,
|
||||
BOPAlgo_VectorOfVFI,
|
||||
Handle(IntTools_Context),
|
||||
IntTools_Context> BOPAlgo_VFIFunctor;
|
||||
//
|
||||
typedef BOPTools_ContextCnt
|
||||
<BOPAlgo_VFIFunctor,
|
||||
BOPAlgo_VectorOfVFI,
|
||||
Handle(IntTools_Context)> BOPAlgo_VFICnt;
|
||||
//
|
||||
|
||||
//=======================================================================
|
||||
//function : FillImagesFaces
|
||||
//purpose :
|
||||
@@ -474,7 +443,7 @@ void BOPAlgo_Builder::BuildSplitFaces()
|
||||
}// for (i=0; i<aNbS; ++i) {
|
||||
//
|
||||
//===================================================
|
||||
BOPAlgo_BuilderFaceCnt::Perform(myRunParallel, aVBF);
|
||||
BOPTools_Parallel::Perform (myRunParallel, aVBF);
|
||||
//===================================================
|
||||
//
|
||||
Standard_Integer aNbBF = aVBF.Length();
|
||||
@@ -663,7 +632,7 @@ void BOPAlgo_Builder::FillSameDomainFaces()
|
||||
|
||||
//================================================================
|
||||
// Perform analysis
|
||||
BOPAlgo_BuilderSDFaceCnt::Perform(myRunParallel, aVPSB, myContext);
|
||||
BOPTools_Parallel::Perform (myRunParallel, aVPSB, myContext);
|
||||
//================================================================
|
||||
|
||||
NCollection_List<TopTools_ListOfShape> aMBlocks(aAllocator);
|
||||
@@ -816,7 +785,7 @@ void BOPAlgo_Builder::FillInternalVertices()
|
||||
|
||||
// Perform classification
|
||||
//================================================================
|
||||
BOPAlgo_VFICnt::Perform(myRunParallel, aVVFI, myContext);
|
||||
BOPTools_Parallel::Perform (myRunParallel, aVVFI, myContext);
|
||||
//================================================================
|
||||
|
||||
Standard_Integer aNbVFI = aVVFI.Length();
|
||||
|
@@ -341,13 +341,6 @@ private:
|
||||
|
||||
// Vector of Solid Builders
|
||||
typedef NCollection_Vector<BOPAlgo_SplitSolid> BOPAlgo_VectorOfBuilderSolid;
|
||||
// Functors to split solids
|
||||
typedef BOPTools_Functor<BOPAlgo_SplitSolid,
|
||||
BOPAlgo_VectorOfBuilderSolid> BOPAlgo_BuilderSolidFunctor;
|
||||
//
|
||||
typedef BOPTools_Cnt<BOPAlgo_BuilderSolidFunctor,
|
||||
BOPAlgo_VectorOfBuilderSolid> BOPAlgo_BuilderSolidCnt;
|
||||
//=======================================================================
|
||||
|
||||
//=======================================================================
|
||||
//function : BuildSplitSolids
|
||||
@@ -447,7 +440,7 @@ void BOPAlgo_Builder::BuildSplitSolids(TopTools_DataMapOfShapeShape& theDraftSol
|
||||
aNbBS=aVBS.Length();
|
||||
//
|
||||
//===================================================
|
||||
BOPAlgo_BuilderSolidCnt::Perform(myRunParallel, aVBS);
|
||||
BOPTools_Parallel::Perform (myRunParallel, aVBS);
|
||||
//===================================================
|
||||
//
|
||||
for (k = 0; k < aNbBS; ++k)
|
||||
|
@@ -102,17 +102,7 @@ class BOPAlgo_FaceSelfIntersect :
|
||||
|
||||
//=======================================================================
|
||||
|
||||
typedef NCollection_Vector
|
||||
<BOPAlgo_FaceSelfIntersect> BOPAlgo_VectorOfFaceSelfIntersect;
|
||||
//
|
||||
typedef BOPTools_Functor
|
||||
<BOPAlgo_FaceSelfIntersect,
|
||||
BOPAlgo_VectorOfFaceSelfIntersect> BOPAlgo_FaceSelfIntersectFunctor;
|
||||
//
|
||||
typedef BOPTools_Cnt
|
||||
<BOPAlgo_FaceSelfIntersectFunctor,
|
||||
BOPAlgo_VectorOfFaceSelfIntersect> BOPAlgo_FaceSelfIntersectCnt;
|
||||
|
||||
typedef NCollection_Vector<BOPAlgo_FaceSelfIntersect> BOPAlgo_VectorOfFaceSelfIntersect;
|
||||
|
||||
//=======================================================================
|
||||
//function :
|
||||
@@ -447,7 +437,7 @@ void BOPAlgo_CheckerSI::CheckFaceSelfIntersection()
|
||||
|
||||
Standard_Integer aNbFace = aVFace.Length();
|
||||
//======================================================
|
||||
BOPAlgo_FaceSelfIntersectCnt::Perform(myRunParallel, aVFace);
|
||||
BOPTools_Parallel::Perform (myRunParallel, aVFace);
|
||||
//======================================================
|
||||
//
|
||||
for (Standard_Integer k = 0; k < aNbFace; k++)
|
||||
|
@@ -115,19 +115,8 @@ class BOPAlgo_VertexSolid {
|
||||
Handle(IntTools_Context) myContext;
|
||||
};
|
||||
//=======================================================================
|
||||
typedef NCollection_Vector
|
||||
<BOPAlgo_VertexSolid> BOPAlgo_VectorOfVertexSolid;
|
||||
//
|
||||
typedef BOPTools_ContextFunctor
|
||||
<BOPAlgo_VertexSolid,
|
||||
BOPAlgo_VectorOfVertexSolid,
|
||||
Handle(IntTools_Context),
|
||||
IntTools_Context> BOPAlgo_VertexSolidFunctor;
|
||||
//
|
||||
typedef BOPTools_ContextCnt
|
||||
<BOPAlgo_VertexSolidFunctor,
|
||||
BOPAlgo_VectorOfVertexSolid,
|
||||
Handle(IntTools_Context)> BOPAlgo_VertexSolidCnt;
|
||||
typedef NCollection_Vector<BOPAlgo_VertexSolid> BOPAlgo_VectorOfVertexSolid;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//=======================================================================
|
||||
//class : BOPAlgo_ShapeSolid
|
||||
@@ -185,17 +174,8 @@ class BOPAlgo_ShapeSolid {
|
||||
BOPDS_DS* myDS;
|
||||
};
|
||||
//=======================================================================
|
||||
typedef NCollection_Vector
|
||||
<BOPAlgo_ShapeSolid> BOPAlgo_VectorOfShapeSolid;
|
||||
//
|
||||
typedef BOPTools_Functor
|
||||
<BOPAlgo_ShapeSolid,
|
||||
BOPAlgo_VectorOfShapeSolid> BOPAlgo_ShapeSolidFunctor;
|
||||
//
|
||||
typedef BOPTools_Cnt
|
||||
<BOPAlgo_ShapeSolidFunctor,
|
||||
BOPAlgo_VectorOfShapeSolid> BOPAlgo_ShapeSolidCnt;
|
||||
//
|
||||
typedef NCollection_Vector<BOPAlgo_ShapeSolid> BOPAlgo_VectorOfShapeSolid;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//=======================================================================
|
||||
//class : BOPAlgo_SolidSolid
|
||||
@@ -225,18 +205,7 @@ class BOPAlgo_SolidSolid : public BOPAlgo_ShapeSolid {
|
||||
};
|
||||
};
|
||||
//=======================================================================
|
||||
typedef NCollection_Vector
|
||||
<BOPAlgo_SolidSolid> BOPAlgo_VectorOfSolidSolid;
|
||||
//
|
||||
typedef BOPTools_Functor
|
||||
<BOPAlgo_SolidSolid,
|
||||
BOPAlgo_VectorOfSolidSolid> BOPAlgo_SolidSolidFunctor;
|
||||
//
|
||||
typedef BOPTools_Cnt
|
||||
<BOPAlgo_SolidSolidFunctor,
|
||||
BOPAlgo_VectorOfSolidSolid> BOPAlgo_SolidSolidCnt;
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
typedef NCollection_Vector<BOPAlgo_SolidSolid> BOPAlgo_VectorOfSolidSolid;
|
||||
|
||||
//=======================================================================
|
||||
//function : PerformVZ
|
||||
@@ -286,7 +255,7 @@ void BOPAlgo_CheckerSI::PerformVZ()
|
||||
//
|
||||
aNbVVS=aVVS.Length();
|
||||
//=============================================================
|
||||
BOPAlgo_VertexSolidCnt::Perform(myRunParallel, aVVS, myContext);
|
||||
BOPTools_Parallel::Perform (myRunParallel, aVVS, myContext);
|
||||
//=============================================================
|
||||
for (k=0; k < aNbVVS; ++k) {
|
||||
const BOPAlgo_VertexSolid& aVertexSolid=aVVS(k);
|
||||
@@ -344,7 +313,7 @@ void BOPAlgo_CheckerSI::PerformZZ()
|
||||
//
|
||||
aNbSolidSolid=aVSolidSolid.Length();
|
||||
//======================================================
|
||||
BOPAlgo_SolidSolidCnt::Perform(myRunParallel, aVSolidSolid);
|
||||
BOPTools_Parallel::Perform (myRunParallel, aVSolidSolid);
|
||||
//======================================================
|
||||
//
|
||||
BOPDS_VectorOfInterfZZ& aZZs=myDS->InterfZZ();
|
||||
@@ -391,7 +360,7 @@ void BOPAlgo_CheckerSI::PerformSZ(const TopAbs_ShapeEnum aTS)
|
||||
//
|
||||
aNbShapeSolid=aVShapeSolid.Length();
|
||||
//======================================================
|
||||
BOPAlgo_ShapeSolidCnt::Perform(myRunParallel, aVShapeSolid);
|
||||
BOPTools_Parallel::Perform (myRunParallel, aVShapeSolid);
|
||||
//======================================================
|
||||
//
|
||||
BOPDS_VectorOfInterfEZ& aEZs=myDS->InterfEZ();
|
||||
|
@@ -136,20 +136,8 @@ class BOPAlgo_VertexEdge : public BOPAlgo_Algo {
|
||||
Handle(BOPDS_PaveBlock) myPB;
|
||||
};
|
||||
//=======================================================================
|
||||
typedef NCollection_Vector
|
||||
<BOPAlgo_VertexEdge> BOPAlgo_VectorOfVertexEdge;
|
||||
//
|
||||
typedef BOPTools_ContextFunctor
|
||||
<BOPAlgo_VertexEdge,
|
||||
BOPAlgo_VectorOfVertexEdge,
|
||||
Handle(IntTools_Context),
|
||||
IntTools_Context> BOPAlgo_VertexEdgeFunctor;
|
||||
//
|
||||
typedef BOPTools_ContextCnt
|
||||
<BOPAlgo_VertexEdgeFunctor,
|
||||
BOPAlgo_VectorOfVertexEdge,
|
||||
Handle(IntTools_Context)> BOPAlgo_VertexEdgeCnt;
|
||||
//
|
||||
typedef NCollection_Vector<BOPAlgo_VertexEdge> BOPAlgo_VectorOfVertexEdge;
|
||||
|
||||
//=======================================================================
|
||||
// function: PerformVE
|
||||
// purpose:
|
||||
@@ -271,7 +259,7 @@ void BOPAlgo_PaveFiller::IntersectVE
|
||||
//
|
||||
// Perform intersection
|
||||
//=============================================================
|
||||
BOPAlgo_VertexEdgeCnt::Perform(myRunParallel, aVVE, myContext);
|
||||
BOPTools_Parallel::Perform (myRunParallel, aVVE, myContext);
|
||||
//=============================================================
|
||||
//
|
||||
// Keep the modified edges for further update
|
||||
|
@@ -114,18 +114,8 @@ class BOPAlgo_EdgeEdge :
|
||||
};
|
||||
//
|
||||
//=======================================================================
|
||||
typedef NCollection_Vector
|
||||
<BOPAlgo_EdgeEdge> BOPAlgo_VectorOfEdgeEdge;
|
||||
//
|
||||
typedef BOPTools_Functor
|
||||
<BOPAlgo_EdgeEdge,
|
||||
BOPAlgo_VectorOfEdgeEdge> BOPAlgo_EdgeEdgeFunctor;
|
||||
//
|
||||
typedef BOPTools_Cnt
|
||||
<BOPAlgo_EdgeEdgeFunctor,
|
||||
BOPAlgo_VectorOfEdgeEdge> BOPAlgo_EdgeEdgeCnt;
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
typedef NCollection_Vector<BOPAlgo_EdgeEdge> BOPAlgo_VectorOfEdgeEdge;
|
||||
|
||||
//=======================================================================
|
||||
// function: PerformEE
|
||||
// purpose:
|
||||
@@ -234,7 +224,7 @@ void BOPAlgo_PaveFiller::PerformEE()
|
||||
//
|
||||
aNbEdgeEdge=aVEdgeEdge.Length();
|
||||
//======================================================
|
||||
BOPAlgo_EdgeEdgeCnt::Perform(myRunParallel, aVEdgeEdge);
|
||||
BOPTools_Parallel::Perform (myRunParallel, aVEdgeEdge);
|
||||
//======================================================
|
||||
//
|
||||
for (k = 0; k < aNbEdgeEdge; ++k) {
|
||||
@@ -1050,7 +1040,7 @@ void BOPAlgo_PaveFiller::ForceInterfEE()
|
||||
anAlloc->Reset();
|
||||
|
||||
// Perform intersection of the found pairs
|
||||
BOPAlgo_EdgeEdgeCnt::Perform(myRunParallel, aVEdgeEdge);
|
||||
BOPTools_Parallel::Perform (myRunParallel, aVEdgeEdge);
|
||||
|
||||
BOPDS_VectorOfInterfEE& aEEs = myDS->InterfEE();
|
||||
if (aEEs.IsEmpty())
|
||||
|
@@ -132,20 +132,8 @@ class BOPAlgo_VertexFace : public BOPAlgo_Algo {
|
||||
Handle(IntTools_Context) myContext;
|
||||
};
|
||||
//=======================================================================
|
||||
typedef NCollection_Vector<BOPAlgo_VertexFace>
|
||||
BOPAlgo_VectorOfVertexFace;
|
||||
//
|
||||
typedef BOPTools_ContextFunctor
|
||||
<BOPAlgo_VertexFace,
|
||||
BOPAlgo_VectorOfVertexFace,
|
||||
Handle(IntTools_Context),
|
||||
IntTools_Context> BOPAlgo_VertexFaceFunctor;
|
||||
//
|
||||
typedef BOPTools_ContextCnt
|
||||
<BOPAlgo_VertexFaceFunctor,
|
||||
BOPAlgo_VectorOfVertexFace,
|
||||
Handle(IntTools_Context)> BOPAlgo_VertexFaceCnt;
|
||||
//
|
||||
typedef NCollection_Vector<BOPAlgo_VertexFace> BOPAlgo_VectorOfVertexFace;
|
||||
|
||||
//=======================================================================
|
||||
// function: PerformVF
|
||||
// purpose:
|
||||
@@ -234,7 +222,7 @@ void BOPAlgo_PaveFiller::PerformVF()
|
||||
//
|
||||
aNbVF=aVVF.Length();
|
||||
//================================================================
|
||||
BOPAlgo_VertexFaceCnt::Perform(myRunParallel, aVVF, myContext);
|
||||
BOPTools_Parallel::Perform (myRunParallel, aVVF, myContext);
|
||||
//================================================================
|
||||
//
|
||||
for (k=0; k < aNbVF; ++k) {
|
||||
|
@@ -128,18 +128,7 @@ class BOPAlgo_EdgeFace :
|
||||
//
|
||||
//=======================================================================
|
||||
typedef NCollection_Vector<BOPAlgo_EdgeFace> BOPAlgo_VectorOfEdgeFace;
|
||||
//
|
||||
typedef BOPTools_ContextFunctor
|
||||
<BOPAlgo_EdgeFace,
|
||||
BOPAlgo_VectorOfEdgeFace,
|
||||
Handle(IntTools_Context),
|
||||
IntTools_Context> BOPAlgo_EdgeFaceFunctor;
|
||||
//
|
||||
typedef BOPTools_ContextCnt
|
||||
<BOPAlgo_EdgeFaceFunctor,
|
||||
BOPAlgo_VectorOfEdgeFace,
|
||||
Handle(IntTools_Context)> BOPAlgo_EdgeFaceCnt;
|
||||
//
|
||||
|
||||
//=======================================================================
|
||||
//function : PerformEF
|
||||
//purpose :
|
||||
@@ -265,7 +254,7 @@ void BOPAlgo_PaveFiller::PerformEF()
|
||||
//
|
||||
aNbEdgeFace=aVEdgeFace.Length();
|
||||
//=================================================================
|
||||
BOPAlgo_EdgeFaceCnt::Perform(myRunParallel, aVEdgeFace, myContext);
|
||||
BOPTools_Parallel::Perform (myRunParallel, aVEdgeFace, myContext);
|
||||
//=================================================================
|
||||
//
|
||||
for (k=0; k < aNbEdgeFace; ++k) {
|
||||
@@ -972,7 +961,7 @@ void BOPAlgo_PaveFiller::ForceInterfEF(const BOPDS_IndexedMapOfPaveBlock& theMPB
|
||||
anAlloc->Reset();
|
||||
|
||||
// Perform intersection of the found pairs
|
||||
BOPAlgo_EdgeFaceCnt::Perform(myRunParallel, aVEdgeFace, myContext);
|
||||
BOPTools_Parallel::Perform (myRunParallel, aVEdgeFace, myContext);
|
||||
|
||||
BOPDS_VectorOfInterfEF& aEFs = myDS->InterfEF();
|
||||
if (theAddInterf && aEFs.IsEmpty())
|
||||
|
@@ -165,16 +165,8 @@ class BOPAlgo_FaceFace :
|
||||
};
|
||||
//
|
||||
//=======================================================================
|
||||
typedef NCollection_Vector
|
||||
<BOPAlgo_FaceFace> BOPAlgo_VectorOfFaceFace;
|
||||
//
|
||||
typedef BOPTools_Functor
|
||||
<BOPAlgo_FaceFace,
|
||||
BOPAlgo_VectorOfFaceFace> BOPAlgo_FaceFaceFunctor;
|
||||
//
|
||||
typedef BOPTools_Cnt
|
||||
<BOPAlgo_FaceFaceFunctor,
|
||||
BOPAlgo_VectorOfFaceFace> BOPAlgo_FaceFaceCnt;
|
||||
typedef NCollection_Vector<BOPAlgo_FaceFace> BOPAlgo_VectorOfFaceFace;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//=======================================================================
|
||||
//function : PerformFF
|
||||
@@ -287,7 +279,7 @@ void BOPAlgo_PaveFiller::PerformFF()
|
||||
//
|
||||
//======================================================
|
||||
// Perform intersection
|
||||
BOPAlgo_FaceFaceCnt::Perform(myRunParallel, aVFaceFace);
|
||||
BOPTools_Parallel::Perform (myRunParallel, aVFaceFace);
|
||||
//======================================================
|
||||
// Treatment of the results
|
||||
Standard_Integer k, aNbFaceFace = aVFaceFace.Length();
|
||||
|
@@ -169,20 +169,8 @@ class BOPAlgo_SplitEdge : public BOPAlgo_Algo {
|
||||
};
|
||||
//
|
||||
//=======================================================================
|
||||
typedef NCollection_Vector
|
||||
<BOPAlgo_SplitEdge> BOPAlgo_VectorOfSplitEdge;
|
||||
//
|
||||
typedef BOPTools_ContextFunctor
|
||||
<BOPAlgo_SplitEdge,
|
||||
BOPAlgo_VectorOfSplitEdge,
|
||||
Handle(IntTools_Context),
|
||||
IntTools_Context> BOPAlgo_SplitEdgeFunctor;
|
||||
//
|
||||
typedef BOPTools_ContextCnt
|
||||
<BOPAlgo_SplitEdgeFunctor,
|
||||
BOPAlgo_VectorOfSplitEdge,
|
||||
Handle(IntTools_Context)> BOPAlgo_SplitEdgeCnt;
|
||||
//
|
||||
typedef NCollection_Vector<BOPAlgo_SplitEdge> BOPAlgo_VectorOfSplitEdge;
|
||||
|
||||
//=======================================================================
|
||||
//class : BOPAlgo_MPC
|
||||
//purpose :
|
||||
@@ -333,20 +321,8 @@ class BOPAlgo_MPC : public BOPAlgo_Algo {
|
||||
};
|
||||
//
|
||||
//=======================================================================
|
||||
typedef NCollection_Vector
|
||||
<BOPAlgo_MPC> BOPAlgo_VectorOfMPC;
|
||||
//
|
||||
typedef BOPTools_ContextFunctor
|
||||
<BOPAlgo_MPC,
|
||||
BOPAlgo_VectorOfMPC,
|
||||
Handle(IntTools_Context),
|
||||
IntTools_Context> BOPAlgo_MPCFunctor;
|
||||
//
|
||||
typedef BOPTools_ContextCnt
|
||||
<BOPAlgo_MPCFunctor,
|
||||
BOPAlgo_VectorOfMPC,
|
||||
Handle(IntTools_Context)> BOPAlgo_MPCCnt;
|
||||
//
|
||||
typedef NCollection_Vector<BOPAlgo_MPC> BOPAlgo_VectorOfMPC;
|
||||
|
||||
//=======================================================================
|
||||
//class : BOPAlgo_BPC
|
||||
//purpose :
|
||||
@@ -391,18 +367,8 @@ class BOPAlgo_BPC {
|
||||
Standard_Boolean myToUpdate;
|
||||
};
|
||||
//=======================================================================
|
||||
typedef NCollection_Vector
|
||||
<BOPAlgo_BPC> BOPAlgo_VectorOfBPC;
|
||||
//
|
||||
typedef BOPTools_Functor
|
||||
<BOPAlgo_BPC,
|
||||
BOPAlgo_VectorOfBPC> BOPAlgo_BPCFunctor;
|
||||
//
|
||||
typedef BOPTools_Cnt
|
||||
<BOPAlgo_BPCFunctor,
|
||||
BOPAlgo_VectorOfBPC> BOPAlgo_BPCCnt;
|
||||
//
|
||||
//
|
||||
typedef NCollection_Vector<BOPAlgo_BPC> BOPAlgo_VectorOfBPC;
|
||||
|
||||
//=======================================================================
|
||||
// function: MakeSplitEdges
|
||||
// purpose:
|
||||
@@ -524,7 +490,7 @@ void BOPAlgo_PaveFiller::MakeSplitEdges()
|
||||
//
|
||||
aNbVBSE=aVBSE.Length();
|
||||
//======================================================
|
||||
BOPAlgo_SplitEdgeCnt::Perform(myRunParallel, aVBSE, myContext);
|
||||
BOPTools_Parallel::Perform (myRunParallel, aVBSE, myContext);
|
||||
//======================================================
|
||||
//
|
||||
for (k=0; k < aNbVBSE; ++k) {
|
||||
@@ -753,7 +719,7 @@ void BOPAlgo_PaveFiller::MakePCurves()
|
||||
}//if (bPCurveOnS1 || bPCurveOnS2 ) {
|
||||
//
|
||||
//======================================================
|
||||
BOPAlgo_MPCCnt::Perform(myRunParallel, aVMPC, myContext);
|
||||
BOPTools_Parallel::Perform (myRunParallel, aVMPC, myContext);
|
||||
//======================================================
|
||||
|
||||
// Add warnings of the failed projections and update edges with new pcurves
|
||||
@@ -876,7 +842,7 @@ void BOPAlgo_PaveFiller::Prepare()
|
||||
}
|
||||
//
|
||||
//======================================================
|
||||
BOPAlgo_BPCCnt::Perform(myRunParallel, aVBPC);
|
||||
BOPTools_Parallel::Perform (myRunParallel, aVBPC);
|
||||
//======================================================
|
||||
|
||||
// pcurves are built, and now update edges
|
||||
|
@@ -63,20 +63,8 @@ class BOPAlgo_ShrunkRange : public IntTools_ShrunkRange {
|
||||
};
|
||||
//
|
||||
//=======================================================================
|
||||
typedef NCollection_Vector
|
||||
<BOPAlgo_ShrunkRange> BOPAlgo_VectorOfShrunkRange;
|
||||
//
|
||||
typedef BOPTools_ContextFunctor
|
||||
<BOPAlgo_ShrunkRange,
|
||||
BOPAlgo_VectorOfShrunkRange,
|
||||
Handle(IntTools_Context),
|
||||
IntTools_Context> BOPAlgo_ShrunkRangeFunctor;
|
||||
//
|
||||
typedef BOPTools_ContextCnt
|
||||
<BOPAlgo_ShrunkRangeFunctor,
|
||||
BOPAlgo_VectorOfShrunkRange,
|
||||
Handle(IntTools_Context)> BOPAlgo_ShrunkRangeCnt;
|
||||
//
|
||||
typedef NCollection_Vector<BOPAlgo_ShrunkRange> BOPAlgo_VectorOfShrunkRange;
|
||||
|
||||
//=======================================================================
|
||||
// function: FillShrunkData
|
||||
// purpose:
|
||||
@@ -141,7 +129,7 @@ void BOPAlgo_PaveFiller::FillShrunkData(const TopAbs_ShapeEnum aType1,
|
||||
//
|
||||
aNbVSD=aVSD.Length();
|
||||
//=============================================================
|
||||
BOPAlgo_ShrunkRangeCnt::Perform(myRunParallel, aVSD, myContext);
|
||||
BOPTools_Parallel::Perform (myRunParallel, aVSD, myContext);
|
||||
//=============================================================
|
||||
//
|
||||
for (k=0; k < aNbVSD; ++k) {
|
||||
|
@@ -716,12 +716,6 @@ private: //! @name Fields
|
||||
|
||||
typedef NCollection_Vector<FillGap> VectorOfFillGap;
|
||||
|
||||
typedef BOPTools_Functor <FillGap, VectorOfFillGap> FillGapFunctor;
|
||||
|
||||
typedef BOPTools_Cnt <FillGapFunctor, VectorOfFillGap> FillGapCnt;
|
||||
|
||||
//=======================================================================
|
||||
|
||||
//=======================================================================
|
||||
// function: RemoveFeatures
|
||||
// purpose: Remove features by filling the gaps by extension of the
|
||||
@@ -762,7 +756,7 @@ void BOPAlgo_RemoveFeatures::RemoveFeatures()
|
||||
}
|
||||
|
||||
// Perform the reconstruction of the adjacent faces
|
||||
FillGapCnt::Perform(myRunParallel, aVFG);
|
||||
BOPTools_Parallel::Perform (myRunParallel, aVFG);
|
||||
|
||||
// Even if the history is not requested, it is necessary to track:
|
||||
// - The solids modification after each feature removal to find
|
||||
|
@@ -71,17 +71,8 @@ class BOPAlgo_CBK {
|
||||
BOPTools_ConnexityBlock *myPCB;
|
||||
};
|
||||
//=======================================================================
|
||||
typedef NCollection_Vector
|
||||
<BOPAlgo_CBK> BOPAlgo_VectorOfCBK;
|
||||
//
|
||||
typedef BOPTools_Functor
|
||||
<BOPAlgo_CBK,
|
||||
BOPAlgo_VectorOfCBK> BOPAlgo_CBKFunctor;
|
||||
//
|
||||
typedef BOPTools_Cnt
|
||||
<BOPAlgo_CBKFunctor,
|
||||
BOPAlgo_VectorOfCBK> BOPAlgo_CBKCnt;
|
||||
//
|
||||
typedef NCollection_Vector<BOPAlgo_CBK> BOPAlgo_VectorOfCBK;
|
||||
|
||||
//=======================================================================
|
||||
//function :
|
||||
//purpose :
|
||||
@@ -560,7 +551,7 @@ void BOPAlgo_ShellSplitter::MakeShells()
|
||||
//
|
||||
aNbVCBK=aVCBK.Length();
|
||||
//===================================================
|
||||
BOPAlgo_CBKCnt::Perform(myRunParallel, aVCBK);
|
||||
BOPTools_Parallel::Perform (myRunParallel, aVCBK);
|
||||
//===================================================
|
||||
for (k=0; k<aNbVCBK; ++k) {
|
||||
BOPAlgo_CBK& aCBK=aVCBK(k);
|
||||
|
@@ -958,16 +958,8 @@ Standard_Boolean FindPlane(const TopoDS_Shape& theWire,
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
class BOPAlgo_TNV;
|
||||
typedef NCollection_Vector
|
||||
<BOPAlgo_TNV> BOPAlgo_VectorOfTNV;
|
||||
//
|
||||
typedef BOPTools_Functor
|
||||
<BOPAlgo_TNV,
|
||||
BOPAlgo_VectorOfTNV> BOPAlgo_TNVFunctor;
|
||||
//
|
||||
typedef BOPTools_Cnt
|
||||
<BOPAlgo_TNVFunctor,
|
||||
BOPAlgo_VectorOfTNV> BOPAlgo_TNVCnt;
|
||||
typedef NCollection_Vector<BOPAlgo_TNV> BOPAlgo_VectorOfTNV;
|
||||
|
||||
//=======================================================================
|
||||
class BOPAlgo_TNV : public BOPTools_BoxBndTreeSelector{
|
||||
public:
|
||||
@@ -1090,7 +1082,7 @@ void BOPAlgo_Tools::IntersectVertices(const TopTools_IndexedDataMapOfShapeReal&
|
||||
aTreeFiller.Fill();
|
||||
//
|
||||
// Perform intersection
|
||||
BOPAlgo_TNVCnt::Perform(theRunParallel, aVTNV);
|
||||
BOPTools_Parallel::Perform (theRunParallel, aVTNV);
|
||||
//
|
||||
// Fence map
|
||||
TColStd_MapOfInteger aMFence;
|
||||
@@ -1529,16 +1521,6 @@ void BOPAlgo_FillIn3DParts::MakeConnexityBlock(const TopoDS_Face& theFStart,
|
||||
// Vector of solid classifiers
|
||||
typedef NCollection_Vector<BOPAlgo_FillIn3DParts> BOPAlgo_VectorOfFillIn3DParts;
|
||||
|
||||
// Functors to perform classification
|
||||
typedef BOPTools_ContextFunctor<BOPAlgo_FillIn3DParts,
|
||||
BOPAlgo_VectorOfFillIn3DParts,
|
||||
Handle(IntTools_Context),
|
||||
IntTools_Context> BOPAlgo_FillIn3DPartsFunctor;
|
||||
|
||||
typedef BOPTools_ContextCnt<BOPAlgo_FillIn3DPartsFunctor,
|
||||
BOPAlgo_VectorOfFillIn3DParts,
|
||||
Handle(IntTools_Context)> BOPAlgo_FillIn3DPartsCnt;
|
||||
|
||||
//=======================================================================
|
||||
//function : ClassifyFaces
|
||||
//purpose :
|
||||
@@ -1629,7 +1611,7 @@ void BOPAlgo_Tools::ClassifyFaces(const TopTools_ListOfShape& theFaces,
|
||||
|
||||
// Perform classification
|
||||
//================================================================
|
||||
BOPAlgo_FillIn3DPartsCnt::Perform(theRunParallel, aVFIP, theContext);
|
||||
BOPTools_Parallel::Perform (theRunParallel, aVFIP, theContext);
|
||||
//================================================================
|
||||
|
||||
// Analyze the results and fill the resulting map
|
||||
|
@@ -169,19 +169,7 @@ protected:
|
||||
Handle(IntTools_Context) myContext;
|
||||
};
|
||||
|
||||
typedef NCollection_Vector<BOPAlgo_WS_ConnexityBlock> \
|
||||
BOPAlgo_VectorOfConnexityBlock;
|
||||
//
|
||||
typedef BOPTools_ContextFunctor
|
||||
<BOPAlgo_WS_ConnexityBlock,
|
||||
BOPAlgo_VectorOfConnexityBlock,
|
||||
Handle(IntTools_Context),
|
||||
IntTools_Context> BOPAlgo_SplitBlockFunctor;
|
||||
//
|
||||
typedef BOPTools_ContextCnt
|
||||
<BOPAlgo_SplitBlockFunctor,
|
||||
BOPAlgo_VectorOfConnexityBlock,
|
||||
Handle(IntTools_Context)> BOPAlgo_SplitBlockCnt;
|
||||
typedef NCollection_Vector<BOPAlgo_WS_ConnexityBlock> BOPAlgo_VectorOfConnexityBlock;
|
||||
|
||||
//=======================================================================
|
||||
//function : MakeWires
|
||||
@@ -214,7 +202,7 @@ void BOPAlgo_WireSplitter::MakeWires()
|
||||
}
|
||||
}
|
||||
//===================================================
|
||||
BOPAlgo_SplitBlockCnt::Perform(myRunParallel, aVCB, myContext);
|
||||
BOPTools_Parallel::Perform (myRunParallel, aVCB, myContext);
|
||||
//===================================================
|
||||
aNbVCB=aVCB.Length();
|
||||
for (k=0; k<aNbVCB; ++k) {
|
||||
|
@@ -73,9 +73,7 @@ class BOPDS_TSR : public BOPTools_BoxBndTreeSelector{
|
||||
};
|
||||
//
|
||||
//=======================================================================
|
||||
typedef NCollection_Vector <BOPDS_TSR> BOPDS_VectorOfTSR;
|
||||
typedef BOPTools_Functor <BOPDS_TSR,BOPDS_VectorOfTSR> BOPDS_TSRFunctor;
|
||||
typedef BOPTools_Cnt <BOPDS_TSRFunctor, BOPDS_VectorOfTSR> BOPDS_TSRCnt;
|
||||
typedef NCollection_Vector<BOPDS_TSR> BOPDS_VectorOfTSR;
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
@@ -323,7 +321,7 @@ void BOPDS_Iterator::Intersect(const Handle(IntTools_Context)& theCtx,
|
||||
aTreeFiller.Fill();
|
||||
//
|
||||
//===========================================
|
||||
BOPDS_TSRCnt::Perform(myRunParallel, aVTSR);
|
||||
BOPTools_Parallel::Perform (myRunParallel, aVTSR);
|
||||
//===========================================
|
||||
//
|
||||
BOPDS_MapOfPair aMPFence;
|
||||
@@ -454,7 +452,7 @@ void BOPDS_Iterator::IntersectExt(const TColStd_MapOfInteger& theIndices)
|
||||
}
|
||||
|
||||
// Perform selection
|
||||
BOPDS_TSRCnt::Perform(myRunParallel, aVTSR);
|
||||
BOPTools_Parallel::Perform (myRunParallel, aVTSR);
|
||||
|
||||
// Treat selections
|
||||
|
||||
|
@@ -159,15 +159,7 @@ class BOPTools_CPC {
|
||||
//
|
||||
//=======================================================================
|
||||
typedef NCollection_Vector<BOPTools_CPC> BOPTools_VectorOfCPC;
|
||||
//
|
||||
typedef BOPTools_Functor
|
||||
<BOPTools_CPC,
|
||||
BOPTools_VectorOfCPC> BOPTools_CPCFunctor;
|
||||
//
|
||||
typedef BOPTools_Cnt
|
||||
<BOPTools_CPCFunctor,
|
||||
BOPTools_VectorOfCPC> BOPTools_CPCCnt;
|
||||
//
|
||||
|
||||
//=======================================================================
|
||||
//class : BOPTools_CWT
|
||||
//purpose :
|
||||
@@ -199,15 +191,7 @@ class BOPTools_CWT {
|
||||
};
|
||||
//=======================================================================
|
||||
typedef NCollection_Vector<BOPTools_CWT> BOPTools_VectorOfCWT;
|
||||
//
|
||||
typedef BOPTools_Functor
|
||||
<BOPTools_CWT,
|
||||
BOPTools_VectorOfCWT> BOPTools_CWTFunctor;
|
||||
//
|
||||
typedef BOPTools_Cnt
|
||||
<BOPTools_CWTFunctor,
|
||||
BOPTools_VectorOfCWT> BOPTools_CWTCnt;
|
||||
//
|
||||
|
||||
//=======================================================================
|
||||
//class : BOPTools_CDT
|
||||
//purpose :
|
||||
@@ -250,15 +234,7 @@ class BOPTools_CDT {
|
||||
};
|
||||
//=======================================================================
|
||||
typedef NCollection_Vector<BOPTools_CDT> BOPTools_VectorOfCDT;
|
||||
//
|
||||
typedef BOPTools_Functor
|
||||
<BOPTools_CDT,
|
||||
BOPTools_VectorOfCDT> BOPTools_CDTFunctor;
|
||||
//
|
||||
typedef BOPTools_Cnt
|
||||
<BOPTools_CDTFunctor,
|
||||
BOPTools_VectorOfCDT> BOPTools_CDTCnt;
|
||||
//
|
||||
|
||||
//=======================================================================
|
||||
//class : BOPTools_CVT
|
||||
//purpose :
|
||||
@@ -291,15 +267,7 @@ class BOPTools_CVT {
|
||||
//
|
||||
//=======================================================================
|
||||
typedef NCollection_Vector<BOPTools_CVT> BOPTools_VectorOfCVT;
|
||||
//
|
||||
typedef BOPTools_Functor
|
||||
<BOPTools_CVT,
|
||||
BOPTools_VectorOfCVT> BOPTools_CVTFunctor;
|
||||
//
|
||||
typedef BOPTools_Cnt
|
||||
<BOPTools_CVTFunctor,
|
||||
BOPTools_VectorOfCVT> BOPTools_CVTCnt;
|
||||
//
|
||||
|
||||
//=======================================================================
|
||||
//class : BOPTools_CET
|
||||
//purpose :
|
||||
@@ -331,18 +299,7 @@ class BOPTools_CET {
|
||||
};
|
||||
//=======================================================================
|
||||
typedef NCollection_Vector<BOPTools_CET> BOPTools_VectorOfCET;
|
||||
//
|
||||
typedef BOPTools_Functor
|
||||
<BOPTools_CET,
|
||||
BOPTools_VectorOfCET> BOPTools_CETFunctor;
|
||||
//
|
||||
typedef BOPTools_Cnt
|
||||
<BOPTools_CETFunctor,
|
||||
BOPTools_VectorOfCET> BOPTools_CETCnt;
|
||||
//
|
||||
//
|
||||
//=======================================================================
|
||||
//
|
||||
|
||||
//=======================================================================
|
||||
// Function : CorrectTolerances
|
||||
// purpose :
|
||||
@@ -380,7 +337,7 @@ void BOPTools_AlgoTools::CorrectPointOnCurve
|
||||
}
|
||||
//
|
||||
//======================================================
|
||||
BOPTools_CPCCnt::Perform(bRunParallel, aVCPC);
|
||||
BOPTools_Parallel::Perform (bRunParallel, aVCPC);
|
||||
//======================================================
|
||||
}
|
||||
//=======================================================================
|
||||
@@ -418,9 +375,9 @@ void BOPTools_AlgoTools::CorrectCurveOnSurface
|
||||
}
|
||||
//
|
||||
//======================================================
|
||||
BOPTools_CWTCnt::Perform(bRunParallel, aVCWT);
|
||||
BOPTools_Parallel::Perform (bRunParallel, aVCWT);
|
||||
//======================================================
|
||||
BOPTools_CDTCnt::Perform(bRunParallel, aVCDT);
|
||||
BOPTools_Parallel::Perform (bRunParallel, aVCDT);
|
||||
//======================================================
|
||||
}
|
||||
//=======================================================================
|
||||
@@ -445,7 +402,7 @@ void BOPTools_AlgoTools::CorrectShapeTolerances
|
||||
}
|
||||
//
|
||||
//======================================================
|
||||
BOPTools_CVTCnt::Perform(bRunParallel, aVCVT);
|
||||
BOPTools_Parallel::Perform (bRunParallel, aVCVT);
|
||||
//======================================================
|
||||
//
|
||||
aExp.Init(aShape, TopAbs_FACE);
|
||||
@@ -457,7 +414,7 @@ void BOPTools_AlgoTools::CorrectShapeTolerances
|
||||
}
|
||||
//
|
||||
//======================================================
|
||||
BOPTools_CETCnt::Perform(bRunParallel, aVCET);
|
||||
BOPTools_Parallel::Perform (bRunParallel, aVCET);
|
||||
//======================================================
|
||||
}
|
||||
//
|
||||
|
@@ -18,158 +18,178 @@
|
||||
#include <Standard_Macro.hxx>
|
||||
#include <Standard_NotImplemented.hxx>
|
||||
#include <OSD_Parallel.hxx>
|
||||
#include <OSD_ThreadPool.hxx>
|
||||
#include <NCollection_DataMap.hxx>
|
||||
#include <Standard_Mutex.hxx>
|
||||
#include <OSD_Thread.hxx>
|
||||
|
||||
//
|
||||
// 1. Implementation of Functors/Starters
|
||||
//
|
||||
// 1.1. Pure version
|
||||
//
|
||||
|
||||
//=======================================================================
|
||||
//class : BOPTools_Functor
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
template <class TypeSolver, class TypeSolverVector>
|
||||
class BOPTools_Functor
|
||||
//! Implementation of Functors/Starters
|
||||
class BOPTools_Parallel
|
||||
{
|
||||
public:
|
||||
//! Constructor.
|
||||
explicit BOPTools_Functor(TypeSolverVector& theSolverVec)
|
||||
: mySolvers(theSolverVec) {}
|
||||
|
||||
//! Defines functor interface.
|
||||
void operator() (const Standard_Integer theIndex) const
|
||||
template<class TypeSolverVector>
|
||||
class Functor
|
||||
{
|
||||
TypeSolver& aSolver = mySolvers(theIndex);
|
||||
aSolver.Perform();
|
||||
}
|
||||
public:
|
||||
//! Constructor.
|
||||
explicit Functor(TypeSolverVector& theSolverVec) : mySolvers (theSolverVec) {}
|
||||
|
||||
private:
|
||||
BOPTools_Functor(const BOPTools_Functor&);
|
||||
BOPTools_Functor& operator= (const BOPTools_Functor&);
|
||||
|
||||
private:
|
||||
TypeSolverVector& mySolvers;
|
||||
};
|
||||
|
||||
//=======================================================================
|
||||
//class : BOPTools_Cnt
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
template <class TypeFunctor, class TypeSolverVector>
|
||||
class BOPTools_Cnt
|
||||
{
|
||||
public:
|
||||
static void Perform( const Standard_Boolean isRunParallel,
|
||||
TypeSolverVector& theSolverVector )
|
||||
{
|
||||
TypeFunctor aFunctor(theSolverVector);
|
||||
OSD_Parallel::For(0, theSolverVector.Length(), aFunctor, !isRunParallel);
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// 1.2. Context dependent version
|
||||
//
|
||||
|
||||
//=======================================================================
|
||||
//class : BOPTools_ContextFunctor
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
template <class TypeSolver, class TypeSolverVector,
|
||||
class TypeContext, typename TN>
|
||||
class BOPTools_ContextFunctor
|
||||
{
|
||||
//! Auxiliary thread ID hasher.
|
||||
struct Hasher
|
||||
{
|
||||
static Standard_Integer HashCode(const Standard_ThreadId theKey,
|
||||
const Standard_Integer Upper)
|
||||
//! Defines functor interface.
|
||||
void operator() (const Standard_Integer theIndex) const
|
||||
{
|
||||
return ::HashCode((Standard_Size)theKey, Upper);
|
||||
typename TypeSolverVector::value_type& aSolver = mySolvers[theIndex];
|
||||
aSolver.Perform();
|
||||
}
|
||||
|
||||
static Standard_Boolean IsEqual(const Standard_ThreadId theKey1,
|
||||
const Standard_ThreadId theKey2)
|
||||
{
|
||||
return theKey1 == theKey2;
|
||||
}
|
||||
private:
|
||||
Functor(const Functor&);
|
||||
Functor& operator= (const Functor&);
|
||||
|
||||
private:
|
||||
TypeSolverVector& mySolvers;
|
||||
};
|
||||
|
||||
typedef NCollection_DataMap<Standard_ThreadId, TypeContext, Hasher> ContextMap;
|
||||
|
||||
public:
|
||||
|
||||
//! Constructor
|
||||
explicit BOPTools_ContextFunctor( TypeSolverVector& theVector )
|
||||
: mySolverVector(theVector) {}
|
||||
|
||||
//! Binds main thread context
|
||||
void SetContext( TypeContext& theContext )
|
||||
//! Functor storing map of thread id -> algorithm context
|
||||
template<class TypeSolverVector, class TypeContext>
|
||||
class ContextFunctor
|
||||
{
|
||||
myContexts.Bind(OSD_Thread::Current(), theContext);
|
||||
}
|
||||
|
||||
//! Returns current thread context
|
||||
TypeContext& GetThreadContext() const
|
||||
{
|
||||
const Standard_ThreadId aThreadID = OSD_Thread::Current();
|
||||
if ( myContexts.IsBound(aThreadID) )
|
||||
//! Auxiliary thread ID hasher.
|
||||
struct Hasher
|
||||
{
|
||||
TypeContext& aContext = myContexts(aThreadID);
|
||||
if ( aContext.IsNull() == Standard_False )
|
||||
return aContext;
|
||||
static Standard_Integer HashCode(const Standard_ThreadId theKey,
|
||||
const Standard_Integer Upper)
|
||||
{
|
||||
return ::HashCode((Standard_Size)theKey, Upper);
|
||||
}
|
||||
|
||||
static Standard_Boolean IsEqual(const Standard_ThreadId theKey1,
|
||||
const Standard_ThreadId theKey2)
|
||||
{
|
||||
return theKey1 == theKey2;
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
//! Constructor
|
||||
explicit ContextFunctor (TypeSolverVector& theVector) : mySolverVector(theVector) {}
|
||||
|
||||
//! Binds main thread context
|
||||
void SetContext (const opencascade::handle<TypeContext>& theContext)
|
||||
{
|
||||
myContextMap.Bind (OSD_Thread::Current(), theContext);
|
||||
}
|
||||
|
||||
// Create new context
|
||||
TypeContext aContext = new TN
|
||||
( NCollection_BaseAllocator::CommonBaseAllocator() );
|
||||
//! Returns current thread context
|
||||
const opencascade::handle<TypeContext>& GetThreadContext() const
|
||||
{
|
||||
const Standard_ThreadId aThreadID = OSD_Thread::Current();
|
||||
if (const opencascade::handle<TypeContext>* aContextPtr = myContextMap.Seek (aThreadID))
|
||||
{
|
||||
if (!aContextPtr->IsNull())
|
||||
{
|
||||
return *aContextPtr;
|
||||
}
|
||||
}
|
||||
|
||||
Standard_Mutex::Sentry aLocker(myMutex);
|
||||
myContexts.Bind(aThreadID, aContext);
|
||||
// Create new context
|
||||
opencascade::handle<TypeContext> aContext = new TypeContext (NCollection_BaseAllocator::CommonBaseAllocator());
|
||||
|
||||
return myContexts(aThreadID);
|
||||
}
|
||||
Standard_Mutex::Sentry aLocker (myMutex);
|
||||
myContextMap.Bind (aThreadID, aContext);
|
||||
return myContextMap (aThreadID);
|
||||
}
|
||||
|
||||
//! Defines functor interface
|
||||
void operator()( const Standard_Integer theIndex ) const
|
||||
//! Defines functor interface
|
||||
void operator()( const Standard_Integer theIndex ) const
|
||||
{
|
||||
const opencascade::handle<TypeContext>& aContext = GetThreadContext();
|
||||
typename TypeSolverVector::value_type& aSolver = mySolverVector[theIndex];
|
||||
|
||||
aSolver.SetContext(aContext);
|
||||
aSolver.Perform();
|
||||
}
|
||||
|
||||
private:
|
||||
ContextFunctor(const ContextFunctor&);
|
||||
ContextFunctor& operator= (const ContextFunctor&);
|
||||
|
||||
private:
|
||||
TypeSolverVector& mySolverVector;
|
||||
mutable NCollection_DataMap<Standard_ThreadId, opencascade::handle<TypeContext>, Hasher> myContextMap;
|
||||
mutable Standard_Mutex myMutex;
|
||||
};
|
||||
|
||||
//! Functor storing array of algorithm contexts per thread in pool
|
||||
template<class TypeSolverVector, class TypeContext>
|
||||
class ContextFunctor2
|
||||
{
|
||||
TypeContext& aContext = GetThreadContext();
|
||||
TypeSolver& aSolver = mySolverVector(theIndex);
|
||||
public:
|
||||
|
||||
aSolver.SetContext(aContext);
|
||||
aSolver.Perform();
|
||||
}
|
||||
//! Constructor
|
||||
explicit ContextFunctor2 (TypeSolverVector& theVector, const OSD_ThreadPool::Launcher& thePoolLauncher)
|
||||
: mySolverVector(theVector),
|
||||
myContextArray (thePoolLauncher.LowerThreadIndex(), thePoolLauncher.UpperThreadIndex()) {}
|
||||
|
||||
private:
|
||||
BOPTools_ContextFunctor(const BOPTools_ContextFunctor&);
|
||||
BOPTools_ContextFunctor& operator= (const BOPTools_ContextFunctor&);
|
||||
//! Binds main thread context
|
||||
void SetContext (const opencascade::handle<TypeContext>& theContext)
|
||||
{
|
||||
myContextArray.ChangeLast() = theContext; // OSD_ThreadPool::Launcher::UpperThreadIndex() is reserved for a main thread
|
||||
}
|
||||
|
||||
private:
|
||||
TypeSolverVector& mySolverVector;
|
||||
mutable ContextMap myContexts;
|
||||
mutable Standard_Mutex myMutex;
|
||||
};
|
||||
//! Defines functor interface with serialized thread index.
|
||||
void operator() (int theThreadIndex,
|
||||
int theIndex) const
|
||||
{
|
||||
opencascade::handle<TypeContext>& aContext = myContextArray.ChangeValue (theThreadIndex);
|
||||
if (aContext.IsNull())
|
||||
{
|
||||
aContext = new TypeContext (NCollection_BaseAllocator::CommonBaseAllocator());
|
||||
}
|
||||
typename TypeSolverVector::value_type& aSolver = mySolverVector[theIndex];
|
||||
aSolver.SetContext (aContext);
|
||||
aSolver.Perform();
|
||||
}
|
||||
|
||||
private:
|
||||
ContextFunctor2(const ContextFunctor2&);
|
||||
ContextFunctor2& operator= (const ContextFunctor2&);
|
||||
|
||||
private:
|
||||
TypeSolverVector& mySolverVector;
|
||||
mutable NCollection_Array1< opencascade::handle<TypeContext> > myContextArray;
|
||||
};
|
||||
|
||||
//=======================================================================
|
||||
//class : BOPTools_ContextCnt
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
template <class TypeFunctor, class TypeSolverVector, class TypeContext>
|
||||
class BOPTools_ContextCnt
|
||||
{
|
||||
public:
|
||||
static void Perform( const Standard_Boolean isRunParallel,
|
||||
TypeSolverVector& theSolverVector,
|
||||
TypeContext& theContext )
|
||||
{
|
||||
TypeFunctor aFunctor(theSolverVector);
|
||||
aFunctor.SetContext(theContext);
|
||||
|
||||
OSD_Parallel::For(0, theSolverVector.Length(), aFunctor, !isRunParallel);
|
||||
//! Pure version
|
||||
template<class TypeSolverVector>
|
||||
static void Perform (Standard_Boolean theIsRunParallel,
|
||||
TypeSolverVector& theSolverVector)
|
||||
{
|
||||
Functor<TypeSolverVector> aFunctor (theSolverVector);
|
||||
OSD_Parallel::For (0, theSolverVector.Length(), aFunctor, !theIsRunParallel);
|
||||
}
|
||||
|
||||
//! Context dependent version
|
||||
template<class TypeSolverVector, class TypeContext>
|
||||
static void Perform (Standard_Boolean theIsRunParallel,
|
||||
TypeSolverVector& theSolverVector,
|
||||
opencascade::handle<TypeContext>& theContext)
|
||||
{
|
||||
if (OSD_Parallel::ToUseOcctThreads())
|
||||
{
|
||||
const Handle(OSD_ThreadPool)& aThreadPool = OSD_ThreadPool::DefaultPool();
|
||||
OSD_ThreadPool::Launcher aPoolLauncher (*aThreadPool, theIsRunParallel ? theSolverVector.Length() : 0);
|
||||
ContextFunctor2<TypeSolverVector, TypeContext> aFunctor (theSolverVector, aPoolLauncher);
|
||||
aFunctor.SetContext (theContext);
|
||||
aPoolLauncher.Perform (0, theSolverVector.Length(), aFunctor);
|
||||
}
|
||||
else
|
||||
{
|
||||
ContextFunctor<TypeSolverVector, TypeContext> aFunctor (theSolverVector);
|
||||
aFunctor.SetContext (theContext);
|
||||
OSD_Parallel::For (0, theSolverVector.Length(), aFunctor, !theIsRunParallel);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@@ -210,6 +210,20 @@ gp_Pnt Bnd_Box::CornerMin() const
|
||||
return aCornerMin;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
// function : CornerMin
|
||||
// purpose :
|
||||
//=======================================================================
|
||||
|
||||
gp_Pnt Bnd_Box::Center() const
|
||||
{
|
||||
if (IsVoid())
|
||||
{
|
||||
throw Standard_ConstructionError("Bnd_Box is void");
|
||||
}
|
||||
return (CornerMin().Coord() + CornerMax().Coord()) / 2.0;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : CornerMax
|
||||
//purpose :
|
||||
|
@@ -142,6 +142,12 @@ public:
|
||||
//! Standard_ConstructionError exception will be thrown if the box is void.
|
||||
//! if IsVoid()
|
||||
Standard_EXPORT gp_Pnt CornerMax() const;
|
||||
|
||||
//! Returns the center of this bounding box.
|
||||
//! If this bounding box is infinite (i.e. "open"), returned values
|
||||
//! may be equal to +/- Precision::Infinite().
|
||||
//! Standard_ConstructionError exception will be thrown if the box is void.
|
||||
Standard_EXPORT gp_Pnt Center() const;
|
||||
|
||||
//! The Box will be infinitely long in the Xmin
|
||||
//! direction.
|
||||
|
@@ -95,12 +95,25 @@ public:
|
||||
//! Converts numeric expression, that can involve DRAW
|
||||
//! variables, to real value.
|
||||
Standard_EXPORT static Standard_Real Atof (const Standard_CString Name);
|
||||
|
||||
|
||||
//! Converts the numeric expression, that can involve DRAW variables, to a real value
|
||||
//! @param theExpressionString the strings that containes the expression involving DRAW variables to be parsed
|
||||
//! @param theParsedRealValue a real value that is a result of parsing
|
||||
//! @return true if parsing was successfull, or false otherwise
|
||||
Standard_EXPORT static bool ParseReal (const Standard_CString theExpressionString, Standard_Real& theParsedRealValue);
|
||||
|
||||
//! Converts numeric expression, that can involve DRAW
|
||||
//! variables, to integer value.
|
||||
//! Implemented as cast of Atof() to integer.
|
||||
Standard_EXPORT static Standard_Integer Atoi (const Standard_CString Name);
|
||||
|
||||
|
||||
//! Converts the numeric expression, that can involve DRAW variables, to an integer value
|
||||
//! @param theExpressionString the strings that containes the expression involving DRAW variables to be parsed
|
||||
//! @param theParsedIntegerValue an integer value that is a result of parsing
|
||||
//! @return true if parsing was successfull, or false otherwise
|
||||
Standard_EXPORT static bool ParseInteger (const Standard_CString theExpressionString,
|
||||
Standard_Integer& theParsedIntegerValue);
|
||||
|
||||
//! Returns last graphic selection description.
|
||||
Standard_EXPORT static void LastPick (Standard_Integer& view, Standard_Integer& X, Standard_Integer& Y, Standard_Integer& button);
|
||||
|
||||
|
@@ -29,6 +29,8 @@
|
||||
#include <OSD_Exception_CTRL_BREAK.hxx>
|
||||
#include <OSD_MAllocHook.hxx>
|
||||
#include <OSD_MemInfo.hxx>
|
||||
#include <OSD_Parallel.hxx>
|
||||
#include <OSD_ThreadPool.hxx>
|
||||
#include <Standard_Macro.hxx>
|
||||
#include <Standard_SStream.hxx>
|
||||
#include <Standard_Stream.hxx>
|
||||
@@ -808,6 +810,82 @@ static int dmeminfo (Draw_Interpretor& theDI,
|
||||
return 0;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
//function : dparallel
|
||||
//purpose :
|
||||
//==============================================================================
|
||||
static int dparallel (Draw_Interpretor& theDI,
|
||||
Standard_Integer theArgNb,
|
||||
const char** theArgVec)
|
||||
{
|
||||
const Handle(OSD_ThreadPool)& aDefPool = OSD_ThreadPool::DefaultPool();
|
||||
if (theArgNb <= 1)
|
||||
{
|
||||
theDI << "NbLogicalProcessors: " << OSD_Parallel::NbLogicalProcessors() << "\n"
|
||||
<< "NbThreads: " << aDefPool->NbThreads() << "\n"
|
||||
<< "NbDefThreads: " << aDefPool->NbDefaultThreadsToLaunch() << "\n"
|
||||
<< "UseOcct: " << (OSD_Parallel::ToUseOcctThreads() ? 1 : 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (Standard_Integer anIter = 1; anIter < theArgNb; ++anIter)
|
||||
{
|
||||
TCollection_AsciiString anArg (theArgVec[anIter]);
|
||||
anArg.LowerCase();
|
||||
if (anIter + 1 < theArgNb
|
||||
&& (anArg == "-nbthreads"
|
||||
|| anArg == "-threads"))
|
||||
{
|
||||
const Standard_Integer aVal = Draw::Atoi (theArgVec[++anIter]);
|
||||
aDefPool->Init (aVal);
|
||||
}
|
||||
else if (anIter + 1 < theArgNb
|
||||
&& (anArg == "-nbdefthreads"
|
||||
|| anArg == "-defthreads"
|
||||
|| anArg == "-nbmaxdefthreads"
|
||||
|| anArg == "-maxdefthreads"))
|
||||
{
|
||||
const Standard_Integer aVal = Draw::Atoi (theArgVec[++anIter]);
|
||||
if (aVal <= 0 || aVal > aDefPool->NbThreads())
|
||||
{
|
||||
std::cout << "Syntax error: maximum number of threads to use should be <= of threads in the pool\n";
|
||||
return 1;
|
||||
}
|
||||
aDefPool->SetNbDefaultThreadsToLaunch (aVal);
|
||||
}
|
||||
else if (anIter + 1 < theArgNb
|
||||
&& (anArg == "-useocct"
|
||||
|| anArg == "-touseocct"
|
||||
|| anArg == "-occt"))
|
||||
{
|
||||
const Standard_Integer aVal = Draw::Atoi (theArgVec[++anIter]);
|
||||
OSD_Parallel::SetUseOcctThreads (aVal == 1);
|
||||
if (OSD_Parallel::ToUseOcctThreads() != (aVal == 1))
|
||||
{
|
||||
std::cout << "Warning: unable to switch threads library - no options available\n";
|
||||
}
|
||||
}
|
||||
else if (anIter + 1 < theArgNb
|
||||
&& (anArg == "-usetbb"
|
||||
|| anArg == "-tousetbb"
|
||||
|| anArg == "-tbb"))
|
||||
{
|
||||
const Standard_Integer aVal = Draw::Atoi (theArgVec[++anIter]);
|
||||
OSD_Parallel::SetUseOcctThreads (aVal == 0);
|
||||
if (OSD_Parallel::ToUseOcctThreads() != (aVal == 0))
|
||||
{
|
||||
std::cout << "Warning: unable to switch threads library - no options available\n";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Syntax error: unknown argument '" << anArg << "'\n";
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
//function : dperf
|
||||
//purpose :
|
||||
@@ -977,6 +1055,16 @@ void Draw::BasicCommands(Draw_Interpretor& theCommands)
|
||||
theCommands.Add("dsetsignal","dsetsignal [fpe=0] -- set OSD signal handler, with FPE option if argument is given",
|
||||
__FILE__,dsetsignal,g);
|
||||
|
||||
theCommands.Add("dparallel",
|
||||
"dparallel [-occt {0|1}] [-nbThreads Count] [-nbDefThreads Count]"
|
||||
"\n\t\t: Manages global parallelization parameters:"
|
||||
"\n\t\t: -occt use OCCT implementation or external library (if available)"
|
||||
"\n\t\t: -nbThreads specify the number of threads in default thread pool"
|
||||
"\n\t\t: -nbDefThreads specify the upper limit of threads to be used for default thread pool"
|
||||
"\n\t\t: within single parallelization call (should be <= of overall number of threads),"
|
||||
"\n\t\t: so that nested algorithm can also use this pool",
|
||||
__FILE__,dparallel,g);
|
||||
|
||||
// Logging commands; note that their names are hard-coded in the code
|
||||
// of Draw_Interpretor, thus should not be changed without update of that code!
|
||||
theCommands.Add("dlog", "manage logging of commands and output; run without args to get help",
|
||||
|
@@ -1122,9 +1122,10 @@ static Standard_Real Parse(char*& name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : Atof
|
||||
//purpose :
|
||||
// function : Atof
|
||||
// purpose :
|
||||
//=======================================================================
|
||||
Standard_Real Draw::Atof(const Standard_CString name)
|
||||
{
|
||||
@@ -1132,6 +1133,7 @@ Standard_Real Draw::Atof(const Standard_CString name)
|
||||
char* n = new char[1+strlen(name)];
|
||||
char* b = n;
|
||||
strcpy(n,name);
|
||||
Draw_ParseFailed = Standard_False;
|
||||
Standard_Real x = Parse(n);
|
||||
while ((*n == ' ') || (*n == '\t')) n++;
|
||||
if (*n) Draw_ParseFailed = Standard_True;
|
||||
@@ -1139,10 +1141,51 @@ Standard_Real Draw::Atof(const Standard_CString name)
|
||||
return x;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
// function : ParseReal
|
||||
// purpose :
|
||||
//=======================================================================
|
||||
bool Draw::ParseReal (const Standard_CString theExpressionString, Standard_Real& theParsedRealValue)
|
||||
{
|
||||
const Standard_Real aParsedRealValue = Atof (theExpressionString);
|
||||
if (Draw_ParseFailed)
|
||||
{
|
||||
Draw_ParseFailed = Standard_False;
|
||||
return false;
|
||||
}
|
||||
theParsedRealValue = aParsedRealValue;
|
||||
return true;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
// function : Atoi
|
||||
// purpose :
|
||||
//=======================================================================
|
||||
Standard_Integer Draw::Atoi(const Standard_CString name)
|
||||
{
|
||||
return (Standard_Integer ) Draw::Atof(name);
|
||||
return (Standard_Integer) Draw::Atof(name);
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
// function : ParseInteger
|
||||
// purpose :
|
||||
//=======================================================================
|
||||
bool Draw::ParseInteger (const Standard_CString theExpressionString, Standard_Integer& theParsedIntegerValue)
|
||||
{
|
||||
Standard_Real aParsedRealValue = 0.0;
|
||||
if (!ParseReal (theExpressionString, aParsedRealValue))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
const Standard_Integer aParsedIntegerValue = static_cast<Standard_Integer> (aParsedRealValue);
|
||||
if (static_cast<Standard_Real> (aParsedIntegerValue) != aParsedRealValue)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
theParsedIntegerValue = aParsedIntegerValue;
|
||||
return true;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : Set
|
||||
//purpose : set a TCL var
|
||||
|
@@ -283,6 +283,21 @@ GeomFill_SectionPlacement(const Handle(GeomFill_LocationLaw)& L,
|
||||
Handle(TColgp_HArray1OfPnt) Pnts;
|
||||
Standard_Real first = myAdpSection.FirstParameter();
|
||||
Standard_Real last = myAdpSection.LastParameter();
|
||||
if (myAdpSection.IsPeriodic())
|
||||
{
|
||||
//Correct boundaries to avoid mistake of LocateU
|
||||
Handle(Geom_Curve) aCurve = myAdpSection.Curve();
|
||||
if (aCurve->IsInstance(STANDARD_TYPE(Geom_TrimmedCurve)))
|
||||
aCurve = (Handle(Geom_TrimmedCurve)::DownCast(aCurve))->BasisCurve();
|
||||
Standard_Real Ufirst = aCurve->FirstParameter();
|
||||
Standard_Real aPeriod = aCurve->Period();
|
||||
Standard_Real U1 = Ufirst + Floor((first - Ufirst)/aPeriod) * aPeriod;
|
||||
Standard_Real U2 = U1 + aPeriod;
|
||||
if (Abs(first - U1) <= Precision::PConfusion())
|
||||
first = U1;
|
||||
if (Abs(last - U2) <= Precision::PConfusion())
|
||||
last = U2;
|
||||
}
|
||||
Standard_Real t, delta;
|
||||
if (myAdpSection.GetType() == GeomAbs_BSplineCurve)
|
||||
{
|
||||
|
@@ -92,6 +92,10 @@ Graphic3d_Mat4d.hxx
|
||||
Graphic3d_MaterialAspect.cxx
|
||||
Graphic3d_MaterialAspect.hxx
|
||||
Graphic3d_MaterialDefinitionError.hxx
|
||||
Graphic3d_MediaTexture.cxx
|
||||
Graphic3d_MediaTexture.hxx
|
||||
Graphic3d_MediaTextureSet.cxx
|
||||
Graphic3d_MediaTextureSet.hxx
|
||||
Graphic3d_NameOfMaterial.hxx
|
||||
Graphic3d_NameOfTexture1D.hxx
|
||||
Graphic3d_NameOfTexture2D.hxx
|
||||
|
@@ -87,7 +87,6 @@ Graphic3d_Camera::Graphic3d_Camera()
|
||||
myZNear (DEFAULT_ZNEAR),
|
||||
myZFar (DEFAULT_ZFAR),
|
||||
myAspect (1.0),
|
||||
myIsZeroToOneDepth (false),
|
||||
myScale (1000.0),
|
||||
myZFocus (1.0),
|
||||
myZFocusType (FocusType_Relative),
|
||||
@@ -980,7 +979,7 @@ void Graphic3d_Camera::OrthoProj (const Elem_t theLeft,
|
||||
const Elem_t theTop,
|
||||
const Elem_t theNear,
|
||||
const Elem_t theFar,
|
||||
NCollection_Mat4<Elem_t>& theOutMx) const
|
||||
NCollection_Mat4<Elem_t>& theOutMx)
|
||||
{
|
||||
// row 0
|
||||
theOutMx.ChangeValue (0, 0) = Elem_t (2.0) / (theRight - theLeft);
|
||||
@@ -997,16 +996,8 @@ void Graphic3d_Camera::OrthoProj (const Elem_t theLeft,
|
||||
// row 2
|
||||
theOutMx.ChangeValue (2, 0) = Elem_t (0.0);
|
||||
theOutMx.ChangeValue (2, 1) = Elem_t (0.0);
|
||||
if (myIsZeroToOneDepth)
|
||||
{
|
||||
theOutMx.ChangeValue (2, 2) = Elem_t (-1.0) / (theFar - theNear);
|
||||
theOutMx.ChangeValue (2, 3) = -theNear / (theFar - theNear);
|
||||
}
|
||||
else
|
||||
{
|
||||
theOutMx.ChangeValue (2, 2) = Elem_t (-2.0) / (theFar - theNear);
|
||||
theOutMx.ChangeValue (2, 3) = - (theFar + theNear) / (theFar - theNear);
|
||||
}
|
||||
theOutMx.ChangeValue (2, 2) = Elem_t (-2.0) / (theFar - theNear);
|
||||
theOutMx.ChangeValue (2, 3) = - (theFar + theNear) / (theFar - theNear);
|
||||
|
||||
// row 3
|
||||
theOutMx.ChangeValue (3, 0) = Elem_t (0.0);
|
||||
@@ -1026,7 +1017,7 @@ void Graphic3d_Camera::PerspectiveProj (const Elem_t theLeft,
|
||||
const Elem_t theTop,
|
||||
const Elem_t theNear,
|
||||
const Elem_t theFar,
|
||||
NCollection_Mat4<Elem_t>& theOutMx) const
|
||||
NCollection_Mat4<Elem_t>& theOutMx)
|
||||
{
|
||||
// column 0
|
||||
theOutMx.ChangeValue (0, 0) = (Elem_t (2.0) * theNear) / (theRight - theLeft);
|
||||
@@ -1043,27 +1034,13 @@ void Graphic3d_Camera::PerspectiveProj (const Elem_t theLeft,
|
||||
// column 2
|
||||
theOutMx.ChangeValue (0, 2) = (theRight + theLeft) / (theRight - theLeft);
|
||||
theOutMx.ChangeValue (1, 2) = (theTop + theBottom) / (theTop - theBottom);
|
||||
if (myIsZeroToOneDepth)
|
||||
{
|
||||
theOutMx.ChangeValue (2, 2) = theFar / (theNear - theFar);
|
||||
}
|
||||
else
|
||||
{
|
||||
theOutMx.ChangeValue (2, 2) = -(theFar + theNear) / (theFar - theNear);
|
||||
}
|
||||
theOutMx.ChangeValue (2, 2) = -(theFar + theNear) / (theFar - theNear);
|
||||
theOutMx.ChangeValue (3, 2) = Elem_t (-1.0);
|
||||
|
||||
// column 3
|
||||
theOutMx.ChangeValue (0, 3) = Elem_t (0.0);
|
||||
theOutMx.ChangeValue (1, 3) = Elem_t (0.0);
|
||||
if (myIsZeroToOneDepth)
|
||||
{
|
||||
theOutMx.ChangeValue (2, 3) = -(theFar * theNear) / (theFar - theNear);
|
||||
}
|
||||
else
|
||||
{
|
||||
theOutMx.ChangeValue (2, 3) = -(Elem_t (2.0) * theFar * theNear) / (theFar - theNear);
|
||||
}
|
||||
theOutMx.ChangeValue (2, 3) = -(Elem_t (2.0) * theFar * theNear) / (theFar - theNear);
|
||||
theOutMx.ChangeValue (3, 3) = Elem_t (0.0);
|
||||
}
|
||||
|
||||
@@ -1081,7 +1058,7 @@ void Graphic3d_Camera::StereoEyeProj (const Elem_t theLeft,
|
||||
const Elem_t theIOD,
|
||||
const Elem_t theZFocus,
|
||||
const Standard_Boolean theIsLeft,
|
||||
NCollection_Mat4<Elem_t>& theOutMx) const
|
||||
NCollection_Mat4<Elem_t>& theOutMx)
|
||||
{
|
||||
Elem_t aDx = theIsLeft ? Elem_t (0.5) * theIOD : Elem_t (-0.5) * theIOD;
|
||||
Elem_t aDXStereoShift = aDx * theNear / theZFocus;
|
||||
@@ -1428,10 +1405,12 @@ void Graphic3d_Camera::FrustumPoints (NCollection_Array1<Graphic3d_Vec3d>& thePo
|
||||
|
||||
Standard_Real nLeft = 0.0, nRight = 0.0, nTop = 0.0, nBottom = 0.0;
|
||||
Standard_Real fLeft = 0.0, fRight = 0.0, fTop = 0.0, fBottom = 0.0;
|
||||
Standard_Real aNear = myZNear, aFar = myZFar;
|
||||
Standard_Real aNear = 0.0, aFar = 0.0;
|
||||
if (!IsOrthographic())
|
||||
{
|
||||
// handle perspective projection
|
||||
aNear = aProjectionMat.GetValue (2, 3) / (-1.0 + aProjectionMat.GetValue (2, 2));
|
||||
aFar = aProjectionMat.GetValue (2, 3) / ( 1.0 + aProjectionMat.GetValue (2, 2));
|
||||
// Near plane
|
||||
nLeft = aNear * (aProjectionMat.GetValue (0, 2) - 1.0) / aProjectionMat.GetValue (0, 0);
|
||||
nRight = aNear * (aProjectionMat.GetValue (0, 2) + 1.0) / aProjectionMat.GetValue (0, 0);
|
||||
@@ -1446,6 +1425,8 @@ void Graphic3d_Camera::FrustumPoints (NCollection_Array1<Graphic3d_Vec3d>& thePo
|
||||
else
|
||||
{
|
||||
// handle orthographic projection
|
||||
aNear = (1.0 / aProjectionMat.GetValue (2, 2)) * (aProjectionMat.GetValue (2, 3) + 1.0);
|
||||
aFar = (1.0 / aProjectionMat.GetValue (2, 2)) * (aProjectionMat.GetValue (2, 3) - 1.0);
|
||||
// Near plane
|
||||
nLeft = ( 1.0 + aProjectionMat.GetValue (0, 3)) / (-aProjectionMat.GetValue (0, 0));
|
||||
fLeft = nLeft;
|
||||
|
@@ -326,20 +326,6 @@ public:
|
||||
return myZFar;
|
||||
}
|
||||
|
||||
//! Return TRUE if camera should calculate projection matrix for [0, 1] depth range or for [-1, 1] range.
|
||||
//! FALSE by default.
|
||||
Standard_Boolean IsZeroToOneDepth() const { return myIsZeroToOneDepth; }
|
||||
|
||||
//! Set using [0, 1] depth range or [-1, 1] range.
|
||||
void SetZeroToOneDepth (Standard_Boolean theIsZeroToOne)
|
||||
{
|
||||
if (myIsZeroToOneDepth != theIsZeroToOne)
|
||||
{
|
||||
myIsZeroToOneDepth = theIsZeroToOne;
|
||||
InvalidateProjection();
|
||||
}
|
||||
}
|
||||
|
||||
//! Changes width / height display ratio.
|
||||
//! @param theAspect [in] the display ratio.
|
||||
Standard_EXPORT void SetAspect (const Standard_Real theAspect);
|
||||
@@ -576,14 +562,14 @@ private:
|
||||
//! @param theFar [in] the far mapping (clipping) coordinate.
|
||||
//! @param theOutMx [out] the projection matrix.
|
||||
template <typename Elem_t>
|
||||
void
|
||||
static void
|
||||
OrthoProj (const Elem_t theLeft,
|
||||
const Elem_t theRight,
|
||||
const Elem_t theBottom,
|
||||
const Elem_t theTop,
|
||||
const Elem_t theNear,
|
||||
const Elem_t theFar,
|
||||
NCollection_Mat4<Elem_t>& theOutMx) const;
|
||||
NCollection_Mat4<Elem_t>& theOutMx);
|
||||
|
||||
//! Compose perspective projection matrix for
|
||||
//! the passed camera volume mapping.
|
||||
@@ -595,14 +581,14 @@ private:
|
||||
//! @param theFar [in] the far mapping (clipping) coordinate.
|
||||
//! @param theOutMx [out] the projection matrix.
|
||||
template <typename Elem_t>
|
||||
void
|
||||
static void
|
||||
PerspectiveProj (const Elem_t theLeft,
|
||||
const Elem_t theRight,
|
||||
const Elem_t theBottom,
|
||||
const Elem_t theTop,
|
||||
const Elem_t theNear,
|
||||
const Elem_t theFar,
|
||||
NCollection_Mat4<Elem_t>& theOutMx) const;
|
||||
NCollection_Mat4<Elem_t>& theOutMx);
|
||||
|
||||
//! Compose projection matrix for L/R stereo eyes.
|
||||
//! @param theLeft [in] the left mapping (clipping) coordinate.
|
||||
@@ -617,7 +603,7 @@ private:
|
||||
//! @param theIsLeft [in] boolean flag to choose between L/R eyes.
|
||||
//! @param theOutMx [out] the projection matrix.
|
||||
template <typename Elem_t>
|
||||
void
|
||||
static void
|
||||
StereoEyeProj (const Elem_t theLeft,
|
||||
const Elem_t theRight,
|
||||
const Elem_t theBottom,
|
||||
@@ -627,7 +613,7 @@ private:
|
||||
const Elem_t theIOD,
|
||||
const Elem_t theZFocus,
|
||||
const Standard_Boolean theIsLeft,
|
||||
NCollection_Mat4<Elem_t>& theOutMx) const;
|
||||
NCollection_Mat4<Elem_t>& theOutMx);
|
||||
|
||||
//! Construct "look at" orientation transformation.
|
||||
//! Reference point differs for perspective and ortho modes
|
||||
@@ -680,7 +666,6 @@ private:
|
||||
Standard_Real myZNear; //!< Distance to near clipping plane.
|
||||
Standard_Real myZFar; //!< Distance to far clipping plane.
|
||||
Standard_Real myAspect; //!< Width to height display ratio.
|
||||
Standard_Boolean myIsZeroToOneDepth; //!< use [0, 1] depth range or [-1, 1]
|
||||
|
||||
Standard_Real myScale; //!< Specifies parallel scale for orthographic projection.
|
||||
Standard_Real myZFocus; //!< Stereographic focus value.
|
||||
|
102
src/Graphic3d/Graphic3d_MediaTexture.cxx
Normal file
102
src/Graphic3d/Graphic3d_MediaTexture.cxx
Normal file
@@ -0,0 +1,102 @@
|
||||
// Created by: Kirill GAVRILOV
|
||||
// Copyright (c) 2019 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
// activate some C99 macros like UINT64_C in "stdint.h" which used by FFmpeg
|
||||
#ifndef __STDC_CONSTANT_MACROS
|
||||
#define __STDC_CONSTANT_MACROS
|
||||
#endif
|
||||
|
||||
#include <Graphic3d_MediaTexture.hxx>
|
||||
|
||||
#include <Graphic3d_TextureParams.hxx>
|
||||
#include <Media_Frame.hxx>
|
||||
#include <Message.hxx>
|
||||
#include <Message_Messenger.hxx>
|
||||
|
||||
#ifdef HAVE_FFMPEG
|
||||
#include <Standard_WarningsDisable.hxx>
|
||||
extern "C"
|
||||
{
|
||||
#include <libavcodec/avcodec.h>
|
||||
#include <libavutil/imgutils.h>
|
||||
};
|
||||
#include <Standard_WarningsRestore.hxx>
|
||||
#endif
|
||||
|
||||
IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_MediaTexture, Graphic3d_Texture2D)
|
||||
|
||||
// ================================================================
|
||||
// Function : Graphic3d_MediaTexture
|
||||
// Purpose :
|
||||
// ================================================================
|
||||
Graphic3d_MediaTexture::Graphic3d_MediaTexture (const Handle(Media_HMutex)& theMutex,
|
||||
Standard_Integer thePlane)
|
||||
: Graphic3d_Texture2D ("", Graphic3d_TOT_2D),
|
||||
myMutex (theMutex),
|
||||
myPlane (thePlane)
|
||||
{
|
||||
myParams->SetModulate(false);
|
||||
myParams->SetRepeat (false);
|
||||
myParams->SetFilter (Graphic3d_TOTF_BILINEAR);
|
||||
myParams->SetTextureUnit (Graphic3d_TextureUnit(int(Graphic3d_TextureUnit_0) + thePlane));
|
||||
}
|
||||
|
||||
// ================================================================
|
||||
// Function : GetImage
|
||||
// Purpose :
|
||||
// ================================================================
|
||||
Handle(Image_PixMap) Graphic3d_MediaTexture::GetImage() const
|
||||
{
|
||||
Standard_Mutex::Sentry aLock (myMutex.get());
|
||||
if (myFrame.IsNull()
|
||||
|| myFrame->IsLocked()
|
||||
|| myFrame->IsEmpty()
|
||||
|| myFrame->SizeX() < 1
|
||||
|| myFrame->SizeY() < 1)
|
||||
{
|
||||
return Handle(Image_PixMap)();
|
||||
}
|
||||
|
||||
if (myPixMapWrapper.IsNull())
|
||||
{
|
||||
myPixMapWrapper = new Image_PixMap();
|
||||
}
|
||||
|
||||
#ifdef HAVE_FFMPEG
|
||||
const AVFrame* aFrame = myFrame->Frame();
|
||||
const Image_Format anOcctFmt = Media_Frame::FormatFFmpeg2Occt (myFrame->Format());
|
||||
if (anOcctFmt != Image_Format_UNKNOWN)
|
||||
{
|
||||
if (myPlane != 0
|
||||
|| !myPixMapWrapper->InitWrapper (anOcctFmt, aFrame->data[0], aFrame->width, aFrame->height, aFrame->linesize[0]))
|
||||
{
|
||||
return Handle(Image_PixMap)();
|
||||
}
|
||||
return myPixMapWrapper;
|
||||
}
|
||||
else if (myFrame->Format() == AV_PIX_FMT_YUV420P
|
||||
|| myFrame->Format() == AV_PIX_FMT_YUVJ420P)
|
||||
{
|
||||
const Graphic3d_Vec2i aSize = myPlane == 0 ? myFrame->Size() : myFrame->Size() / 2;
|
||||
if (myPlane > 3
|
||||
|| !myPixMapWrapper->InitWrapper (Image_Format_Gray, aFrame->data[myPlane], aSize.x(), aSize.y(), aFrame->linesize[myPlane]))
|
||||
{
|
||||
return Handle(Image_PixMap)();
|
||||
}
|
||||
return myPixMapWrapper;
|
||||
}
|
||||
#endif
|
||||
|
||||
return Handle(Image_PixMap)();
|
||||
}
|
57
src/Graphic3d/Graphic3d_MediaTexture.hxx
Normal file
57
src/Graphic3d/Graphic3d_MediaTexture.hxx
Normal file
@@ -0,0 +1,57 @@
|
||||
// Created by: Kirill GAVRILOV
|
||||
// Copyright (c) 2019 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _Graphic3d_MediaTexture_HeaderFile
|
||||
#define _Graphic3d_MediaTexture_HeaderFile
|
||||
|
||||
#include <Graphic3d_Texture2D.hxx>
|
||||
#include <NCollection_DefineAlloc.hxx>
|
||||
#include <NCollection_Shared.hxx>
|
||||
#include <Standard_Mutex.hxx>
|
||||
|
||||
class Media_Frame;
|
||||
typedef NCollection_Shared<Standard_Mutex> Media_HMutex;
|
||||
|
||||
//! Texture adapter for Media_Frame.
|
||||
class Graphic3d_MediaTexture : public Graphic3d_Texture2D
|
||||
{
|
||||
DEFINE_STANDARD_RTTIEXT(Graphic3d_MediaTexture, Graphic3d_Texture2D)
|
||||
public:
|
||||
|
||||
//! Main constructor.
|
||||
Standard_EXPORT Graphic3d_MediaTexture (const Handle(Media_HMutex)& theMutex,
|
||||
Standard_Integer thePlane = -1);
|
||||
|
||||
//! Image reader.
|
||||
Standard_EXPORT virtual Handle(Image_PixMap) GetImage() const Standard_OVERRIDE;
|
||||
|
||||
//! Return the frame.
|
||||
const Handle(Media_Frame)& Frame() const { return myFrame; }
|
||||
|
||||
//! Set the frame.
|
||||
void SetFrame (const Handle(Media_Frame)& theFrame) { myFrame = theFrame; }
|
||||
|
||||
//! Regenerate a new texture id
|
||||
void GenerateNewId() { generateId(); }
|
||||
|
||||
protected:
|
||||
|
||||
mutable Handle(Media_HMutex) myMutex;
|
||||
Handle(Media_Frame) myFrame;
|
||||
Standard_Integer myPlane;
|
||||
mutable Handle(Image_PixMap) myPixMapWrapper;
|
||||
|
||||
};
|
||||
|
||||
#endif // _Graphic3d_MediaTexture_HeaderFile
|
260
src/Graphic3d/Graphic3d_MediaTextureSet.cxx
Normal file
260
src/Graphic3d/Graphic3d_MediaTextureSet.cxx
Normal file
@@ -0,0 +1,260 @@
|
||||
// Created by: Kirill GAVRILOV
|
||||
// Copyright (c) 2019 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
// activate some C99 macros like UINT64_C in "stdint.h" which used by FFmpeg
|
||||
#ifndef __STDC_CONSTANT_MACROS
|
||||
#define __STDC_CONSTANT_MACROS
|
||||
#endif
|
||||
|
||||
#include <Graphic3d_MediaTextureSet.hxx>
|
||||
|
||||
#include <Media_Frame.hxx>
|
||||
#include <Media_PlayerContext.hxx>
|
||||
#include <Graphic3d_ShaderProgram.hxx>
|
||||
|
||||
#ifdef HAVE_FFMPEG
|
||||
#include <Standard_WarningsDisable.hxx>
|
||||
extern "C"
|
||||
{
|
||||
#include <libavcodec/avcodec.h>
|
||||
#include <libavutil/imgutils.h>
|
||||
};
|
||||
#include <Standard_WarningsRestore.hxx>
|
||||
#endif
|
||||
|
||||
IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_MediaTextureSet, Graphic3d_TextureSet)
|
||||
|
||||
// ================================================================
|
||||
// Function : Graphic3d_MediaTexture
|
||||
// Purpose :
|
||||
// ================================================================
|
||||
Graphic3d_MediaTextureSet::Graphic3d_MediaTextureSet()
|
||||
: Graphic3d_TextureSet (4),
|
||||
myMutex (new Media_HMutex()),
|
||||
myCallbackFunction(NULL),
|
||||
myCallbackUserPtr (NULL),
|
||||
myProgress (0.0),
|
||||
myDuration (0.0),
|
||||
myFront (0),
|
||||
myToPresentFrame (Standard_False),
|
||||
myIsPlanarYUV (Standard_False),
|
||||
myIsFullRangeYUV (Standard_True)
|
||||
{
|
||||
myFramePair[0] = new Media_Frame();
|
||||
myFramePair[1] = new Media_Frame();
|
||||
|
||||
for (Standard_Integer aPlaneIter = 0; aPlaneIter < Size(); ++aPlaneIter)
|
||||
{
|
||||
Handle(Graphic3d_MediaTexture) aTexture = new Graphic3d_MediaTexture (myMutex, aPlaneIter);
|
||||
SetValue (Lower() + aPlaneIter, aTexture);
|
||||
}
|
||||
|
||||
#define EOL "\n"
|
||||
TCollection_AsciiString aSrcVert =
|
||||
EOL"out vec2 TexCoord;"
|
||||
EOL"void main()"
|
||||
EOL"{"
|
||||
EOL" TexCoord = occTexCoord.st;"
|
||||
EOL " gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;"
|
||||
EOL"}";
|
||||
|
||||
TCollection_AsciiString F_SHADER_YUV2RGB_MPEG =
|
||||
EOL"const float TheRangeBits = 1.0;"
|
||||
EOL"vec3 convertToRGB (in vec3 theYUV)"
|
||||
EOL"{"
|
||||
EOL" vec3 aYUV = theYUV.rgb;"
|
||||
EOL" aYUV *= TheRangeBits;"
|
||||
EOL" aYUV.x = 1.1643 * (aYUV.x - 0.0625);"
|
||||
EOL" aYUV.y -= 0.5;"
|
||||
EOL" aYUV.z -= 0.5;"
|
||||
EOL" vec3 aColor = vec3(0.0);"
|
||||
EOL" aColor.r = aYUV.x + 1.5958 * aYUV.z;"
|
||||
EOL" aColor.g = aYUV.x - 0.39173 * aYUV.y - 0.81290 * aYUV.z;"
|
||||
EOL" aColor.b = aYUV.x + 2.017 * aYUV.y;"
|
||||
EOL" return aColor;"
|
||||
EOL"}";
|
||||
|
||||
TCollection_AsciiString F_SHADER_YUV2RGB_FULL =
|
||||
EOL"const float TheRangeBits = 1.0;"
|
||||
EOL"vec3 convertToRGB (in vec3 theYUV)"
|
||||
EOL"{"
|
||||
EOL" vec3 aYUV = theYUV.rgb;"
|
||||
EOL" aYUV *= TheRangeBits;"
|
||||
EOL" aYUV.x = aYUV.x;"
|
||||
EOL" aYUV.y -= 0.5;"
|
||||
EOL" aYUV.z -= 0.5;"
|
||||
EOL" vec3 aColor = vec3(0.0);"
|
||||
EOL" aColor.r = aYUV.x + 1.402 * aYUV.z;"
|
||||
EOL" aColor.g = aYUV.x - 0.344 * aYUV.y - 0.714 * aYUV.z;"
|
||||
EOL" aColor.b = aYUV.x + 1.772 * aYUV.y;"
|
||||
EOL" return aColor;"
|
||||
EOL"}";
|
||||
|
||||
TCollection_AsciiString aSrcFrag =
|
||||
EOL"in vec2 TexCoord;"
|
||||
EOL"uniform sampler2D occSampler1;"
|
||||
EOL"uniform sampler2D occSampler2;"
|
||||
EOL"vec3 convertToRGB (in vec3 theYUV);"
|
||||
EOL"void main()"
|
||||
EOL"{"
|
||||
EOL" vec3 aYUV = vec3 (occTexture2D (occSampler0, TexCoord.st).r,"
|
||||
EOL" occTexture2D (occSampler1, TexCoord.st).r,"
|
||||
EOL" occTexture2D (occSampler2, TexCoord.st).r);"
|
||||
EOL " occSetFragColor (vec4 (convertToRGB (aYUV), 1.0));"
|
||||
EOL"}";
|
||||
|
||||
myShaderYUV = new Graphic3d_ShaderProgram();
|
||||
myShaderYUV->SetHeader ("#version 150");
|
||||
myShaderYUV->SetNbLightsMax (0);
|
||||
myShaderYUV->SetNbClipPlanesMax (0);
|
||||
myShaderYUV->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert));
|
||||
myShaderYUV->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag + F_SHADER_YUV2RGB_MPEG));
|
||||
|
||||
myShaderYUVJ = new Graphic3d_ShaderProgram();
|
||||
myShaderYUVJ->SetHeader ("#version 150");
|
||||
myShaderYUVJ->SetNbLightsMax (0);
|
||||
myShaderYUVJ->SetNbClipPlanesMax (0);
|
||||
myShaderYUVJ->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert));
|
||||
myShaderYUVJ->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag + F_SHADER_YUV2RGB_FULL));
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : SetCallback
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void Graphic3d_MediaTextureSet::SetCallback (CallbackOnUpdate_t theCallbackFunction,
|
||||
void* theCallbackUserPtr)
|
||||
{
|
||||
myCallbackFunction = theCallbackFunction;
|
||||
myCallbackUserPtr = theCallbackUserPtr;
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : Notify
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void Graphic3d_MediaTextureSet::Notify()
|
||||
{
|
||||
if (myCallbackFunction != NULL)
|
||||
{
|
||||
myCallbackFunction (myCallbackUserPtr);
|
||||
}
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : OpenInput
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void Graphic3d_MediaTextureSet::OpenInput (const TCollection_AsciiString& thePath,
|
||||
Standard_Boolean theToWait)
|
||||
{
|
||||
if (myPlayerCtx.IsNull())
|
||||
{
|
||||
if (thePath.IsEmpty())
|
||||
{
|
||||
myInput.Clear();
|
||||
return;
|
||||
}
|
||||
|
||||
myPlayerCtx = new Media_PlayerContext (this);
|
||||
}
|
||||
|
||||
myProgress = 0.0;
|
||||
myDuration = 0.0;
|
||||
|
||||
myPlayerCtx->SetInput (thePath, theToWait);
|
||||
myInput = thePath;
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : LockFrame
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
Handle(Media_Frame) Graphic3d_MediaTextureSet::LockFrame()
|
||||
{
|
||||
{
|
||||
Standard_Mutex::Sentry aLock (myMutex.get());
|
||||
if (!myToPresentFrame)
|
||||
{
|
||||
Handle(Media_Frame) aFrame = myFramePair[myFront == 0 ? 1 : 0];
|
||||
if (aFrame->IsLocked())
|
||||
{
|
||||
return Handle(Media_Frame)();
|
||||
}
|
||||
|
||||
aFrame->SetLocked (true);
|
||||
return aFrame;
|
||||
}
|
||||
}
|
||||
|
||||
Notify();
|
||||
return Handle(Media_Frame)();
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : ReleaseFrame
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void Graphic3d_MediaTextureSet::ReleaseFrame (const Handle(Media_Frame)& theFrame)
|
||||
{
|
||||
{
|
||||
Standard_Mutex::Sentry aLock (myMutex.get());
|
||||
theFrame->SetLocked (false);
|
||||
myToPresentFrame = true;
|
||||
}
|
||||
|
||||
if (myCallbackFunction != NULL)
|
||||
{
|
||||
myCallbackFunction (myCallbackUserPtr);
|
||||
}
|
||||
}
|
||||
|
||||
// ================================================================
|
||||
// Function : SwapFrames
|
||||
// Purpose :
|
||||
// ================================================================
|
||||
Standard_Boolean Graphic3d_MediaTextureSet::SwapFrames()
|
||||
{
|
||||
if (myPlayerCtx.IsNull())
|
||||
{
|
||||
return Standard_False;
|
||||
}
|
||||
Standard_Boolean isPaused = Standard_False;
|
||||
myPlayerCtx->PlaybackState (isPaused, myProgress, myDuration);
|
||||
|
||||
Standard_Mutex::Sentry aLock (myMutex.get());
|
||||
if (!myToPresentFrame)
|
||||
{
|
||||
return Standard_False;
|
||||
}
|
||||
|
||||
myToPresentFrame = false;
|
||||
myFront = myFront == 0 ? 1 : 0;
|
||||
const Handle(Media_Frame)& aFront = myFramePair[myFront];
|
||||
myFrameSize = aFront->Size();
|
||||
#ifdef HAVE_FFMPEG
|
||||
myIsPlanarYUV = aFront->Format() == AV_PIX_FMT_YUV420P
|
||||
|| aFront->Format() == AV_PIX_FMT_YUVJ420P;
|
||||
#endif
|
||||
myIsFullRangeYUV = aFront->IsFullRangeYUV();
|
||||
for (int aPlaneIter = Lower(); aPlaneIter <= Upper(); ++aPlaneIter)
|
||||
{
|
||||
if (Graphic3d_MediaTexture* aTexture = dynamic_cast<Graphic3d_MediaTexture*> (Value (aPlaneIter).get()))
|
||||
{
|
||||
aTexture->SetFrame (aFront);
|
||||
aTexture->UpdateRevision();
|
||||
}
|
||||
}
|
||||
return Standard_True;
|
||||
}
|
113
src/Graphic3d/Graphic3d_MediaTextureSet.hxx
Normal file
113
src/Graphic3d/Graphic3d_MediaTextureSet.hxx
Normal file
@@ -0,0 +1,113 @@
|
||||
// Created by: Kirill GAVRILOV
|
||||
// Copyright (c) 2019 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _Graphic3d_MediaTextureSet_HeaderFile
|
||||
#define _Graphic3d_MediaTextureSet_HeaderFile
|
||||
|
||||
#include <Media_IFrameQueue.hxx>
|
||||
#include <Graphic3d_MediaTexture.hxx>
|
||||
#include <Graphic3d_TextureSet.hxx>
|
||||
|
||||
class Graphic3d_ShaderProgram;
|
||||
class Media_PlayerContext;
|
||||
|
||||
//! Texture adapter for Media_Frame.
|
||||
class Graphic3d_MediaTextureSet : public Graphic3d_TextureSet, public Media_IFrameQueue
|
||||
{
|
||||
DEFINE_STANDARD_RTTIEXT(Graphic3d_MediaTextureSet, Graphic3d_TextureSet)
|
||||
public:
|
||||
|
||||
//! Callback definition.
|
||||
typedef void (*CallbackOnUpdate_t)(void* theUserPtr);
|
||||
|
||||
public:
|
||||
|
||||
//! Empty constructor.
|
||||
Standard_EXPORT Graphic3d_MediaTextureSet();
|
||||
|
||||
//! Setup callback to be called on queue progress (e.g. when new frame should be displayed).
|
||||
Standard_EXPORT void SetCallback (CallbackOnUpdate_t theCallbackFunction, void* theCallbackUserPtr);
|
||||
|
||||
//! Call callback.
|
||||
Standard_EXPORT void Notify();
|
||||
|
||||
//! Return input media.
|
||||
const TCollection_AsciiString& Input() const { return myInput; }
|
||||
|
||||
//! Open specified file.
|
||||
//! Passing an empty path would close current input.
|
||||
Standard_EXPORT void OpenInput (const TCollection_AsciiString& thePath,
|
||||
Standard_Boolean theToWait);
|
||||
|
||||
//! Return player context; it can be NULL until first OpenInput().
|
||||
const Handle(Media_PlayerContext)& PlayerContext() const { return myPlayerCtx; }
|
||||
|
||||
//! Swap front/back frames.
|
||||
Standard_EXPORT Standard_Boolean SwapFrames();
|
||||
|
||||
//! Return front frame dimensions.
|
||||
Graphic3d_Vec2i FrameSize() const { return myFrameSize; }
|
||||
|
||||
//! Return shader program for displaying texture set.
|
||||
Handle(Graphic3d_ShaderProgram) ShaderProgram() const
|
||||
{
|
||||
if (myIsPlanarYUV)
|
||||
{
|
||||
return myIsFullRangeYUV ? myShaderYUVJ : myShaderYUV;
|
||||
}
|
||||
return Handle(Graphic3d_ShaderProgram)();
|
||||
}
|
||||
|
||||
//! Return TRUE if texture set defined 3 YUV planes.
|
||||
Standard_Boolean IsPlanarYUV() const { return myIsPlanarYUV; }
|
||||
|
||||
//! Return TRUE if YUV range is full.
|
||||
Standard_Boolean IsFullRangeYUV() const { return myIsFullRangeYUV; }
|
||||
|
||||
//! Return duration in seconds.
|
||||
double Duration() const { return myDuration; }
|
||||
|
||||
//! Return playback progress in seconds.
|
||||
double Progress() const { return myProgress; }
|
||||
|
||||
//! @name Media_IFrameQueue interface
|
||||
private:
|
||||
|
||||
//! Lock the frame for decoding into.
|
||||
virtual Handle(Media_Frame) LockFrame() Standard_OVERRIDE;
|
||||
|
||||
//! Release the frame to present decoding results.
|
||||
virtual void ReleaseFrame (const Handle(Media_Frame)& theFrame) Standard_OVERRIDE;
|
||||
|
||||
protected:
|
||||
|
||||
Handle(Media_PlayerContext) myPlayerCtx; //!< player context
|
||||
Handle(Media_Frame) myFramePair[2]; //!< front/back frames pair
|
||||
Handle(Graphic3d_ShaderProgram) myShaderYUV; //!< shader program for YUV texture set
|
||||
Handle(Graphic3d_ShaderProgram) myShaderYUVJ; //!< shader program for YUVJ texture set
|
||||
Handle(Media_HMutex) myMutex; //!< mutex for accessing frames
|
||||
TCollection_AsciiString myInput; //!< input media
|
||||
CallbackOnUpdate_t myCallbackFunction; //!< callback function
|
||||
void* myCallbackUserPtr; //!< callback data
|
||||
Graphic3d_Vec2i myFrameSize; //!< front frame size
|
||||
Standard_Real myProgress; //!< playback progress in seconds
|
||||
Standard_Real myDuration; //!< stream duration
|
||||
Standard_Integer myFront; //!< index of front texture
|
||||
Standard_Boolean myToPresentFrame; //!< flag
|
||||
Standard_Boolean myIsPlanarYUV; //!< front frame contains planar YUV data or native texture format
|
||||
Standard_Boolean myIsFullRangeYUV; //!< front frame defines full-range or reduced-range YUV
|
||||
|
||||
};
|
||||
|
||||
#endif // _Graphic3d_MediaTextureSet_HeaderFile
|
@@ -283,7 +283,7 @@ Standard_Boolean Image_VideoRecorder::addVideoStream (const Image_VideoParams& t
|
||||
// some formats want stream headers to be separate
|
||||
if (myAVContext->oformat->flags & AVFMT_GLOBALHEADER)
|
||||
{
|
||||
aCodecCtx->flags |= CODEC_FLAG_GLOBAL_HEADER;
|
||||
aCodecCtx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
|
||||
}
|
||||
return Standard_True;
|
||||
#else
|
||||
@@ -456,18 +456,6 @@ Standard_Boolean Image_VideoRecorder::writeVideoFrame (const Standard_Boolean th
|
||||
AVPacket aPacket;
|
||||
memset (&aPacket, 0, sizeof(aPacket));
|
||||
av_init_packet (&aPacket);
|
||||
if ((myAVContext->oformat->flags & AVFMT_RAWPICTURE) != 0
|
||||
&& !theToFlush)
|
||||
{
|
||||
// raw video case - directly store the picture in the packet
|
||||
aPacket.flags |= AV_PKT_FLAG_KEY;
|
||||
aPacket.stream_index = myVideoStream->index;
|
||||
aPacket.data = myFrame->data[0];
|
||||
aPacket.size = sizeof(AVPicture);
|
||||
|
||||
aResAv = av_interleaved_write_frame (myAVContext, &aPacket);
|
||||
}
|
||||
else
|
||||
{
|
||||
// encode the image
|
||||
myFrame->pts = myFrameCount;
|
||||
|
@@ -2077,7 +2077,7 @@ void IntAna_QuadQuadGeo::Perform(const gp_Pln& Pln,
|
||||
}
|
||||
//
|
||||
if (Abs(aDR) < aTolNum) {
|
||||
aDist=aRMin;
|
||||
aDist = (aDist < 0) ? -aRMin : aRMin;
|
||||
}
|
||||
//
|
||||
typeres = IntAna_Circle;
|
||||
|
17
src/Media/FILES
Normal file
17
src/Media/FILES
Normal file
@@ -0,0 +1,17 @@
|
||||
Media_BufferPool.cxx
|
||||
Media_BufferPool.hxx
|
||||
Media_CodecContext.cxx
|
||||
Media_CodecContext.hxx
|
||||
Media_FormatContext.cxx
|
||||
Media_FormatContext.hxx
|
||||
Media_Frame.cxx
|
||||
Media_Frame.hxx
|
||||
Media_Packet.cxx
|
||||
Media_Packet.hxx
|
||||
Media_PlayerContext.cxx
|
||||
Media_PlayerContext.hxx
|
||||
Media_Scaler.cxx
|
||||
Media_Scaler.hxx
|
||||
Media_Timer.cxx
|
||||
Media_Timer.hxx
|
||||
Media_IFrameQueue.hxx
|
107
src/Media/Media_BufferPool.cxx
Normal file
107
src/Media/Media_BufferPool.cxx
Normal file
@@ -0,0 +1,107 @@
|
||||
// Created by: Kirill GAVRILOV
|
||||
// Copyright (c) 2019 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
// activate some C99 macros like UINT64_C in "stdint.h" which used by FFmpeg
|
||||
#ifndef __STDC_CONSTANT_MACROS
|
||||
#define __STDC_CONSTANT_MACROS
|
||||
#endif
|
||||
|
||||
#include <Media_BufferPool.hxx>
|
||||
|
||||
#include <Media_Frame.hxx>
|
||||
|
||||
#ifdef HAVE_FFMPEG
|
||||
#include <Standard_WarningsDisable.hxx>
|
||||
extern "C"
|
||||
{
|
||||
#include <libavcodec/avcodec.h>
|
||||
#include <libavutil/imgutils.h>
|
||||
};
|
||||
#include <Standard_WarningsRestore.hxx>
|
||||
#endif
|
||||
|
||||
IMPLEMENT_STANDARD_RTTIEXT(Media_BufferPool, Standard_Transient)
|
||||
|
||||
// =======================================================================
|
||||
// function : Media_BufferPool
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
Media_BufferPool::Media_BufferPool()
|
||||
: myPool (NULL),
|
||||
myBufferSize (0)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : ~Media_BufferPool
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
Media_BufferPool::~Media_BufferPool()
|
||||
{
|
||||
Release();
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : Release
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void Media_BufferPool::Release()
|
||||
{
|
||||
if (myPool != NULL)
|
||||
{
|
||||
#ifdef HAVE_FFMPEG
|
||||
av_buffer_pool_uninit (&myPool);
|
||||
#endif
|
||||
myPool = NULL;
|
||||
myBufferSize = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : Init
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
bool Media_BufferPool::Init (int theBufferSize)
|
||||
{
|
||||
if (myBufferSize == theBufferSize)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
Release();
|
||||
if (theBufferSize == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef HAVE_FFMPEG
|
||||
myPool = av_buffer_pool_init (theBufferSize, NULL);
|
||||
#endif
|
||||
myBufferSize = theBufferSize;
|
||||
return myPool != NULL;
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : GetBuffer
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
AVBufferRef* Media_BufferPool::GetBuffer()
|
||||
{
|
||||
#ifdef HAVE_FFMPEG
|
||||
return av_buffer_pool_get (myPool);
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
61
src/Media/Media_BufferPool.hxx
Normal file
61
src/Media/Media_BufferPool.hxx
Normal file
@@ -0,0 +1,61 @@
|
||||
// Created by: Kirill GAVRILOV
|
||||
// Copyright (c) 2019 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _Media_BufferPool_HeaderFile
|
||||
#define _Media_BufferPool_HeaderFile
|
||||
|
||||
#include <Standard_Transient.hxx>
|
||||
#include <Standard_Type.hxx>
|
||||
|
||||
struct AVBufferPool;
|
||||
struct AVBufferRef;
|
||||
|
||||
//! AVBufferPool wrapper.
|
||||
class Media_BufferPool : public Standard_Transient
|
||||
{
|
||||
DEFINE_STANDARD_RTTIEXT(Media_BufferPool, Standard_Transient)
|
||||
public:
|
||||
|
||||
//! Empty constructor
|
||||
Standard_EXPORT Media_BufferPool();
|
||||
|
||||
//! Destructor
|
||||
Standard_EXPORT ~Media_BufferPool();
|
||||
|
||||
//! Release the pool (reference-counted buffer will be released when needed).
|
||||
Standard_EXPORT void Release();
|
||||
|
||||
//! (Re-)initialize the pool.
|
||||
Standard_EXPORT bool Init (int theBufferSize);
|
||||
|
||||
//! Return buffer size within the pool.
|
||||
int BufferSize() const { return myBufferSize; }
|
||||
|
||||
//! Get new buffer from the pool.
|
||||
Standard_EXPORT AVBufferRef* GetBuffer();
|
||||
|
||||
private:
|
||||
|
||||
// prevent copies
|
||||
Media_BufferPool (const Media_BufferPool& theCopy);
|
||||
Media_BufferPool& operator=(const Media_BufferPool& theCopy);
|
||||
|
||||
protected:
|
||||
|
||||
AVBufferPool* myPool;
|
||||
int myBufferSize;
|
||||
|
||||
};
|
||||
|
||||
#endif // _Media_BufferPool_HeaderFile
|
277
src/Media/Media_CodecContext.cxx
Normal file
277
src/Media/Media_CodecContext.cxx
Normal file
@@ -0,0 +1,277 @@
|
||||
// Created by: Kirill GAVRILOV
|
||||
// Copyright (c) 2019 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
// activate some C99 macros like UINT64_C in "stdint.h" which used by FFmpeg
|
||||
#ifndef __STDC_CONSTANT_MACROS
|
||||
#define __STDC_CONSTANT_MACROS
|
||||
#endif
|
||||
|
||||
#include <Media_CodecContext.hxx>
|
||||
|
||||
#include <Media_Frame.hxx>
|
||||
#include <Media_FormatContext.hxx>
|
||||
|
||||
#include <Message.hxx>
|
||||
#include <Message_Messenger.hxx>
|
||||
#include <OSD_Parallel.hxx>
|
||||
|
||||
#ifdef HAVE_FFMPEG
|
||||
#include <Standard_WarningsDisable.hxx>
|
||||
extern "C"
|
||||
{
|
||||
#include <libavformat/avformat.h>
|
||||
};
|
||||
#include <Standard_WarningsRestore.hxx>
|
||||
#endif
|
||||
|
||||
IMPLEMENT_STANDARD_RTTIEXT(Media_CodecContext, Standard_Transient)
|
||||
|
||||
// =======================================================================
|
||||
// function : Media_CodecContext
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
Media_CodecContext::Media_CodecContext()
|
||||
: myCodecCtx (NULL),
|
||||
myCodec (NULL),
|
||||
myPtsStartBase (0.0),
|
||||
myPtsStartStream(0.0),
|
||||
myTimeBase (1.0),
|
||||
myStreamIndex (0),
|
||||
myPixelAspectRatio (1.0f)
|
||||
{
|
||||
#ifdef HAVE_FFMPEG
|
||||
myCodecCtx = avcodec_alloc_context3 (NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : ~Media_CodecContext
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
Media_CodecContext::~Media_CodecContext()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : Init
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
bool Media_CodecContext::Init (const AVStream& theStream,
|
||||
double thePtsStartBase,
|
||||
int theNbThreads)
|
||||
{
|
||||
#ifdef HAVE_FFMPEG
|
||||
return Init (theStream, thePtsStartBase, theNbThreads, AV_CODEC_ID_NONE);
|
||||
#else
|
||||
return Init (theStream, thePtsStartBase, theNbThreads, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : Init
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
bool Media_CodecContext::Init (const AVStream& theStream,
|
||||
double thePtsStartBase,
|
||||
int theNbThreads,
|
||||
int theCodecId)
|
||||
{
|
||||
#ifdef HAVE_FFMPEG
|
||||
myStreamIndex = theStream.index;
|
||||
if (avcodec_parameters_to_context (myCodecCtx, theStream.codecpar) < 0)
|
||||
{
|
||||
Message::DefaultMessenger()->Send ("Internal error: unable to copy codec parameters", Message_Fail);
|
||||
Close();
|
||||
return false;
|
||||
}
|
||||
|
||||
myTimeBase = av_q2d (theStream.time_base);
|
||||
myPtsStartBase = thePtsStartBase;
|
||||
myPtsStartStream = Media_FormatContext::StreamUnitsToSeconds (theStream, theStream.start_time);
|
||||
|
||||
const AVCodecID aCodecId = theCodecId != AV_CODEC_ID_NONE ? (AVCodecID )theCodecId : theStream.codecpar->codec_id;
|
||||
myCodec = avcodec_find_decoder (aCodecId);
|
||||
if (myCodec == NULL)
|
||||
{
|
||||
Message::DefaultMessenger()->Send ("FFmpeg: unable to find decoder", Message_Fail);
|
||||
Close();
|
||||
return false;
|
||||
}
|
||||
|
||||
myCodecCtx->codec_id = aCodecId;
|
||||
AVDictionary* anOpts = NULL;
|
||||
av_dict_set (&anOpts, "refcounted_frames", "1", 0);
|
||||
if (theStream.codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
|
||||
{
|
||||
myCodecCtx->thread_count = theNbThreads <= -1 ? OSD_Parallel::NbLogicalProcessors() : theNbThreads;
|
||||
}
|
||||
|
||||
if (avcodec_open2 (myCodecCtx, myCodec, &anOpts) < 0)
|
||||
{
|
||||
Message::DefaultMessenger()->Send ("FFmpeg: unable to open decoder", Message_Fail);
|
||||
Close();
|
||||
return false;
|
||||
}
|
||||
|
||||
myPixelAspectRatio = 1.0f;
|
||||
if (theStream.sample_aspect_ratio.num && av_cmp_q(theStream.sample_aspect_ratio, myCodecCtx->sample_aspect_ratio))
|
||||
{
|
||||
myPixelAspectRatio = float(theStream.sample_aspect_ratio.num) / float(theStream.sample_aspect_ratio.den);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (myCodecCtx->sample_aspect_ratio.num == 0
|
||||
|| myCodecCtx->sample_aspect_ratio.den == 0)
|
||||
{
|
||||
myPixelAspectRatio = 1.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
myPixelAspectRatio = float(myCodecCtx->sample_aspect_ratio.num) / float(myCodecCtx->sample_aspect_ratio.den);
|
||||
}
|
||||
}
|
||||
|
||||
if (theStream.codecpar->codec_type == AVMEDIA_TYPE_VIDEO
|
||||
&& (myCodecCtx->width <= 0
|
||||
|| myCodecCtx->height <= 0))
|
||||
{
|
||||
Message::DefaultMessenger()->Send ("FFmpeg: video stream has invalid dimensions", Message_Fail);
|
||||
Close();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
#else
|
||||
(void )&theStream;
|
||||
(void )thePtsStartBase;
|
||||
(void )theNbThreads;
|
||||
(void )theCodecId;
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : Close
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void Media_CodecContext::Close()
|
||||
{
|
||||
if (myCodecCtx != NULL)
|
||||
{
|
||||
#ifdef HAVE_FFMPEG
|
||||
avcodec_free_context (&myCodecCtx);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : Flush
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void Media_CodecContext::Flush()
|
||||
{
|
||||
if (myCodecCtx != NULL)
|
||||
{
|
||||
#ifdef HAVE_FFMPEG
|
||||
avcodec_flush_buffers (myCodecCtx);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : SizeX
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
int Media_CodecContext::SizeX() const
|
||||
{
|
||||
#ifdef HAVE_FFMPEG
|
||||
return (myCodecCtx != NULL) ? myCodecCtx->width : 0;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : SizeY
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
int Media_CodecContext::SizeY() const
|
||||
{
|
||||
#ifdef HAVE_FFMPEG
|
||||
return (myCodecCtx != NULL) ? myCodecCtx->height : 0;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : CanProcessPacket
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
bool Media_CodecContext::CanProcessPacket (const Handle(Media_Packet)& thePacket) const
|
||||
{
|
||||
return !thePacket.IsNull()
|
||||
&& myStreamIndex == thePacket->StreamIndex();
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : SendPacket
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
bool Media_CodecContext::SendPacket (const Handle(Media_Packet)& thePacket)
|
||||
{
|
||||
if (!CanProcessPacket (thePacket))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef HAVE_FFMPEG
|
||||
const int aRes = avcodec_send_packet (myCodecCtx, thePacket->Packet());
|
||||
if (aRes < 0 && aRes != AVERROR_EOF)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : ReceiveFrame
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
bool Media_CodecContext::ReceiveFrame (const Handle(Media_Frame)& theFrame)
|
||||
{
|
||||
if (theFrame.IsNull())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef HAVE_FFMPEG
|
||||
const int aRes2 = avcodec_receive_frame (myCodecCtx, theFrame->ChangeFrame());
|
||||
if (aRes2 < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const int64_t aPacketPts = theFrame->BestEffortTimestamp() != AV_NOPTS_VALUE ? theFrame->BestEffortTimestamp() : 0;
|
||||
const double aFramePts = double(aPacketPts) * myTimeBase - myPtsStartBase;
|
||||
theFrame->SetPts (aFramePts);
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
100
src/Media/Media_CodecContext.hxx
Normal file
100
src/Media/Media_CodecContext.hxx
Normal file
@@ -0,0 +1,100 @@
|
||||
// Created by: Kirill GAVRILOV
|
||||
// Copyright (c) 2019 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _Media_CodecContext_HeaderFile
|
||||
#define _Media_CodecContext_HeaderFile
|
||||
|
||||
#include <Media_Packet.hxx>
|
||||
|
||||
struct AVCodec;
|
||||
struct AVCodecContext;
|
||||
struct AVStream;
|
||||
class Media_Frame;
|
||||
|
||||
//! AVCodecContext wrapper - the coder/decoder holder.
|
||||
class Media_CodecContext : public Standard_Transient
|
||||
{
|
||||
DEFINE_STANDARD_RTTIEXT(Media_CodecContext, Standard_Transient)
|
||||
public:
|
||||
|
||||
//! Constructor.
|
||||
Standard_EXPORT Media_CodecContext();
|
||||
|
||||
//! Destructor.
|
||||
Standard_EXPORT virtual ~Media_CodecContext();
|
||||
|
||||
//! Return context.
|
||||
AVCodecContext* Context() const { return myCodecCtx; }
|
||||
|
||||
//! Open codec specified within the stream.
|
||||
//! @param theStream stream to open
|
||||
//! @param thePtsStartBase PTS start in seconds
|
||||
//! @param theNbThreads amount of threads to use for AVMEDIA_TYPE_VIDEO stream;
|
||||
//! -1 means OSD_Parallel::NbLogicalProcessors(),
|
||||
//! 0 means auto by FFmpeg itself
|
||||
//! >0 means specified number of threads (decoder should support multi-threading to take effect)
|
||||
Standard_EXPORT bool Init (const AVStream& theStream,
|
||||
double thePtsStartBase,
|
||||
int theNbThreads = -1);
|
||||
|
||||
//! Open codec.
|
||||
//! @param theStream stream to open
|
||||
//! @param thePtsStartBase PTS start in seconds
|
||||
//! @param theNbThreads amount of threads to use for AVMEDIA_TYPE_VIDEO stream;
|
||||
//! -1 means OSD_Parallel::NbLogicalProcessors(),
|
||||
//! 0 means auto by FFmpeg itself
|
||||
//! >0 means specified number of threads (decoder should support multi-threading to take effect)
|
||||
//! @param theCodecId codec (AVCodecID) to open
|
||||
Standard_EXPORT bool Init (const AVStream& theStream,
|
||||
double thePtsStartBase,
|
||||
int theNbThreads,
|
||||
int theCodecId);
|
||||
|
||||
//! Close input.
|
||||
Standard_EXPORT void Close();
|
||||
|
||||
//! @return source frame width
|
||||
Standard_EXPORT int SizeX() const;
|
||||
|
||||
//! @return source frame height
|
||||
Standard_EXPORT int SizeY() const;
|
||||
|
||||
//! Return stream index.
|
||||
int StreamIndex() const { return myStreamIndex; }
|
||||
|
||||
//! avcodec_flush_buffers() wrapper.
|
||||
Standard_EXPORT void Flush();
|
||||
|
||||
//! Return true if packet belongs to this stream.
|
||||
Standard_EXPORT bool CanProcessPacket (const Handle(Media_Packet)& thePacket) const;
|
||||
|
||||
//! avcodec_send_packet() wrapper.
|
||||
Standard_EXPORT bool SendPacket (const Handle(Media_Packet)& thePacket);
|
||||
|
||||
//! avcodec_receive_frame() wrapper.
|
||||
Standard_EXPORT bool ReceiveFrame (const Handle(Media_Frame)& theFrame);
|
||||
|
||||
protected:
|
||||
|
||||
AVCodecContext* myCodecCtx; //!< codec context
|
||||
AVCodec* myCodec; //!< opened codec
|
||||
double myPtsStartBase; //!< starting PTS in context
|
||||
double myPtsStartStream; //!< starting PTS in the stream
|
||||
double myTimeBase; //!< stream timebase
|
||||
int myStreamIndex; //!< stream index
|
||||
float myPixelAspectRatio; //!< pixel aspect ratio
|
||||
|
||||
};
|
||||
|
||||
#endif // _Media_CodecContext_HeaderFile
|
558
src/Media/Media_FormatContext.cxx
Normal file
558
src/Media/Media_FormatContext.cxx
Normal file
@@ -0,0 +1,558 @@
|
||||
// Created by: Kirill GAVRILOV
|
||||
// Copyright (c) 2019 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
// activate some C99 macros like UINT64_C in "stdint.h" which used by FFmpeg
|
||||
#ifndef __STDC_CONSTANT_MACROS
|
||||
#define __STDC_CONSTANT_MACROS
|
||||
#endif
|
||||
|
||||
#include <Media_FormatContext.hxx>
|
||||
|
||||
#include <Message.hxx>
|
||||
#include <Message_Messenger.hxx>
|
||||
|
||||
#ifdef HAVE_FFMPEG
|
||||
#include <Standard_WarningsDisable.hxx>
|
||||
extern "C"
|
||||
{
|
||||
#include <libavformat/avformat.h>
|
||||
};
|
||||
#include <Standard_WarningsRestore.hxx>
|
||||
#endif
|
||||
|
||||
IMPLEMENT_STANDARD_RTTIEXT(Media_FormatContext, Standard_Transient)
|
||||
|
||||
namespace
|
||||
{
|
||||
static const double THE_SECONDS_IN_HOUR = 3600.0;
|
||||
static const double THE_SECONDS_IN_MINUTE = 60.0;
|
||||
static const double THE_SECOND_IN_HOUR = 1.0 / THE_SECONDS_IN_HOUR;
|
||||
static const double THE_SECOND_IN_MINUTE = 1.0 / THE_SECONDS_IN_MINUTE;
|
||||
|
||||
#ifdef HAVE_FFMPEG
|
||||
static const AVRational ST_AV_TIME_BASE_Q = {1, AV_TIME_BASE};
|
||||
static const double ST_AV_TIME_BASE_D = av_q2d (ST_AV_TIME_BASE_Q);
|
||||
|
||||
//! Format framerate value.
|
||||
static TCollection_AsciiString formatFps (double theVal)
|
||||
{
|
||||
const uint64_t aVal = uint64_t(theVal * 100.0 + 0.5);
|
||||
char aBuff[256];
|
||||
if(aVal == 0)
|
||||
{
|
||||
Sprintf (aBuff, "%1.4f", theVal);
|
||||
}
|
||||
else if (aVal % 100)
|
||||
{
|
||||
Sprintf (aBuff, "%3.2f", theVal);
|
||||
}
|
||||
else if (aVal % (100 * 1000))
|
||||
{
|
||||
Sprintf (aBuff, "%1.0f", theVal);
|
||||
}
|
||||
else
|
||||
{
|
||||
Sprintf (aBuff, "%1.0fk", theVal / 1000);
|
||||
}
|
||||
return aBuff;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : FormatAVErrorDescription
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
TCollection_AsciiString Media_FormatContext::FormatAVErrorDescription (int theErrCodeAV)
|
||||
{
|
||||
#ifdef HAVE_FFMPEG
|
||||
char aBuff[4096];
|
||||
memset (aBuff, 0, sizeof(aBuff));
|
||||
if (av_strerror (theErrCodeAV, aBuff, 4096) != -1)
|
||||
{
|
||||
return TCollection_AsciiString (aBuff);
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
wchar_t aBuffW[4096];
|
||||
memset (aBuffW, 0, sizeof(aBuffW));
|
||||
if (_wcserror_s (aBuffW, 4096, AVUNERROR(theErrCodeAV)) == 0)
|
||||
{
|
||||
return TCollection_AsciiString (aBuffW);
|
||||
}
|
||||
#elif defined(_WIN32)
|
||||
// MinGW has only thread-unsafe variant
|
||||
char* anErrDesc = strerror (AVUNERROR(theErrCodeAV));
|
||||
if (anErrDesc != NULL)
|
||||
{
|
||||
return TCollection_AsciiString (anErrDesc);
|
||||
}
|
||||
#endif
|
||||
return TCollection_AsciiString (aBuff);
|
||||
#else
|
||||
return TCollection_AsciiString ("AVError #") + theErrCodeAV;
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : FormatUnitsToSeconds
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
double Media_FormatContext::FormatUnitsToSeconds (int64_t theTimeUnits)
|
||||
{
|
||||
#ifdef HAVE_FFMPEG
|
||||
return (theTimeUnits != AV_NOPTS_VALUE)
|
||||
? (ST_AV_TIME_BASE_D * theTimeUnits) : 0.0;
|
||||
#else
|
||||
(void )theTimeUnits;
|
||||
return 0.0;
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : UnitsToSeconds
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
double Media_FormatContext::UnitsToSeconds (const AVRational& theTimeBase,
|
||||
int64_t theTimeUnits)
|
||||
{
|
||||
#ifdef HAVE_FFMPEG
|
||||
return (theTimeUnits != AV_NOPTS_VALUE)
|
||||
? (av_q2d (theTimeBase) * theTimeUnits) : 0.0;
|
||||
#else
|
||||
(void )&theTimeBase;
|
||||
(void )theTimeUnits;
|
||||
return 0.0;
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : StreamUnitsToSeconds
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
double Media_FormatContext::StreamUnitsToSeconds (const AVStream& theStream,
|
||||
int64_t theTimeUnits)
|
||||
{
|
||||
#ifdef HAVE_FFMPEG
|
||||
return UnitsToSeconds (theStream.time_base, theTimeUnits);
|
||||
#else
|
||||
(void )&theStream;
|
||||
(void )theTimeUnits;
|
||||
return 0.0;
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : SecondsToUnits
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
int64_t Media_FormatContext::SecondsToUnits (double theTimeSeconds)
|
||||
{
|
||||
#ifdef HAVE_FFMPEG
|
||||
return int64_t(theTimeSeconds / ST_AV_TIME_BASE_D);
|
||||
#else
|
||||
(void )theTimeSeconds;
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : SecondsToUnits
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
int64_t Media_FormatContext::SecondsToUnits (const AVRational& theTimeBase,
|
||||
double theTimeSeconds)
|
||||
{
|
||||
#ifdef HAVE_FFMPEG
|
||||
return int64_t(theTimeSeconds / av_q2d (theTimeBase));
|
||||
#else
|
||||
(void )&theTimeBase;
|
||||
(void )theTimeSeconds;
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : Media_FormatContext
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
int64_t Media_FormatContext::StreamSecondsToUnits (const AVStream& theStream,
|
||||
double theTimeSeconds)
|
||||
{
|
||||
#ifdef HAVE_FFMPEG
|
||||
return SecondsToUnits (theStream.time_base, theTimeSeconds);
|
||||
#else
|
||||
(void )&theStream;
|
||||
(void )theTimeSeconds;
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : Media_FormatContext
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
Media_FormatContext::Media_FormatContext()
|
||||
: myFormatCtx (NULL),
|
||||
myPtsStartBase(0.0),
|
||||
myDuration (0.0)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : ~Media_FormatContext
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
Media_FormatContext::~Media_FormatContext()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : NbSteams
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
unsigned int Media_FormatContext::NbSteams() const
|
||||
{
|
||||
#ifdef HAVE_FFMPEG
|
||||
return myFormatCtx->nb_streams;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : Stream
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
const AVStream& Media_FormatContext::Stream (unsigned int theIndex) const
|
||||
{
|
||||
#ifdef HAVE_FFMPEG
|
||||
return *myFormatCtx->streams[theIndex];
|
||||
#else
|
||||
(void )theIndex;
|
||||
throw Standard_ProgramError("Media_FormatContext::Stream()");
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : OpenInput
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
bool Media_FormatContext::OpenInput (const TCollection_AsciiString& theInput)
|
||||
{
|
||||
#ifdef HAVE_FFMPEG
|
||||
const int avErrCode = avformat_open_input (&myFormatCtx, theInput.ToCString(), NULL, NULL);
|
||||
if (avErrCode != 0)
|
||||
{
|
||||
Message::DefaultMessenger()->Send (TCollection_AsciiString ("FFmpeg: Couldn't open video file '") + theInput
|
||||
+ "'\nError: " + FormatAVErrorDescription (avErrCode), Message_Fail);
|
||||
Close();
|
||||
return false;
|
||||
}
|
||||
|
||||
// retrieve stream information
|
||||
if (avformat_find_stream_info (myFormatCtx, NULL) < 0)
|
||||
{
|
||||
Message::DefaultMessenger()->Send (TCollection_AsciiString ("FFmpeg: Couldn't find stream information in '") + theInput + "'", Message_Fail);
|
||||
Close();
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
av_dump_format (myFormatCtx, 0, theInput.ToCString(), false);
|
||||
#endif
|
||||
|
||||
myDuration = 0.0;
|
||||
myPtsStartBase = 0.0;
|
||||
|
||||
TCollection_AsciiString anExt = theInput;
|
||||
anExt.LowerCase();
|
||||
if (anExt.EndsWith (".png")
|
||||
|| anExt.EndsWith (".jpg")
|
||||
|| anExt.EndsWith (".jpeg")
|
||||
|| anExt.EndsWith (".mpo")
|
||||
|| anExt.EndsWith (".bmp")
|
||||
|| anExt.EndsWith (".tif")
|
||||
|| anExt.EndsWith (".tiff"))
|
||||
{
|
||||
// black-list images to workaround non-zero duration
|
||||
return true;
|
||||
}
|
||||
|
||||
myDuration = FormatUnitsToSeconds (myFormatCtx->duration);
|
||||
if (myFormatCtx->nb_streams != 0)
|
||||
{
|
||||
myPtsStartBase = 2.e+100;
|
||||
for (unsigned int aStreamId = 0; aStreamId < myFormatCtx->nb_streams; ++aStreamId)
|
||||
{
|
||||
const AVStream& aStream = *myFormatCtx->streams[aStreamId];
|
||||
myPtsStartBase = Min (myPtsStartBase, StreamUnitsToSeconds (aStream, aStream.start_time));
|
||||
myDuration = Max (myDuration, StreamUnitsToSeconds (aStream, aStream.duration));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
#else
|
||||
Message::DefaultMessenger()->Send ("Error: FFmpeg library is unavailable", Message_Fail);
|
||||
(void )theInput;
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : Close
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void Media_FormatContext::Close()
|
||||
{
|
||||
if (myFormatCtx != NULL)
|
||||
{
|
||||
#ifdef HAVE_FFMPEG
|
||||
avformat_close_input (&myFormatCtx);
|
||||
//avformat_free_context (myFormatCtx);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : FormatTime
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
TCollection_AsciiString Media_FormatContext::FormatTime (double theSeconds)
|
||||
{
|
||||
double aSecIn = theSeconds;
|
||||
unsigned int aHours = (unsigned int )(aSecIn * THE_SECOND_IN_HOUR);
|
||||
aSecIn -= double(aHours) * THE_SECONDS_IN_HOUR;
|
||||
unsigned int aMinutes = (unsigned int )(aSecIn * THE_SECOND_IN_MINUTE);
|
||||
aSecIn -= double(aMinutes) * THE_SECONDS_IN_MINUTE;
|
||||
unsigned int aSeconds = (unsigned int )aSecIn;
|
||||
aSecIn -= double(aSeconds);
|
||||
double aMilliSeconds = 1000.0 * aSecIn;
|
||||
|
||||
char aBuffer[64];
|
||||
if (aHours > 0)
|
||||
{
|
||||
Sprintf (aBuffer, "%02u:%02u:%02u", aHours, aMinutes, aSeconds);
|
||||
return aBuffer;
|
||||
}
|
||||
else if (aMinutes > 0)
|
||||
{
|
||||
Sprintf (aBuffer, "%02u:%02u", aMinutes, aSeconds);
|
||||
return aBuffer;
|
||||
}
|
||||
else if (aSeconds > 0)
|
||||
{
|
||||
Sprintf (aBuffer, "%2u s", aSeconds);
|
||||
return aBuffer;
|
||||
}
|
||||
|
||||
return TCollection_AsciiString (aMilliSeconds) + " ms";
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : FormatTimeProgress
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
TCollection_AsciiString Media_FormatContext::FormatTimeProgress (double theProgress,
|
||||
double theDuration)
|
||||
{
|
||||
double aSecIn1 = theProgress;
|
||||
unsigned int aHours1 = (unsigned int )(aSecIn1 * THE_SECOND_IN_HOUR);
|
||||
aSecIn1 -= double(aHours1) * THE_SECONDS_IN_HOUR;
|
||||
unsigned int aMinutes1 = (unsigned int )(aSecIn1 * THE_SECOND_IN_MINUTE);
|
||||
aSecIn1 -= double(aMinutes1) * THE_SECONDS_IN_MINUTE;
|
||||
unsigned int aSeconds1 = (unsigned int )aSecIn1;
|
||||
aSecIn1 -= double(aSeconds1);
|
||||
|
||||
double aSecIn2 = theDuration;
|
||||
unsigned int aHours2 = (unsigned int )(aSecIn2 * THE_SECOND_IN_HOUR);
|
||||
aSecIn2 -= double(aHours2) * THE_SECONDS_IN_HOUR;
|
||||
unsigned int aMinutes2 = (unsigned int )(aSecIn2 * THE_SECOND_IN_MINUTE);
|
||||
aSecIn2 -= double(aMinutes2) * THE_SECONDS_IN_MINUTE;
|
||||
unsigned int aSeconds2 = (unsigned int )aSecIn2;
|
||||
aSecIn2 -= double(aSeconds2);
|
||||
|
||||
char aBuffer[256];
|
||||
if (aHours1 > 0
|
||||
|| aHours2 > 0)
|
||||
{
|
||||
Sprintf (aBuffer, "%02u:%02u:%02u / %02u:%02u:%02u", aHours1, aMinutes1, aSeconds1, aHours2, aMinutes2, aSeconds2);
|
||||
return aBuffer;
|
||||
}
|
||||
Sprintf (aBuffer, "%02u:%02u / %02u:%02u", aMinutes1, aSeconds1, aMinutes2, aSeconds2);
|
||||
return aBuffer;
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : StreamInfo
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
TCollection_AsciiString Media_FormatContext::StreamInfo (unsigned int theIndex,
|
||||
AVCodecContext* theCodecCtx) const
|
||||
{
|
||||
#ifdef HAVE_FFMPEG
|
||||
const AVStream& aStream = *myFormatCtx->streams[theIndex];
|
||||
|
||||
AVCodecContext* aCodecCtx = theCodecCtx;
|
||||
if (aCodecCtx == NULL)
|
||||
{
|
||||
Standard_DISABLE_DEPRECATION_WARNINGS
|
||||
aCodecCtx = aStream.codec;
|
||||
Standard_ENABLE_DEPRECATION_WARNINGS
|
||||
}
|
||||
|
||||
char aFrmtBuff[4096] = {};
|
||||
avcodec_string (aFrmtBuff, sizeof(aFrmtBuff), aCodecCtx, 0);
|
||||
TCollection_AsciiString aStreamInfo (aFrmtBuff);
|
||||
|
||||
if (aStream.sample_aspect_ratio.num && av_cmp_q(aStream.sample_aspect_ratio, aStream.codecpar->sample_aspect_ratio))
|
||||
{
|
||||
AVRational aDispAspectRatio;
|
||||
av_reduce (&aDispAspectRatio.num, &aDispAspectRatio.den,
|
||||
aStream.codecpar->width * int64_t(aStream.sample_aspect_ratio.num),
|
||||
aStream.codecpar->height * int64_t(aStream.sample_aspect_ratio.den),
|
||||
1024 * 1024);
|
||||
aStreamInfo = aStreamInfo + ", SAR " + aStream.sample_aspect_ratio.num + ":" + aStream.sample_aspect_ratio.den
|
||||
+ " DAR " + aDispAspectRatio.num + ":" + aDispAspectRatio.den;
|
||||
}
|
||||
|
||||
if (aStream.codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
|
||||
{
|
||||
if (aStream.avg_frame_rate.den != 0 && aStream.avg_frame_rate.num != 0)
|
||||
{
|
||||
aStreamInfo += TCollection_AsciiString(", ") + formatFps (av_q2d (aStream.avg_frame_rate)) + " fps";
|
||||
}
|
||||
if (aStream.r_frame_rate.den != 0 && aStream.r_frame_rate.num != 0)
|
||||
{
|
||||
aStreamInfo += TCollection_AsciiString(", ") + formatFps (av_q2d (aStream.r_frame_rate)) + " tbr";
|
||||
}
|
||||
if (aStream.time_base.den != 0 && aStream.time_base.num != 0)
|
||||
{
|
||||
aStreamInfo += TCollection_AsciiString(", ") + formatFps(1 / av_q2d (aStream.time_base)) + " tbn";
|
||||
}
|
||||
if (aCodecCtx->time_base.den != 0 && aCodecCtx->time_base.num != 0)
|
||||
{
|
||||
aStreamInfo += TCollection_AsciiString(", ") + formatFps(1 / av_q2d (aCodecCtx->time_base)) + " tbc";
|
||||
}
|
||||
}
|
||||
if (myDuration > 0.0)
|
||||
{
|
||||
aStreamInfo += TCollection_AsciiString(", duration: ") + FormatTime (myDuration);
|
||||
}
|
||||
return aStreamInfo;
|
||||
#else
|
||||
(void )theIndex;
|
||||
(void )theCodecCtx;
|
||||
return TCollection_AsciiString();
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : ReadPacket
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
bool Media_FormatContext::ReadPacket (const Handle(Media_Packet)& thePacket)
|
||||
{
|
||||
if (thePacket.IsNull())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef HAVE_FFMPEG
|
||||
return av_read_frame (myFormatCtx, thePacket->ChangePacket()) >= 0;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : SeekStream
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
bool Media_FormatContext::SeekStream (unsigned int theStreamId,
|
||||
double theSeekPts,
|
||||
bool theToSeekBack)
|
||||
{
|
||||
#ifdef HAVE_FFMPEG
|
||||
const int aFlags = theToSeekBack ? AVSEEK_FLAG_BACKWARD : 0;
|
||||
AVStream& aStream = *myFormatCtx->streams[theStreamId];
|
||||
if ((aStream.disposition & AV_DISPOSITION_ATTACHED_PIC) != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int64_t aSeekTarget = StreamSecondsToUnits (aStream, theSeekPts + StreamUnitsToSeconds (aStream, aStream.start_time));
|
||||
bool isSeekDone = av_seek_frame (myFormatCtx, theStreamId, aSeekTarget, aFlags) >= 0;
|
||||
|
||||
// try 10 more times in backward direction to work-around huge duration between key frames
|
||||
// will not work for some streams with undefined cur_dts (AV_NOPTS_VALUE)!!!
|
||||
for (int aTries = 10; isSeekDone && theToSeekBack && aTries > 0 && (aStream.cur_dts > aSeekTarget); --aTries)
|
||||
{
|
||||
aSeekTarget -= StreamSecondsToUnits (aStream, 1.0);
|
||||
isSeekDone = av_seek_frame (myFormatCtx, theStreamId, aSeekTarget, aFlags) >= 0;
|
||||
}
|
||||
if (isSeekDone)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
TCollection_AsciiString aStreamType = aStream.codecpar->codec_type == AVMEDIA_TYPE_VIDEO
|
||||
? "Video"
|
||||
: (aStream.codecpar->codec_type == AVMEDIA_TYPE_AUDIO
|
||||
? "Audio"
|
||||
: "");
|
||||
Message::DefaultMessenger()->Send (TCollection_AsciiString ("Error while seeking ") + aStreamType + " stream to "
|
||||
+ theSeekPts + " sec (" + (theSeekPts + StreamUnitsToSeconds (aStream, aStream.start_time)) + " sec)",
|
||||
Message_Warning);
|
||||
return false;
|
||||
#else
|
||||
(void )theStreamId;
|
||||
(void )theSeekPts;
|
||||
(void )theToSeekBack;
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : Seek
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
bool Media_FormatContext::Seek (double theSeekPts,
|
||||
bool theToSeekBack)
|
||||
{
|
||||
#ifdef HAVE_FFMPEG
|
||||
const int aFlags = theToSeekBack ? AVSEEK_FLAG_BACKWARD : 0;
|
||||
int64_t aSeekTarget = SecondsToUnits (theSeekPts);
|
||||
if (av_seek_frame (myFormatCtx, -1, aSeekTarget, aFlags) >= 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
const char* aFileName =
|
||||
#if(LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(58, 7, 100))
|
||||
myFormatCtx->url;
|
||||
#else
|
||||
myFormatCtx->filename;
|
||||
#endif
|
||||
|
||||
Message::DefaultMessenger()->Send (TCollection_AsciiString("Disaster! Seeking to ") + theSeekPts + " [" + aFileName + "] has failed.", Message_Warning);
|
||||
return false;
|
||||
#else
|
||||
(void )theSeekPts;
|
||||
(void )theToSeekBack;
|
||||
return false;
|
||||
#endif
|
||||
}
|
133
src/Media/Media_FormatContext.hxx
Normal file
133
src/Media/Media_FormatContext.hxx
Normal file
@@ -0,0 +1,133 @@
|
||||
// Created by: Kirill GAVRILOV
|
||||
// Copyright (c) 2019 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _Media_FormatContext_HeaderFile
|
||||
#define _Media_FormatContext_HeaderFile
|
||||
|
||||
#include <Media_Packet.hxx>
|
||||
|
||||
#include <TCollection_AsciiString.hxx>
|
||||
|
||||
struct AVCodecContext;
|
||||
struct AVFormatContext;
|
||||
struct AVStream;
|
||||
struct AVRational;
|
||||
|
||||
//! AVFormatContext wrapper - the media input/output stream holder.
|
||||
class Media_FormatContext : public Standard_Transient
|
||||
{
|
||||
DEFINE_STANDARD_RTTIEXT(Media_FormatContext, Standard_Transient)
|
||||
public:
|
||||
//! Returns string description for AVError code.
|
||||
Standard_EXPORT static TCollection_AsciiString FormatAVErrorDescription (int theErrCodeAV);
|
||||
|
||||
//! Convert time units into seconds for context.
|
||||
//! @param theTimeUnits value to convert
|
||||
//! @return converted time units in seconds
|
||||
Standard_EXPORT static double FormatUnitsToSeconds (int64_t theTimeUnits);
|
||||
|
||||
//! Convert time units into seconds. Returns zero for invalid value.
|
||||
//! @param theTimeBase the timebase
|
||||
//! @param theTimeUnits value to convert
|
||||
//! @return converted time units in seconds
|
||||
Standard_EXPORT static double UnitsToSeconds (const AVRational& theTimeBase,
|
||||
int64_t theTimeUnits);
|
||||
|
||||
//! Convert time units into seconds using stream base.
|
||||
//! @param theStream the stream;
|
||||
//! @param theTimeUnits value to convert;
|
||||
//! @return converted time units in seconds.
|
||||
Standard_EXPORT static double StreamUnitsToSeconds (const AVStream& theStream,
|
||||
int64_t theTimeUnits);
|
||||
|
||||
//! Convert seconds into time units for context.
|
||||
//! @param theTimeSeconds value to convert
|
||||
//! @return time units
|
||||
Standard_EXPORT static int64_t SecondsToUnits (double theTimeSeconds);
|
||||
|
||||
//! Convert seconds into time units.
|
||||
//! @param theTimeBase the timebase
|
||||
//! @param theTimeSeconds value to convert
|
||||
//! @return time units
|
||||
Standard_EXPORT static int64_t SecondsToUnits (const AVRational& theTimeBase,
|
||||
double theTimeSeconds);
|
||||
|
||||
//! Convert seconds into time units for stream.
|
||||
//! @param theStream the stream
|
||||
//! @param theTimeSeconds value to convert
|
||||
//! @return time units
|
||||
Standard_EXPORT static int64_t StreamSecondsToUnits (const AVStream& theStream,
|
||||
double theTimeSeconds);
|
||||
|
||||
//! Time formatter.
|
||||
Standard_EXPORT static TCollection_AsciiString FormatTime (double theSeconds);
|
||||
|
||||
//! Time progress / duration formatter.
|
||||
Standard_EXPORT static TCollection_AsciiString FormatTimeProgress (double theProgress,
|
||||
double theDuration);
|
||||
|
||||
public:
|
||||
|
||||
//! Constructor.
|
||||
Standard_EXPORT Media_FormatContext();
|
||||
|
||||
//! Destructor.
|
||||
Standard_EXPORT virtual ~Media_FormatContext();
|
||||
|
||||
//! Return context.
|
||||
AVFormatContext* Context() const { return myFormatCtx; }
|
||||
|
||||
//! Open input.
|
||||
Standard_EXPORT bool OpenInput (const TCollection_AsciiString& theInput);
|
||||
|
||||
//! Close input.
|
||||
Standard_EXPORT void Close();
|
||||
|
||||
//! Return amount of streams.
|
||||
Standard_EXPORT unsigned int NbSteams() const;
|
||||
|
||||
//! Return stream.
|
||||
Standard_EXPORT const AVStream& Stream (unsigned int theIndex) const;
|
||||
|
||||
//! Format stream info.
|
||||
Standard_EXPORT TCollection_AsciiString StreamInfo (unsigned int theIndex,
|
||||
AVCodecContext* theCodecCtx = NULL) const;
|
||||
|
||||
//! Return PTS start base in seconds.
|
||||
double PtsStartBase() const { return myPtsStartBase; }
|
||||
|
||||
//! Return duration in seconds.
|
||||
double Duration() const { return myDuration; }
|
||||
|
||||
//! av_read_frame() wrapper.
|
||||
Standard_EXPORT bool ReadPacket (const Handle(Media_Packet)& thePacket);
|
||||
|
||||
//! Seek stream to specified position.
|
||||
Standard_EXPORT bool SeekStream (unsigned int theStreamId,
|
||||
double theSeekPts,
|
||||
bool toSeekBack);
|
||||
|
||||
//! Seek context to specified position.
|
||||
Standard_EXPORT bool Seek (double theSeekPts,
|
||||
bool toSeekBack);
|
||||
|
||||
protected:
|
||||
|
||||
AVFormatContext* myFormatCtx; //!< format context
|
||||
double myPtsStartBase; //!< start time
|
||||
double myDuration; //!< duration
|
||||
|
||||
};
|
||||
|
||||
#endif // _Media_FormatContext_HeaderFile
|
296
src/Media/Media_Frame.cxx
Normal file
296
src/Media/Media_Frame.cxx
Normal file
@@ -0,0 +1,296 @@
|
||||
// Created by: Kirill GAVRILOV
|
||||
// Copyright (c) 2019 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
// activate some C99 macros like UINT64_C in "stdint.h" which used by FFmpeg
|
||||
#ifndef __STDC_CONSTANT_MACROS
|
||||
#define __STDC_CONSTANT_MACROS
|
||||
#endif
|
||||
|
||||
#include <Media_Frame.hxx>
|
||||
|
||||
#include <Media_Scaler.hxx>
|
||||
|
||||
#ifdef HAVE_FFMPEG
|
||||
#include <Standard_WarningsDisable.hxx>
|
||||
extern "C"
|
||||
{
|
||||
#include <libavcodec/avcodec.h>
|
||||
#include <libavutil/imgutils.h>
|
||||
};
|
||||
#include <Standard_WarningsRestore.hxx>
|
||||
#endif
|
||||
|
||||
IMPLEMENT_STANDARD_RTTIEXT(Media_Frame, Standard_Transient)
|
||||
|
||||
// =======================================================================
|
||||
// function : FormatFFmpeg2Occt
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
Image_Format Media_Frame::FormatFFmpeg2Occt (int theFormat)
|
||||
{
|
||||
#ifdef HAVE_FFMPEG
|
||||
switch (theFormat)
|
||||
{
|
||||
case AV_PIX_FMT_RGBA:
|
||||
return Image_Format_RGBA;
|
||||
case AV_PIX_FMT_BGRA:
|
||||
return Image_Format_BGRA;
|
||||
case AV_PIX_FMT_RGB0:
|
||||
return Image_Format_RGB32;
|
||||
case AV_PIX_FMT_BGR0:
|
||||
return Image_Format_BGR32;
|
||||
case AV_PIX_FMT_RGB24:
|
||||
return Image_Format_RGB;
|
||||
case AV_PIX_FMT_BGR24:
|
||||
return Image_Format_BGR;
|
||||
case AV_PIX_FMT_GRAY8:
|
||||
return Image_Format_Gray;
|
||||
default:
|
||||
return Image_Format_UNKNOWN;
|
||||
}
|
||||
#else
|
||||
(void )theFormat;
|
||||
return Image_Format_UNKNOWN;
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : FormatOcct2FFmpeg
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
int Media_Frame::FormatOcct2FFmpeg (Image_Format theFormat)
|
||||
{
|
||||
#ifdef HAVE_FFMPEG
|
||||
switch (theFormat)
|
||||
{
|
||||
case Image_Format_RGBA:
|
||||
return AV_PIX_FMT_RGBA;
|
||||
case Image_Format_BGRA:
|
||||
return AV_PIX_FMT_BGRA;
|
||||
case Image_Format_RGB32:
|
||||
return AV_PIX_FMT_RGB0;
|
||||
case Image_Format_BGR32:
|
||||
return AV_PIX_FMT_BGR0;
|
||||
case Image_Format_RGB:
|
||||
return AV_PIX_FMT_RGB24;
|
||||
case Image_Format_BGR:
|
||||
return AV_PIX_FMT_BGR24;
|
||||
case Image_Format_Gray:
|
||||
return AV_PIX_FMT_GRAY8;
|
||||
case Image_Format_Alpha:
|
||||
return AV_PIX_FMT_GRAY8;
|
||||
case Image_Format_GrayF:
|
||||
case Image_Format_AlphaF:
|
||||
case Image_Format_RGBAF:
|
||||
case Image_Format_RGBF:
|
||||
case Image_Format_BGRAF:
|
||||
case Image_Format_BGRF:
|
||||
case Image_Format_UNKNOWN:
|
||||
return AV_PIX_FMT_NONE; // unsupported
|
||||
}
|
||||
return AV_PIX_FMT_NONE;
|
||||
#else
|
||||
(void )theFormat;
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : Media_Frame
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
Media_Frame::Media_Frame()
|
||||
: myFrame (NULL),
|
||||
myFramePts (0.0),
|
||||
myPixelRatio(1.0f),
|
||||
myIsLocked (false)
|
||||
{
|
||||
#ifdef HAVE_FFMPEG
|
||||
myFrame = av_frame_alloc();
|
||||
#endif
|
||||
Unref();
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : ~Media_Frame
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
Media_Frame::~Media_Frame()
|
||||
{
|
||||
#ifdef HAVE_FFMPEG
|
||||
av_frame_free (&myFrame);
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : Unref
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void Media_Frame::Unref()
|
||||
{
|
||||
#ifdef HAVE_FFMPEG
|
||||
av_frame_unref (myFrame);
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : IsFullRangeYUV
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
bool Media_Frame::IsFullRangeYUV() const
|
||||
{
|
||||
#ifdef HAVE_FFMPEG
|
||||
return Format() == AV_PIX_FMT_YUVJ420P
|
||||
|| myFrame->color_range == AVCOL_RANGE_JPEG;
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : Swap
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void Media_Frame::Swap (const Handle(Media_Frame)& theFrame1,
|
||||
const Handle(Media_Frame)& theFrame2)
|
||||
{
|
||||
std::swap (theFrame1->myFrame, theFrame2->myFrame);
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : IsEmpty
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
bool Media_Frame::IsEmpty() const
|
||||
{
|
||||
#ifdef HAVE_FFMPEG
|
||||
return myFrame->format == -1; // AV_PIX_FMT_NONE
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : SizeX
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
int Media_Frame::SizeX() const
|
||||
{
|
||||
#ifdef HAVE_FFMPEG
|
||||
return myFrame->width;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : SizeY
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
int Media_Frame::SizeY() const
|
||||
{
|
||||
#ifdef HAVE_FFMPEG
|
||||
return myFrame->height;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : Format
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
int Media_Frame::Format() const
|
||||
{
|
||||
#ifdef HAVE_FFMPEG
|
||||
return myFrame->format;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : Plane
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
uint8_t* Media_Frame::Plane (int thePlaneId) const
|
||||
{
|
||||
#ifdef HAVE_FFMPEG
|
||||
return myFrame->data[thePlaneId];
|
||||
#else
|
||||
(void )thePlaneId;
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : LineSize
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
int Media_Frame::LineSize (int thePlaneId) const
|
||||
{
|
||||
#ifdef HAVE_FFMPEG
|
||||
return myFrame->linesize[thePlaneId];
|
||||
#else
|
||||
(void )thePlaneId;
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : BestEffortTimestamp
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
int64_t Media_Frame::BestEffortTimestamp() const
|
||||
{
|
||||
#ifdef HAVE_FFMPEG
|
||||
return myFrame->best_effort_timestamp;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : InitWrapper
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
bool Media_Frame::InitWrapper (const Handle(Image_PixMap)& thePixMap)
|
||||
{
|
||||
Unref();
|
||||
if (thePixMap.IsNull())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef HAVE_FFMPEG
|
||||
myFrame->format = FormatOcct2FFmpeg (thePixMap->Format());
|
||||
if (myFrame->format == AV_PIX_FMT_NONE)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
myFrame->width = (int )thePixMap->SizeX();
|
||||
myFrame->height = (int )thePixMap->SizeY();
|
||||
myFrame->data[0] = (uint8_t* )thePixMap->ChangeData();
|
||||
myFrame->linesize[0] = (int )thePixMap->SizeRowBytes();
|
||||
for (int aPlaneIter = 1; aPlaneIter < AV_NUM_DATA_POINTERS; ++aPlaneIter)
|
||||
{
|
||||
myFrame->data [aPlaneIter] = NULL;
|
||||
myFrame->linesize[aPlaneIter] = 0;
|
||||
}
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
118
src/Media/Media_Frame.hxx
Normal file
118
src/Media/Media_Frame.hxx
Normal file
@@ -0,0 +1,118 @@
|
||||
// Created by: Kirill GAVRILOV
|
||||
// Copyright (c) 2019 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _Media_Frame_HeaderFile
|
||||
#define _Media_Frame_HeaderFile
|
||||
|
||||
#include <Graphic3d_Vec2.hxx>
|
||||
#include <Image_PixMap.hxx>
|
||||
#include <Standard_Transient.hxx>
|
||||
#include <Standard_Type.hxx>
|
||||
|
||||
struct AVFrame;
|
||||
|
||||
//! AVFrame wrapper - the frame (decoded image/audio sample data) holder.
|
||||
class Media_Frame : public Standard_Transient
|
||||
{
|
||||
DEFINE_STANDARD_RTTIEXT(Media_Frame, Standard_Transient)
|
||||
public:
|
||||
|
||||
//! Convert pixel format from FFmpeg (AVPixelFormat) to OCCT.
|
||||
Standard_EXPORT static Image_Format FormatFFmpeg2Occt (int theFormat);
|
||||
|
||||
//! Convert pixel format from OCCT to FFmpeg (AVPixelFormat).
|
||||
//! Returns -1 (AV_PIX_FMT_NONE) if undefined.
|
||||
Standard_EXPORT static int FormatOcct2FFmpeg (Image_Format theFormat);
|
||||
|
||||
//! Swap AVFrame* within two frames.
|
||||
Standard_EXPORT static void Swap (const Handle(Media_Frame)& theFrame1,
|
||||
const Handle(Media_Frame)& theFrame2);
|
||||
|
||||
public:
|
||||
|
||||
//! Empty constructor
|
||||
Standard_EXPORT Media_Frame();
|
||||
|
||||
//! Destructor
|
||||
Standard_EXPORT virtual ~Media_Frame();
|
||||
|
||||
//! Return true if frame does not contain any data.
|
||||
Standard_EXPORT bool IsEmpty() const;
|
||||
|
||||
//! av_frame_unref() wrapper.
|
||||
Standard_EXPORT void Unref();
|
||||
|
||||
//! Return image dimensions.
|
||||
Graphic3d_Vec2i Size() const { return Graphic3d_Vec2i (SizeX(), SizeY()); }
|
||||
|
||||
//! Return image width.
|
||||
Standard_EXPORT int SizeX() const;
|
||||
|
||||
//! Return image height.
|
||||
Standard_EXPORT int SizeY() const;
|
||||
|
||||
//! Return pixel format (AVPixelFormat).
|
||||
Standard_EXPORT int Format() const;
|
||||
|
||||
//! Return TRUE if YUV range is full.
|
||||
Standard_EXPORT bool IsFullRangeYUV() const;
|
||||
|
||||
//! Access data plane for specified Id.
|
||||
Standard_EXPORT uint8_t* Plane (int thePlaneId) const;
|
||||
|
||||
//! @return linesize in bytes for specified data plane
|
||||
Standard_EXPORT int LineSize (int thePlaneId) const;
|
||||
|
||||
//! @return frame timestamp estimated using various heuristics, in stream time base
|
||||
Standard_EXPORT int64_t BestEffortTimestamp() const;
|
||||
|
||||
//! Return frame.
|
||||
const AVFrame* Frame() const { return myFrame; }
|
||||
|
||||
//! Return frame.
|
||||
AVFrame* ChangeFrame() { return myFrame; }
|
||||
|
||||
//! Return presentation timestamp (PTS).
|
||||
double Pts() const { return myFramePts; }
|
||||
|
||||
//! Set presentation timestamp (PTS).
|
||||
void SetPts (double thePts) { myFramePts = thePts; }
|
||||
|
||||
//! Return PAR.
|
||||
float PixelAspectRatio() const { return myPixelRatio; }
|
||||
|
||||
//! Set PAR.
|
||||
void SetPixelAspectRatio (float theRatio) { myPixelRatio = theRatio; }
|
||||
|
||||
//! Return locked state.
|
||||
bool IsLocked() const { return myIsLocked; }
|
||||
|
||||
//! Lock/free frame for edition.
|
||||
void SetLocked (bool theToLock) { myIsLocked = theToLock; }
|
||||
|
||||
public:
|
||||
|
||||
//! Wrap allocated image pixmap.
|
||||
Standard_EXPORT bool InitWrapper (const Handle(Image_PixMap)& thePixMap);
|
||||
|
||||
protected:
|
||||
|
||||
AVFrame* myFrame; //!< frame
|
||||
double myFramePts; //!< presentation timestamp
|
||||
float myPixelRatio; //!< pixel aspect ratio
|
||||
bool myIsLocked; //!< locked state
|
||||
|
||||
};
|
||||
|
||||
#endif // _Media_Frame_HeaderFile
|
32
src/Media/Media_IFrameQueue.hxx
Normal file
32
src/Media/Media_IFrameQueue.hxx
Normal file
@@ -0,0 +1,32 @@
|
||||
// Created by: Kirill GAVRILOV
|
||||
// Copyright (c) 2019 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _Media_IFrameQueue_HeaderFile
|
||||
#define _Media_IFrameQueue_HeaderFile
|
||||
|
||||
#include <Media_Frame.hxx>
|
||||
|
||||
//! Interface defining frame queuing.
|
||||
class Media_IFrameQueue
|
||||
{
|
||||
public:
|
||||
|
||||
//! Lock the frame, e.g. take ownership on a single (not currently displayed) frame from the queue to perform decoding into.
|
||||
virtual Handle(Media_Frame) LockFrame() = 0;
|
||||
|
||||
//! Release previously locked frame, e.g. it can be displayed on the screen.
|
||||
virtual void ReleaseFrame (const Handle(Media_Frame)& theFrame) = 0;
|
||||
};
|
||||
|
||||
#endif // _Media_IFrameQueue_HeaderFile
|
180
src/Media/Media_Packet.cxx
Normal file
180
src/Media/Media_Packet.cxx
Normal file
@@ -0,0 +1,180 @@
|
||||
// Created by: Kirill GAVRILOV
|
||||
// Copyright (c) 2019 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
// activate some C99 macros like UINT64_C in "stdint.h" which used by FFmpeg
|
||||
#ifndef __STDC_CONSTANT_MACROS
|
||||
#define __STDC_CONSTANT_MACROS
|
||||
#endif
|
||||
|
||||
#include <Media_Packet.hxx>
|
||||
|
||||
#ifdef HAVE_FFMPEG
|
||||
#include <Standard_WarningsDisable.hxx>
|
||||
extern "C"
|
||||
{
|
||||
#include <libavcodec/avcodec.h>
|
||||
};
|
||||
#include <Standard_WarningsRestore.hxx>
|
||||
#endif
|
||||
|
||||
IMPLEMENT_STANDARD_RTTIEXT(Media_Packet, Standard_Transient)
|
||||
|
||||
// =======================================================================
|
||||
// function : Media_Packet
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
Media_Packet::Media_Packet()
|
||||
: myPacket (NULL)
|
||||
{
|
||||
#ifdef HAVE_FFMPEG
|
||||
myPacket = av_packet_alloc();
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : ~Media_Packet
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
Media_Packet::~Media_Packet()
|
||||
{
|
||||
#ifdef HAVE_FFMPEG
|
||||
av_packet_free (&myPacket);
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : Unref
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void Media_Packet::Unref()
|
||||
{
|
||||
#ifdef HAVE_FFMPEG
|
||||
av_packet_unref (myPacket);
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : Data
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
const uint8_t* Media_Packet::Data() const
|
||||
{
|
||||
#ifdef HAVE_FFMPEG
|
||||
return myPacket->data;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : ChangeData
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
uint8_t* Media_Packet::ChangeData()
|
||||
{
|
||||
#ifdef HAVE_FFMPEG
|
||||
return myPacket->data;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : Size
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
int Media_Packet::Size() const
|
||||
{
|
||||
#ifdef HAVE_FFMPEG
|
||||
return myPacket->size;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : Pts
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
int64_t Media_Packet::Pts() const
|
||||
{
|
||||
#ifdef HAVE_FFMPEG
|
||||
return myPacket->pts;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : Dts
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
int64_t Media_Packet::Dts() const
|
||||
{
|
||||
#ifdef HAVE_FFMPEG
|
||||
return myPacket->dts;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : Duration
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
int64_t Media_Packet::Duration() const
|
||||
{
|
||||
#ifdef HAVE_FFMPEG
|
||||
return myPacket->duration;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : StreamIndex
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
int Media_Packet::StreamIndex() const
|
||||
{
|
||||
#ifdef HAVE_FFMPEG
|
||||
return myPacket->stream_index;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : IsKeyFrame
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
bool Media_Packet::IsKeyFrame() const
|
||||
{
|
||||
#ifdef HAVE_FFMPEG
|
||||
return (myPacket->flags & AV_PKT_FLAG_KEY) != 0;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : SetKeyFrame
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void Media_Packet::SetKeyFrame()
|
||||
{
|
||||
#ifdef HAVE_FFMPEG
|
||||
myPacket->flags |= AV_PKT_FLAG_KEY;
|
||||
#endif
|
||||
}
|
84
src/Media/Media_Packet.hxx
Normal file
84
src/Media/Media_Packet.hxx
Normal file
@@ -0,0 +1,84 @@
|
||||
// Created by: Kirill GAVRILOV
|
||||
// Copyright (c) 2019 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _Media_Packet_HeaderFile
|
||||
#define _Media_Packet_HeaderFile
|
||||
|
||||
#include <Standard_Transient.hxx>
|
||||
#include <Standard_Type.hxx>
|
||||
|
||||
struct AVPacket;
|
||||
|
||||
//! AVPacket wrapper - the packet (data chunk for decoding/encoding) holder.
|
||||
class Media_Packet : public Standard_Transient
|
||||
{
|
||||
DEFINE_STANDARD_RTTIEXT(Media_Packet, Standard_Transient)
|
||||
public:
|
||||
|
||||
//! Empty constructor
|
||||
Standard_EXPORT Media_Packet();
|
||||
|
||||
//! Destructor.
|
||||
Standard_EXPORT virtual ~Media_Packet();
|
||||
|
||||
//! av_packet_unref() wrapper.
|
||||
Standard_EXPORT void Unref();
|
||||
|
||||
//! Return packet.
|
||||
const AVPacket* Packet() const { return myPacket; }
|
||||
|
||||
//! Return packet.
|
||||
AVPacket* ChangePacket() { return myPacket; }
|
||||
|
||||
//! Return data.
|
||||
Standard_EXPORT const uint8_t* Data() const;
|
||||
|
||||
//! Return data.
|
||||
Standard_EXPORT uint8_t* ChangeData();
|
||||
|
||||
//! Return data size.
|
||||
Standard_EXPORT int Size() const;
|
||||
|
||||
//! Return presentation timestamp (PTS).
|
||||
Standard_EXPORT int64_t Pts() const;
|
||||
|
||||
//! Return decoding timestamp (DTS).
|
||||
Standard_EXPORT int64_t Dts() const;
|
||||
|
||||
//! Return Duration.
|
||||
Standard_EXPORT int64_t Duration() const;
|
||||
|
||||
//! Return Duration in seconds.
|
||||
double DurationSeconds() const { return myDurationSec; }
|
||||
|
||||
//! Set Duration in seconds.
|
||||
void SetDurationSeconds (double theDurationSec) { myDurationSec = theDurationSec; }
|
||||
|
||||
//! Return stream index.
|
||||
Standard_EXPORT int StreamIndex() const;
|
||||
|
||||
//! Return TRUE for a key frame.
|
||||
Standard_EXPORT bool IsKeyFrame() const;
|
||||
|
||||
//! Mark as key frame.
|
||||
Standard_EXPORT void SetKeyFrame();
|
||||
|
||||
protected:
|
||||
|
||||
AVPacket* myPacket; //!< packet
|
||||
double myDurationSec; //!< packet duration in seconds
|
||||
|
||||
};
|
||||
|
||||
#endif // _Media_Packet_HeaderFile
|
668
src/Media/Media_PlayerContext.cxx
Normal file
668
src/Media/Media_PlayerContext.cxx
Normal file
@@ -0,0 +1,668 @@
|
||||
// Created by: Kirill GAVRILOV
|
||||
// Copyright (c) 2019 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
// activate some C99 macros like UINT64_C in "stdint.h" which used by FFmpeg
|
||||
#ifndef __STDC_CONSTANT_MACROS
|
||||
#define __STDC_CONSTANT_MACROS
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include <Media_PlayerContext.hxx>
|
||||
|
||||
#include <Image_AlienPixMap.hxx>
|
||||
#include <Media_BufferPool.hxx>
|
||||
#include <Media_FormatContext.hxx>
|
||||
#include <Media_CodecContext.hxx>
|
||||
#include <Media_Scaler.hxx>
|
||||
#include <Message.hxx>
|
||||
#include <Message_Messenger.hxx>
|
||||
#include <OSD.hxx>
|
||||
|
||||
#ifdef HAVE_FFMPEG
|
||||
#include <Standard_WarningsDisable.hxx>
|
||||
extern "C"
|
||||
{
|
||||
#include <libavcodec/avcodec.h>
|
||||
#include <libavformat/avformat.h>
|
||||
#include <libavutil/imgutils.h>
|
||||
};
|
||||
#include <Standard_WarningsRestore.hxx>
|
||||
#endif
|
||||
|
||||
IMPLEMENT_STANDARD_RTTIEXT(Media_PlayerContext, Standard_Transient)
|
||||
|
||||
//================================================================
|
||||
// Function : Media_PlayerContext
|
||||
// Purpose :
|
||||
//================================================================
|
||||
Media_PlayerContext::Media_PlayerContext (Media_IFrameQueue* theFrameQueue)
|
||||
: myFrameQueue (theFrameQueue),
|
||||
myThread (doThreadWrapper),
|
||||
myWakeEvent (false),
|
||||
myNextEvent (false),
|
||||
myDuration (0.0),
|
||||
myToForceRgb(true),
|
||||
myToShutDown(false),
|
||||
mySeekTo (0.0),
|
||||
myPlayEvent (Media_PlayerEvent_NONE)
|
||||
{
|
||||
myThread.Run (this);
|
||||
|
||||
#if defined(_WIN32) && !defined(OCCT_UWP)
|
||||
// Adjust system timer
|
||||
// By default Windows2K+ timer has ugly precision
|
||||
// Thus - Sleep(1) may be long 14ms!
|
||||
// We force best available precision to make Sleep() more adequate
|
||||
// This affect whole system while running application!
|
||||
TIMECAPS aTimeCaps = {0, 0};
|
||||
if (timeGetDevCaps (&aTimeCaps, sizeof(aTimeCaps)) == TIMERR_NOERROR)
|
||||
{
|
||||
timeBeginPeriod (aTimeCaps.wPeriodMin);
|
||||
}
|
||||
else
|
||||
{
|
||||
timeBeginPeriod (1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//================================================================
|
||||
// Function : ~Media_PlayerContext
|
||||
// Purpose :
|
||||
//================================================================
|
||||
Media_PlayerContext::~Media_PlayerContext()
|
||||
{
|
||||
myToShutDown = Standard_True;
|
||||
myWakeEvent.Set();
|
||||
myThread.Wait();
|
||||
|
||||
#if defined(_WIN32) && !defined(OCCT_UWP)
|
||||
// restore timer adjustments
|
||||
TIMECAPS aTimeCaps = {0, 0};
|
||||
if (timeGetDevCaps (&aTimeCaps, sizeof(aTimeCaps)) == TIMERR_NOERROR)
|
||||
{
|
||||
timeEndPeriod (aTimeCaps.wPeriodMin);
|
||||
}
|
||||
else
|
||||
{
|
||||
timeEndPeriod (1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//================================================================
|
||||
// Function : DumpFirstFrame
|
||||
// Purpose :
|
||||
//================================================================
|
||||
Handle(Media_Frame) Media_PlayerContext::DumpFirstFrame (const TCollection_AsciiString& theSrcVideo,
|
||||
TCollection_AsciiString& theMediaInfo)
|
||||
{
|
||||
theMediaInfo.Clear();
|
||||
Handle(Media_FormatContext) aFormatCtx = new Media_FormatContext();
|
||||
if (!aFormatCtx->OpenInput (theSrcVideo))
|
||||
{
|
||||
return Handle(Media_Frame)();
|
||||
}
|
||||
|
||||
Handle(Media_CodecContext) aVideoCtx;
|
||||
#ifdef HAVE_FFMPEG
|
||||
for (unsigned int aStreamId = 0; aStreamId < aFormatCtx->NbSteams(); ++aStreamId)
|
||||
{
|
||||
const AVStream& aStream = aFormatCtx->Stream (aStreamId);
|
||||
const AVMediaType aCodecType = aStream.codecpar->codec_type;
|
||||
if (aCodecType == AVMEDIA_TYPE_VIDEO)
|
||||
{
|
||||
aVideoCtx = new Media_CodecContext();
|
||||
if (!aVideoCtx->Init (aStream, aFormatCtx->PtsStartBase(), 1))
|
||||
{
|
||||
return Handle(Media_Frame)();
|
||||
}
|
||||
|
||||
theMediaInfo = aFormatCtx->StreamInfo (aStreamId, aVideoCtx->Context());
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (aVideoCtx.IsNull())
|
||||
{
|
||||
Message::DefaultMessenger()->Send (TCollection_AsciiString ("FFmpeg: no video stream in '") + theSrcVideo + "'", Message_Fail);
|
||||
return Handle(Media_Frame)();
|
||||
}
|
||||
|
||||
Handle(Media_Packet) aPacket = new Media_Packet();
|
||||
Handle(Media_Frame) aFrame = new Media_Frame();
|
||||
for (;;)
|
||||
{
|
||||
if (!aFormatCtx->ReadPacket (aPacket))
|
||||
{
|
||||
Message::DefaultMessenger()->Send (TCollection_AsciiString ("FFmpeg: unable to read from '") + theSrcVideo + "'", Message_Fail);
|
||||
return Handle(Media_Frame)();
|
||||
}
|
||||
if (!aVideoCtx->CanProcessPacket (aPacket))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (aVideoCtx->SendPacket (aPacket)
|
||||
&& aVideoCtx->ReceiveFrame (aFrame))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (aFrame->IsEmpty()
|
||||
|| aFrame->SizeX() < 1
|
||||
|| aFrame->SizeY() < 1)
|
||||
{
|
||||
Message::DefaultMessenger()->Send (TCollection_AsciiString ("FFmpeg: unable to decode first video frame from '") + theSrcVideo + "'", Message_Fail);
|
||||
return Handle(Media_Frame)();
|
||||
}
|
||||
return aFrame;
|
||||
}
|
||||
|
||||
//================================================================
|
||||
// Function : DumpFirstFrame
|
||||
// Purpose :
|
||||
//================================================================
|
||||
bool Media_PlayerContext::DumpFirstFrame (const TCollection_AsciiString& theSrcVideo,
|
||||
const TCollection_AsciiString& theOutImage,
|
||||
TCollection_AsciiString& theMediaInfo,
|
||||
int theMaxSize)
|
||||
{
|
||||
Handle(Media_Frame) aFrame = DumpFirstFrame (theSrcVideo, theMediaInfo);
|
||||
if (aFrame.IsNull())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Handle(Image_AlienPixMap) aPixMap = new Image_AlienPixMap();
|
||||
int aResSizeX = aFrame->SizeX(), aResSizeY = aFrame->SizeY();
|
||||
if (theMaxSize > 0)
|
||||
{
|
||||
if (aResSizeX > aResSizeY)
|
||||
{
|
||||
aResSizeX = theMaxSize;
|
||||
aResSizeY = int((double(aFrame->SizeY()) / double(aFrame->SizeX())) * double(aResSizeX));
|
||||
}
|
||||
else
|
||||
{
|
||||
aResSizeY = theMaxSize;
|
||||
aResSizeX = int((double(aFrame->SizeX()) / double(aFrame->SizeY())) * double(aResSizeY));
|
||||
}
|
||||
}
|
||||
if (!aPixMap->InitZero (Image_Format_RGB, aResSizeX, aResSizeY))
|
||||
{
|
||||
Message::DefaultMessenger()->Send ("FFmpeg: Failed allocation of RGB frame (out of memory)", Message_Fail);
|
||||
return false;
|
||||
}
|
||||
|
||||
//Image_Format aFormat = aFrame->FormatFFmpeg2Occt (aFrame->Format());
|
||||
//if (aFormat == Image_Format_UNKNOWN || theMaxSize > 0)
|
||||
{
|
||||
Handle(Media_Frame) anRgbFrame = new Media_Frame();
|
||||
anRgbFrame->InitWrapper (aPixMap);
|
||||
|
||||
Media_Scaler aScaler;
|
||||
if (!aScaler.Convert (aFrame, anRgbFrame))
|
||||
{
|
||||
Message::DefaultMessenger()->Send (TCollection_AsciiString ("FFmpeg: unable to convert frame into RGB '") + theSrcVideo + "'", Message_Fail);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
aPixMap->SetTopDown (true);
|
||||
return aPixMap->Save (theOutImage);
|
||||
}
|
||||
|
||||
//================================================================
|
||||
// Function : SetInput
|
||||
// Purpose :
|
||||
//================================================================
|
||||
void Media_PlayerContext::SetInput (const TCollection_AsciiString& theInputPath,
|
||||
Standard_Boolean theToWait)
|
||||
{
|
||||
{
|
||||
Standard_Mutex::Sentry aLock (myMutex);
|
||||
if (theToWait)
|
||||
{
|
||||
myNextEvent.Reset();
|
||||
}
|
||||
myInputPath = theInputPath;
|
||||
myPlayEvent = Media_PlayerEvent_NEXT;
|
||||
myWakeEvent.Set();
|
||||
}
|
||||
if (theToWait)
|
||||
{
|
||||
myNextEvent.Wait();
|
||||
}
|
||||
}
|
||||
|
||||
//================================================================
|
||||
// Function : PlaybackState
|
||||
// Purpose :
|
||||
//================================================================
|
||||
void Media_PlayerContext::PlaybackState (Standard_Boolean& theIsPaused,
|
||||
Standard_Real& theProgress,
|
||||
Standard_Real& theDuration)
|
||||
{
|
||||
Standard_Mutex::Sentry aLock (myMutex);
|
||||
theIsPaused = !myTimer.IsStarted();
|
||||
theProgress = myTimer.ElapsedTime();
|
||||
theDuration = myDuration;
|
||||
}
|
||||
|
||||
//================================================================
|
||||
// Function : pushPlayEvent
|
||||
// Purpose :
|
||||
//================================================================
|
||||
void Media_PlayerContext::PlayPause (Standard_Boolean& theIsPaused,
|
||||
Standard_Real& theProgress,
|
||||
Standard_Real& theDuration)
|
||||
{
|
||||
Standard_Mutex::Sentry aLock (myMutex);
|
||||
theProgress = myTimer.ElapsedTime();
|
||||
theDuration = myDuration;
|
||||
if (myTimer.IsStarted())
|
||||
{
|
||||
pushPlayEvent (Media_PlayerEvent_PAUSE);
|
||||
theIsPaused = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
pushPlayEvent (Media_PlayerEvent_RESUME);
|
||||
theIsPaused = false;
|
||||
}
|
||||
}
|
||||
|
||||
//================================================================
|
||||
// Function : Seek
|
||||
// Purpose :
|
||||
//================================================================
|
||||
void Media_PlayerContext::Seek (Standard_Real thePosSec)
|
||||
{
|
||||
Standard_Mutex::Sentry aLock (myMutex);
|
||||
mySeekTo = thePosSec;
|
||||
pushPlayEvent (Media_PlayerEvent_SEEK);
|
||||
}
|
||||
|
||||
//================================================================
|
||||
// Function : pushPlayEvent
|
||||
// Purpose :
|
||||
//================================================================
|
||||
void Media_PlayerContext::pushPlayEvent (Media_PlayerEvent thePlayEvent)
|
||||
{
|
||||
Standard_Mutex::Sentry aLock (myMutex);
|
||||
myPlayEvent = thePlayEvent;
|
||||
myWakeEvent.Set();
|
||||
}
|
||||
|
||||
//================================================================
|
||||
// Function : popPlayEvent
|
||||
// Purpose :
|
||||
//================================================================
|
||||
bool Media_PlayerContext::popPlayEvent (Media_PlayerEvent& thePlayEvent,
|
||||
const Handle(Media_FormatContext)& theFormatCtx,
|
||||
const Handle(Media_CodecContext)& theVideoCtx,
|
||||
const Handle(Media_Frame)& theFrame)
|
||||
{
|
||||
if (myPlayEvent == Media_PlayerEvent_NONE)
|
||||
{
|
||||
thePlayEvent = Media_PlayerEvent_NONE;
|
||||
return false;
|
||||
}
|
||||
|
||||
Standard_Mutex::Sentry aLock (myMutex);
|
||||
thePlayEvent = myPlayEvent;
|
||||
if (thePlayEvent == Media_PlayerEvent_PAUSE)
|
||||
{
|
||||
myTimer.Pause();
|
||||
}
|
||||
else if (thePlayEvent == Media_PlayerEvent_RESUME)
|
||||
{
|
||||
myTimer.Start();
|
||||
}
|
||||
else if (thePlayEvent == Media_PlayerEvent_SEEK)
|
||||
{
|
||||
if (!theFormatCtx.IsNull()
|
||||
&& !theVideoCtx.IsNull())
|
||||
{
|
||||
if (!theFormatCtx->SeekStream (theVideoCtx->StreamIndex(), mySeekTo, false))
|
||||
{
|
||||
theFormatCtx->Seek (mySeekTo, false);
|
||||
}
|
||||
theVideoCtx->Flush();
|
||||
if (!theFrame.IsNull())
|
||||
{
|
||||
theFrame->Unref();
|
||||
}
|
||||
myTimer.Seek (mySeekTo);
|
||||
}
|
||||
}
|
||||
|
||||
myPlayEvent = Media_PlayerEvent_NONE;
|
||||
return thePlayEvent != Media_PlayerEvent_NONE;
|
||||
}
|
||||
|
||||
//! Returns nearest (greater or equal) aligned number.
|
||||
static int getAligned (size_t theNumber,
|
||||
size_t theAlignment = 32)
|
||||
{
|
||||
return int(theNumber + theAlignment - 1 - (theNumber - 1) % theAlignment);
|
||||
}
|
||||
|
||||
//================================================================
|
||||
// Function : receiveFrame
|
||||
// Purpose :
|
||||
//================================================================
|
||||
bool Media_PlayerContext::receiveFrame (const Handle(Media_Frame)& theFrame,
|
||||
const Handle(Media_CodecContext)& theVideoCtx)
|
||||
{
|
||||
if (myFrameTmp.IsNull())
|
||||
{
|
||||
myFrameTmp = new Media_Frame();
|
||||
}
|
||||
if (!theVideoCtx->ReceiveFrame (myFrameTmp))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
theFrame->SetPts (myFrameTmp->Pts());
|
||||
theFrame->SetPixelAspectRatio (myFrameTmp->PixelAspectRatio());
|
||||
|
||||
Image_Format anOcctFmt = Media_Frame::FormatFFmpeg2Occt (myFrameTmp->Format());
|
||||
if (anOcctFmt != Image_Format_UNKNOWN)
|
||||
{
|
||||
Media_Frame::Swap (theFrame, myFrameTmp);
|
||||
return true;
|
||||
}
|
||||
#ifdef HAVE_FFMPEG
|
||||
else if (!myToForceRgb
|
||||
&& (myFrameTmp->Format() == AV_PIX_FMT_YUV420P
|
||||
|| myFrameTmp->Format() == AV_PIX_FMT_YUVJ420P))
|
||||
{
|
||||
Media_Frame::Swap (theFrame, myFrameTmp);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
theFrame->Unref();
|
||||
if (myFrameTmp->IsEmpty()
|
||||
|| myFrameTmp->Size().x() < 1
|
||||
|| myFrameTmp->Size().y() < 1)
|
||||
{
|
||||
theFrame->Unref();
|
||||
return false;
|
||||
}
|
||||
|
||||
const Graphic3d_Vec2i aSize = myFrameTmp->Size();
|
||||
const Graphic3d_Vec2i aSizeUV = myFrameTmp->Size() / 2;
|
||||
AVFrame* aFrame = theFrame->ChangeFrame();
|
||||
if (myToForceRgb)
|
||||
{
|
||||
if (myBufferPools[0].IsNull())
|
||||
{
|
||||
myBufferPools[0] = new Media_BufferPool();
|
||||
}
|
||||
|
||||
const int aLineSize = getAligned (aSize.x() * 3);
|
||||
const int aBufSize = aLineSize * aSize.y();
|
||||
if (!myBufferPools[0]->Init (aBufSize))
|
||||
{
|
||||
Message::DefaultMessenger()->Send ("FFmpeg: unable to allocate RGB24 frame buffer", Message_Fail);
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef HAVE_FFMPEG
|
||||
aFrame->buf[0] = myBufferPools[0]->GetBuffer();
|
||||
if (aFrame->buf[0] == NULL)
|
||||
{
|
||||
theFrame->Unref();
|
||||
Message::DefaultMessenger()->Send ("FFmpeg: unable to allocate RGB24 frame buffer", Message_Fail);
|
||||
return false;
|
||||
}
|
||||
|
||||
aFrame->format = AV_PIX_FMT_RGB24;
|
||||
aFrame->width = aSize.x();
|
||||
aFrame->height = aSize.y();
|
||||
aFrame->linesize[0] = aLineSize;
|
||||
aFrame->data[0] = aFrame->buf[0]->data;
|
||||
#else
|
||||
(void )aFrame;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int aPlaneIter = 0; aPlaneIter < 3; ++aPlaneIter)
|
||||
{
|
||||
if (myBufferPools[aPlaneIter].IsNull())
|
||||
{
|
||||
myBufferPools[aPlaneIter] = new Media_BufferPool();
|
||||
}
|
||||
}
|
||||
|
||||
const int aLineSize = getAligned (aSize.x());
|
||||
const int aLineSizeUV = getAligned (aSizeUV.x());
|
||||
const int aBufSize = aLineSize * aSize.y();
|
||||
const int aBufSizeUV = aLineSizeUV * aSizeUV.y();
|
||||
if (!myBufferPools[0]->Init (aBufSize)
|
||||
|| !myBufferPools[1]->Init (aBufSizeUV)
|
||||
|| !myBufferPools[2]->Init (aBufSizeUV))
|
||||
{
|
||||
Message::DefaultMessenger()->Send ("FFmpeg: unable to allocate YUV420P frame buffers", Message_Fail);
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef HAVE_FFMPEG
|
||||
aFrame->buf[0] = myBufferPools[0]->GetBuffer();
|
||||
aFrame->buf[1] = myBufferPools[1]->GetBuffer();
|
||||
aFrame->buf[2] = myBufferPools[2]->GetBuffer();
|
||||
if (aFrame->buf[0] == NULL
|
||||
|| aFrame->buf[1] == NULL
|
||||
|| aFrame->buf[2] == NULL)
|
||||
{
|
||||
theFrame->Unref();
|
||||
Message::DefaultMessenger()->Send ("FFmpeg: unable to allocate YUV420P frame buffers", Message_Fail);
|
||||
return false;
|
||||
}
|
||||
|
||||
aFrame->format = AV_PIX_FMT_YUV420P;
|
||||
aFrame->width = aSize.x();
|
||||
aFrame->height = aSize.y();
|
||||
aFrame->linesize[0] = aLineSize;
|
||||
aFrame->linesize[1] = aLineSizeUV;
|
||||
aFrame->linesize[2] = aLineSizeUV;
|
||||
aFrame->data[0] = aFrame->buf[0]->data;
|
||||
aFrame->data[1] = aFrame->buf[1]->data;
|
||||
aFrame->data[2] = aFrame->buf[2]->data;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (myScaler.IsNull())
|
||||
{
|
||||
myScaler = new Media_Scaler();
|
||||
}
|
||||
if (!myScaler->Convert (myFrameTmp, theFrame))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
myFrameTmp->Unref();
|
||||
return true;
|
||||
}
|
||||
|
||||
//================================================================
|
||||
// Function : doThreadLoop
|
||||
// Purpose :
|
||||
//================================================================
|
||||
void Media_PlayerContext::doThreadLoop()
|
||||
{
|
||||
OSD::SetSignal (false);
|
||||
Handle(Media_Frame) aFrame;
|
||||
bool wasSeeked = false;
|
||||
for (;;)
|
||||
{
|
||||
myWakeEvent.Wait();
|
||||
myWakeEvent.Reset();
|
||||
if (myToShutDown)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
TCollection_AsciiString anInput;
|
||||
{
|
||||
Standard_Mutex::Sentry aLock (myMutex);
|
||||
std::swap (anInput, myInputPath);
|
||||
if (myPlayEvent == Media_PlayerEvent_NEXT)
|
||||
{
|
||||
myPlayEvent = Media_PlayerEvent_NONE;
|
||||
}
|
||||
}
|
||||
myNextEvent.Set();
|
||||
if (anInput.IsEmpty())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Handle(Media_FormatContext) aFormatCtx = new Media_FormatContext();
|
||||
if (!aFormatCtx->OpenInput (anInput))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Handle(Media_CodecContext) aVideoCtx;
|
||||
#ifdef HAVE_FFMPEG
|
||||
for (unsigned int aStreamId = 0; aStreamId < aFormatCtx->NbSteams(); ++aStreamId)
|
||||
{
|
||||
const AVStream& aStream = aFormatCtx->Stream (aStreamId);
|
||||
const AVMediaType aCodecType = aStream.codecpar->codec_type;
|
||||
if (aCodecType == AVMEDIA_TYPE_VIDEO)
|
||||
{
|
||||
aVideoCtx = new Media_CodecContext();
|
||||
if (!aVideoCtx->Init (aStream, aFormatCtx->PtsStartBase(), 1))
|
||||
{
|
||||
aVideoCtx.Nullify();
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (aVideoCtx.IsNull())
|
||||
{
|
||||
Message::DefaultMessenger()->Send (TCollection_AsciiString ("FFmpeg: no video stream in '") + anInput + "'", Message_Fail);
|
||||
continue;
|
||||
}
|
||||
|
||||
Handle(Media_Packet) aPacket = new Media_Packet();
|
||||
Media_PlayerEvent aPlayEvent = Media_PlayerEvent_NONE;
|
||||
{
|
||||
Standard_Mutex::Sentry aLock (myMutex);
|
||||
myTimer.Stop();
|
||||
myTimer.Start();
|
||||
myDuration = aFormatCtx->Duration();
|
||||
}
|
||||
if (!aFrame.IsNull())
|
||||
{
|
||||
aFrame->Unref();
|
||||
}
|
||||
const double anUploadDelaySec = 1.0 / 60.0 + 0.0001;
|
||||
for (;;)
|
||||
{
|
||||
if (myToShutDown)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else if (!aFormatCtx->ReadPacket (aPacket))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
popPlayEvent (aPlayEvent, aFormatCtx, aVideoCtx, aFrame);
|
||||
if (aPlayEvent == Media_PlayerEvent_NEXT)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if (aPlayEvent == Media_PlayerEvent_SEEK)
|
||||
{
|
||||
wasSeeked = true;
|
||||
}
|
||||
|
||||
bool isAccepted = false;
|
||||
if (aVideoCtx->CanProcessPacket (aPacket))
|
||||
{
|
||||
isAccepted = true;
|
||||
aVideoCtx->SendPacket (aPacket);
|
||||
}
|
||||
aPacket->Unref();
|
||||
if (!isAccepted)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
for (;;)
|
||||
{
|
||||
if (myToShutDown)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else if (popPlayEvent (aPlayEvent, aFormatCtx, aVideoCtx, aFrame))
|
||||
{
|
||||
if (aPlayEvent == Media_PlayerEvent_NEXT)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if (aPlayEvent == Media_PlayerEvent_SEEK)
|
||||
{
|
||||
wasSeeked = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (aFrame.IsNull())
|
||||
{
|
||||
aFrame = myFrameQueue->LockFrame();
|
||||
if (aFrame.IsNull())
|
||||
{
|
||||
OSD::MilliSecSleep (1);
|
||||
continue;
|
||||
}
|
||||
aFrame->Unref();
|
||||
}
|
||||
if (aFrame->IsEmpty()
|
||||
&& !receiveFrame (aFrame, aVideoCtx))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
const double aTime = myTimer.ElapsedTime() - anUploadDelaySec;
|
||||
if (wasSeeked
|
||||
|| (aFrame->Pts() <= aTime
|
||||
&& myTimer.IsStarted()))
|
||||
{
|
||||
wasSeeked = false;
|
||||
myFrameQueue->ReleaseFrame (aFrame);
|
||||
aFrame.Nullify();
|
||||
break;
|
||||
}
|
||||
|
||||
OSD::MilliSecSleep (1);
|
||||
}
|
||||
if (aPlayEvent == Media_PlayerEvent_NEXT)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
155
src/Media/Media_PlayerContext.hxx
Normal file
155
src/Media/Media_PlayerContext.hxx
Normal file
@@ -0,0 +1,155 @@
|
||||
// Created by: Kirill GAVRILOV
|
||||
// Copyright (c) 2019 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _Media_PlayerContext_HeaderFile
|
||||
#define _Media_PlayerContext_HeaderFile
|
||||
|
||||
#include <Media_IFrameQueue.hxx>
|
||||
#include <Media_Timer.hxx>
|
||||
#include <OSD_Thread.hxx>
|
||||
#include <Standard_Condition.hxx>
|
||||
#include <Standard_Mutex.hxx>
|
||||
#include <Standard_Transient.hxx>
|
||||
#include <Standard_Type.hxx>
|
||||
#include <TCollection_AsciiString.hxx>
|
||||
|
||||
class Media_BufferPool;
|
||||
class Media_CodecContext;
|
||||
class Media_FormatContext;
|
||||
class Media_Scaler;
|
||||
|
||||
//! Player context.
|
||||
class Media_PlayerContext : public Standard_Transient
|
||||
{
|
||||
DEFINE_STANDARD_RTTIEXT(Media_PlayerContext, Standard_Transient)
|
||||
public:
|
||||
|
||||
//! Dump first video frame.
|
||||
//! @param theSrcVideo [in] path to the video
|
||||
//! @param theMediaInfo [out] video description
|
||||
Standard_EXPORT static Handle(Media_Frame) DumpFirstFrame (const TCollection_AsciiString& theSrcVideo,
|
||||
TCollection_AsciiString& theMediaInfo);
|
||||
|
||||
//! Dump first video frame.
|
||||
//! @param theSrcVideo [in] path to the video
|
||||
//! @param theOutImage [in] path to make a screenshot
|
||||
//! @param theMediaInfo [out] video description
|
||||
//! @param theMaxSize [in] when positive - downscales image to specified size
|
||||
Standard_EXPORT static bool DumpFirstFrame (const TCollection_AsciiString& theSrcVideo,
|
||||
const TCollection_AsciiString& theOutImage,
|
||||
TCollection_AsciiString& theMediaInfo,
|
||||
int theMaxSize = 0);
|
||||
|
||||
public:
|
||||
|
||||
//! Main constructor.
|
||||
//! Note that Frame Queue is stored as pointer,
|
||||
//! and it is expected that this context is stored as a class field of Frame Queue.
|
||||
Standard_EXPORT Media_PlayerContext (Media_IFrameQueue* theFrameQueue);
|
||||
|
||||
//! Destructor.
|
||||
Standard_EXPORT virtual ~Media_PlayerContext();
|
||||
|
||||
public:
|
||||
|
||||
//! Set new input for playback.
|
||||
Standard_EXPORT void SetInput (const TCollection_AsciiString& theInputPath,
|
||||
Standard_Boolean theToWait);
|
||||
|
||||
//! Return playback state.
|
||||
Standard_EXPORT void PlaybackState (Standard_Boolean& theIsPaused,
|
||||
Standard_Real& theProgress,
|
||||
Standard_Real& theDuration);
|
||||
|
||||
//! Pause/Pause playback depending on the current state.
|
||||
Standard_EXPORT void PlayPause (Standard_Boolean& theIsPaused,
|
||||
Standard_Real& theProgress,
|
||||
Standard_Real& theDuration);
|
||||
|
||||
//! Seek to specified position.
|
||||
Standard_EXPORT void Seek (Standard_Real thePosSec);
|
||||
|
||||
//! Pause playback.
|
||||
void Pause() { pushPlayEvent (Media_PlayerEvent_PAUSE); }
|
||||
|
||||
//! Resume playback.
|
||||
void Resume() { pushPlayEvent (Media_PlayerEvent_RESUME); }
|
||||
|
||||
//! Return TRUE if queue requires RGB pixel format or can handle also YUV pixel format; TRUE by default.
|
||||
bool ToForceRgb() const { return myToForceRgb; }
|
||||
|
||||
//! Set if queue requires RGB pixel format or can handle also YUV pixel format.
|
||||
void SetForceRgb (bool theToForce) { myToForceRgb = theToForce; }
|
||||
|
||||
private:
|
||||
|
||||
//! Internal enumeration for events.
|
||||
enum Media_PlayerEvent
|
||||
{
|
||||
Media_PlayerEvent_NONE = 0,
|
||||
Media_PlayerEvent_PAUSE,
|
||||
Media_PlayerEvent_RESUME,
|
||||
Media_PlayerEvent_SEEK,
|
||||
Media_PlayerEvent_NEXT,
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
//! Thread loop.
|
||||
Standard_EXPORT void doThreadLoop();
|
||||
|
||||
//! Push new playback event.
|
||||
Standard_EXPORT void pushPlayEvent (Media_PlayerEvent thePlayEvent);
|
||||
|
||||
//! Fetch new playback event.
|
||||
Standard_EXPORT bool popPlayEvent (Media_PlayerEvent& thePlayEvent,
|
||||
const Handle(Media_FormatContext)& theFormatCtx,
|
||||
const Handle(Media_CodecContext)& theVideoCtx,
|
||||
const Handle(Media_Frame)& theFrame);
|
||||
|
||||
//! Decode new frame.
|
||||
bool receiveFrame (const Handle(Media_Frame)& theFrame,
|
||||
const Handle(Media_CodecContext)& theVideoCtx);
|
||||
|
||||
//! Thread creation callback.
|
||||
static Standard_Address doThreadWrapper (Standard_Address theData)
|
||||
{
|
||||
Media_PlayerContext* aThis = (Media_PlayerContext* )theData;
|
||||
aThis->doThreadLoop();
|
||||
return 0;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
Media_IFrameQueue* myFrameQueue; //!< frame queue
|
||||
OSD_Thread myThread; //!< working thread
|
||||
Standard_Mutex myMutex; //!< mutex for events
|
||||
Standard_Condition myWakeEvent; //!< event to wake up working thread and proceed new playback event
|
||||
Standard_Condition myNextEvent; //!< event to check if working thread processed next file event (e.g. released file handles of previous input)
|
||||
Media_Timer myTimer; //!< playback timer
|
||||
Standard_Real myDuration; //!< playback duration
|
||||
|
||||
Handle(Media_BufferPool) myBufferPools[4]; //!< per-plane pools
|
||||
Handle(Media_Frame) myFrameTmp; //!< temporary object holding decoded frame
|
||||
Handle(Media_Scaler) myScaler; //!< pixel format conversion tool
|
||||
bool myToForceRgb; //!< flag indicating if queue requires RGB pixel format or can handle also YUV pixel format
|
||||
|
||||
volatile bool myToShutDown; //!< flag to terminate working thread
|
||||
TCollection_AsciiString myInputPath; //!< new input to open
|
||||
volatile Standard_Real mySeekTo; //!< new seeking position
|
||||
volatile Media_PlayerEvent myPlayEvent; //!< playback event
|
||||
|
||||
};
|
||||
|
||||
#endif // _Media_PlayerContext_HeaderFile
|
151
src/Media/Media_Scaler.cxx
Normal file
151
src/Media/Media_Scaler.cxx
Normal file
@@ -0,0 +1,151 @@
|
||||
// Created by: Kirill GAVRILOV
|
||||
// Copyright (c) 2019 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
// activate some C99 macros like UINT64_C in "stdint.h" which used by FFmpeg
|
||||
#ifndef __STDC_CONSTANT_MACROS
|
||||
#define __STDC_CONSTANT_MACROS
|
||||
#endif
|
||||
|
||||
#include <Media_Scaler.hxx>
|
||||
|
||||
#ifdef HAVE_FFMPEG
|
||||
#include <Standard_WarningsDisable.hxx>
|
||||
extern "C"
|
||||
{
|
||||
#include <libavcodec/avcodec.h>
|
||||
#include <libavutil/imgutils.h>
|
||||
#include <libswscale/swscale.h>
|
||||
};
|
||||
#include <Standard_WarningsRestore.hxx>
|
||||
#endif
|
||||
|
||||
IMPLEMENT_STANDARD_RTTIEXT(Media_Scaler, Standard_Transient)
|
||||
|
||||
// =======================================================================
|
||||
// function : Media_Scaler
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
Media_Scaler::Media_Scaler()
|
||||
: mySwsContext (NULL),
|
||||
mySrcFormat (0),
|
||||
myResFormat (0)
|
||||
{
|
||||
#ifdef HAVE_FFMPEG
|
||||
mySrcFormat = AV_PIX_FMT_NONE;
|
||||
myResFormat = AV_PIX_FMT_NONE;
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : ~Media_Scaler
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
Media_Scaler::~Media_Scaler()
|
||||
{
|
||||
Release();
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : Release
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void Media_Scaler::Release()
|
||||
{
|
||||
if (mySwsContext != NULL)
|
||||
{
|
||||
#ifdef HAVE_FFMPEG
|
||||
sws_freeContext (mySwsContext);
|
||||
#endif
|
||||
mySwsContext = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : Convert
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
bool Media_Scaler::Init (const Graphic3d_Vec2i& theSrcDims,
|
||||
int theSrcFormat,
|
||||
const Graphic3d_Vec2i& theResDims,
|
||||
int theResFormat)
|
||||
{
|
||||
#ifdef HAVE_FFMPEG
|
||||
if (theSrcDims.x() < 1
|
||||
|| theSrcDims.y() < 1
|
||||
|| theResDims.x() < 1
|
||||
|| theResDims.y() < 1
|
||||
|| theSrcFormat == AV_PIX_FMT_NONE
|
||||
|| theResFormat == AV_PIX_FMT_NONE)
|
||||
{
|
||||
Release();
|
||||
return false;
|
||||
}
|
||||
else if (mySrcDims == theSrcDims
|
||||
&& myResDims == theResDims
|
||||
&& mySrcFormat == theSrcFormat
|
||||
&& myResFormat == theResFormat)
|
||||
{
|
||||
return mySwsContext != NULL;
|
||||
}
|
||||
|
||||
Release();
|
||||
mySrcDims = theSrcDims;
|
||||
myResDims = theResDims;
|
||||
mySrcFormat = theSrcFormat;
|
||||
myResFormat = theResFormat;
|
||||
mySwsContext = sws_getContext (theSrcDims.x(), theSrcDims.y(), (AVPixelFormat )theSrcFormat,
|
||||
theResDims.x(), theResDims.y(), (AVPixelFormat )theResFormat,
|
||||
SWS_BICUBIC, NULL, NULL, NULL);
|
||||
return mySwsContext != NULL;
|
||||
#else
|
||||
(void )theSrcDims;
|
||||
(void )theSrcFormat;
|
||||
(void )theResDims;
|
||||
(void )theResFormat;
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : Convert
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
bool Media_Scaler::Convert (const Handle(Media_Frame)& theSrc,
|
||||
const Handle(Media_Frame)& theRes)
|
||||
{
|
||||
if (theSrc.IsNull()
|
||||
|| theSrc->IsEmpty()
|
||||
|| theRes.IsNull()
|
||||
|| theRes->IsEmpty()
|
||||
|| theSrc == theRes)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Init (theSrc->Size(), theSrc->Format(),
|
||||
theRes->Size(), theRes->Format()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef HAVE_FFMPEG
|
||||
sws_scale (mySwsContext,
|
||||
theSrc->Frame()->data, theSrc->Frame()->linesize,
|
||||
0, theSrc->SizeY(),
|
||||
theRes->ChangeFrame()->data, theRes->Frame()->linesize);
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
68
src/Media/Media_Scaler.hxx
Normal file
68
src/Media/Media_Scaler.hxx
Normal file
@@ -0,0 +1,68 @@
|
||||
// Created by: Kirill GAVRILOV
|
||||
// Copyright (c) 2019 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _Media_Scaler_HeaderFile
|
||||
#define _Media_Scaler_HeaderFile
|
||||
|
||||
#include <Media_Frame.hxx>
|
||||
|
||||
#include <Standard_Transient.hxx>
|
||||
#include <Standard_Type.hxx>
|
||||
#include <Graphic3d_Vec2.hxx>
|
||||
|
||||
struct SwsContext;
|
||||
|
||||
//! SwsContext wrapper - tool performing image scaling and pixel format conversion.
|
||||
class Media_Scaler : public Standard_Transient
|
||||
{
|
||||
DEFINE_STANDARD_RTTIEXT(Media_Scaler, Standard_Transient)
|
||||
public:
|
||||
|
||||
//! Empty constructor.
|
||||
Standard_EXPORT Media_Scaler();
|
||||
|
||||
//! Destructor.
|
||||
Standard_EXPORT virtual ~Media_Scaler();
|
||||
|
||||
//! sws_freeContext() wrapper.
|
||||
Standard_EXPORT void Release();
|
||||
|
||||
//! sws_getContext() wrapper - creates conversion context.
|
||||
//! @param theSrcDims dimensions of input frame
|
||||
//! @param theSrcFormat pixel format (AVPixelFormat) of input frame
|
||||
//! @param theResDims dimensions of destination frame
|
||||
//! @param theResFormat pixel format (AVPixelFormat) of destination frame
|
||||
Standard_EXPORT bool Init (const Graphic3d_Vec2i& theSrcDims,
|
||||
int theSrcFormat,
|
||||
const Graphic3d_Vec2i& theResDims,
|
||||
int theResFormat);
|
||||
|
||||
//! Convert one frame to another.
|
||||
Standard_EXPORT bool Convert (const Handle(Media_Frame)& theSrc,
|
||||
const Handle(Media_Frame)& theRes);
|
||||
|
||||
//! Return TRUE if context was initialized.
|
||||
bool IsValid() const { return mySwsContext != NULL; }
|
||||
|
||||
protected:
|
||||
|
||||
SwsContext* mySwsContext; //!< conversion context
|
||||
Graphic3d_Vec2i mySrcDims; //!< dimensions of input frame
|
||||
int mySrcFormat; //!< pixel format (AVPixelFormat) of input frame
|
||||
Graphic3d_Vec2i myResDims; //!< dimensions of destination frame
|
||||
int myResFormat; //!< pixel format (AVPixelFormat) of destination frame
|
||||
|
||||
};
|
||||
|
||||
#endif // _Media_Scaler_HeaderFile
|
@@ -12,15 +12,15 @@
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#include <AIS_AnimationTimer.hxx>
|
||||
#include <Media_Timer.hxx>
|
||||
|
||||
IMPLEMENT_STANDARD_RTTIEXT(AIS_AnimationTimer, Standard_Transient)
|
||||
IMPLEMENT_STANDARD_RTTIEXT(Media_Timer, Standard_Transient)
|
||||
|
||||
//=============================================================================
|
||||
//function : Pause
|
||||
//purpose :
|
||||
//=============================================================================
|
||||
void AIS_AnimationTimer::Pause()
|
||||
void Media_Timer::Pause()
|
||||
{
|
||||
myTimer.Stop();
|
||||
myTimerFrom += myTimer.ElapsedTime() * myTimerSpeed;
|
||||
@@ -31,7 +31,7 @@ void AIS_AnimationTimer::Pause()
|
||||
//function : Stop
|
||||
//purpose :
|
||||
//=============================================================================
|
||||
void AIS_AnimationTimer::Stop()
|
||||
void Media_Timer::Stop()
|
||||
{
|
||||
myTimer.Stop();
|
||||
myTimer.Reset();
|
||||
@@ -42,7 +42,7 @@ void AIS_AnimationTimer::Stop()
|
||||
//function : SetPlaybackSpeed
|
||||
//purpose :
|
||||
//=============================================================================
|
||||
void AIS_AnimationTimer::SetPlaybackSpeed (const Standard_Real theSpeed)
|
||||
void Media_Timer::SetPlaybackSpeed (const Standard_Real theSpeed)
|
||||
{
|
||||
if (!myTimer.IsStarted())
|
||||
{
|
||||
@@ -61,7 +61,7 @@ void AIS_AnimationTimer::SetPlaybackSpeed (const Standard_Real theSpeed)
|
||||
//function : SetPlaybackSpeed
|
||||
//purpose :
|
||||
//=============================================================================
|
||||
void AIS_AnimationTimer::Seek (const Standard_Real theTime)
|
||||
void Media_Timer::Seek (const Standard_Real theTime)
|
||||
{
|
||||
const Standard_Boolean isStarted = myTimer.IsStarted();
|
||||
myTimer.Stop();
|
74
src/Media/Media_Timer.hxx
Normal file
74
src/Media/Media_Timer.hxx
Normal file
@@ -0,0 +1,74 @@
|
||||
// Created by: Kirill Gavrilov
|
||||
// Copyright (c) 2016 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _Media_Timer_HeaderFile
|
||||
#define _Media_Timer_HeaderFile
|
||||
|
||||
#include <OSD_Timer.hxx>
|
||||
#include <Standard_Transient.hxx>
|
||||
#include <Standard_Type.hxx>
|
||||
|
||||
//! Auxiliary class defining the animation timer.
|
||||
class Media_Timer : public Standard_Transient
|
||||
{
|
||||
DEFINE_STANDARD_RTTIEXT(Media_Timer, Standard_Transient)
|
||||
public:
|
||||
|
||||
//! Empty constructor.
|
||||
Media_Timer() : myTimerFrom (0.0), myTimerSpeed (1.0) {}
|
||||
|
||||
//! Return elapsed time in seconds.
|
||||
Standard_Real ElapsedTime() const
|
||||
{
|
||||
return myTimerFrom + myTimer.ElapsedTime() * myTimerSpeed;
|
||||
}
|
||||
|
||||
//! Return playback speed coefficient (1.0 means normal speed).
|
||||
Standard_Real PlaybackSpeed() const { return myTimerSpeed; }
|
||||
|
||||
//! Setup playback speed coefficient.
|
||||
Standard_EXPORT void SetPlaybackSpeed (const Standard_Real theSpeed);
|
||||
|
||||
//! Return true if timer has been started.
|
||||
Standard_Boolean IsStarted() const
|
||||
{
|
||||
return myTimer.IsStarted();
|
||||
}
|
||||
|
||||
//! Start the timer.
|
||||
void Start()
|
||||
{
|
||||
myTimer.Start();
|
||||
}
|
||||
|
||||
//! Pause the timer.
|
||||
Standard_EXPORT void Pause();
|
||||
|
||||
//! Stop the timer.
|
||||
Standard_EXPORT void Stop();
|
||||
|
||||
//! Seek the timer to specified position.
|
||||
Standard_EXPORT void Seek (const Standard_Real theTime);
|
||||
|
||||
protected:
|
||||
|
||||
OSD_Timer myTimer;
|
||||
Standard_Real myTimerFrom;
|
||||
Standard_Real myTimerSpeed;
|
||||
|
||||
};
|
||||
|
||||
DEFINE_STANDARD_HANDLE(Media_Timer, Standard_Transient)
|
||||
|
||||
#endif // _Media_Timer_HeaderFile
|
@@ -49,6 +49,17 @@ public:
|
||||
InitIdentity();
|
||||
}
|
||||
|
||||
//! Conversion constructor (explicitly converts some 4 x 4 matrix with other element type
|
||||
//! to a new 4 x 4 matrix with the element type Element_t,
|
||||
//! whose elements are static_cast'ed corresponding elements of theOtherMat4 matrix)
|
||||
//! @tparam OtherElement_t the element type of the other 4 x 4 matrix theOtherVec4
|
||||
//! @param theOtherMat4 the 4 x 4 matrix that needs to be converted
|
||||
template <typename OtherElement_t>
|
||||
explicit NCollection_Mat4 (const NCollection_Mat4<OtherElement_t>& theOtherMat4)
|
||||
{
|
||||
ConvertFrom (theOtherMat4);
|
||||
}
|
||||
|
||||
//! Get element at the specified row and column.
|
||||
//! @param theRow [in] the row.to address.
|
||||
//! @param theCol [in] the column to address.
|
||||
|
@@ -57,6 +57,18 @@ public:
|
||||
v[1] = theY;
|
||||
}
|
||||
|
||||
//! Conversion constructor (explicitly converts some 2-component vector with other element type
|
||||
//! to a new 2-component vector with the element type Element_t,
|
||||
//! whose elements are static_cast'ed corresponding elements of theOtherVec2 vector)
|
||||
//! @tparam OtherElement_t the element type of the other 2-component vector theOtherVec2
|
||||
//! @param theOtherVec2 the 2-component vector that needs to be converted
|
||||
template <typename OtherElement_t>
|
||||
explicit NCollection_Vec2 (const NCollection_Vec2<OtherElement_t>& theOtherVec2)
|
||||
{
|
||||
v[0] = static_cast<Element_t> (theOtherVec2[0]);
|
||||
v[1] = static_cast<Element_t> (theOtherVec2[1]);
|
||||
}
|
||||
|
||||
//! Assign new values to the vector.
|
||||
void SetValues (const Element_t theX,
|
||||
const Element_t theY)
|
||||
|
@@ -73,6 +73,19 @@ public:
|
||||
v[2] = theZ;
|
||||
}
|
||||
|
||||
//! Conversion constructor (explicitly converts some 3-component vector with other element type
|
||||
//! to a new 3-component vector with the element type Element_t,
|
||||
//! whose elements are static_cast'ed corresponding elements of theOtherVec3 vector)
|
||||
//! @tparam OtherElement_t the element type of the other 3-component vector theOtherVec3
|
||||
//! @param theOtherVec3 the 3-component vector that needs to be converted
|
||||
template <typename OtherElement_t>
|
||||
explicit NCollection_Vec3 (const NCollection_Vec3<OtherElement_t>& theOtherVec3)
|
||||
{
|
||||
v[0] = static_cast<Element_t> (theOtherVec3[0]);
|
||||
v[1] = static_cast<Element_t> (theOtherVec3[1]);
|
||||
v[2] = static_cast<Element_t> (theOtherVec3[2]);
|
||||
}
|
||||
|
||||
//! Assign new values to the vector.
|
||||
void SetValues (const Element_t theX,
|
||||
const Element_t theY,
|
||||
|
@@ -73,6 +73,20 @@ public:
|
||||
v[3] = theW;
|
||||
}
|
||||
|
||||
//! Conversion constructor (explicitly converts some 4-component vector with other element type
|
||||
//! to a new 4-component vector with the element type Element_t,
|
||||
//! whose elements are static_cast'ed corresponding elements of theOtherVec4 vector)
|
||||
//! @tparam OtherElement_t the element type of the other 4-component vector theOtherVec4
|
||||
//! @param theOtherVec4 the 4-component vector that needs to be converted
|
||||
template <typename OtherElement_t>
|
||||
explicit NCollection_Vec4 (const NCollection_Vec4<OtherElement_t>& theOtherVec4)
|
||||
{
|
||||
v[0] = static_cast<Element_t> (theOtherVec4[0]);
|
||||
v[1] = static_cast<Element_t> (theOtherVec4[1]);
|
||||
v[2] = static_cast<Element_t> (theOtherVec4[2]);
|
||||
v[3] = static_cast<Element_t> (theOtherVec4[3]);
|
||||
}
|
||||
|
||||
//! Assign new values to the vector.
|
||||
void SetValues (const Element_t theX,
|
||||
const Element_t theY,
|
||||
|
@@ -18,7 +18,6 @@ proc Visualization:toolkits { } {
|
||||
set aResult [list TKService \
|
||||
TKV3d \
|
||||
TKOpenGl \
|
||||
TKVulkan \
|
||||
TKMeshVS]
|
||||
|
||||
if { [info exists ::env(HAVE_VTK)] && "$::env(HAVE_VTK)" == "true" } {
|
||||
|
@@ -171,6 +171,34 @@ namespace {
|
||||
}
|
||||
#endif
|
||||
|
||||
static Standard_Boolean OSD_Parallel_ToUseOcctThreads =
|
||||
#ifdef HAVE_TBB
|
||||
Standard_False;
|
||||
#else
|
||||
Standard_True;
|
||||
#endif
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : ToUseOcctThreads
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
Standard_Boolean OSD_Parallel::ToUseOcctThreads()
|
||||
{
|
||||
return OSD_Parallel_ToUseOcctThreads;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : SetUseOcctThreads
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
void OSD_Parallel::SetUseOcctThreads (Standard_Boolean theToUseOcct)
|
||||
{
|
||||
#ifdef HAVE_TBB
|
||||
OSD_Parallel_ToUseOcctThreads = theToUseOcct;
|
||||
#else
|
||||
(void )theToUseOcct;
|
||||
#endif
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
|
@@ -14,6 +14,7 @@
|
||||
#ifndef OSD_Parallel_HeaderFile
|
||||
#define OSD_Parallel_HeaderFile
|
||||
|
||||
#include <OSD_ThreadPool.hxx>
|
||||
#include <Standard_Type.hxx>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
@@ -242,6 +243,24 @@ private:
|
||||
const Functor& myFunctor;
|
||||
};
|
||||
|
||||
//! Wrapper redirecting functor taking element index to functor taking also thread index.
|
||||
template<class Functor>
|
||||
class FunctorWrapperForThreadPool
|
||||
{
|
||||
public:
|
||||
FunctorWrapperForThreadPool (const Functor& theFunctor) : myFunctor(theFunctor) {}
|
||||
|
||||
void operator() (int theThreadIndex, int theElemIndex) const
|
||||
{
|
||||
(void )theThreadIndex;
|
||||
myFunctor (theElemIndex);
|
||||
}
|
||||
private:
|
||||
FunctorWrapperForThreadPool (const FunctorWrapperForThreadPool&);
|
||||
void operator= (const FunctorWrapperForThreadPool&);
|
||||
const Functor& myFunctor;
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
//! Simple primitive for parallelization of "foreach" loops, e.g.:
|
||||
@@ -250,19 +269,33 @@ private:
|
||||
//! @endcode
|
||||
//! Implementation of framework-dependent functionality should be provided by
|
||||
//! forEach_impl function defined in opencascade::parallel namespace.
|
||||
//! @param theBegin the first index (incusive)
|
||||
//! @param theBegin the first index (inclusive)
|
||||
//! @param theEnd the last index (exclusive)
|
||||
//! @param theFunctor functor providing an interface "void operator(InputIterator theIter){}"
|
||||
//! performing task for the specified iterator position
|
||||
//! @param theNbItems number of items passed by iterator, -1 if unknown
|
||||
Standard_EXPORT static void forEach (UniversalIterator& theBegin,
|
||||
UniversalIterator& theEnd,
|
||||
const FunctorInterface& theFunctor,
|
||||
Standard_Integer theNbItems);
|
||||
Standard_EXPORT static void forEachOcct (UniversalIterator& theBegin,
|
||||
UniversalIterator& theEnd,
|
||||
const FunctorInterface& theFunctor,
|
||||
Standard_Integer theNbItems);
|
||||
|
||||
//! Same as forEachOcct() but can be implemented using external threads library.
|
||||
Standard_EXPORT static void forEachExternal (UniversalIterator& theBegin,
|
||||
UniversalIterator& theEnd,
|
||||
const FunctorInterface& theFunctor,
|
||||
Standard_Integer theNbItems);
|
||||
|
||||
public: //! @name public methods
|
||||
|
||||
//! Returns number of logical proccesrs.
|
||||
//! Returns TRUE if OCCT threads should be used instead of auxiliary threads library;
|
||||
//! default value is FALSE if alternative library has been enabled while OCCT building and TRUE otherwise.
|
||||
Standard_EXPORT static Standard_Boolean ToUseOcctThreads();
|
||||
|
||||
//! Sets if OCCT threads should be used instead of auxiliary threads library.
|
||||
//! Has no effect if OCCT has been built with no auxiliary threads library.
|
||||
Standard_EXPORT static void SetUseOcctThreads (Standard_Boolean theToUseOcct);
|
||||
|
||||
//! Returns number of logical processors.
|
||||
Standard_EXPORT static Standard_Integer NbLogicalProcessors();
|
||||
|
||||
//! Simple primitive for parallelization of "foreach" loops, equivalent to:
|
||||
@@ -271,7 +304,7 @@ public: //! @name public methods
|
||||
//! theFunctor(*anIter);
|
||||
//! }
|
||||
//! @endcode
|
||||
//! @param theBegin the first index (incusive)
|
||||
//! @param theBegin the first index (inclusive)
|
||||
//! @param theEnd the last index (exclusive)
|
||||
//! @param theFunctor functor providing an interface "void operator(InputIterator theIter){}"
|
||||
//! performing task for specified iterator position
|
||||
@@ -294,7 +327,14 @@ public: //! @name public methods
|
||||
UniversalIterator aBegin(new IteratorWrapper<InputIterator>(theBegin));
|
||||
UniversalIterator aEnd (new IteratorWrapper<InputIterator>(theEnd));
|
||||
FunctorWrapperIter<InputIterator,Functor> aFunctor (theFunctor);
|
||||
forEach(aBegin, aEnd, aFunctor, theNbItems);
|
||||
if (ToUseOcctThreads())
|
||||
{
|
||||
forEachOcct (aBegin, aEnd, aFunctor, theNbItems);
|
||||
}
|
||||
else
|
||||
{
|
||||
forEachExternal (aBegin, aEnd, aFunctor, theNbItems);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -304,7 +344,7 @@ public: //! @name public methods
|
||||
//! theFunctor(anIter);
|
||||
//! }
|
||||
//! @endcode
|
||||
//! @param theBegin the first index (incusive)
|
||||
//! @param theBegin the first index (inclusive)
|
||||
//! @param theEnd the last index (exclusive)
|
||||
//! @param theFunctor functor providing an interface "void operator(int theIndex){}"
|
||||
//! performing task for specified index
|
||||
@@ -315,17 +355,25 @@ public: //! @name public methods
|
||||
const Functor& theFunctor,
|
||||
const Standard_Boolean isForceSingleThreadExecution = Standard_False)
|
||||
{
|
||||
if (isForceSingleThreadExecution || (theEnd - theBegin) == 1)
|
||||
const Standard_Integer aRange = theEnd - theBegin;
|
||||
if (isForceSingleThreadExecution || aRange == 1)
|
||||
{
|
||||
for (Standard_Integer it (theBegin); it != theEnd; ++it)
|
||||
theFunctor(it);
|
||||
}
|
||||
else if (ToUseOcctThreads())
|
||||
{
|
||||
const Handle(OSD_ThreadPool)& aThreadPool = OSD_ThreadPool::DefaultPool();
|
||||
OSD_ThreadPool::Launcher aPoolLauncher (*aThreadPool, aRange);
|
||||
FunctorWrapperForThreadPool<Functor> aFunctor (theFunctor);
|
||||
aPoolLauncher.Perform (theBegin, theEnd, aFunctor);
|
||||
}
|
||||
else
|
||||
{
|
||||
UniversalIterator aBegin(new IteratorWrapper<Standard_Integer>(theBegin));
|
||||
UniversalIterator aEnd (new IteratorWrapper<Standard_Integer>(theEnd));
|
||||
FunctorWrapperInt<Functor> aFunctor (theFunctor);
|
||||
forEach(aBegin, aEnd, aFunctor, theEnd - theBegin);
|
||||
forEachExternal (aBegin, aEnd, aFunctor, aRange);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -27,14 +27,14 @@
|
||||
#include <tbb/task_scheduler_init.h>
|
||||
|
||||
//=======================================================================
|
||||
//function : forEach
|
||||
//function : forEachExternal
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
|
||||
void OSD_Parallel::forEach (UniversalIterator& theBegin,
|
||||
UniversalIterator& theEnd,
|
||||
const FunctorInterface& theFunctor,
|
||||
Standard_Integer theNbItems)
|
||||
void OSD_Parallel::forEachExternal (UniversalIterator& theBegin,
|
||||
UniversalIterator& theEnd,
|
||||
const FunctorInterface& theFunctor,
|
||||
Standard_Integer theNbItems)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@@ -14,9 +14,6 @@
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
// Version of parallel executor used when TBB is not available
|
||||
#ifndef HAVE_TBB
|
||||
|
||||
#include <OSD_Parallel.hxx>
|
||||
|
||||
#include <OSD_ThreadPool.hxx>
|
||||
@@ -142,13 +139,13 @@ namespace
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : forEach
|
||||
//purpose :
|
||||
//function : forEachOcct
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
void OSD_Parallel::forEach (UniversalIterator& theBegin,
|
||||
UniversalIterator& theEnd,
|
||||
const FunctorInterface& theFunctor,
|
||||
Standard_Integer theNbItems)
|
||||
void OSD_Parallel::forEachOcct (UniversalIterator& theBegin,
|
||||
UniversalIterator& theEnd,
|
||||
const FunctorInterface& theFunctor,
|
||||
Standard_Integer theNbItems)
|
||||
{
|
||||
const Handle(OSD_ThreadPool)& aThreadPool = OSD_ThreadPool::DefaultPool();
|
||||
const Standard_Integer aNbThreads = theNbItems != -1 ? Min (theNbItems, aThreadPool->NbDefaultThreadsToLaunch()) : -1;
|
||||
@@ -156,4 +153,18 @@ void OSD_Parallel::forEach (UniversalIterator& theBegin,
|
||||
aLauncher.Perform (theBegin, theEnd, theFunctor);
|
||||
}
|
||||
|
||||
// Version of parallel executor used when TBB is not available
|
||||
#ifndef HAVE_TBB
|
||||
//=======================================================================
|
||||
//function : forEachExternal
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
void OSD_Parallel::forEachExternal (UniversalIterator& theBegin,
|
||||
UniversalIterator& theEnd,
|
||||
const FunctorInterface& theFunctor,
|
||||
Standard_Integer theNbItems)
|
||||
{
|
||||
forEachOcct (theBegin, theEnd, theFunctor, theNbItems);
|
||||
}
|
||||
|
||||
#endif /* ! HAVE_TBB */
|
||||
|
@@ -16,6 +16,7 @@
|
||||
#include <OSD_ThreadPool.hxx>
|
||||
|
||||
#include <OSD.hxx>
|
||||
#include <OSD_Parallel.hxx>
|
||||
#include <Standard_Atomic.hxx>
|
||||
#include <TCollection_AsciiString.hxx>
|
||||
|
||||
|
@@ -18,7 +18,6 @@
|
||||
|
||||
#include <NCollection_Array1.hxx>
|
||||
#include <OSD_Thread.hxx>
|
||||
#include <OSD_Parallel.hxx>
|
||||
#include <Standard_Atomic.hxx>
|
||||
#include <Standard_Condition.hxx>
|
||||
#include <Standard_Mutex.hxx>
|
||||
|
@@ -36,7 +36,6 @@ OpenGl_Caps::OpenGl_Caps()
|
||||
useSystemBuffer (Standard_True),
|
||||
#endif
|
||||
swapInterval (1),
|
||||
useZeroToOneDepth (true), ///(Standard_False),
|
||||
buffersNoSwap (Standard_False),
|
||||
contextStereo (Standard_False),
|
||||
#ifdef OCCT_DEBUG
|
||||
@@ -71,7 +70,6 @@ OpenGl_Caps& OpenGl_Caps::operator= (const OpenGl_Caps& theCopy)
|
||||
ffpEnable = theCopy.ffpEnable;
|
||||
useSystemBuffer = theCopy.useSystemBuffer;
|
||||
swapInterval = theCopy.swapInterval;
|
||||
useZeroToOneDepth = theCopy.useZeroToOneDepth;
|
||||
buffersNoSwap = theCopy.buffersNoSwap;
|
||||
contextStereo = theCopy.contextStereo;
|
||||
contextDebug = theCopy.contextDebug;
|
||||
|
@@ -34,7 +34,6 @@ public: //! @name flags to disable particular functionality, should be used only
|
||||
Standard_Boolean usePolygonMode; //!< Enables Polygon Mode instead of built-in GLSL programs (OFF by default; unsupported on OpenGL ES)
|
||||
Standard_Boolean useSystemBuffer; //!< Enables usage of system backbuffer for blitting (OFF by default on desktop OpenGL and ON on OpenGL ES for testing)
|
||||
Standard_Integer swapInterval; //!< controls swap interval - 0 for VSync off and 1 for VSync on, 1 by default
|
||||
Standard_Boolean useZeroToOneDepth; //!< use [0, 1] depth range instead of [-1, 1] range, when possible (OFF by default)
|
||||
|
||||
public: //! @name context creation parameters
|
||||
|
||||
|
@@ -136,7 +136,6 @@ OpenGl_Context::OpenGl_Context (const Handle(OpenGl_Caps)& theCaps)
|
||||
arbTexBindless (NULL),
|
||||
arbTBO (NULL),
|
||||
arbTboRGB32 (Standard_False),
|
||||
arbClipControl (Standard_False),
|
||||
arbIns (NULL),
|
||||
arbDbg (NULL),
|
||||
arbFBO (NULL),
|
||||
@@ -1273,7 +1272,6 @@ void OpenGl_Context::init (const Standard_Boolean theIsCoreProfile)
|
||||
core45back = NULL;
|
||||
arbTBO = NULL;
|
||||
arbTboRGB32 = Standard_False;
|
||||
arbClipControl = Standard_False;
|
||||
arbIns = NULL;
|
||||
arbDbg = NULL;
|
||||
arbFBO = NULL;
|
||||
@@ -2551,12 +2549,6 @@ void OpenGl_Context::init (const Standard_Boolean theIsCoreProfile)
|
||||
arbTexBindless = (OpenGl_ArbTexBindless* )(&(*myFuncs));
|
||||
}
|
||||
|
||||
if (CheckExtension ("GL_ARB_clip_control")
|
||||
&& FindProcShort (glClipControl))
|
||||
{
|
||||
arbClipControl = Standard_True;
|
||||
}
|
||||
|
||||
if (!has12)
|
||||
{
|
||||
checkWrongVersion (1, 2);
|
||||
@@ -2783,7 +2775,6 @@ void OpenGl_Context::init (const Standard_Boolean theIsCoreProfile)
|
||||
return;
|
||||
}
|
||||
core45 = (OpenGl_GlCore45* )(&(*myFuncs));
|
||||
arbClipControl = Standard_True;
|
||||
if (!isCoreProfile)
|
||||
{
|
||||
core45back = (OpenGl_GlCore45Back* )(&(*myFuncs));
|
||||
|
@@ -881,7 +881,6 @@ public: //! @name extensions
|
||||
OpenGl_ArbTexBindless* arbTexBindless; //!< GL_ARB_bindless_texture
|
||||
OpenGl_ArbTBO* arbTBO; //!< GL_ARB_texture_buffer_object
|
||||
Standard_Boolean arbTboRGB32; //!< GL_ARB_texture_buffer_object_rgb32 (3-component TBO), in core since 4.0
|
||||
Standard_Boolean arbClipControl; //!< GL_ARB_clip_control, in core since 4.5
|
||||
OpenGl_ArbIns* arbIns; //!< GL_ARB_draw_instanced
|
||||
OpenGl_ArbDbg* arbDbg; //!< GL_ARB_debug_output
|
||||
OpenGl_ArbFBO* arbFBO; //!< GL_ARB_framebuffer_object
|
||||
|
@@ -662,9 +662,6 @@ protected: //! @name data types related to ray-tracing
|
||||
//! Actual ray-tracing depth (number of ray bounces).
|
||||
Standard_Integer NbBounces;
|
||||
|
||||
//! Define depth computation
|
||||
Standard_Boolean IsZeroToOneDepth;
|
||||
|
||||
//! Enables/disables light propagation through transparent media.
|
||||
Standard_Boolean TransparentShadows;
|
||||
|
||||
@@ -699,7 +696,6 @@ protected: //! @name data types related to ray-tracing
|
||||
RaytracingParams()
|
||||
: StackSize (THE_DEFAULT_STACK_SIZE),
|
||||
NbBounces (THE_DEFAULT_NB_BOUNCES),
|
||||
IsZeroToOneDepth (Standard_False),
|
||||
TransparentShadows (Standard_False),
|
||||
GlobalIllumination (Standard_False),
|
||||
UseBindlessTextures (Standard_False),
|
||||
|
@@ -1115,11 +1115,6 @@ TCollection_AsciiString OpenGl_View::generateShaderPrefix (const Handle(OpenGl_C
|
||||
TCollection_AsciiString ("#define STACK_SIZE ") + TCollection_AsciiString (myRaytraceParameters.StackSize) + "\n" +
|
||||
TCollection_AsciiString ("#define NB_BOUNCES ") + TCollection_AsciiString (myRaytraceParameters.NbBounces);
|
||||
|
||||
if (myRaytraceParameters.IsZeroToOneDepth)
|
||||
{
|
||||
aPrefixString += TCollection_AsciiString ("\n#define ZERO_TO_ONE_DEPTH");
|
||||
}
|
||||
|
||||
if (myRaytraceParameters.TransparentShadows)
|
||||
{
|
||||
aPrefixString += TCollection_AsciiString ("\n#define TRANSPARENT_SHADOWS");
|
||||
@@ -1199,71 +1194,20 @@ Handle(OpenGl_ShaderObject) OpenGl_View::initShader (const GLenum
|
||||
const Handle(OpenGl_Context)& theGlContext)
|
||||
{
|
||||
Handle(OpenGl_ShaderObject) aShader = new OpenGl_ShaderObject (theType);
|
||||
|
||||
if (!aShader->Create (theGlContext))
|
||||
{
|
||||
const TCollection_ExtendedString aMessage = TCollection_ExtendedString ("Error: Failed to create ") +
|
||||
(theType == GL_VERTEX_SHADER ? "vertex" : "fragment") + " shader object";
|
||||
|
||||
theGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
|
||||
GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, aMessage);
|
||||
|
||||
aShader->Release (theGlContext.operator->());
|
||||
|
||||
theGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
|
||||
TCollection_ExtendedString ("Error: Failed to create ") +
|
||||
(theType == GL_VERTEX_SHADER ? "vertex" : "fragment") + " shader object");
|
||||
aShader->Release (theGlContext.get());
|
||||
return Handle(OpenGl_ShaderObject)();
|
||||
}
|
||||
|
||||
if (!aShader->LoadSource (theGlContext, theSource.Source()))
|
||||
if (!aShader->LoadAndCompile (theGlContext, "", theSource.Source()))
|
||||
{
|
||||
const TCollection_ExtendedString aMessage = TCollection_ExtendedString ("Error: Failed to set ") +
|
||||
(theType == GL_VERTEX_SHADER ? "vertex" : "fragment") + " shader source";
|
||||
|
||||
theGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
|
||||
GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, aMessage);
|
||||
|
||||
aShader->Release (theGlContext.operator->());
|
||||
|
||||
aShader->Release (theGlContext.get());
|
||||
return Handle(OpenGl_ShaderObject)();
|
||||
}
|
||||
|
||||
TCollection_AsciiString aBuildLog;
|
||||
|
||||
if (!aShader->Compile (theGlContext))
|
||||
{
|
||||
aShader->FetchInfoLog (theGlContext, aBuildLog);
|
||||
|
||||
const TCollection_ExtendedString aMessage = TCollection_ExtendedString ("Error: Failed to compile ") +
|
||||
(theType == GL_VERTEX_SHADER ? "vertex" : "fragment") + " shader object:\n" + aBuildLog;
|
||||
|
||||
theGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
|
||||
GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, aMessage);
|
||||
|
||||
aShader->Release (theGlContext.operator->());
|
||||
|
||||
#ifdef RAY_TRACE_PRINT_INFO
|
||||
std::cout << "Shader build log:\n" << aBuildLog << "\n";
|
||||
#endif
|
||||
|
||||
return Handle(OpenGl_ShaderObject)();
|
||||
}
|
||||
else if (theGlContext->caps->glslWarnings)
|
||||
{
|
||||
aShader->FetchInfoLog (theGlContext, aBuildLog);
|
||||
|
||||
if (!aBuildLog.IsEmpty() && !aBuildLog.IsEqual ("No errors.\n"))
|
||||
{
|
||||
const TCollection_ExtendedString aMessage = TCollection_ExtendedString (theType == GL_VERTEX_SHADER ?
|
||||
"Vertex" : "Fragment") + " shader was compiled with following warnings:\n" + aBuildLog;
|
||||
|
||||
theGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
|
||||
GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_LOW, aMessage);
|
||||
}
|
||||
|
||||
#ifdef RAY_TRACE_PRINT_INFO
|
||||
std::cout << "Shader build log:\n" << aBuildLog << "\n";
|
||||
#endif
|
||||
}
|
||||
|
||||
return aShader;
|
||||
}
|
||||
|
||||
@@ -1382,16 +1326,12 @@ Standard_Boolean OpenGl_View::initRaytraceResources (const Standard_Integer theS
|
||||
}
|
||||
}
|
||||
|
||||
const bool isZeroToOneDepth = myCaps->useZeroToOneDepth
|
||||
&& myWorkspace->GetGlContext()->arbClipControl;
|
||||
if (isZeroToOneDepth != myRaytraceParameters.IsZeroToOneDepth
|
||||
|| myRenderParams.RaytracingDepth != myRaytraceParameters.NbBounces
|
||||
if (myRenderParams.RaytracingDepth != myRaytraceParameters.NbBounces
|
||||
|| myRenderParams.IsTransparentShadowEnabled != myRaytraceParameters.TransparentShadows
|
||||
|| myRenderParams.IsGlobalIlluminationEnabled != myRaytraceParameters.GlobalIllumination
|
||||
|| myRenderParams.TwoSidedBsdfModels != myRaytraceParameters.TwoSidedBsdfModels
|
||||
|| myRaytraceGeometry.HasTextures() != myRaytraceParameters.UseBindlessTextures)
|
||||
{
|
||||
myRaytraceParameters.IsZeroToOneDepth = isZeroToOneDepth;
|
||||
myRaytraceParameters.NbBounces = myRenderParams.RaytracingDepth;
|
||||
myRaytraceParameters.TransparentShadows = myRenderParams.IsTransparentShadowEnabled;
|
||||
myRaytraceParameters.GlobalIllumination = myRenderParams.IsGlobalIlluminationEnabled;
|
||||
|
@@ -168,17 +168,6 @@ void OpenGl_View::Redraw()
|
||||
aCtx->FrameStats()->FrameStart (myWorkspace->View(), false);
|
||||
aCtx->SetLineFeather (myRenderParams.LineFeather);
|
||||
|
||||
#if !defined(GL_ES_VERSION_2_0)
|
||||
if (aCtx->arbClipControl)
|
||||
{
|
||||
if (myCaps->useZeroToOneDepth != myCamera->IsZeroToOneDepth())
|
||||
{
|
||||
myCamera->SetZeroToOneDepth (myCaps->useZeroToOneDepth);
|
||||
}
|
||||
aCtx->Functions()->glClipControl (GL_LOWER_LEFT, myCamera->IsZeroToOneDepth() ? GL_ZERO_TO_ONE : GL_NEGATIVE_ONE_TO_ONE);
|
||||
}
|
||||
#endif
|
||||
|
||||
// release pending GL resources
|
||||
aCtx->ReleaseDelayed();
|
||||
|
||||
|
@@ -14,6 +14,7 @@ Quantity_CoefficientOfExpansion.hxx
|
||||
Quantity_Color.cxx
|
||||
Quantity_Color.hxx
|
||||
Quantity_ColorHasher.hxx
|
||||
Quantity_ColorRGBA.cxx
|
||||
Quantity_ColorRGBA.hxx
|
||||
Quantity_ColorRGBAHasher.hxx
|
||||
Quantity_ColorDefinitionError.hxx
|
||||
|
@@ -16,6 +16,7 @@
|
||||
#include <Quantity_Color.hxx>
|
||||
|
||||
#include <Quantity_ColorDefinitionError.hxx>
|
||||
#include <Quantity_ColorRGBA.hxx>
|
||||
#include <Standard_ErrorHandler.hxx>
|
||||
#include <Standard_OutOfRange.hxx>
|
||||
#include <TCollection_AsciiString.hxx>
|
||||
@@ -66,6 +67,21 @@ Standard_Boolean Quantity_Color::ColorFromName (const Standard_CString theName,
|
||||
return Standard_False;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
// function : ColorFromHex
|
||||
// purpose :
|
||||
//=======================================================================
|
||||
bool Quantity_Color::ColorFromHex (const Standard_CString theHexColorString, Quantity_Color& theColor)
|
||||
{
|
||||
Quantity_ColorRGBA aColorRGBA;
|
||||
if (!Quantity_ColorRGBA::ColorFromHex (theHexColorString, aColorRGBA, true))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
theColor = aColorRGBA.GetRGB();
|
||||
return true;
|
||||
}
|
||||
|
||||
Quantity_Color::Quantity_Color () {
|
||||
|
||||
Quantity_Color::ValuesOf
|
||||
|
@@ -222,7 +222,31 @@ Standard_Boolean operator == (const Quantity_Color& Other) const
|
||||
//! corresponds to "BLACK" is Quantity_NOC_BLACK.
|
||||
//! Returns false if name is unknown.
|
||||
Standard_EXPORT static Standard_Boolean ColorFromName (const Standard_CString theName, Quantity_NameOfColor& theColor);
|
||||
|
||||
|
||||
//! Finds color from predefined names.
|
||||
//! For example, the name of the color which
|
||||
//! corresponds to "BLACK" is Quantity_NOC_BLACK.
|
||||
//! Returns false if name is unknown.
|
||||
//! @param theColorNameString the color name
|
||||
//! @param theColor a found color
|
||||
//! @return false if the color name is unknown, or true if the search by color name was successful
|
||||
static Standard_Boolean ColorFromName (const Standard_CString theColorNameString, Quantity_Color& theColor)
|
||||
{
|
||||
Quantity_NameOfColor aColorName = Quantity_NOC_BLACK;
|
||||
if (!ColorFromName (theColorNameString, aColorName))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
theColor = aColorName;
|
||||
return true;
|
||||
}
|
||||
|
||||
//! Parses the string as a hex color (like "#FF0" for short RGB color, or "#FFFF00" for RGB color)
|
||||
//! @param theHexColorString the string to be parsed
|
||||
//! @param theColor a color that is a result of parsing
|
||||
//! @return true if parsing was successful, or false otherwise
|
||||
Standard_EXPORT static bool ColorFromHex (const Standard_CString theHexColorString, Quantity_Color& theColor);
|
||||
|
||||
//! Converts HLS components into RGB ones.
|
||||
Standard_EXPORT static void HlsRgb (const Standard_Real H, const Standard_Real L, const Standard_Real S, Standard_Real& R, Standard_Real& G, Standard_Real& B);
|
||||
|
||||
|
200
src/Quantity/Quantity_ColorRGBA.cxx
Normal file
200
src/Quantity/Quantity_ColorRGBA.cxx
Normal file
@@ -0,0 +1,200 @@
|
||||
// Created on: 2019-03-22
|
||||
// Created by: Timur Izmaylov
|
||||
// Copyright (c) 2019 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#include <Quantity_ColorRGBA.hxx>
|
||||
|
||||
#include <Graphic3d_Vec4.hxx>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
//! The integer type used to represent some color or color component
|
||||
typedef unsigned int ColorInteger;
|
||||
|
||||
//! Defines all possible lengths of strings representing color in hex format
|
||||
enum HexColorLength
|
||||
{
|
||||
HexColorLength_ShortRGB = 3, //!< short RGB hex color format
|
||||
HexColorLength_ShortRGBA = 4, //!< short RGBA hex color format
|
||||
HexColorLength_RGB = 6, //!< RGB hex color format
|
||||
HexColorLength_RGBA = 8 //!< RGBA hex color format
|
||||
};
|
||||
|
||||
//! Takes next color component from the integer representing a color (it is a step in a process of a conversion
|
||||
//! implemented by the function ConvertIntegerToColorRGBA)
|
||||
//! @param theColorInteger the integer representing a color
|
||||
//! @param theColorComponentBase the base of the numeral system used to represent a color
|
||||
//! @return a color component taken from the integer
|
||||
static Standard_ShortReal takeColorComponentFromInteger (ColorInteger& theColorInteger,
|
||||
const ColorInteger theColorComponentBase)
|
||||
{
|
||||
Standard_ASSERT_RETURN (theColorComponentBase >= 2,
|
||||
__FUNCTION__ ": 'theColorComponentBase' must be greater than 1.",
|
||||
0.0f);
|
||||
const ColorInteger aColorComponentMaxValue = theColorComponentBase - 1;
|
||||
const ColorInteger aColorComponentAsInteger = theColorInteger % theColorComponentBase;
|
||||
const Standard_ShortReal aColorComponent = aColorComponentAsInteger * 1.0f / aColorComponentMaxValue;
|
||||
theColorInteger /= theColorComponentBase;
|
||||
return aColorComponent;
|
||||
}
|
||||
|
||||
//! Converts the integer representing a color to a RGBA color object
|
||||
//! @param theColorInteger the integer representing a color (using the numerical system based
|
||||
//! on theColorComponentBase value, where color components represent digits:
|
||||
//! an alpha component is a low number and a red component is a high number)
|
||||
//! @param theColorComponentBase the base of the numeral system used to represent a color
|
||||
//! @param hasAlphaComponent true if the integer to be converted contains an alpha component value
|
||||
//! @param theColor a color that is a result of a conversion
|
||||
//! @return true if a conversion was successful, or false otherwise
|
||||
static bool convertIntegerToColorRGBA (ColorInteger theColorInteger,
|
||||
const ColorInteger theColorComponentBase,
|
||||
const bool hasAlphaComponent,
|
||||
Quantity_ColorRGBA& theColor)
|
||||
{
|
||||
Standard_ASSERT_RETURN (theColorComponentBase >= 2,
|
||||
__FUNCTION__ ": 'theColorComponentBase' must be greater than 1.",
|
||||
0.0f);
|
||||
Graphic3d_Vec4 aColor (1.0f);
|
||||
if (hasAlphaComponent)
|
||||
{
|
||||
const Standard_ShortReal anAlphaComponent = takeColorComponentFromInteger (theColorInteger,
|
||||
theColorComponentBase);
|
||||
aColor.a() = anAlphaComponent;
|
||||
}
|
||||
for (Standard_Integer aColorComponentIndex = 2; aColorComponentIndex >= 0; --aColorComponentIndex)
|
||||
{
|
||||
const Standard_ShortReal aColorComponent = takeColorComponentFromInteger (theColorInteger, theColorComponentBase);
|
||||
aColor[aColorComponentIndex] = aColorComponent;
|
||||
}
|
||||
if (theColorInteger != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
theColor = Quantity_ColorRGBA (aColor);
|
||||
return true;
|
||||
}
|
||||
|
||||
//! Converts the string to an integer number using the number base
|
||||
//! @tparam TheNumber the type of a resulting number
|
||||
//! @param theString the string to be converted
|
||||
//! @param theNumber a number that is the result of the conversion
|
||||
//! @param theBase the base of a numeral system used to represent a number in a string form
|
||||
//! @return true if a conversion was successful, or false otherwise
|
||||
template <typename TheNumber>
|
||||
static bool convertStringToInteger (const char* const theString, TheNumber& theNumber, const TheNumber theBase = 10)
|
||||
{
|
||||
std::stringstream aConversionStringStream;
|
||||
aConversionStringStream << std::setbase (theBase) << theString;
|
||||
if (aConversionStringStream.fail())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
aConversionStringStream >> theNumber;
|
||||
if (aConversionStringStream.fail())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//! Checks if the character is a hexadecimal digit (0 .. 9, a .. f, A .. F)
|
||||
//! @param theCharacter the character to be checked
|
||||
//! @return true if the checking character is a hexadecimal digit, or false otherwise
|
||||
static bool isHexDigit (const char theCharacter)
|
||||
{
|
||||
return std::isxdigit (static_cast<unsigned char> (theCharacter)) != 0;
|
||||
}
|
||||
|
||||
//! Checks if the string consists only of hexadecimal digits (0 .. 9, a .. f, A .. F)
|
||||
//! @param theString the string to be checked
|
||||
//! @param theLength the length of the checked string
|
||||
//! @return true if the checking string consists only of hexadecimal digits, or false otherwise
|
||||
//! an empty string is not interpreted as a hex string
|
||||
static bool isHexString (const char* const theString, const std::size_t theLength)
|
||||
{
|
||||
if (theLength == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// std::all_of is not used due to VS2008 compilability limitation
|
||||
return std::count_if (theString, theString + theLength, isHexDigit) == static_cast<std::ptrdiff_t> (theLength);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
//=======================================================================
|
||||
// function : ColorFromHex
|
||||
// purpose :
|
||||
//=======================================================================
|
||||
bool Quantity_ColorRGBA::ColorFromHex (const char* const theHexColorString,
|
||||
Quantity_ColorRGBA& theColor,
|
||||
const bool theAlphaComponentIsOff)
|
||||
{
|
||||
std::size_t aHexColorStringLength = std::strlen (theHexColorString);
|
||||
if (aHexColorStringLength == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const bool hasPrefix = (theHexColorString[0] == '#');
|
||||
const std::size_t aPrefixLength = hasPrefix ? 1 : 0;
|
||||
const char* const aHexColorString = theHexColorString + aPrefixLength;
|
||||
aHexColorStringLength -= aPrefixLength;
|
||||
if (!isHexString (aHexColorString, aHexColorStringLength))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
ColorInteger aHexColorInteger;
|
||||
if (!convertStringToInteger (aHexColorString, aHexColorInteger, 16u))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool hasAlphaComponent = false;
|
||||
bool isShort = false;
|
||||
switch (static_cast<HexColorLength> (aHexColorStringLength))
|
||||
{
|
||||
case HexColorLength_ShortRGBA:
|
||||
hasAlphaComponent = true;
|
||||
Standard_FALLTHROUGH
|
||||
case HexColorLength_ShortRGB:
|
||||
isShort = true;
|
||||
break;
|
||||
case HexColorLength_RGBA:
|
||||
hasAlphaComponent = true;
|
||||
break;
|
||||
case HexColorLength_RGB:
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
if (theAlphaComponentIsOff && hasAlphaComponent)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// to distinguish with a usual integer color component value
|
||||
if (isShort && !hasAlphaComponent && !hasPrefix)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const ColorInteger THE_HEX_COLOR_COMPONENT_BASE = 1 << 8;
|
||||
const ColorInteger THE_HEX_COLOR_COMPONENT_SHORT_BASE = 1 << 4;
|
||||
const ColorInteger aColorComponentBase = isShort ? THE_HEX_COLOR_COMPONENT_SHORT_BASE : THE_HEX_COLOR_COMPONENT_BASE;
|
||||
return convertIntegerToColorRGBA (aHexColorInteger, aColorComponentBase, hasAlphaComponent, theColor);
|
||||
}
|
@@ -91,6 +91,36 @@ public:
|
||||
//! Two colors are considered to be equal if their distance is no greater than Epsilon().
|
||||
bool operator== (const Quantity_ColorRGBA& theOther) const { return IsEqual (theOther); }
|
||||
|
||||
//! Finds color from predefined names.
|
||||
//! For example, the name of the color which
|
||||
//! corresponds to "BLACK" is Quantity_NOC_BLACK.
|
||||
//! Returns false if name is unknown.
|
||||
//! An alpha component is set to 1.0.
|
||||
//! @param theColorNameString the color name
|
||||
//! @param theColor a found color
|
||||
//! @return false if the color name is unknown, or true if the search by color name was successful
|
||||
static Standard_Boolean ColorFromName (const Standard_CString theColorNameString, Quantity_ColorRGBA& theColor)
|
||||
{
|
||||
Quantity_ColorRGBA aColor;
|
||||
if (!Quantity_Color::ColorFromName (theColorNameString, aColor.ChangeRGB()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
theColor = aColor;
|
||||
return true;
|
||||
}
|
||||
|
||||
//! Parses the string as a hex color (like "#FF0" for short RGB color, "#FF0F" for short RGBA color,
|
||||
//! "#FFFF00" for RGB color, or "#FFFF00FF" for RGBA color)
|
||||
//! @param theHexColorString the string to be parsed
|
||||
//! @param theColor a color that is a result of parsing
|
||||
//! @param theAlphaComponentIsOff the flag that indicates if a color alpha component is presented
|
||||
//! in the input string (false) or not (true)
|
||||
//! @return true if parsing was successful, or false otherwise
|
||||
Standard_EXPORT static bool ColorFromHex (const char* const theHexColorString,
|
||||
Quantity_ColorRGBA& theColor,
|
||||
const bool theAlphaComponentIsOff = false);
|
||||
|
||||
private:
|
||||
|
||||
static void myTestSize3() { Standard_STATIC_ASSERT (sizeof(float) * 3 == sizeof(Quantity_Color)); }
|
||||
|
@@ -180,7 +180,6 @@ static NCollection_Vec4<Standard_Real> safePointCast (const gp_Pnt& thePnt)
|
||||
//=======================================================================
|
||||
gp_Pnt SelectMgr_FrustumBuilder::unProject (const gp_Pnt& thePnt) const
|
||||
{
|
||||
/// TODO why these are not cached?
|
||||
Graphic3d_Mat4d aInvView;
|
||||
Graphic3d_Mat4d aInvProj;
|
||||
|
||||
@@ -218,7 +217,6 @@ gp_Pnt SelectMgr_FrustumBuilder::ProjectPntOnViewPlane (const Standard_Real& the
|
||||
{
|
||||
aX = 2.0 * theX / myWidth - 1.0;
|
||||
anY = (myHeight - 1 - theY) / myHeight * 2.0 - 1.0;
|
||||
/// TODO wrong NDC
|
||||
aZ = 2.0 * theZ - 1.0;
|
||||
}
|
||||
else
|
||||
|
@@ -804,11 +804,7 @@ vec4 PathTrace (in SRay theRay, in vec3 theInverse, in int theNbSamples)
|
||||
vec4 aNDCPoint = uViewMat * vec4 (theRay.Origin, 1.f);
|
||||
|
||||
float aPolygonOffset = PolygonOffset (aHit.Normal, theRay.Origin);
|
||||
#ifdef ZERO_TO_ONE_DEPTH
|
||||
aRaytraceDepth = (aNDCPoint.z / aNDCPoint.w + aPolygonOffset * POLYGON_OFFSET_SCALE);
|
||||
#else
|
||||
aRaytraceDepth = (aNDCPoint.z / aNDCPoint.w + aPolygonOffset * POLYGON_OFFSET_SCALE) * 0.5f + 0.5f;
|
||||
#endif
|
||||
}
|
||||
|
||||
SBSDF aBSDF;
|
||||
|
@@ -1012,11 +1012,7 @@ vec4 Radiance (in SRay theRay, in vec3 theInverse)
|
||||
vec4 aNDCPoint = uViewMat * vec4 (theRay.Origin, 1.f);
|
||||
|
||||
float aPolygonOffset = PolygonOffset (aHit.Normal, theRay.Origin);
|
||||
#ifdef ZERO_TO_ONE_DEPTH
|
||||
aRaytraceDepth = (aNDCPoint.z / aNDCPoint.w + aPolygonOffset * POLYGON_OFFSET_SCALE);
|
||||
#else
|
||||
aRaytraceDepth = (aNDCPoint.z / aNDCPoint.w + aPolygonOffset * POLYGON_OFFSET_SCALE) * 0.5f + 0.5f;
|
||||
#endif
|
||||
}
|
||||
|
||||
vec3 aNormal = SmoothNormal (aHit.UV, aTriIndex);
|
||||
|
@@ -807,11 +807,7 @@ static const char Shaders_PathtraceBase_fs[] =
|
||||
" vec4 aNDCPoint = uViewMat * vec4 (theRay.Origin, 1.f);\n"
|
||||
"\n"
|
||||
" float aPolygonOffset = PolygonOffset (aHit.Normal, theRay.Origin);\n"
|
||||
" #ifdef ZERO_TO_ONE_DEPTH\n"
|
||||
" aRaytraceDepth = (aNDCPoint.z / aNDCPoint.w + aPolygonOffset * POLYGON_OFFSET_SCALE);\n"
|
||||
" #else\n"
|
||||
" aRaytraceDepth = (aNDCPoint.z / aNDCPoint.w + aPolygonOffset * POLYGON_OFFSET_SCALE) * 0.5f + 0.5f;\n"
|
||||
" #endif\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" SBSDF aBSDF;\n"
|
||||
|
@@ -1015,11 +1015,7 @@ static const char Shaders_RaytraceBase_fs[] =
|
||||
" vec4 aNDCPoint = uViewMat * vec4 (theRay.Origin, 1.f);\n"
|
||||
"\n"
|
||||
" float aPolygonOffset = PolygonOffset (aHit.Normal, theRay.Origin);\n"
|
||||
" #ifdef ZERO_TO_ONE_DEPTH\n"
|
||||
" aRaytraceDepth = (aNDCPoint.z / aNDCPoint.w + aPolygonOffset * POLYGON_OFFSET_SCALE);\n"
|
||||
" #else\n"
|
||||
" aRaytraceDepth = (aNDCPoint.z / aNDCPoint.w + aPolygonOffset * POLYGON_OFFSET_SCALE) * 0.5f + 0.5f;\n"
|
||||
" #endif\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" vec3 aNormal = SmoothNormal (aHit.UV, aTriIndex);\n"
|
||||
|
@@ -17,6 +17,8 @@ StdPrs_Plane.hxx
|
||||
StdPrs_Point.hxx
|
||||
StdPrs_PoleCurve.cxx
|
||||
StdPrs_PoleCurve.hxx
|
||||
StdPrs_SectionLines.cxx
|
||||
StdPrs_SectionLines.hxx
|
||||
StdPrs_ShadedShape.cxx
|
||||
StdPrs_ShadedShape.hxx
|
||||
StdPrs_ShadedSurface.cxx
|
||||
|
376
src/StdPrs/StdPrs_SectionLines.cxx
Normal file
376
src/StdPrs/StdPrs_SectionLines.cxx
Normal file
@@ -0,0 +1,376 @@
|
||||
// Created on: 2019-04-11
|
||||
// Created by: Timur Izmaylov
|
||||
// Copyright (c) 2019 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#include <StdPrs_SectionLines.hxx>
|
||||
|
||||
#include <BRepBndLib.hxx>
|
||||
#include <BRepBuilderAPI_MakeEdge.hxx>
|
||||
#include <BRep_Tool.hxx>
|
||||
#include <Bnd_Box.hxx>
|
||||
#include <Graphic3d_ArrayOfSegments.hxx>
|
||||
#include <Poly_Triangulation.hxx>
|
||||
#include <Precision.hxx>
|
||||
#include <TColgp_SequenceOfPnt.hxx>
|
||||
#include <TopExp_Explorer.hxx>
|
||||
#include <TopoDS.hxx>
|
||||
#include <TopoDS_Builder.hxx>
|
||||
#include <TopoDS_Edge.hxx>
|
||||
#include <TopoDS_Face.hxx>
|
||||
#include <gp_Pln.hxx>
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
//! Pair of points
|
||||
typedef std::pair<gp_Pnt, gp_Pnt> PointPair;
|
||||
|
||||
//! Segment of line
|
||||
typedef PointPair Segment;
|
||||
|
||||
//! Array of segments
|
||||
typedef std::vector<Segment> Segments;
|
||||
|
||||
//! Triple of points
|
||||
typedef gp_Pnt PointTriple[3];
|
||||
|
||||
//! Triangle (a set of 3 points)
|
||||
typedef PointTriple Triangle;
|
||||
|
||||
//! Array of triangles
|
||||
typedef std::vector<Triangle> Triangles;
|
||||
|
||||
//! Adds the segment to the array of segments
|
||||
//! @param thePoint1 the first end of segment
|
||||
//! @param thePoint2 the second end of segment
|
||||
//! @param theSegments the array of segments
|
||||
static void addSegment (const gp_Pnt& thePoint1, const gp_Pnt& thePoint2, Segments& theSegments)
|
||||
{
|
||||
if (thePoint1.Distance (thePoint2) <= Precision::Confusion())
|
||||
{
|
||||
return;
|
||||
}
|
||||
const PointPair anEdge (thePoint1, thePoint2);
|
||||
theSegments.push_back (anEdge);
|
||||
}
|
||||
|
||||
//! Adds the point to the section
|
||||
//! @param theVertex1 the first vertex of the crossed edge
|
||||
//! @param theDistanceToPlane1 the signed distance from the first vertex of the crossed edge to the plane
|
||||
//! @param theVertex2 the second vertex of the crossed edge
|
||||
//! @param theDistanceToPlane2 the signed distance from the second vertex of the crossed edge to the plane
|
||||
//! @param theSectionPoints the container of section points where found point should be added
|
||||
//! @param theNumberOfSectionPoints the number of points which are already in theSectionPoints container
|
||||
static void addSectionPoint (const gp_Pnt& theVertex1,
|
||||
const Standard_Real theDistanceToPlane1,
|
||||
const gp_Pnt& theVertex2,
|
||||
const Standard_Real theDistanceToPlane2,
|
||||
PointTriple& theSectionPoints,
|
||||
std::size_t& theNumberOfSectionPoints)
|
||||
{
|
||||
if (theDistanceToPlane1 * theDistanceToPlane2 > 0.0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
const Standard_Real aDistanceParameter = theDistanceToPlane1 / (theDistanceToPlane1 - theDistanceToPlane2);
|
||||
theSectionPoints[theNumberOfSectionPoints] = theVertex1.Coord()
|
||||
+ aDistanceParameter * (theVertex2.Coord() - theVertex1.Coord());
|
||||
++theNumberOfSectionPoints;
|
||||
}
|
||||
|
||||
//! Add points found as the result of crossing the triangle with the plane to the section
|
||||
//! @param theTriangle the triangle that is crossed with the plane
|
||||
//! @param areVerticesOnSectionPlane the array of flags that shows whether the triangle vertex
|
||||
//! with corresponding index is on the section plane
|
||||
//! @param theDistancesToPlane the array of signed distances from the plane to the triangle vertex with corresponding
|
||||
//! index
|
||||
//! @param theSectionPoints the container of section points where found point should be added
|
||||
//! @param theNumberOfSectionPoints the number of points which are already in theSectionPoints container
|
||||
static void addSectionPoints (const Triangle& theTriangle,
|
||||
const bool (&areVerticesOnSectionPlane)[3],
|
||||
const Standard_Real (&theDistancesToPlane)[3],
|
||||
PointTriple& theSectionPoints,
|
||||
std::size_t& theNumberOfSectionPoints)
|
||||
{
|
||||
for (std::size_t aVertexIndex1 = 0; aVertexIndex1 < 2; ++aVertexIndex1)
|
||||
{
|
||||
const bool isVertex1OnSectionPlane = areVerticesOnSectionPlane[aVertexIndex1];
|
||||
if (isVertex1OnSectionPlane)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
for (std::size_t aVertexIndex2 = aVertexIndex1 + 1; aVertexIndex2 < 3; ++aVertexIndex2)
|
||||
{
|
||||
const bool isVertex2OnSectionPlane = areVerticesOnSectionPlane[aVertexIndex2];
|
||||
if (isVertex2OnSectionPlane)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
addSectionPoint (theTriangle[aVertexIndex1],
|
||||
theDistancesToPlane[aVertexIndex1],
|
||||
theTriangle[aVertexIndex2],
|
||||
theDistancesToPlane[aVertexIndex2],
|
||||
theSectionPoints,
|
||||
theNumberOfSectionPoints);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! Add all segments between points (2 or 3) from point triple to the section
|
||||
//! @param theSectionPoints the points to be added
|
||||
//! @param theNumberOfSectionPoints the number of section points to be added
|
||||
//! @param theSectionSegments the container of section segments where the new segments should be added
|
||||
static void addAllSectionPoints (const PointTriple& theSectionPoints,
|
||||
const std::size_t theNumberOfSectionPoints,
|
||||
Segments& theSectionSegments)
|
||||
{
|
||||
if (theNumberOfSectionPoints < 2)
|
||||
{
|
||||
return;
|
||||
}
|
||||
for (std::size_t aPointIndex1 = 0; aPointIndex1 < theNumberOfSectionPoints - 1; ++aPointIndex1)
|
||||
{
|
||||
for (std::size_t aPointIndex2 = aPointIndex1 + 1; aPointIndex2 < theNumberOfSectionPoints; ++aPointIndex2)
|
||||
{
|
||||
addSegment (theSectionPoints[aPointIndex1], theSectionPoints[aPointIndex2], theSectionSegments);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! Add all segments between triangle vertices that are on the section plane
|
||||
//! @param theTriangle the triangle which vertices should be added
|
||||
//! @param areVerticesOnSectionPlane the array of flags that shows whether the triangle vertex
|
||||
//! with corresponding index is on the section plane
|
||||
//! @param theSectionSegments the container of section segments where the new segments should be added
|
||||
static void addAllTriangleVerticesOnSectionPlane (const Triangle& theTriangle,
|
||||
const bool (&areVerticesOnSectionPlane)[3],
|
||||
Segments& theSectionSegments)
|
||||
{
|
||||
for (std::size_t aVertexIndex1 = 0; aVertexIndex1 < 2; ++aVertexIndex1)
|
||||
{
|
||||
const bool isVertex1OnSectionPlane = areVerticesOnSectionPlane[aVertexIndex1];
|
||||
if (!isVertex1OnSectionPlane)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
for (std::size_t aVertexIndex2 = aVertexIndex1 + 1; aVertexIndex2 < 3; ++aVertexIndex2)
|
||||
{
|
||||
const bool isVertex2OnSectionPlane = areVerticesOnSectionPlane[aVertexIndex2];
|
||||
if (!isVertex2OnSectionPlane)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
addSegment (theTriangle[aVertexIndex1], theTriangle[aVertexIndex2], theSectionSegments);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! Computes a cross section of the triangle with the plane
|
||||
//! @param theTriangle the triangle to be sectioned
|
||||
//! @param theSectionPlane the section plane
|
||||
//! @param theSectionSegments the container of section segments where the new segments should be added
|
||||
static void crossSection (const Triangle& theTriangle, const gp_Pln& theSectionPlane, Segments& theSectionSegments)
|
||||
{
|
||||
Standard_Real aDistancesToPlane[3];
|
||||
bool areVerticesOnSectionPlane[3];
|
||||
std::size_t aNumberOfVerticesOnSectionPlane = 0;
|
||||
for (std::size_t aVertexIndex = 0; aVertexIndex < 3; ++aVertexIndex)
|
||||
{
|
||||
const gp_Pnt aNode = theTriangle[aVertexIndex];
|
||||
Standard_Real& aDistanceToPlane = aDistancesToPlane[aVertexIndex];
|
||||
aDistanceToPlane = theSectionPlane.SignedDistance (aNode);
|
||||
bool& isVertexOnSectionPlane = areVerticesOnSectionPlane[aVertexIndex];
|
||||
isVertexOnSectionPlane = (Abs (aDistanceToPlane) <= Precision::Confusion());
|
||||
if (isVertexOnSectionPlane)
|
||||
{
|
||||
++aNumberOfVerticesOnSectionPlane;
|
||||
}
|
||||
}
|
||||
if (aNumberOfVerticesOnSectionPlane <= 1)
|
||||
{
|
||||
PointTriple aSectionPoints;
|
||||
std::size_t aNumberOfSectionPoints = 0;
|
||||
for (std::size_t aVertexIndex = 0; aVertexIndex < 3; ++aVertexIndex)
|
||||
{
|
||||
if (areVerticesOnSectionPlane[aVertexIndex])
|
||||
{
|
||||
aSectionPoints[aNumberOfSectionPoints] = theTriangle[aVertexIndex];
|
||||
++aNumberOfSectionPoints;
|
||||
}
|
||||
}
|
||||
addSectionPoints (
|
||||
theTriangle, areVerticesOnSectionPlane, aDistancesToPlane, aSectionPoints, aNumberOfSectionPoints);
|
||||
addAllSectionPoints (aSectionPoints, aNumberOfSectionPoints, theSectionSegments);
|
||||
}
|
||||
else
|
||||
{
|
||||
addAllTriangleVerticesOnSectionPlane (theTriangle, areVerticesOnSectionPlane, theSectionSegments);
|
||||
}
|
||||
}
|
||||
|
||||
//! Gets a triangle of the triangulated face
|
||||
//! @param theNodes the nodes of the face
|
||||
//! @param thePolyTriangle the indices of the triangle nodes
|
||||
//! @param theFaceLocation the location of the face
|
||||
//! @param theTriangle a triangle that should be extracted from the triangulated face
|
||||
static void getTriangleOnFace (const TColgp_Array1OfPnt& theNodes,
|
||||
const Poly_Triangle& thePolyTriangle,
|
||||
const TopLoc_Location& theFaceLocation,
|
||||
Triangle& theTriangle)
|
||||
{
|
||||
Standard_Integer aVertexNumbers[3];
|
||||
thePolyTriangle.Get (aVertexNumbers[0], aVertexNumbers[1], aVertexNumbers[2]);
|
||||
for (std::size_t aVertexIndex = 0; aVertexIndex < 3; ++aVertexIndex)
|
||||
{
|
||||
const Standard_Integer aNodeNumber = aVertexNumbers[aVertexIndex];
|
||||
const gp_Pnt aNode = theNodes (aNodeNumber);
|
||||
const gp_Pnt aTransformedNode = aNode.Transformed (theFaceLocation);
|
||||
theTriangle[aVertexIndex] = aTransformedNode;
|
||||
}
|
||||
}
|
||||
|
||||
//! Computes a cross section of the face triangulation with the plane
|
||||
//! @param theFaceTriangulation the triangulation of the face to be sectioned
|
||||
//! @param theFaceLocation the location of the face
|
||||
//! @param theSectionPlane the section plane
|
||||
//! @param theSectionSegments the container of section segments where the new segments should be added
|
||||
static void crossSection (const Handle (Poly_Triangulation) & theFaceTriangulation,
|
||||
const TopLoc_Location& theFaceLocation,
|
||||
const gp_Pln& theSectionPlane,
|
||||
Segments& theSectionSegments)
|
||||
{
|
||||
const Poly_Array1OfTriangle& aTriangles = theFaceTriangulation->Triangles();
|
||||
const TColgp_Array1OfPnt& aFaceNodes = theFaceTriangulation->Nodes();
|
||||
for (Standard_Integer aTriangleIndex = 1; aTriangleIndex <= aTriangles.Size(); ++aTriangleIndex)
|
||||
{
|
||||
const Poly_Triangle& aPolyTriangle = aTriangles (aTriangleIndex);
|
||||
Triangle aTriangle;
|
||||
getTriangleOnFace (aFaceNodes, aPolyTriangle, theFaceLocation, aTriangle);
|
||||
crossSection (aTriangle, theSectionPlane, theSectionSegments);
|
||||
}
|
||||
}
|
||||
|
||||
//! Checks whether the shape's bounding box intersects with the plane
|
||||
//! @param theShape the shape which bounding box takes part in checking on intersection with the given plane
|
||||
//! @param thePlane the plane that takes part in checking on intersection with the given shape's bounding box
|
||||
//! @return true if the shape's bounding box intersects with the plane, or false otherwise
|
||||
static bool intersects (const TopoDS_Shape& theShape, const gp_Pln& thePlane)
|
||||
{
|
||||
Bnd_Box aBoundingBox;
|
||||
BRepBndLib::Add (theShape, aBoundingBox);
|
||||
return !aBoundingBox.IsOut (thePlane);
|
||||
}
|
||||
|
||||
//! Computes a cross section of the face triangulation with the plane
|
||||
//! @param theFaceTriangulation the triangulation of the face to be sectioned
|
||||
//! @param theFaceLocation the location of the face
|
||||
//! @param theSectionPlane the section plane
|
||||
//! @param theSectionSegments the container of section segments where the new segments should be added
|
||||
static void crossSection (const TopoDS_Face& theFace, const gp_Pln& theSectionPlane, Segments& theSectionSegments)
|
||||
{
|
||||
if (!intersects (theFace, theSectionPlane))
|
||||
{
|
||||
return;
|
||||
}
|
||||
TopLoc_Location aFaceLocation;
|
||||
const Handle (Poly_Triangulation)& aFaceTriangulation = BRep_Tool::Triangulation (theFace, aFaceLocation);
|
||||
if (aFaceTriangulation.IsNull())
|
||||
{
|
||||
return;
|
||||
}
|
||||
crossSection (aFaceTriangulation, aFaceLocation, theSectionPlane, theSectionSegments);
|
||||
}
|
||||
|
||||
//! Computes a cross section of the shape with the plane
|
||||
//! @param theShape the shape consisting of triangulated faces
|
||||
//! @param theSectionPlane the plane that intersects the shape
|
||||
//! @param theSectionSegments the container of section segments where the section segments should be added
|
||||
static void crossSection (const TopoDS_Shape& theShape, const gp_Pln& theSectionPlane, Segments& theSectionSegments)
|
||||
{
|
||||
if (!intersects (theShape, theSectionPlane))
|
||||
{
|
||||
return;
|
||||
}
|
||||
for (TopExp_Explorer aFaceIterator (theShape, TopAbs_FACE); aFaceIterator.More(); aFaceIterator.Next())
|
||||
{
|
||||
const TopoDS_Face& aFace = TopoDS::Face (aFaceIterator.Current());
|
||||
crossSection (aFace, theSectionPlane, theSectionSegments);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
//=======================================================================
|
||||
// function : CrossSectionAsShape
|
||||
// purpose :
|
||||
//=======================================================================
|
||||
TopoDS_Compound StdPrs_SectionLines::CrossSectionAsShape (const TopoDS_Shape& theShape, const gp_Pln& theSectionPlane)
|
||||
{
|
||||
Segments aSectionSegments;
|
||||
crossSection (theShape, theSectionPlane, aSectionSegments);
|
||||
TopoDS_Builder aShapeBuilder;
|
||||
TopoDS_Compound aSectionShape;
|
||||
aShapeBuilder.MakeCompound (aSectionShape);
|
||||
for (Segments::const_iterator aSectionSegmentIterator = aSectionSegments.begin();
|
||||
aSectionSegmentIterator != aSectionSegments.end();
|
||||
++aSectionSegmentIterator)
|
||||
{
|
||||
const Segment& aSectionSegment = *aSectionSegmentIterator;
|
||||
const TopoDS_Edge aSectionEdge = BRepBuilderAPI_MakeEdge (aSectionSegment.first, aSectionSegment.second);
|
||||
aShapeBuilder.Add (aSectionShape, aSectionEdge);
|
||||
}
|
||||
return aSectionShape;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
// function : CrossSectionAsArraysOfSegments
|
||||
// purpose :
|
||||
//=======================================================================
|
||||
Handle (Graphic3d_ArrayOfPrimitives) StdPrs_SectionLines::CrossSectionAsArrayOfSegments (const TopoDS_Shape& theShape,
|
||||
const gp_Pln& theSectionPlane)
|
||||
{
|
||||
Segments aSectionSegments;
|
||||
crossSection (theShape, theSectionPlane, aSectionSegments);
|
||||
const Standard_Integer aNumberOfSectionEdges = static_cast<Standard_Integer> (2 * aSectionSegments.size());
|
||||
const Handle (Graphic3d_ArrayOfSegments)
|
||||
anArrayOfSectionEdges = new Graphic3d_ArrayOfSegments (aNumberOfSectionEdges);
|
||||
for (Segments::const_iterator aSectionSegmentIterator = aSectionSegments.begin();
|
||||
aSectionSegmentIterator != aSectionSegments.end();
|
||||
++aSectionSegmentIterator)
|
||||
{
|
||||
const Segment& aSectionSegment = *aSectionSegmentIterator;
|
||||
anArrayOfSectionEdges->AddVertex (aSectionSegment.first);
|
||||
anArrayOfSectionEdges->AddVertex (aSectionSegment.second);
|
||||
}
|
||||
return anArrayOfSectionEdges;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
// function : CrossSectionAsArraysOfTrianglesAndEdges
|
||||
// purpose :
|
||||
//=======================================================================
|
||||
void StdPrs_SectionLines::CrossSectionAsArraysOfTrianglesAndSegments (const TopoDS_Shape& theShape,
|
||||
const gp_Pln& theSectionPlane,
|
||||
Handle (Graphic3d_ArrayOfPrimitives)
|
||||
& theArrayOfSectionTriangles,
|
||||
Handle (Graphic3d_ArrayOfPrimitives)
|
||||
& theArrayOfSectionSegments)
|
||||
{
|
||||
(void)theShape;
|
||||
(void)theSectionPlane;
|
||||
(void)theArrayOfSectionTriangles;
|
||||
(void)theArrayOfSectionSegments;
|
||||
}
|
57
src/StdPrs/StdPrs_SectionLines.hxx
Normal file
57
src/StdPrs/StdPrs_SectionLines.hxx
Normal file
@@ -0,0 +1,57 @@
|
||||
// Created on: 2019-04-11
|
||||
// Created by: Timur Izmaylov
|
||||
// Copyright (c) 2019 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _StdPrs_SectionLines_HeaderFile
|
||||
#define _StdPrs_SectionLines_HeaderFile
|
||||
|
||||
#include <Standard_Handle.hxx>
|
||||
|
||||
class Graphic3d_ArrayOfPrimitives;
|
||||
class TopoDS_Shape;
|
||||
class gp_Pln;
|
||||
class TopoDS_Compound;
|
||||
|
||||
//! Tool for computing a cross section of a TopoDS_Shape with some plane.
|
||||
class StdPrs_SectionLines
|
||||
{
|
||||
public:
|
||||
//! Computes a cross section of the shape with the plane
|
||||
//! @param theShape the shape consisting of triangulated faces
|
||||
//! @param theSectionPlane the plane that intersects the shape
|
||||
//! @return a resulting shape of a cross section
|
||||
Standard_EXPORT static TopoDS_Compound CrossSectionAsShape (const TopoDS_Shape& theShape,
|
||||
const gp_Pln& theSectionPlane);
|
||||
|
||||
//! Computes a cross section of the shape with the plane
|
||||
//! @param theShape the shape consisting of triangulated faces
|
||||
//! @param theSectionPlane the plane that intersects the shape
|
||||
//! @return a resulting list of segments
|
||||
Standard_EXPORT static Handle (Graphic3d_ArrayOfPrimitives)
|
||||
CrossSectionAsArrayOfSegments (const TopoDS_Shape& theShape, const gp_Pln& theSectionPlane);
|
||||
|
||||
//! Computes a cross section of the shape with the plane
|
||||
//! @param theShape the shape consisting of triangulated faces
|
||||
//! @param theSectionPlane the plane that intersects the shape
|
||||
//! @param theArrayOfSectionTriangles a resulting list of triangles
|
||||
//! @param theArrayOfSectionSegments a resulting list of line segments
|
||||
Standard_EXPORT static void CrossSectionAsArraysOfTrianglesAndSegments (const TopoDS_Shape& theShape,
|
||||
const gp_Pln& theSectionPlane,
|
||||
Handle (Graphic3d_ArrayOfPrimitives)
|
||||
& theArrayOfSectionTriangles,
|
||||
Handle (Graphic3d_ArrayOfPrimitives)
|
||||
& theArrayOfSectionSegments);
|
||||
};
|
||||
|
||||
#endif // _StdPrs_SectionLines_HeaderFile
|
@@ -20,3 +20,4 @@ CSF_IOKit
|
||||
CSF_FreeImagePlus
|
||||
CSF_FREETYPE
|
||||
CSF_FFmpeg
|
||||
CSF_winmm
|
||||
|
@@ -3,6 +3,7 @@ InterfaceGraphic
|
||||
SelectBasics
|
||||
Xw
|
||||
Image
|
||||
Media
|
||||
WNT
|
||||
Cocoa
|
||||
TColQuantity
|
||||
|
@@ -18,7 +18,6 @@ TKMesh
|
||||
TKV3d
|
||||
TKDraw
|
||||
TKOpenGl
|
||||
TKVulkan
|
||||
CSF_TclLibs
|
||||
CSF_TclTkLibs
|
||||
CSF_XwLibs
|
||||
|
@@ -1,3 +0,0 @@
|
||||
project(TKVulkan)
|
||||
|
||||
OCCT_INCLUDE_CMAKE_FILE (adm/cmake/occt_toolkit)
|
@@ -1,13 +0,0 @@
|
||||
TKernel
|
||||
TKService
|
||||
TKMath
|
||||
TKV3d
|
||||
CSF_TBB
|
||||
CSF_FREETYPE
|
||||
CSF_vulkan
|
||||
CSF_user32
|
||||
CSF_gdi32
|
||||
CSF_XwLibs
|
||||
CSF_Appkit
|
||||
CSF_IOKit
|
||||
CSF_objc
|
@@ -1,2 +0,0 @@
|
||||
EXTERNLIB
|
||||
PACKAGES
|
@@ -1 +0,0 @@
|
||||
Vulkan
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user