// not used #include "decoderthread.h" /* * TODO: * o need to maintain aspect ratio while resizing * o clicking in the middle of the slider bar should 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() { channel = NULL; geometry.setX(0); geometry.setY(0); geometry.setWidth(0); geometry.setHeight(0); stream_id = 101; elapsedTime = 0; la_seekPos = -1; videoTimer = NULL; audioTimer = NULL; } void DecoderThread::run() { /* need a media file */ if (filename.length() == 0) { emit on_decoderErrorMsg("No media file", "Please select a media file to play"); return; } } 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) { /* 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); //videoTimer->start(1500); //audioTimer->start(500); playVideo = new PlayVideo(NULL, &videoQueue, channel, 101); playVideoThread = new QThread(this); connect(playVideoThread, SIGNAL(started()), playVideo, SLOT(play())); playVideo->moveToThread(playVideoThread); playVideoThread->start(); playAudio = new PlayAudio(NULL, &audioQueue, channel, 101); playAudioThread = new QThread(this); connect(playAudioThread, SIGNAL(started()), playAudio, SLOT(play())); playAudio->moveToThread(playAudioThread); playAudioThread->start(); return; } 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 */ break; } if (is_video_frame) videoQueue.enqueue(mediaPkt); else audioQueue.enqueue(mediaPkt); } /* end while (1) */ } 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) { this->filename = filename; } void DecoderThread::stopPlayer() { pktTimer->stop(); audioQueue.clear(); videoQueue.clear(); } void DecoderThread::pausePlayer() { pktTimer->stop(); } void DecoderThread::resumePlayer() { pktTimer->start(100); } void DecoderThread::close() { } void DecoderThread::audioTimerCallback() { MediaPacket *pkt; int delayInMs; if (audioQueue.isEmpty()) { qDebug() << "audioTimerCallback: got empty"; audioTimer->setInterval(100); return; } 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); } void DecoderThread::videoTimerCallback() { MediaPacket *pkt; int delayInMs; if (videoQueue.isEmpty()) { qDebug() << "videoTimerCallback: GOT EMPTY"; videoTimer->setInterval(100); return; } pkt = videoQueue.dequeue(); delayInMs = (int) 10; // ((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); } void DecoderThread::pktTimerCallback() { MediaPacket *mediaPkt; int is_video_frame; int rv; while (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; } if (is_video_frame) videoQueue.enqueue(mediaPkt); else audioQueue.enqueue(mediaPkt); } } void DecoderThread::updateSlider() { 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 >= 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(); }