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.
218 lines
5.2 KiB
218 lines
5.2 KiB
12 years ago
|
#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;
|
||
|
}
|