Closed RJVB closed 1 year ago
Probably not surprisingly the dynamic casting does work with any issue in FFDecVTP::open()
:
bool FFDecVTB::open(StreamInfo &streamInfo)
{
// ...
#ifdef USE_OPENGL
if (QMPlay2Core.renderer() == QMPlay2CoreClass::Renderer::OpenGL && !vtbOpenGL)
{
auto vOGL = new VTBOpenGL(m_hwDeviceBufferRef);
vtbOpenGL = shared_ptr<VTBOpenGL>(vOGL); //make_shared<VTBOpenGL>(m_hwDeviceBufferRef);
auto hDC = dynamic_cast<HWDecContext*>(vOGL);
auto hDCptr = dynamic_pointer_cast<HWDecContext>(vtbOpenGL);
auto hDC2 = shared_ptr<HWDecContext>(vtbOpenGL);
auto oGHWI = dynamic_cast<OpenGLHWInterop*>(vOGL);
auto oGHWIptr = dynamic_pointer_cast<OpenGLHWInterop>(vtbOpenGL);
auto oGHWIptr2 = dynamic_pointer_cast<OpenGLHWInterop>(hDC2);
qWarning() << "vOGL" << vOGL << "vtbOpenGL" << vtbOpenGL.get();
qWarning() << "hDC" << hDC << "hDCptr" << hDCptr.get();
qWarning() << "oGHWI" << oGHWI << "oGHWIptr" << oGHWIptr.get() << "oGHWIptr2" << oGHWIptr2.get();
prints
[26 May 2023 18:52:05.843] vOGL 0x10d253150 vtbOpenGL 0x10d253150
[26 May 2023 18:52:05.844] hDC 0x10d253150 hDCptr 0x10d253150
[26 May 2023 18:52:05.845] oGHWI 0x10d253150 oGHWIptr 0x10d253150 oGHWIptr2 0x10d253150
[26 May 2023 18:52:05.846] virtual bool OpenGLWriter::setHWDecContext(const shared_ptr<HWDecContext> &) hwDecContext 0x10d253150 hwInterop 0x0 hwInterop2 0x0
dynamic_cast
might not work across libraries e.g. if symbols are hidden and are not exported or RTTI is disabled. VTBOpenGL
is in different library than OpenGLWriter
and HWDecContext
. What did you modify in QMPlay2? First try to remove -fvisibility=hidden -fvisibility-inlines-hidden
from CMake and recompile.
You probably right and I do make mods. I double-checked though and none of my modifications have anything to do with the way C++ is built. IOW I don't disable RTTI and I don't mess with your visibility settings.
I can exclude shared_ptr
now, though - I added a few methods to pass the VTBOpenGL*
directly into OpenGLWriter
and do the shared_ptr business there. But the dynamic cast already failed before that conversion. This means I can probably also exclude the possibility that this is a libc++ issue.
I've now added
string(REPLACE "-fvisibility=hidden" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
string(REPLACE "-fvisibility-inlines-hidden" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
to src/modules/FFmpeg/CMakeLists.txt
and that doesn't make a difference... should I do the same for libqmplay2?
Well, apparently I should. Now it works...
I told you to remove existing -fvisibility=hidden -fvisibility-inlines-hidden
, not replace in FFmpeg :sweat_smile:
So what should be done to properly make it working? Could you check which class or classes requires __attribute__((visibility("default")))
to make it work with default CMake settings?
Replacing with an empty string is removing, no? I know what you told me, but I figured we'd both be more interested in not setting more classes to default visibility that necessary ... and it's indeed enough not to hide then in libFFmpeg and libQMplay2. In fact, I didn't even test if libFFmpeg needs to export everything...
I'll check the attribute thing. Probably only needs to be set for the 3 involved classes at most, no? (Good little "chore" for when my mother in law is there this weekend ;) )
Just so I understand this a bit better: is it libFFmpeg that needs to be able to access normally hidden things from the 2 classes in libQMplay2, the other way round, or both? I would have guessed that the dynamic cast failed only because libFFmpeg didn't export all the required symbols, but apparently I was wrong.
Replacing with an empty string is removing, no?
Yes, but in entire software, not in a single library.
I don't understand why it works on Linux, new macOS and Windows :smile:
I'll check the attribute thing.
:+1:
Try to add to HWDecContext
and OpenGLHWInterop
. If still not, try also for VTBOpenGL
.
I don't understand why it works on Linux, new macOS and Windows :smile:
So maybe something related to the C++ runtime (libc++, libstdc++ etc) after all? Your assumption re: visibility made sense though, the runtime can't use information that wasn't emitted by the compiler so indeed, why...
I never understand why anything works on MSWin ;)
I never understand why anything works on MSWin ;)
:rofl: Especially with symbols in DLLs - sometimes I don't know what's going on there and trying until it links :sweat_smile:
The two classes in libqmplay2 are header-only, maybe your compiler needs them to have visible attribute anyway... When you'll be able to check it, I'm curious :smile: Tried on macOS 10.13 and no issue there.
Do you happen to know what clang version is used on 10.13? I'm using clang 9.0 which should be new enough (clang 8 definitely is on Linux).
I do build the compiler chain without RTTI but that shouldn't have any impact on code generated by the compiler.
Try to add to
HWDecContext
andOpenGLHWInterop
. If still not, try also forVTBOpenGL
.
No luck. Besides, HWDecContext
already has QMPLAY2SHAREDLIB_EXPORT
which is supposed to do the same thing I think.
Do you happen to know what clang version is used on 10.13? I'm using clang 9.0 which should be new enough (clang 8 definitely is on Linux).
Apple has their own clang versioning... Some numbers are similar, but it's not the same :angry: It's 10.0.0.10001145 (Xcode 10.1) on my macOS VM.
HWDecContext already has QMPLAY2SHAREDLIB_EXPORT
Where :astonished: ?
Do you happen to know what clang version is used on 10.13? I'm using clang 9.0 which should be new enough (clang 8 definitely is on Linux).
Apple has their own clang versioning... Some numbers are similar, but it's not the same 😠 It's 10.0.0.10001145 (Xcode 10.1) on my macOS VM.
HWDecContext already has QMPLAY2SHAREDLIB_EXPORT
Where 😲 ?
Sorry, I may need new glasses :-/
Sorry, I may need new glasses :-/
Try to change visibility of this again. Otherwise I don't have any idea... Maybe add CMake option to not hide symbols optionally.
Apple has their own clang versioning... Some numbers are similar, but it's not the same :angry: It's 10.0.0.10001145 (Xcode 10.1) on my macOS VM.
The "angry" emoji is for Apple for their stupid versioning, not for you :smile:
which is supposed to do the same thing I think.
Yes, except Windows, because it's more complicated there (dllexport
/dllimport
- one is specified when you compile library, another when you include it in another library... So complicated :smile: ).
Tried again, this time really with VTBOpenGL, OpenGLHWInterop and HWDecContext. It's clearly not enough, but yet
> nm --demangle /Applications/MacPorts/Qt5/QMPlay2.app/Contents/MacOS/modules/libFFmpeg.dylib | fgrep VTBOpenGL | fgrep typeinfo
0000000000022610 s typeinfo for VTBOpenGL
0000000000022580 s typeinfo for std::__1::__shared_ptr_emplace<VTBOpenGL, std::__1::allocator<VTBOpenGL> >
000000000001f3bf s typeinfo name for VTBOpenGL
000000000001f368 s typeinfo name for std::__1::__shared_ptr_emplace<VTBOpenGL, std::__1::allocator<VTBOpenGL> >
> nm --demangle /opt/local/lib/libqmplay2.dylib | egrep 'HWDecContext|OpenGLHWInterop' | fgrep typeinfo
0000000000056890 s typeinfo for HWDecContext
00000000000568a0 s typeinfo for OpenGLHWInterop
0000000000056a10 s typeinfo for std::__1::__function::__func<OpenGLCommon::initialize(std::__1::shared_ptr<OpenGLHWInterop> const&)::$_1, std::__1::allocator<OpenGLCommon::initialize(std::__1::shared_ptr<OpenGLHWInterop> const&)::$_1>, void (unsigned int)>
0000000000056a28 s typeinfo for OpenGLCommon::initialize(std::__1::shared_ptr<OpenGLHWInterop> const&)::$_1
000000000004c787 s typeinfo name for HWDecContext
000000000004c775 s typeinfo name for OpenGLHWInterop
000000000004c8b8 s typeinfo name for std::__1::__function::__func<OpenGLCommon::initialize(std::__1::shared_ptr<OpenGLHWInterop> const&)::$_1, std::__1::allocator<OpenGLCommon::initialize(std::__1::shared_ptr<OpenGLHWInterop> const&)::$_1>, void (unsigned int)>
000000000004c86c s typeinfo name for OpenGLCommon::initialize(std::__1::shared_ptr<OpenGLHWInterop> const&)::$_1
Grrr, building against libc++ 9.0.1 (and its headers) also doesn't help :(
What will happen if you remove -fvisibility=hidden
or -fvisibility-inlines-hidden
(keep one of them and try)?
Maybe add CMake option to not hide symbols optionally.
Do you really prefer to not use hidden visibility (export control) at all, instead of only disabling it for the 2 libraries where it's needed to get VideoToolBox acceleration to work?
Do you really prefer to not use hidden visibility (export control) at all, instead of only disabling it for the 2 libraries where it's needed to get VideoToolBox acceleration to work
It's a workaround for your compiler. It works elsewhere. Hiding saves some kilobytes only.
There are also some calls to dynamic_cast
, who knows if it works with hidden symbols to you :grin: Two of them I can replace for qobject_cast
, but two others I can't.
Have you been able to test down to 10.10 (should work given that you require Qt 5.10)?
As said before, this can't really be a problem with my compiler. I use clang 9, but clang 8 on Linux where I do get VAAPI hardware acceleration. I have clang 11 installed too so could try with that to see if I'm wrong...
Either way, you don't have to add hacks for me; I can just apply those myself for my own builds! ;)
BTW, removing just -fvisibility=hidden
is enough (just for the 2 libraries, but curiously I need to force a rebuild of the entire tree if I change this compiler option).
Theoretically hidden visibility also (or mostly) speeds up launching the application because the loader has less to do.
Have you been able to test down to 10.10 (should work given that you require Qt 5.10)?
I don't have VM with 10.10. Too much things to install everything to build QMPlay2 :sweat_smile:
As said before, this can't really be a problem with my compiler. I use clang 9, but clang 8 on Linux where I do get VAAPI hardware acceleration. I have clang 11 installed too so could try with that to see if I'm wrong...
Maybe some global config you have? Btw. you can use static_pointer_cast
instead. dynamic_pointer_cast
it's just a guard. Can you try with hidden visibility? If VTB will work, try to do a screenshot in QMPlay2 (Atl+S) - there's another dynamic_pointer_cast
for this with HW accell :smile:
Maybe some global config you have?
Of the toolchain? Maybe, but what ...
Btw. you can use
static_pointer_cast
instead.dynamic_pointer_cast
it's just a guard.
In OpenGLWriter::setHWDecContext()
?
In OpenGLWriter::setHWDecContext()?
Yes
Of the toolchain? Maybe, but what ...
Idk :smile:
Well I be ... static_pointer_cast
does the trick too...
And Alt+S gives me "Cannot create screenshot" so I guess the fix has to be applied elsewhere too?
It's here: void VideoThr::screenshot(Frame videoFrame)
, but if you use Vulkan, it'll crash with static_pointer_cast
(you don't use Vulkan on macOS).
hmmm, Vulkan cannot be used at all on Mac (not even on newer ones with the Metal framework)?
Yeah, that (uses the Metal framework underneath).
So the question is, do we use a compile-time conditional or a runtime one, to decide wether to use static_pointer_cast
or dynamic_pointer_cast
?
It works fine to me for compute shaders, but not tried it in QMPlay2 yet.
So the question is, do we use a compile-time conditional or a runtime one, to decide wether to use static_pointer_cast or dynamic_pointer_cast?
If dynamic_pointer_cast
fails, use static_pointer_cast
and crash :grinning:
I don't know what do you mean, if old mac - use static cast?
For curiosity - can you check if const bool self = dynamic_cast<MediaBrowser *>(QMPlay2Ext);
and if (dynamic_cast<YouTube *>(QMPlay2Ext))
are working?
If you have problems with visibility-hidden - better to disable for entire software. Who knows what else will not work or will work differently than expected?
I don't know what do you mean, if old mac - use static cast?
#ifdef Q_OS_MACOS static_pointer_cast
static_pointer_cast
if OpenGL is used.For curiosity - can you check if const bool self = dynamic_cast<MediaBrowser >(QMPlay2Ext); and if (dynamic_cast<YouTube >(QMPlay2Ext)) are working?
Where should I do that?
Where should I do that?
Find occurrences (grep
on entire source) and put qDebug
and compare with and without visibility. Two places in code. It's on playlist context menu -> Extensions. Can't tell exactly, on phone now.
For curiosity - can you check if
const bool self = dynamic_cast<MediaBrowser *>(QMPlay2Ext);
andif (dynamic_cast<YouTube *>(QMPlay2Ext))
are working?
I haven't yet gotten the MediaBrowser trace to output anything but the YouTube dyncast clearly doesn't work with hidden visibility.
I'm going to check if CMAKE_CXX_VISIBILITY_PRESET
has any interest.
I haven't yet gotten the MediaBrowser trace to output anything but the YouTube dyncast clearly doesn't work with hidden visibility.
Correction, apparently the result can be NULL and is so most of the time, so I completely missed the fact that I did get 2 successful dyncasts with hidden visibility too.
The CMAKE_CXX_VISIBILITY_PRESET
variable does do what it promises to do, btw. So I now have:
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1429fdebe650cfdabb41cff2a543a9383c109019..f543b9eb7344299944df1d61323fcc9d87ac6360 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -307,6 +307,9 @@ if(USE_GIT_VERSION)
endif()
add_feature_info("Git version" QMPLAY2_GIT_HEAD "Append Git HEAD to QMPlay2 version")
+option(USE_HIDDEN_VISIBILITY "Use selective export control in shared libraries" ON)
+add_feature_info(VISIBILITY USE_HIDDEN_VISIBILITY "Use selective export control in shared libraries")
+
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") # GCC or Clang
option(USE_LINK_TIME_OPTIMIZATION "Enable link time optimization for release builds" OFF)
add_feature_info("Link Time Optimization" USE_LINK_TIME_OPTIMIZATION "Enable link time optimization for release builds")
@@ -329,9 +332,19 @@ if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang"
endif()
# Hide symbols, and also make sure that debugging symbols are disabled
- set(CMAKE_CXX_FLAGS_RELEASE "${RELEASE_DEBUG_FLAG} -fvisibility=hidden -fvisibility-inlines-hidden ${CMAKE_CXX_FLAGS_RELEASE}")
- set(CMAKE_CXX_FLAGS_MINSIZEREL "${RELEASE_DEBUG_FLAG} -fvisibility=hidden -fvisibility-inlines-hidden ${CMAKE_CXX_FLAGS_MINSIZEREL}")
+ if(USE_HIDDEN_VISIBILITY)
+ set(CMAKE_CXX_VISIBILITY_PRESET hidden)
+ else()
+ # be sure to reset these so code can be rebuilt without the option
+ set(CMAKE_CXX_VISIBILITY_PRESET default)
+ endif()
+ # this one can always be enabled:
+ set(CMAKE_VISIBILITY_INLINES_HIDDEN 1)
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+ set(CMAKE_CXX_FLAGS_RELEASE "${RELEASE_DEBUG_FLAG} ${CMAKE_CXX_FLAGS_RELEASE}")
+ set(CMAKE_CXX_FLAGS_MINSIZEREL "${RELEASE_DEBUG_FLAG} ${CMAKE_CXX_FLAGS_MINSIZEREL}")
if(NOT USE_VULKAN)
+ set(CMAKE_CXX_FLAGS "-fno-exceptions ${CMAKE_CXX_FLAGS}")
set(CMAKE_CXX_FLAGS_RELEASE "-fno-exceptions ${CMAKE_CXX_FLAGS_RELEASE}")
set(CMAKE_CXX_FLAGS_MINSIZEREL "-fno-exceptions ${CMAKE_CXX_FLAGS_MINSIZEREL}")
endif()
@@ -351,8 +364,9 @@ if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang"
endif()
if(USE_LINK_TIME_OPTIMIZATION)
+ set(CMAKE_CXX_FLAGS "-flto ${CMAKE_CXX_FLAGS}")
set(CMAKE_CXX_FLAGS_RELEASE "-flto ${CMAKE_CXX_FLAGS_RELEASE}")
- set(CMAKE_CXX_FLAGS_MINSIZEREL "-flto ${CMAKE_CXX_FLAGS_RELEASE}")
+ set(CMAKE_CXX_FLAGS_MINSIZEREL "-flto ${CMAKE_CXX_FLAGS_MINSIZEREL}")
endif()
if(CMAKE_MODULE_LINKER_FLAGS)
(That's my full mod of the relevant bit of the CMake file; I use a custom CMAKE_BUILD_TYPE
so I (and the project) have complete control over the flags that get passed to the compiler.)
Did you test playback of VP9 videos with VideoToolBox acceleration? These videos cause a "trace/bpt" trap after printing Failed to initialize decoder for 1280x714 @ 0
I notice that at least with my Linux,FFmpeg,Mesa combination these same videos are played with regular Vulkan, not Vulkan/VAAPI.
For that VP9 issue:
diff --git a/src/modules/FFmpeg/FFDecVTB.cpp b/src/modules/FFmpeg/FFDecVTB.cpp
index 74838792da90ec42b95d4facaf67364ab6fccbc5..1f48643c78757516602c4f4b23b015112fde05eb 100644
--- a/src/modules/FFmpeg/FFDecVTB.cpp
+++ b/src/modules/FFmpeg/FFDecVTB.cpp
@@ -77,3 +77,12 @@ bool FFDecVTB::open(StreamInfo &streamInfo)
return false;
-
+ if (streamInfo.params->codec_id == AV_CODEC_ID_VP9)
+ {
+#if __has_builtin(__builtin_available)
+ if (! __builtin_available(macOS 10.15, *))
+#endif
+ {
+ qWarning() << "VP9 not supported by VTB";
+ return false;
+ }
+ }
const AVPixelFormat pix_fmt = streamInfo.pixelFormat();
Correction, apparently the result can be NULL and is so most of the time, so I completely missed the fact that I did get 2 successful dyncasts with hidden visibility too.
Nice, so some dynamic casts works with hidden symbols on your system!
Did you test playback of VP9 videos with VideoToolBox acceleration?
Yes, it worked without problems, also yuv420p10!
These videos cause a "trace/bpt" trap after printing
Failed to initialize decoder for 1280x714 @ 0
Strange, FFmpeg bug?
I notice that at least with my Linux,FFmpeg,Mesa combination these same videos are played with regular Vulkan, not Vulkan/VAAPI.
I don't think your hardware supports VP9. Check vainfo
tool.
These videos cause a "trace/bpt" trap after printing
Failed to initialize decoder for 1280x714 @ 0
Strange, FFmpeg bug?
No idea, or QMPlay2 assumes that VTB always supports VP9 decoding. Which it doesn't. I haven't really been able to pinpoint exactly when that support was added and what hardware is required. I've copied a patch that makes a hopefully reasonably safe assumption about when support should be available and falls back to CPU decoding otherwise.
FWIW I notice that even on my lowly Linux N3150 system CPU decoding is actually faster than using the GPU on the same chip. For 720p videos, that is.
I don't think your hardware supports VP9. Check
vainfo
tool.
I'll need to update vainfo (after figuring out where the source hides nowadays). libva and the intel-vaapi-driver are among the things I've been keeping up-to-date better than the system itself ^^ From what I've been able to see there should be some hardware support for VP9 in an N3150 but it's quite possible that I'm just getting lost in the pretty names.
On a related note: I saw ffmpeg can use OpenCL for hw acceleration. Not of much (or any, in fact) use on my systems but have you considered exposing the option in QMPlay2?
On a related note: I saw ffmpeg can use OpenCL for hw acceleration. Not of much (or any, in fact) use on my systems but have you considered exposing the option in QMPlay2?
I guess FFmpeg uses it for filters, not for decoding video. GPU isn't decoding video itself, it has separate chip for this which supports only some codecs. Anyway OpenCL is a horrible idea. Vulkan compute shaders can be better.
FWIW I notice that even on my lowly Linux N3150 system CPU decoding is actually faster than using the GPU on the same chip. For 720p videos, that is.
It can happen. My Ryzen 7950X is decoding faster than Radeon RX 6900XT :sweat_smile: E.g. Ryzen can smoothly decode 8k 60 FPS VP9 video, Radeon can't :rofl: Moreover when I put everything to powersave mode, watt meter shows less wattage when I decode simple videos on CPU than on GPU. It depends on hardware which decoder is better (CPU or GPU).
some hardware support for VP9 in an N3150
QMPlay2 assumes that VTB always supports VP9 decoding
QMPlay2 can check it additionally, but FFmpeg must do it without a crash. Are you sure your FFmpeg compilation is up-to-date and correct?
It depends on hardware which decoder is better (CPU or GPU).
Some videos can't decode in parallel on CPU (idk why), in this case hardware decoder is the only option (e.g. HEVC 4k 60FPS videos from mobile phones).
QMPlay2 can check it additionally, but FFmpeg must do it without a crash. Are you sure your FFmpeg compilation is up-to-date and correct?
The crash isn't in FFmpeg itself. When I ask FFmpeg to decode a VP9 video with VTB accel it tells me it can't. I'm using FFmpeg 4.4.4, haven't upgraded to v6 yet.
There are already a few checks for unsupported content in FFDecVTB; I suppose you didn't put them there for nothing.
Some videos can't decode in parallel on CPU (idk why), in this case hardware decoder is the only option (e.g. HEVC 4k 60FPS videos from mobile phones).
Well, for playback decoding all that matters anyway is if you can do it at the video's framerate. I'm glad we got VTB to work for me because that old i7 runs hot very easily and the fans can get quite noisy when that happens.
The crash isn't in FFmpeg itself. When I ask FFmpeg to decode a VP9 video with VTB accel it tells me it can't. I'm using FFmpeg 4.4.4, haven't upgraded to v6 yet.
What "trace/bpt" trap
means?
What
"trace/bpt" trap
means?
I suppose it corresponds to "SIGTRAP" but the only thing I know about that one is that it is a "trace trap" which isn't reset when caught...
I'll keep it as is, I can't easily test macOS VTB especially with older hardware. Your system is obsolete and very custom, it might cause some issues, too :smile:
As mentioned in my previous ticket, I have a long-standing fails-to-work issue with VTB in QMPlay2 on my Mac (2011 MPB 8.1 running OS X 10.9.5). This hardware acceleration does work in VLC as far as I can tell, so a priori it's not that my OS is too old (VTB was introduced in 10.8 btw).
I've been trying to trace the origin of the problem but get stuck somewhere on what appears to be a C++ problem...
In
FFDecVTP::open()
:av_hwdevice_ctx_create(&m_hwDeviceBufferRef, AV_HWDEVICE_TYPE_VIDEOTOOLBOX, nullptr, nullptr, 0)
does not fail. The subsequent operation
vtbOpenGL = make_shared<VTBOpenGL>(m_hwDeviceBufferRef);
also appears to succeed (I get a
VTBOpenGL
instance with its own, non-null copy ofm_hwDeviceBufferRef
).Things go wrong in
OpenGLWriter::setHWDecContext()
: the dynamic cast from theHWDecContext
instance to aOpenGLHWInterop
fails. With some trace output:I get
virtual bool OpenGLWriter::setHWDecContext(const shared_ptr<HWDecContext> &) hwDecContext 0x11e4061c8 hwInterop 0x0 hwInterop2 0x0
As far as I can tell this makes little sense:
VTBOpenGL
inheritsOpenGLHWInterop
inheritsHWDecContext
so unless something fishy is going on with theshared_ptr
implementation aVTBOpenGL
instance passed as ahwDecContext
pointer should be dynamic-castable to aOpenGLHWInterop
pointer.Any idea how to figure out what goes wrong and why, here?
How crucial is the use of
shared_ptr
?