1
0
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 Message Date
tiv
3f53006c35 0030599: Visualization - implement StdPrs_SectionLines tool
StdPrs_SectionLines tool is implemented: it is possible to compute a cross section of the shape with the plane.
# Some features have not been implemented yet:
#   * the method StdPrs_SectionLines::Add() that should add objects inside section to the Prs3d_Presentation;
#   * corresponding Draw Harness command;
#   * interactive object that could represent the cross section;
#   * triangles that lie inside the section plane have not been processed yet.
2019-04-19 20:27:36 +03:00
tiv
f9b30c0db3 0030623: Draw Harness - support hex color codes within ViewerTest::ParseColor()
ViewerTest::ParseColor() function is improved to be able to parse the following set of input arguments:
  - "Red Green Blue [Alpha]", where Red, Green, Blue, Alpha must be integers within the range [0, 255] or reals within the range [0.0, 1.0]. Note that "0 0 1" triple is parsed as "0.0 0.0 1.0" and will be interpreted as a blue color.
  - "ColorName [Alpha]", where ColorName is one of WHITE, BLACK, RED, GREEN, BLUE, etc. (look at Quantity_NameOfColor enumeration for all possible variants). Alpha may be integer or real, as described at the previous list item.
  - #HHH, [#]HHH[H], [#]HHHHHH[HH], where H is a hexadecimal digit (0 .. 9, a .. f, or A .. F). There are a short hexadecimal RGB, RGBA formats, and a usual RGB[A], respectively.
2019-04-12 18:48:18 +03:00
jgv
a5278fc126 0030597: BRepOffsetAPI_MakePipeShell raises Standard_RangeError
Constructor of GeomFill_SectionPlacement has been corrected: add correction of boundaries of curve to avoid mistake of LocateU in the case when the curve is BSpline.
2019-04-12 11:34:54 +03:00
kgv
74413ca7d3 0030643: Visualization, Ray-Tracing - shader compilation errors are not properly logged
OpenGl_View::initShader() now uses OpenGl_ShaderObject::LoadAndCompile().
2019-04-10 15:33:55 +03:00
kgv
98e6c6d17b 0030612: Visualization - provide texture map with video as image source
Introduced package Media wrapping FFmpeg structures.
Media_PlayerContext class manages video decoding into Media_IFrameQueue interface.
Graphic3d_MediaTextureSet implements Media_IFrameQueue interface and can be used as texture source.
AIS_MediaPlayer implements simple AIS object displaying video.
2019-04-09 14:18:35 +03:00
kgv
9491df8c1b 0030638: Visualization, TKOpenGl - load OpenGL 4.5 functions within OpenGl_Context 2019-04-09 14:17:47 +03:00
kgv
d325cb7f57 0030635: Visualization - move OpenGl_Layer to Graphic3d_Layer
Renamed classes (moved from TKOpenGl to TKV3d):
- OpenGl_Layer -> Graphic3d_Layer;
- OpenGl_BVHClipPrimitiveSet -> Graphic3d_BvhCStructureSet;
- OpenGl_BVHClipPrimitiveTrsfPersSet -> Graphic3d_BvhCStructureSetTrsfPers;
- OpenGl_BVHTreeSelector -> Graphic3d_CullingTool.

Method OpenGl_Layer::Render() has been moved to OpenGl_LayerList::renderLayer().

Standard Z-layers list definition has been moved
from OpenGl_GraphicDriver to base class Graphic3d_GraphicDriver.
2019-04-09 14:16:33 +03:00
kgv
24ee60ffd7 0030636: Configuration, qmake - unable to build using VS2017 2019-04-09 12:33:43 +03:00
emv
cea8d5c1ab 0030629: Modeling Algorithms - Invalid result of fuse operation
Plane/Torus intersection: take into account the Plane-Torus distance sign to compute the correct location of the section curve.

