parent
d1fc67102a
commit
cae2adb75e
@ -0,0 +1,116 @@
|
||||
#include "demuxmedia.h"
|
||||
|
||||
DemuxMedia::DemuxMedia(QObject *parent, QQueue<MediaPacket *> *audioQueue,
|
||||
QQueue<MediaPacket *> *videoQueue, void *channel, int stream_id) :
|
||||
QObject(parent)
|
||||
{
|
||||
this->audioQueue = audioQueue;
|
||||
this->videoQueue = videoQueue;
|
||||
this->channel = channel;
|
||||
this->stream_id = stream_id;
|
||||
this->threadsStarted = false;
|
||||
this->vcrFlag = 0;
|
||||
|
||||
playAudio = new PlayAudio(NULL, audioQueue, &sendMutex, channel, 101);
|
||||
playAudioThread = new QThread(this);
|
||||
connect(playAudioThread, SIGNAL(started()), playAudio, SLOT(play()));
|
||||
playAudio->moveToThread(playAudioThread);
|
||||
|
||||
playVideo = new PlayVideo(NULL, videoQueue, &sendMutex, channel, 101);
|
||||
playVideoThread = new QThread(this);
|
||||
connect(playVideoThread, SIGNAL(started()), playVideo, SLOT(play()));
|
||||
playVideo->moveToThread(playVideoThread);
|
||||
}
|
||||
|
||||
void DemuxMedia::setVcrOp(int op)
|
||||
{
|
||||
vcrMutex.lock();
|
||||
vcrFlag = op;
|
||||
vcrMutex.unlock();
|
||||
|
||||
if (playVideo)
|
||||
playVideo->setVcrOp(op);
|
||||
|
||||
if (playAudio)
|
||||
playAudio->setVcrOp(op);
|
||||
}
|
||||
|
||||
void DemuxMedia::startDemuxing()
|
||||
{
|
||||
MediaPacket *mediaPkt;
|
||||
int is_video_frame;
|
||||
int rv;
|
||||
|
||||
if ((audioQueue == NULL) || (videoQueue == NULL))
|
||||
return;
|
||||
|
||||
while (1)
|
||||
{
|
||||
vcrMutex.lock();
|
||||
switch (vcrFlag)
|
||||
{
|
||||
case VCR_PLAY:
|
||||
vcrFlag = 0;
|
||||
vcrMutex.unlock();
|
||||
continue;
|
||||
break;
|
||||
|
||||
case VCR_PAUSE:
|
||||
vcrMutex.unlock();
|
||||
usleep(1000 * 100);
|
||||
continue;
|
||||
break;
|
||||
|
||||
case VCR_STOP:
|
||||
vcrMutex.unlock();
|
||||
usleep(1000 * 100);
|
||||
continue;
|
||||
break;
|
||||
|
||||
default:
|
||||
vcrMutex.unlock();
|
||||
break;
|
||||
}
|
||||
|
||||
if ((audioQueue->count() >= 20) || (videoQueue->count() >= 20))
|
||||
{
|
||||
if (!threadsStarted)
|
||||
startAudioVideoThreads();
|
||||
|
||||
usleep(1000 * 20);
|
||||
}
|
||||
|
||||
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 */
|
||||
delete mediaPkt;
|
||||
usleep(1000 * 100);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (is_video_frame)
|
||||
videoQueue->enqueue(mediaPkt);
|
||||
else
|
||||
audioQueue->enqueue(mediaPkt);
|
||||
|
||||
} /* end while (1) */
|
||||
}
|
||||
|
||||
PlayVideo * DemuxMedia::getPlayVideoInstance()
|
||||
{
|
||||
return this->playVideo;
|
||||
}
|
||||
|
||||
void DemuxMedia::startAudioVideoThreads()
|
||||
{
|
||||
if (threadsStarted)
|
||||
return;
|
||||
|
||||
playVideoThread->start();
|
||||
playAudioThread->start();
|
||||
threadsStarted = true;
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
#ifndef DEMUXMEDIA_H
|
||||
#define DEMUXMEDIA_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define __STDC_CONSTANT_MACROS
|
||||
#ifdef _STDINT_H
|
||||
#undef _STDINT_H
|
||||
#endif
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#include <QObject>
|
||||
#include <QQueue>
|
||||
#include <QThread>
|
||||
#include <QMutex>
|
||||
#include <QDebug>
|
||||
|
||||
#include "mediapacket.h"
|
||||
#include "playaudio.h"
|
||||
#include "playvideo.h"
|
||||
|
||||
/* ffmpeg related stuff */
|
||||
extern "C"
|
||||
{
|
||||
#include <libavformat/avformat.h>
|
||||
#include <libavcodec/avcodec.h>
|
||||
}
|
||||
|
||||
#define VCR_PLAY 1
|
||||
#define VCR_PAUSE 2
|
||||
#define VCR_STOP 3
|
||||
#define VCR_REWIND 4
|
||||
#define VCR_POWER_OFF 5
|
||||
|
||||
class DemuxMedia : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit DemuxMedia(QObject *parent = 0, QQueue<MediaPacket *> *audioQueue = 0,
|
||||
QQueue<MediaPacket *> *videoQueue = 0, void *channel = 0, int stream_id = 101);
|
||||
|
||||
void setVcrOp(int op);
|
||||
|
||||
public slots:
|
||||
void startDemuxing();
|
||||
PlayVideo *getPlayVideoInstance();
|
||||
|
||||
private:
|
||||
QQueue<MediaPacket *> *audioQueue;
|
||||
QQueue<MediaPacket *> *videoQueue;
|
||||
QMutex vcrMutex;
|
||||
int vcrFlag;
|
||||
void *channel;
|
||||
PlayVideo *playVideo;
|
||||
QThread *playVideoThread;
|
||||
PlayAudio *playAudio;
|
||||
QThread *playAudioThread;
|
||||
int stream_id;
|
||||
bool threadsStarted;
|
||||
QMutex sendMutex;
|
||||
|
||||
void startAudioVideoThreads();
|
||||
};
|
||||
|
||||
#endif // DEMUXMEDIA_H
|
@ -0,0 +1,5 @@
|
||||
#include "mediapacket.h"
|
||||
|
||||
MediaPacket::MediaPacket()
|
||||
{
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
#ifndef MEDIAPACKET_H
|
||||
#define MEDIAPACKET_H
|
||||
|
||||
class MediaPacket
|
||||
{
|
||||
public:
|
||||
MediaPacket();
|
||||
|
||||
void *av_pkt;
|
||||
int delay_in_us;
|
||||
int seq;
|
||||
};
|
||||
|
||||
#endif // MEDIAPACKET_H
|
@ -0,0 +1,219 @@
|
||||
#include "ourinterface.h"
|
||||
|
||||
OurInterface::OurInterface(QObject *parent) :
|
||||
QObject(parent)
|
||||
{
|
||||
channel = NULL;
|
||||
savedGeometry.setX(0);
|
||||
savedGeometry.setY(0);
|
||||
savedGeometry.setWidth(0);
|
||||
savedGeometry.setHeight(0);
|
||||
stream_id = 101;
|
||||
demuxMedia = 0;
|
||||
//elapsedTime = 0;
|
||||
}
|
||||
|
||||
int OurInterface::oneTimeInit()
|
||||
{
|
||||
/* connect to remote client */
|
||||
if (openVirtualChannel())
|
||||
return -1;
|
||||
|
||||
/* register all formats/codecs */
|
||||
av_register_all();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void OurInterface::oneTimeDeinit()
|
||||
{
|
||||
/* clean up resources */
|
||||
closeVirtualChannel();
|
||||
}
|
||||
|
||||
void OurInterface::initRemoteClient()
|
||||
{
|
||||
int64_t start_time;
|
||||
int64_t duration;
|
||||
|
||||
//elapsedTime = 0;
|
||||
|
||||
if (sendMetadataFile())
|
||||
return;
|
||||
|
||||
if (sendVideoFormat())
|
||||
return;
|
||||
|
||||
if (sendAudioFormat())
|
||||
return;
|
||||
|
||||
if (sendGeometry(savedGeometry))
|
||||
return;
|
||||
|
||||
xrdpvr_play_media(channel, 101, filename.toAscii().data());
|
||||
|
||||
xrdpvr_get_media_duration(&start_time, &duration);
|
||||
qDebug() << "ourInterface:initRemoteClient: emit onMediaDurationInSecs: dur=" << duration;
|
||||
emit onMediaDurationInSeconds(duration);
|
||||
|
||||
/* LK_TODO this needs to be undone in deinitRemoteClient() */
|
||||
if (!demuxMedia)
|
||||
{
|
||||
demuxMedia = new DemuxMedia(NULL, &audioQueue, &videoQueue, channel, stream_id);
|
||||
demuxMediaThread = new QThread(this);
|
||||
connect(demuxMediaThread, SIGNAL(started()), demuxMedia, SLOT(startDemuxing()));
|
||||
demuxMedia->moveToThread(demuxMediaThread);
|
||||
playVideo = demuxMedia->getPlayVideoInstance();
|
||||
}
|
||||
}
|
||||
|
||||
void OurInterface::deInitRemoteClient()
|
||||
{
|
||||
/* perform clean up */
|
||||
xrdpvr_deinit_player(channel, 101);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Open a virtual connection to remote client
|
||||
*
|
||||
* @return 0 on success, -1 on failure
|
||||
******************************************************************************/
|
||||
int OurInterface::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_ErrorMsg("Connection failure",
|
||||
"Error connecting to remote client. Application will close now");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int OurInterface::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 OurInterface::sendMetadataFile()
|
||||
{
|
||||
if (xrdpvr_create_metadata_file(channel, filename.toAscii().data()))
|
||||
{
|
||||
emit on_ErrorMsg("I/O Error",
|
||||
"An error occurred while sending data to remote client");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int OurInterface::sendVideoFormat()
|
||||
{
|
||||
if (xrdpvr_set_video_format(channel, stream_id))
|
||||
{
|
||||
emit on_ErrorMsg("I/O Error",
|
||||
"Error sending video format to remote client");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int OurInterface::sendAudioFormat()
|
||||
{
|
||||
if (xrdpvr_set_audio_format(channel, stream_id))
|
||||
{
|
||||
emit on_ErrorMsg("I/O Error",
|
||||
"Error sending audio format to remote client");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int OurInterface::sendGeometry(QRect rect)
|
||||
{
|
||||
int rv;
|
||||
|
||||
savedGeometry.setX(rect.x());
|
||||
savedGeometry.setY(rect.y());
|
||||
savedGeometry.setWidth(rect.width());
|
||||
savedGeometry.setHeight(rect.height());
|
||||
|
||||
rv = xrdpvr_set_geometry(channel, stream_id, savedGeometry.x(),
|
||||
savedGeometry.y(), savedGeometry.width(),
|
||||
savedGeometry.height());
|
||||
|
||||
if (rv)
|
||||
{
|
||||
emit on_ErrorMsg("I/O Error",
|
||||
"Error sending screen geometry to remote client");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void OurInterface::onGeometryChanged(int x, int y, int width, int height)
|
||||
{
|
||||
savedGeometry.setX(x);
|
||||
savedGeometry.setY(y);
|
||||
savedGeometry.setWidth(width);
|
||||
savedGeometry.setHeight(height);
|
||||
|
||||
#if 1
|
||||
qDebug() << "OurInterface:signal" <<
|
||||
"" << savedGeometry.x() <<
|
||||
"" << savedGeometry.y() <<
|
||||
"" << savedGeometry.width() <<
|
||||
"" << savedGeometry.height();
|
||||
#endif
|
||||
|
||||
qDebug() << "setting geometry:channel=" << channel;
|
||||
|
||||
if (channel)
|
||||
{
|
||||
xrdpvr_set_geometry(channel, 101, savedGeometry.x(), savedGeometry.y(),
|
||||
savedGeometry.width(), savedGeometry.height());
|
||||
}
|
||||
}
|
||||
|
||||
void OurInterface::setFilename(QString filename)
|
||||
{
|
||||
this->filename = filename;
|
||||
}
|
||||
|
||||
void OurInterface::playMedia()
|
||||
{
|
||||
demuxMediaThread->start();
|
||||
}
|
||||
|
||||
PlayVideo * OurInterface::getPlayVideoInstance()
|
||||
{
|
||||
return this->playVideo;
|
||||
}
|
||||
|
||||
void OurInterface::setVcrOp(int op)
|
||||
{
|
||||
if (demuxMedia)
|
||||
demuxMedia->setVcrOp(op);
|
||||
}
|
@ -0,0 +1,75 @@
|
||||
#ifndef OURINTERFACE_H
|
||||
#define OURINTERFACE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define __STDC_CONSTANT_MACROS
|
||||
#ifdef _STDINT_H
|
||||
#undef _STDINT_H
|
||||
#endif
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#include <QObject>
|
||||
#include <QRect>
|
||||
#include <QDebug> // LK_TODO
|
||||
|
||||
#include "xrdpvr.h"
|
||||
#include "xrdpapi.h"
|
||||
#include "demuxmedia.h"
|
||||
#include "playvideo.h"
|
||||
|
||||
/* ffmpeg related stuff */
|
||||
extern "C"
|
||||
{
|
||||
#include <libavformat/avformat.h>
|
||||
#include <libavcodec/avcodec.h>
|
||||
}
|
||||
|
||||
class OurInterface : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit OurInterface(QObject *parent = 0);
|
||||
|
||||
/* public methods */
|
||||
int oneTimeInit();
|
||||
void oneTimeDeinit();
|
||||
void initRemoteClient();
|
||||
void deInitRemoteClient();
|
||||
int sendGeometry(QRect rect);
|
||||
void setFilename(QString filename);
|
||||
void playMedia();
|
||||
PlayVideo *getPlayVideoInstance();
|
||||
void setVcrOp(int op);
|
||||
|
||||
public slots:
|
||||
void onGeometryChanged(int x, int y, int width, int height);
|
||||
|
||||
signals:
|
||||
void on_ErrorMsg(QString title, QString msg);
|
||||
void onMediaDurationInSeconds(int duration);
|
||||
|
||||
private:
|
||||
|
||||
/* private stuff */
|
||||
QQueue<MediaPacket *> audioQueue;
|
||||
QQueue<MediaPacket *> videoQueue;
|
||||
|
||||
DemuxMedia *demuxMedia;
|
||||
QThread *demuxMediaThread;
|
||||
PlayVideo *playVideo;
|
||||
QString filename;
|
||||
void *channel;
|
||||
int stream_id;
|
||||
QRect savedGeometry;
|
||||
|
||||
/* private methods */
|
||||
int openVirtualChannel();
|
||||
int closeVirtualChannel();
|
||||
int sendMetadataFile();
|
||||
int sendVideoFormat();
|
||||
int sendAudioFormat();
|
||||
};
|
||||
|
||||
#endif // INTERFACE_H
|
@ -0,0 +1,87 @@
|
||||
#include "playaudio.h"
|
||||
#include <QDebug>
|
||||
|
||||
PlayAudio::PlayAudio(QObject *parent,
|
||||
QQueue<MediaPacket *> *audioQueue,
|
||||
QMutex *sendMutex,
|
||||
void *channel,
|
||||
int stream_id) :
|
||||
QObject(parent)
|
||||
{
|
||||
this->audioQueue = audioQueue;
|
||||
this->sendMutex = sendMutex;
|
||||
this->channel = channel;
|
||||
this->stream_id = stream_id;
|
||||
this->vcrFlag = 0;
|
||||
}
|
||||
|
||||
void PlayAudio::play()
|
||||
{
|
||||
MediaPacket *pkt;
|
||||
|
||||
while (1)
|
||||
{
|
||||
vcrMutex.lock();
|
||||
switch (vcrFlag)
|
||||
{
|
||||
case VCR_PLAY:
|
||||
vcrFlag = 0;
|
||||
vcrMutex.unlock();
|
||||
continue;
|
||||
break;
|
||||
|
||||
case VCR_PAUSE:
|
||||
vcrMutex.unlock();
|
||||
usleep(1000 * 100);
|
||||
continue;
|
||||
break;
|
||||
|
||||
case VCR_STOP:
|
||||
vcrMutex.unlock();
|
||||
clearAudioQ();
|
||||
usleep(1000 * 100);
|
||||
continue;
|
||||
break;
|
||||
|
||||
default:
|
||||
vcrMutex.unlock();
|
||||
goto label1;
|
||||
break;
|
||||
}
|
||||
|
||||
label1:
|
||||
|
||||
if (audioQueue->isEmpty())
|
||||
{
|
||||
qDebug() << "PlayAudio::play: GOT EMPTY";
|
||||
usleep(1000 * 100);
|
||||
continue;
|
||||
}
|
||||
|
||||
pkt = audioQueue->dequeue();
|
||||
sendMutex->lock();
|
||||
send_audio_pkt(channel, stream_id, pkt->av_pkt);
|
||||
sendMutex->unlock();
|
||||
delete pkt;
|
||||
usleep(pkt->delay_in_us);
|
||||
}
|
||||
}
|
||||
|
||||
void PlayAudio::setVcrOp(int op)
|
||||
{
|
||||
vcrMutex.lock();
|
||||
this->vcrFlag = op;
|
||||
vcrMutex.unlock();
|
||||
}
|
||||
|
||||
void PlayAudio::clearAudioQ()
|
||||
{
|
||||
MediaPacket *pkt;
|
||||
|
||||
while (!audioQueue->isEmpty())
|
||||
{
|
||||
pkt = audioQueue->dequeue();
|
||||
av_free_packet((AVPacket *) pkt->av_pkt);
|
||||
delete pkt;
|
||||
}
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
#ifndef PLAYAUDIO_H
|
||||
#define PLAYAUDIO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define __STDC_CONSTANT_MACROS
|
||||
#ifdef _STDINT_H
|
||||
#undef _STDINT_H
|
||||
#endif
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#include <QObject>
|
||||
#include <QQueue>
|
||||
#include <QMutex>
|
||||
|
||||
#include "mediapacket.h"
|
||||
#include "xrdpvr.h"
|
||||
|
||||
/* ffmpeg related stuff */
|
||||
extern "C"
|
||||
{
|
||||
#include <libavformat/avformat.h>
|
||||
#include <libavcodec/avcodec.h>
|
||||
}
|
||||
|
||||
#define VCR_PLAY 1
|
||||
#define VCR_PAUSE 2
|
||||
#define VCR_STOP 3
|
||||
#define VCR_REWIND 4
|
||||
#define VCR_POWER_OFF 5
|
||||
|
||||
class PlayAudio : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit PlayAudio(QObject *parent = 0,
|
||||
QQueue<MediaPacket *> *audioQueue = 0,
|
||||
QMutex *sendMutex = 0,
|
||||
void *channel = 0,
|
||||
int stream_id = 101);
|
||||
|
||||
void setVcrOp(int op);
|
||||
|
||||
public slots:
|
||||
void play();
|
||||
|
||||
private:
|
||||
QQueue<MediaPacket *> *audioQueue;
|
||||
QMutex *sendMutex;
|
||||
QMutex vcrMutex;
|
||||
int vcrFlag;
|
||||
void *channel;
|
||||
int stream_id;
|
||||
|
||||
void clearAudioQ();
|
||||
};
|
||||
|
||||
#endif // PLAYAUDIO_H
|
@ -0,0 +1,173 @@
|
||||
#include "playvideo.h"
|
||||
#include <QDebug>
|
||||
|
||||
PlayVideo::PlayVideo(QObject *parent,
|
||||
QQueue<MediaPacket *> *videoQueue,
|
||||
QMutex *sendMutex,
|
||||
void *channel,
|
||||
int stream_id) :
|
||||
QObject(parent)
|
||||
{
|
||||
this->videoQueue = videoQueue;
|
||||
this->channel = channel;
|
||||
this->sendMutex = sendMutex;
|
||||
this->stream_id = stream_id;
|
||||
elapsedTime = 0;
|
||||
pausedTime = 0;
|
||||
la_seekPos = -1;
|
||||
vcrFlag = 0;
|
||||
isStopped = false;
|
||||
}
|
||||
|
||||
void PlayVideo::play()
|
||||
{
|
||||
MediaPacket *pkt;
|
||||
|
||||
while (1)
|
||||
{
|
||||
vcrMutex.lock();
|
||||
switch (vcrFlag)
|
||||
{
|
||||
case VCR_PLAY:
|
||||
vcrFlag = 0;
|
||||
vcrMutex.unlock();
|
||||
if (pausedTime)
|
||||
{
|
||||
elapsedTime = av_gettime() - pausedTime;
|
||||
pausedTime = 0;
|
||||
}
|
||||
isStopped = false;
|
||||
continue;
|
||||
break;
|
||||
|
||||
case VCR_PAUSE:
|
||||
vcrMutex.unlock();
|
||||
if (!pausedTime)
|
||||
{
|
||||
/* save amount of video played so far */
|
||||
pausedTime = av_gettime() - elapsedTime;
|
||||
}
|
||||
usleep(1000 * 100);
|
||||
isStopped = false;
|
||||
continue;
|
||||
break;
|
||||
|
||||
case VCR_STOP:
|
||||
vcrMutex.unlock();
|
||||
if (isStopped)
|
||||
{
|
||||
usleep(1000 * 100);
|
||||
continue;
|
||||
}
|
||||
clearVideoQ();
|
||||
elapsedTime = 0;
|
||||
pausedTime = 0;
|
||||
la_seekPos = -1;
|
||||
xrdpvr_seek_media(0, 0);
|
||||
isStopped = true;
|
||||
continue;
|
||||
break;
|
||||
|
||||
default:
|
||||
vcrMutex.unlock();
|
||||
goto label1;
|
||||
break;
|
||||
}
|
||||
|
||||
label1:
|
||||
|
||||
if (videoQueue->isEmpty())
|
||||
{
|
||||
qDebug() << "PlayVideo::play: GOT EMPTY";
|
||||
usleep(1000 * 100);
|
||||
continue;
|
||||
}
|
||||
|
||||
pkt = videoQueue->dequeue();
|
||||
sendMutex->lock();
|
||||
send_video_pkt(channel, stream_id, pkt->av_pkt);
|
||||
sendMutex->unlock();
|
||||
delete pkt;
|
||||
usleep(pkt->delay_in_us);
|
||||
|
||||
updateMediaPos();
|
||||
|
||||
if (elapsedTime == 0)
|
||||
elapsedTime = av_gettime();
|
||||
|
||||
/* time elapsed in 1/100th sec units since play started */
|
||||
emit onElapsedtime((av_gettime() - elapsedTime) / 10000);
|
||||
}
|
||||
}
|
||||
|
||||
void PlayVideo::onMediaSeek(int value)
|
||||
{
|
||||
posMutex.lock();
|
||||
la_seekPos = value;
|
||||
posMutex.unlock();
|
||||
}
|
||||
|
||||
void PlayVideo::updateMediaPos()
|
||||
{
|
||||
#if 0
|
||||
if (elapsedTime == 0)
|
||||
elapsedTime = av_gettime();
|
||||
|
||||
/* time elapsed in 1/100th sec units since play started */
|
||||
emit onElapsedtime((av_gettime() - elapsedTime) / 10000);
|
||||
#endif
|
||||
|
||||
posMutex.lock();
|
||||
if (la_seekPos >= 0)
|
||||
{
|
||||
qDebug() << "seeking to" << la_seekPos;
|
||||
xrdpvr_seek_media(la_seekPos, 0);
|
||||
elapsedTime = av_gettime() - la_seekPos * 1000000;
|
||||
la_seekPos = -1;
|
||||
}
|
||||
posMutex.unlock();
|
||||
}
|
||||
|
||||
void PlayVideo::setVcrOp(int op)
|
||||
{
|
||||
vcrMutex.lock();
|
||||
this->vcrFlag = op;
|
||||
vcrMutex.unlock();
|
||||
}
|
||||
|
||||
void PlayVideo::clearVideoQ()
|
||||
{
|
||||
MediaPacket *pkt;
|
||||
|
||||
while (!videoQueue->isEmpty())
|
||||
{
|
||||
pkt = videoQueue->dequeue();
|
||||
av_free_packet((AVPacket *) pkt->av_pkt);
|
||||
delete pkt;
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
void DecoderThread::updateSlider()
|
||||
{
|
||||
if (elapsedTime == 0)
|
||||
elapsedTime = av_gettime();
|
||||
|
||||
/* time elapsed in 1/100th sec units since play started */
|
||||
emit onElapsedtime((av_gettime() - elapsedTime) / 10000);
|
||||
|
||||
mutex.lock();
|
||||
if (la_seekPos >= 0)
|
||||
{
|
||||
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;
|
||||
}
|
||||
mutex.unlock();
|
||||
}
|
||||
#endif
|
@ -0,0 +1,71 @@
|
||||
#ifndef PLAYVIDEO_H
|
||||
#define PLAYVIDEO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define __STDC_CONSTANT_MACROS
|
||||
#ifdef _STDINT_H
|
||||
#undef _STDINT_H
|
||||
#endif
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#include <QObject>
|
||||
#include <QQueue>
|
||||
#include <QMutex>
|
||||
|
||||
#include "mediapacket.h"
|
||||
#include "xrdpvr.h"
|
||||
#include "xrdpapi.h"
|
||||
|
||||
/* ffmpeg related stuff */
|
||||
extern "C"
|
||||
{
|
||||
#include <libavformat/avformat.h>
|
||||
#include <libavcodec/avcodec.h>
|
||||
}
|
||||
|
||||
#define VCR_PLAY 1
|
||||
#define VCR_PAUSE 2
|
||||
#define VCR_STOP 3
|
||||
#define VCR_REWIND 4
|
||||
#define VCR_POWER_OFF 5
|
||||
|
||||
class PlayVideo : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit PlayVideo(QObject *parent = 0,
|
||||
QQueue<MediaPacket *> *videoQueue = 0,
|
||||
QMutex *sendMutex = 0,
|
||||
void *channel = 0,
|
||||
int stream_id = 101);
|
||||
|
||||
void onMediaSeek(int value);
|
||||
void setVcrOp(int op);
|
||||
|
||||
public slots:
|
||||
void play();
|
||||
|
||||
signals:
|
||||
void onElapsedtime(int val); /* in hundredth of a sec */
|
||||
|
||||
private:
|
||||
QQueue<MediaPacket *> *videoQueue;
|
||||
|
||||
int vcrFlag;
|
||||
QMutex vcrMutex;
|
||||
QMutex *sendMutex;
|
||||
QMutex posMutex;
|
||||
int64_t la_seekPos; /* locked access; must hold posMutex */
|
||||
void *channel;
|
||||
int stream_id;
|
||||
int64_t elapsedTime; /* elapsed time in usecs since play started */
|
||||
int64_t pausedTime; /* time at which stream was paused */
|
||||
bool isStopped;
|
||||
|
||||
void updateMediaPos();
|
||||
void clearVideoQ();
|
||||
};
|
||||
|
||||
#endif // PLAYVIDEO_H
|
Loading…
Reference in new issue