Qt6 porting guidance: QMediaPlayer
-
Quesion 1:
in qt5 i could call the equivalent of:mediaPlayerP->setVideoOutput(const QList<QVideoSink *> &sinks)
this is no longer available, unless enough of us complain, i guess. well here i am.
my media player app can output to 3 different scenes in 3 different windows. with qt6 it can no longer do that.
i thought i might be able to derive
QVideoSink
, and just make aCMultiplexVideoSink
out of it, which is an accepted trick to get aQCameraDevice
to be capable of sending its output to multiple destinations, but you can't derive fromQVideoSink
because there are no virtual methods :(so that method won't work for media player (also won't work for camera, see my other post on that).
how am i supposed to do this now?
Quesion 2:
if one has a requirement to have a video's dimensions and duration BEFORE playing the video (eg: to create a buffer, resize a window, or to set up a timeline GUI that shows the proper end time), an acceptable method in the past was to "preroll" the video by starting to play it with no visible or audible interface, start it (secretly) playing, spin an event loop waiting for the messagesQAbstractVideoSurface::surfaceFormatChanged
andQMediaPlayer::durationChanged
, and when received, store the data, tear it all down, and THEN present the interface and start playing the video.but... there is no
surfaceFormatChanged
signal inQVideoSink
.querying metadata still doesn't provide the frame size (dimensions / resolution) either.
Quesion 3:
similar to above, when constructing aQGraphicsScene
with aQVideoGraphicsItem
that was mapped from aQImage
(not from a video), then, at the first presentation, one could ask the surface if it were active, and if not, one would have to callsurfaceP->start()
(do we need to do this any more?) then one would spin a bit on an event loop waiting forhandleNativeSizeChanged
, so the graphicsItem could know the proper dimensions, so it would not first present with wrong dimensions..like this:
void CG_Overlay::present( QtAbstractVideoSurface *surfaceP, const QVideoFrame& frame) { #if _QT6_ { QSize vidSize(surfaceP->videoSize()); CF_ASSERT(!vidSize.isEmpty()); } #else if (!surfaceP->isActive()) { bool startedB(surfaceP->start(surfaceFormat(frame))); CTimerSince timer; CF_ASSERT(startedB); // wait for dimensions to get got // so the first presentation has // correct aspect ratio setHasDimensions(false); while (!hasDimensions() && !QtFireTimersUntilExpire(timer)) {} } #endif // if you can't get the CDG image to appear for // presentation, see comment in CPixels::hqx_blit() #if _QT6_ surfaceP->newVideoFrame(frame); #else surfaceP->present(frame); #endif }
in the above,
QtAbstractVideoSurface
is aQVideoSink
, and the first assert always fires (vidSize is in fact empty)in qt6 there isn't a way to do this :(
what am i missing?
-dave
-
I did get all of these issues solved yes.
1: create a new subclass ofQtAbstractVideoSurface
, and override thepresent()
function to do your multiplexing, set your subclass as the one video sink
2: instead of hooking intoQAbstractVideoSurface::surfaceFormatChanged
, hook intoQMediaPlayer::metaDataChanged
3: i guess you don't need it if you do the above? -
I did get all of these issues solved yes.
1: create a new subclass ofQtAbstractVideoSurface
, and override thepresent()
function to do your multiplexing, set your subclass as the one video sink
2: instead of hooking intoQAbstractVideoSurface::surfaceFormatChanged
, hook intoQMediaPlayer::metaDataChanged
3: i guess you don't need it if you do the above?