You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
xrdp-proprietary/vrplayer/decoderthread.cpp

218 lines
5.2 KiB

#include "decoderthread.h"
DecoderThread::DecoderThread()
{
vsi = NULL;
channel = NULL;
geometry.setX(0);
geometry.setY(0);
geometry.setWidth(0);
geometry.setHeight(0);
stream_id = 101;
elapsedTime = 0;
la_seekPos = 0;
}
void DecoderThread::run()
{
int64_t start_time;
int64_t duration;
/* TODO what happens if we get called a 2nd time while we are still running */
/* need a media file */
if (filename.length() == 0)
{
emit on_decoderErrorMsg("No media file",
"Please select a media file to play");
return;
}
/* connect to remote client */
if (openVirtualChannel())
return;
vsi = (VideoStateInfo *) av_mallocz(sizeof(VideoStateInfo));
if (vsi == NULL)
{
emit on_decoderErrorMsg("Resource error",
"Memory allocation failed, system out of memory");
return;
}
/* register all formats/codecs */
av_register_all();
if (sendMetadataFile())
return;
if (sendVideoFormat())
return;
if (sendAudioFormat())
return;
if (sendGeometry())
return;
xrdpvr_play_media(channel, 101, filename.toAscii().data());
xrdpvr_get_media_duration(&start_time, &duration);
emit on_mediaDurationInSeconds(duration);
qDebug() << "start_time=" << start_time << " duration=" << duration;
while (xrdpvr_play_frame(channel, 101) == 0)
{
if (elapsedTime == 0)
elapsedTime = av_gettime();
/* time elapsed in 1/100th sec units since play started */
emit on_elapsedtime((av_gettime() - elapsedTime) / 10000);
mutex.lock();
if (la_seekPos)
{
qDebug() << "seeking to" << la_seekPos;
xrdpvr_seek_media(la_seekPos, 0);
elapsedTime = av_gettime() - la_seekPos * 1000000;
la_seekPos = 0;
}
mutex.unlock();
}
/* perform clean up */
xrdpvr_deinit_player(channel, 101);
/* clean up resources */
closeVirtualChannel();
if (vsi)
av_free(vsi);
}
void DecoderThread::on_geometryChanged(int x, int y, int width, int height)
{
geometry.setX(x);
geometry.setY(y);
geometry.setWidth(width);
geometry.setHeight(height);
#if 0
qDebug() << "decoderThread:signal" <<
"" << geometry.x() <<
"" << geometry.y() <<
"" << geometry.width() <<
"" << geometry.height();
#endif
if (channel)
{
xrdpvr_set_geometry(channel, 101, geometry.x(), geometry.y(),
geometry.width(), geometry.height());
}
}
void DecoderThread::on_mediaSeek(int value)
{
mutex.lock();
la_seekPos = value;
mutex.unlock();
}
void DecoderThread::setFilename(QString filename)
{
this->filename = filename;
}
/**
* @brief Open a virtual connection to remote client
*
* @return 0 on success, -1 on failure
******************************************************************************/
int DecoderThread::openVirtualChannel()
{
/* is channel already open? */
if (channel)
return -1;
/* open a virtual channel and connect to remote client */
channel = WTSVirtualChannelOpenEx(WTS_CURRENT_SESSION, "xrdpvr", 0);
if (channel == NULL)
{
emit on_decoderErrorMsg("Connection failure",
"Error connecting to remote client");
return -1;
}
return 0;
}
int DecoderThread::closeVirtualChannel()
{
/* channel must be opened first */
if (!channel)
return -1;
WTSVirtualChannelClose(channel);
return 0;
}
/**
* @brief this is a temp hack while we figure out how to set up the right
* context for avcodec_decode_video2() on the server side; the workaround
* is to send the first 1MB of the media file to the server end which
* reads this file and sets up its context
*
* @return 0 on success, -1 on failure
******************************************************************************/
int DecoderThread::sendMetadataFile()
{
if (xrdpvr_create_metadata_file(channel, filename.toAscii().data()))
{
emit on_decoderErrorMsg("I/O Error",
"An error occurred while sending data to remote client");
return -1;
}
return 0;
}
int DecoderThread::sendVideoFormat()
{
if (xrdpvr_set_video_format(channel, stream_id))
{
emit on_decoderErrorMsg("I/O Error",
"Error sending video format to remote client");
return -1;
}
return 0;
}
int DecoderThread::sendAudioFormat()
{
if (xrdpvr_set_audio_format(channel, stream_id))
{
emit on_decoderErrorMsg("I/O Error",
"Error sending audio format to remote client");
return -1;
}
return 0;
}
int DecoderThread::sendGeometry()
{
int rv;
rv = xrdpvr_set_geometry(channel, stream_id, geometry.x(), geometry.y(),
geometry.width(), geometry.height());
if (rv)
{
emit on_decoderErrorMsg("I/O Error",
"Error sending screen geometry to remote client");
return -1;
}
return 0;
}