[Interest] Qt6 porting guidance: QMediaPlayer

David M. Cotter dave at kjams.com
Thu Jul 8 03:59:08 CEST 2021


in qt5 i could call 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 a "CMultiplexVideoSink" out of it, which is an accepted trick to get a QCameraDevice to be capable of sending its output to multiple destinations, but you can't derive from QVideoSink 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?

next question:
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 messages "QAbstractVideoSurface::surfaceFormatChanged" and "QMediaPlayer::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 in QVideoSink.

does metadata actually work now to the point where i can grab the dimensions and duration without prerolling the movie?

also, and this seems to be something rather important, there used to be a " QMediaPlayer::error" signal that one could listen for. it's gone. how do we know when an error occurs now?

similar to above, when constructing a QGraphicsScene with a QVideoGraphicsItem that was mapped from a QImage (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 call surfaceP->start() (do we need to do this any more?) then one would spin a bit on an event loop waiting for  handleNativeSizeChanged, 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 a QVideoSink., and the first assert fires (vidSize is in fact empty)

in qt6 there isn't a way to do this :(

what am i missing?

-dave
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.qt-project.org/pipermail/interest/attachments/20210707/0d6041bd/attachment.html>


More information about the Interest mailing list