Test case for the issue.
2019-04-08 16:03:41 +03:00
kgv
fc867b96a5 0030618: Modeling Algorithms, BOPTools_Parallel - avoid using map for thread-local contexts without TBB
OSD_Parallel::ToUseOcctThreads() - new flag allowing to use OCCT threads implementation even when compiled with TBB (for testing).
Added new command dparallel for managing default Thread Pool.
OSD_Parallel::For() now avoid creation of universal iterator in simplest case.

BOPTools_Parallel - eliminated redundant typedefs/explicit instantiations of templates.
Added functor using array of per-thread context instead of a map.
2019-04-08 15:59:23 +03:00
176 changed files with 5658 additions and 10921 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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")

View File

@@ -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"

View File

@@ -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 }

View File

@@ -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);

View File

@@ -191,7 +191,7 @@ protected:
protected:
Handle(AIS_AnimationTimer) myTimer;
Handle(Media_Timer) myTimer;
TCollection_AsciiString myName; //!< animation name
NCollection_Sequence<Handle(AIS_Animation)>

View File

@@ -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
View 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);
}

View 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

View File

@@ -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

View File

@@ -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();

View File

@@ -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)

View File

@@ -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++)

View File

@@ -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();

View File

@@ -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

View File

@@ -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())

View File

@@ -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) {

View File

@@ -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())

View File

@@ -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();

View File

@@ -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

View File

@@ -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) {

View File

@@ -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

View File

@@ -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);

View File

@@ -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

View File

@@ -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) {

View File

@@ -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

View File

@@ -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);
//======================================================
}
//

View File

@@ -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);
}
}
};

View File

@@ -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 :

View File

@@ -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.

View File

@@ -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);

View File

@@ -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",

View File

@@ -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

View File

@@ -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)
{

View File

@@ -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

View File

@@ -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;

View File

@@ -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.

View 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)();
}

View 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

View 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;
}

View 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

View File

@@ -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;

View File

@@ -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
View 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

View 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
}

View 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

View 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
}

View 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

View 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
}

View 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
View 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
View 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

View 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
View 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
}

View 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

View 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;
}
}
}
}

View 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
View 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
}

View 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

View File

@@ -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
View 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

View File

@@ -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.

View File

@@ -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)

View File

@@ -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,

View File

@@ -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,

View File

@@ -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" } {

View File

@@ -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
}
//=======================================================================

View File

@@ -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);
}
}

View File

@@ -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
{

View File

@@ -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 */

View File

@@ -16,6 +16,7 @@
#include <OSD_ThreadPool.hxx>
#include <OSD.hxx>
#include <OSD_Parallel.hxx>
#include <Standard_Atomic.hxx>
#include <TCollection_AsciiString.hxx>

View File

@@ -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>

View File

@@ -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;

View File

@@ -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

View File

@@ -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));

View File

@@ -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

View File

@@ -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),

View File

@@ -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;

View File

@@ -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();

View File

@@ -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

View File

@@ -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

View File

@@ -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);

View 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);
}

View File

@@ -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)); }

View File

@@ -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

View File

@@ -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;

View File

@@ -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);

View File

@@ -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"

View File

@@ -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"

View File

@@ -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

View 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;
}

View 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

View File

@@ -20,3 +20,4 @@ CSF_IOKit
CSF_FreeImagePlus
CSF_FREETYPE
CSF_FFmpeg
CSF_winmm

View File

@@ -3,6 +3,7 @@ InterfaceGraphic
SelectBasics
Xw
Image
Media
WNT
Cocoa
TColQuantity

View File

@@ -18,7 +18,6 @@ TKMesh
TKV3d
TKDraw
TKOpenGl
TKVulkan
CSF_TclLibs
CSF_TclTkLibs
CSF_XwLibs

View File

@@ -1,3 +0,0 @@
project(TKVulkan)
OCCT_INCLUDE_CMAKE_FILE (adm/cmake/occt_toolkit)

View File

@@ -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

View File

@@ -1,2 +0,0 @@
EXTERNLIB
PACKAGES

View File

@@ -1 +0,0 @@
Vulkan

Some files were not shown because too many files have changed in this diff Show More