summaryrefslogtreecommitdiffstats
path: root/vrplayer/decoderthread.cpp
diff options
context:
space:
mode:
authorLaxmikant Rashinkar <lk@maya-vm-64.(none)>2012-12-26 18:48:17 -0800
committerLaxmikant Rashinkar <lk@maya-vm-64.(none)>2012-12-26 18:48:17 -0800
commitcae2adb75e2b339017746436c63f7d2b8c35fb63 (patch)
tree7fa8fc022ef3a52f069332642dc0e9c428c9c94c /vrplayer/decoderthread.cpp
parentd1fc67102a273a8e0b170d0c613cf0d611cfa7f8 (diff)
downloadxrdp-proprietary-cae2adb75e2b339017746436c63f7d2b8c35fb63.tar.gz
xrdp-proprietary-cae2adb75e2b339017746436c63f7d2b8c35fb63.zip
o developer checkin
o modified vrplayer to use threads
Diffstat (limited to 'vrplayer/decoderthread.cpp')
-rw-r--r--vrplayer/decoderthread.cpp307
1 files changed, 168 insertions, 139 deletions
diff --git a/vrplayer/decoderthread.cpp b/vrplayer/decoderthread.cpp
index 2ee7a524..e31b1aa3 100644
--- a/vrplayer/decoderthread.cpp
+++ b/vrplayer/decoderthread.cpp
@@ -1,8 +1,17 @@
#include "decoderthread.h"
+/*
+ * TODO:
+ * o need to maintain aspect ratio while resizing
+ * o clicking in the middle of the slider bar shuld move the slider to the middle
+ * o need to be able to rewind the move when it is done playing
+ * o need to be able to load another move and play it w/o restarting player
+ * o pause button needs to work
+ * o need images for btns
+ */
+
DecoderThread::DecoderThread()
{
- vsi = NULL;
channel = NULL;
geometry.setX(0);
geometry.setY(0);
@@ -10,16 +19,13 @@ DecoderThread::DecoderThread()
geometry.setHeight(0);
stream_id = 101;
elapsedTime = 0;
- la_seekPos = 0;
+ la_seekPos = -1;
+ videoTimer = NULL;
+ audioTimer = NULL;
}
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)
{
@@ -27,89 +33,72 @@ void DecoderThread::run()
"Please select a media file to play");
return;
}
+}
- /* connect to remote client */
- if (openVirtualChannel())
- return;
-
- vsi = (VideoStateInfo *) av_mallocz(sizeof(VideoStateInfo));
- if (vsi == NULL)
+void DecoderThread::startMediaPlay()
+{
+ MediaPacket *mediaPkt;
+ int is_video_frame;
+ int rv;
+
+ /* setup video timer; each time this timer fires, it sends */
+ /* one video pkt to the client then resets the callback duration */
+ videoTimer = new QTimer;
+ connect(videoTimer, SIGNAL(timeout()), this, SLOT(videoTimerCallback()));
+ //videoTimer->start(1500);
+
+ /* setup audio timer; does the same as above, but with audio pkts */
+ audioTimer = new QTimer;
+ connect(audioTimer, SIGNAL(timeout()), this, SLOT(audioTimerCallback()));
+ //audioTimer->start(500);
+
+ /* setup pktTimer; each time this timer fires, it reads AVPackets */
+ /* and puts them into audio/video Queues */
+ pktTimer = new QTimer;
+ connect(pktTimer, SIGNAL(timeout()), this, SLOT(pktTimerCallback()));
+
+ while (1)
{
- 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());
+ /* fill the audio/video queues with initial data; thereafter */
+ /* data will be filled by pktTimerCallback() */
+ if ((audioQueue.count() >= 3000) || (videoQueue.count() >= 3000))
+ {
+ //pktTimer->start(50);
- xrdpvr_get_media_duration(&start_time, &duration);
- emit on_mediaDurationInSeconds(duration);
+ //videoTimer->start(1500);
+ //audioTimer->start(500);
- qDebug() << "start_time=" << start_time << " duration=" << duration;
+ playVideo = new PlayVideo(NULL, &videoQueue, channel, 101);
+ playVideoThread = new QThread(this);
+ connect(playVideoThread, SIGNAL(started()), playVideo, SLOT(play()));
+ playVideo->moveToThread(playVideoThread);
+ playVideoThread->start();
- while (xrdpvr_play_frame(channel, 101) == 0)
- {
- if (elapsedTime == 0)
- elapsedTime = av_gettime();
+ playAudio = new PlayAudio(NULL, &audioQueue, channel, 101);
+ playAudioThread = new QThread(this);
+ connect(playAudioThread, SIGNAL(started()), playAudio, SLOT(play()));
+ playAudio->moveToThread(playAudioThread);
+ playAudioThread->start();
- /* time elapsed in 1/100th sec units since play started */
- emit on_elapsedtime((av_gettime() - elapsedTime) / 10000);
+ return;
+ }
- mutex.lock();
- if (la_seekPos)
+ mediaPkt = new MediaPacket;
+ rv = xrdpvr_get_frame(&mediaPkt->av_pkt,
+ &is_video_frame,
+ &mediaPkt->delay_in_us);
+ if (rv < 0)
{
- qDebug() << "seeking to" << la_seekPos;
- xrdpvr_seek_media(la_seekPos, 0);
- elapsedTime = av_gettime() - la_seekPos * 1000000;
- la_seekPos = 0;
+ /* looks like we reached end of file */
+ break;
}
- 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 (is_video_frame)
+ videoQueue.enqueue(mediaPkt);
+ else
+ audioQueue.enqueue(mediaPkt);
- if (channel)
- {
- xrdpvr_set_geometry(channel, 101, geometry.x(), geometry.y(),
- geometry.width(), geometry.height());
- }
+ } /* end while (1) */
}
void DecoderThread::on_mediaSeek(int value)
@@ -117,6 +106,15 @@ void DecoderThread::on_mediaSeek(int value)
mutex.lock();
la_seekPos = value;
mutex.unlock();
+
+ qDebug() << "media seek value=" << value;
+
+ /* pktTimer stops at end of media; need to restart it */
+ if (!pktTimer->isActive())
+ {
+ updateSlider();
+ pktTimer->start(100);
+ }
}
void DecoderThread::setFilename(QString filename)
@@ -124,94 +122,125 @@ 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()
+void DecoderThread::stopPlayer()
{
- /* is channel already open? */
- if (channel)
- return -1;
+ pktTimer->stop();
+ audioQueue.clear();
+ videoQueue.clear();
+}
- /* 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;
+void DecoderThread::pausePlayer()
+{
+ pktTimer->stop();
}
-int DecoderThread::closeVirtualChannel()
+void DecoderThread::resumePlayer()
{
- /* channel must be opened first */
- if (!channel)
- return -1;
+ pktTimer->start(100);
+}
- WTSVirtualChannelClose(channel);
- return 0;
+void DecoderThread::close()
+{
}
-/**
- * @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()
+void DecoderThread::audioTimerCallback()
{
- if (xrdpvr_create_metadata_file(channel, filename.toAscii().data()))
+ MediaPacket *pkt;
+ int delayInMs;
+
+ if (audioQueue.isEmpty())
{
- emit on_decoderErrorMsg("I/O Error",
- "An error occurred while sending data to remote client");
- return -1;
+ qDebug() << "audioTimerCallback: got empty";
+ audioTimer->setInterval(100);
+ return;
}
- return 0;
+ pkt = audioQueue.dequeue();
+ delayInMs = (int) ((float) pkt->delay_in_us / 1000.0);
+ send_audio_pkt(channel, 101, pkt->av_pkt);
+ delete pkt;
+
+ //qDebug() << "audioTimerCallback: delay :" << delayInMs;
+
+ audioTimer->setInterval(delayInMs);
}
-int DecoderThread::sendVideoFormat()
+void DecoderThread::videoTimerCallback()
{
- if (xrdpvr_set_video_format(channel, stream_id))
+ MediaPacket *pkt;
+ int delayInMs;
+
+ if (videoQueue.isEmpty())
{
- emit on_decoderErrorMsg("I/O Error",
- "Error sending video format to remote client");
- return -1;
+ qDebug() << "videoTimerCallback: GOT EMPTY";
+ videoTimer->setInterval(100);
+ return;
}
- return 0;
+ pkt = videoQueue.dequeue();
+ delayInMs = (int) ((float) pkt->delay_in_us / 1000.0);
+ send_video_pkt(channel, 101, pkt->av_pkt);
+ delete pkt;
+ updateSlider();
+ //qDebug() << "videoTimerCallback: delay :" << delayInMs;
+ videoTimer->setInterval(delayInMs);
}
-int DecoderThread::sendAudioFormat()
+void DecoderThread::pktTimerCallback()
{
- if (xrdpvr_set_audio_format(channel, stream_id))
+ MediaPacket *mediaPkt;
+ int is_video_frame;
+ int rv;
+
+ while (1)
{
- emit on_decoderErrorMsg("I/O Error",
- "Error sending audio format to remote client");
- return -1;
- }
+ qDebug() << "pktTimerCallback: audioCount=" << audioQueue.count() << "videoCount=" << videoQueue.count();
+#if 1
+ if ((audioQueue.count() >= 20) || (videoQueue.count() >= 20))
+ return;
+#else
+ if (videoQueue.count() >= 60)
+ return;
+#endif
+ mediaPkt = new MediaPacket;
+ rv = xrdpvr_get_frame(&mediaPkt->av_pkt,
+ &is_video_frame,
+ &mediaPkt->delay_in_us);
+ if (rv < 0)
+ {
+ /* looks like we reached end of file */
+ qDebug() << "###### looks like we reached EOF";
+ pktTimer->stop();
+ // LK_TODO set some flag so audio/video timer also stop when q is empty
+ return;
+ }
- return 0;
+ if (is_video_frame)
+ videoQueue.enqueue(mediaPkt);
+ else
+ audioQueue.enqueue(mediaPkt);
+ }
}
-int DecoderThread::sendGeometry()
+void DecoderThread::updateSlider()
{
- int rv;
+ if (elapsedTime == 0)
+ elapsedTime = av_gettime();
- rv = xrdpvr_set_geometry(channel, stream_id, geometry.x(), geometry.y(),
- geometry.width(), geometry.height());
+ /* time elapsed in 1/100th sec units since play started */
+ emit on_elapsedtime((av_gettime() - elapsedTime) / 10000);
- if (rv)
+ mutex.lock();
+ if (la_seekPos >= 0)
{
- emit on_decoderErrorMsg("I/O Error",
- "Error sending screen geometry to remote client");
- return -1;
+ qDebug() << "seeking to" << la_seekPos;
+ //audioTimer->stop();
+ //videoTimer->stop();
+ xrdpvr_seek_media(la_seekPos, 0);
+ elapsedTime = av_gettime() - la_seekPos * 1000000;
+ //audioTimer->start(10);
+ //videoTimer->start(10);
+ la_seekPos = -1;
}
- return 0;
+ mutex.unlock();
}