diff options
30 files changed, 2140 insertions, 468 deletions
diff --git a/common/arch.h b/common/arch.h index 6a29b0a9..988153c2 100644 --- a/common/arch.h +++ b/common/arch.h @@ -32,6 +32,12 @@ defined(__AIX__) || defined(__PPC__) || defined(__mips__) || \ defined(__ia64__) || defined(__ppc__) || defined(__arm__) #define NEED_ALIGN +#elif defined(__x86__) || defined(__x86_64__) || \ + defined(__AMD64__) || defined(_M_IX86) || \ + defined(__i386__) +#define NO_NEED_ALIGN +#else +#warning unknown arch #endif #endif @@ -62,6 +68,8 @@ #define EXPORT_CC #endif +#ifndef DEFINED_Ts +#define DEFINED_Ts typedef char ti8; typedef unsigned char tui8; typedef signed char tsi8; @@ -94,5 +102,6 @@ typedef int tsock; typedef unsigned long long tui64; typedef signed long long tsi64; #endif +#endif #endif diff --git a/libxrdp/xrdp_mppc_enc.c b/libxrdp/xrdp_mppc_enc.c index 05aa6bb6..15125d54 100644 --- a/libxrdp/xrdp_mppc_enc.c +++ b/libxrdp/xrdp_mppc_enc.c @@ -573,18 +573,21 @@ compress_rdp_5(struct xrdp_mppc_enc *enc, tui8 *srcData, int len) outputBuffer = enc->outputBuffer; g_memset(outputBuffer, 0, len); enc->flags = PACKET_COMPR_TYPE_64K; + if (enc->first_pkt) { enc->first_pkt = 0; enc->flagsHold |= PACKET_AT_FRONT; } - if ((enc->historyOffset + len) > enc->buf_len) + if ((enc->historyOffset + len) >= enc->buf_len) { /* historyBuffer cannot hold srcData - rewind it */ enc->historyOffset = 0; - enc->flagsHold |= PACKET_AT_FRONT; g_memset(hash_table, 0, enc->buf_len * 2); + g_memset(enc->historyBuffer, 0, enc->buf_len); // added + enc->first_pkt = 0; + enc->flagsHold |= PACKET_AT_FRONT; } /* point to next free byte in historyBuffer */ @@ -602,7 +605,7 @@ compress_rdp_5(struct xrdp_mppc_enc *enc, tui8 *srcData, int len) /* first 2 bytes,because minimum LoM is 3 */ if (historyOffset == 0) { - /* encode first two bytes are literals */ + /* encode first two bytes as literals */ for (x = 0; x < 2; x++) { data = *(historyPointer + x); @@ -974,8 +977,14 @@ compress_rdp_5(struct xrdp_mppc_enc *enc, tui8 *srcData, int len) /* give up */ enc->historyOffset = 0; g_memset(hash_table, 0, enc->buf_len * 2); + g_memset(enc->historyBuffer, 0, enc->buf_len); enc->flagsHold |= PACKET_FLUSHED; enc->first_pkt = 1; + + g_memcpy(enc->outputBuffer, srcData, len); + enc->bytes_in_opb = len; + enc->flags = 0x81; + return 1; } else if (opb_index + 1 > len) @@ -984,8 +993,14 @@ compress_rdp_5(struct xrdp_mppc_enc *enc, tui8 *srcData, int len) /* give up */ enc->historyOffset = 0; g_memset(hash_table, 0, enc->buf_len * 2); + g_memset(enc->historyBuffer, 0, enc->buf_len); enc->flagsHold |= PACKET_FLUSHED; enc->first_pkt = 1; + + g_memcpy(enc->outputBuffer, srcData, len); + enc->bytes_in_opb = len; + enc->flags = 0x81; + return 1; } @@ -1000,8 +1015,14 @@ compress_rdp_5(struct xrdp_mppc_enc *enc, tui8 *srcData, int len) /* give up */ enc->historyOffset = 0; g_memset(hash_table, 0, enc->buf_len * 2); + g_memset(enc->historyBuffer, 0, enc->buf_len); enc->flagsHold |= PACKET_FLUSHED; enc->first_pkt = 1; + + g_memcpy(enc->outputBuffer, srcData, len); + enc->bytes_in_opb = len; + enc->flags = 0x81; + return 1; } enc->flags |= PACKET_COMPRESSED; @@ -1011,6 +1032,8 @@ compress_rdp_5(struct xrdp_mppc_enc *enc, tui8 *srcData, int len) enc->flagsHold = 0; DLOG(("\n")); + //g_writeln("compression ratio: %f", (float) len / (float) enc->bytes_in_opb); + return 1; } diff --git a/libxrdp/xrdp_rdp.c b/libxrdp/xrdp_rdp.c index 48deb6e2..7e68ec1f 100644 --- a/libxrdp/xrdp_rdp.c +++ b/libxrdp/xrdp_rdp.c @@ -400,29 +400,26 @@ xrdp_rdp_send_data(struct xrdp_rdp *self, struct stream *s, "tocomplen %d", mppc_enc->flags, mppc_enc->bytes_in_opb, mppc_enc->historyOffset, tocomplen)); - if (mppc_enc->flags & RDP_MPPC_COMPRESSED) - { - clen = mppc_enc->bytes_in_opb + 18; - pdulen = clen; - ctype = mppc_enc->flags; - iso_offset = (int)(s->iso_hdr - s->data); - mcs_offset = (int)(s->mcs_hdr - s->data); - sec_offset = (int)(s->sec_hdr - s->data); - rdp_offset = (int)(s->rdp_hdr - s->data); - - /* outputBuffer has 64 bytes preceding it */ - ls.data = mppc_enc->outputBuffer - (rdp_offset + 18); - ls.p = ls.data + rdp_offset; - ls.end = ls.p + clen; - ls.size = clen; - ls.iso_hdr = ls.data + iso_offset; - ls.mcs_hdr = ls.data + mcs_offset; - ls.sec_hdr = ls.data + sec_offset; - ls.rdp_hdr = ls.data + rdp_offset; - ls.channel_hdr = 0; - ls.next_packet = 0; - s = &ls; - } + clen = mppc_enc->bytes_in_opb + 18; + pdulen = clen; + ctype = mppc_enc->flags; + iso_offset = (int)(s->iso_hdr - s->data); + mcs_offset = (int)(s->mcs_hdr - s->data); + sec_offset = (int)(s->sec_hdr - s->data); + rdp_offset = (int)(s->rdp_hdr - s->data); + + /* outputBuffer has 64 bytes preceding it */ + ls.data = mppc_enc->outputBuffer - (rdp_offset + 18); + ls.p = ls.data + rdp_offset; + ls.end = ls.p + clen; + ls.size = clen; + ls.iso_hdr = ls.data + iso_offset; + ls.mcs_hdr = ls.data + mcs_offset; + ls.sec_hdr = ls.data + sec_offset; + ls.rdp_hdr = ls.data + rdp_offset; + ls.channel_hdr = 0; + ls.next_packet = 0; + s = &ls; } else { diff --git a/sesman/chansrv/chansrv.c b/sesman/chansrv/chansrv.c index 01c6a43d..964c7abc 100644 --- a/sesman/chansrv/chansrv.c +++ b/sesman/chansrv/chansrv.c @@ -647,8 +647,9 @@ process_message_channel_data(struct stream *s) { rv = drdynvc_data_in(s, chan_id, chan_flags, length, total_length); } - else if (chan_id == ((struct xrdp_api_data *) - (g_api_con_trans->callback_data))->chan_id) + else if ((g_api_con_trans != 0) && + (chan_id == ((struct xrdp_api_data *) + (g_api_con_trans->callback_data))->chan_id)) { LOG(10, ("process_message_channel_data length %d total_length %d " "chan_flags 0x%8.8x", length, total_length, chan_flags)); @@ -664,7 +665,7 @@ process_message_channel_data(struct stream *s) if (chan_flags & 2) /* last */ { s_mark_end(ls); - trans_write_copy(g_api_con_trans); + rv = trans_force_write(g_api_con_trans); } } } diff --git a/vrplayer/decoder.cpp b/vrplayer/decoder.cpp index b1741997..10e562e9 100644 --- a/vrplayer/decoder.cpp +++ b/vrplayer/decoder.cpp @@ -13,6 +13,7 @@ Decoder::Decoder(QObject *parent) : *****************************************************************************/ int Decoder::init(QString filename) { + printf("Decoder::init\n"); if (channel) return -1; diff --git a/vrplayer/decoderthread.cpp b/vrplayer/decoderthread.cpp index e31b1aa3..36ba4c85 100644 --- a/vrplayer/decoderthread.cpp +++ b/vrplayer/decoderthread.cpp @@ -1,3 +1,23 @@ + + +// not used + + + + + + + + + + + + + + + + + #include "decoderthread.h" /* @@ -178,7 +198,7 @@ void DecoderThread::videoTimerCallback() } pkt = videoQueue.dequeue(); - delayInMs = (int) ((float) pkt->delay_in_us / 1000.0); + delayInMs = (int) 10; // ((float) pkt->delay_in_us / 1000.0); send_video_pkt(channel, 101, pkt->av_pkt); delete pkt; updateSlider(); diff --git a/vrplayer/demuxmedia.cpp b/vrplayer/demuxmedia.cpp index c6893ceb..0e2091f6 100644 --- a/vrplayer/demuxmedia.cpp +++ b/vrplayer/demuxmedia.cpp @@ -3,26 +3,25 @@ #include "demuxmedia.h" -DemuxMedia::DemuxMedia(QObject *parent, QQueue<MediaPacket *> *audioQueue, - QQueue<MediaPacket *> *videoQueue, void *channel, int stream_id) : - QObject(parent) +DemuxMedia::DemuxMedia(QObject *parent, 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; + this->elapsedTime = 0; + this->la_seekPos = -1; + this->isStopped = 0; + this->pausedTime = 0; + this->videoQueue = videoQueue; - 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); + playVideo = new PlayVideo(NULL, videoQueue, &sendMutex, channel, 101, 24); playVideoThread = new QThread(this); connect(playVideoThread, SIGNAL(started()), playVideo, SLOT(play())); playVideo->moveToThread(playVideoThread); + + playVideoThread->start(); + } void DemuxMedia::setVcrOp(int op) @@ -30,12 +29,6 @@ void DemuxMedia::setVcrOp(int op) vcrMutex.lock(); vcrFlag = op; vcrMutex.unlock(); - - if (playVideo) - playVideo->setVcrOp(op); - - if (playAudio) - playAudio->setVcrOp(op); } void DemuxMedia::startDemuxing() @@ -44,9 +37,6 @@ void DemuxMedia::startDemuxing() int is_video_frame; int rv; - if ((audioQueue == NULL) || (videoQueue == NULL)) - return; - while (1) { vcrMutex.lock(); @@ -55,18 +45,40 @@ void DemuxMedia::startDemuxing() 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(); - usleep(1000 * 100); + + if (isStopped) + { + usleep(1000 * 100); + continue; + } + elapsedTime = 0; + pausedTime = 0; + la_seekPos = -1; + xrdpvr_seek_media(0, 0); + isStopped = true; continue; break; @@ -75,14 +87,6 @@ void DemuxMedia::startDemuxing() 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, @@ -91,31 +95,61 @@ void DemuxMedia::startDemuxing() { /* looks like we reached end of file */ delete mediaPkt; - playVideo->onMediaRestarted(); usleep(1000 * 100); xrdpvr_seek_media(0, 0); + this->elapsedTime = 0; continue; } if (is_video_frame) + { + sendMutex.lock(); +#if 1 videoQueue->enqueue(mediaPkt); +#else + send_video_pkt(channel, stream_id, mediaPkt->av_pkt); + delete mediaPkt; +#endif + sendMutex.unlock(); + } else - audioQueue->enqueue(mediaPkt); + { + int frame; + sendMutex.lock(); + send_audio_pkt(channel, stream_id, mediaPkt->av_pkt); + sendMutex.unlock(); + xrdpvr_read_ack(channel, &frame); + delete mediaPkt; + } + + updateMediaPos(); + if (elapsedTime == 0) + { + elapsedTime = av_gettime(); + } + + /* time elapsed in 1/100th sec units since play started */ + emit onElapsedtime((av_gettime() - elapsedTime) / 10000); + } /* end while (1) */ } -PlayVideo * DemuxMedia::getPlayVideoInstance() +void DemuxMedia::onMediaSeek(int value) { - return this->playVideo; + posMutex.lock(); + la_seekPos = value; + posMutex.unlock(); } -void DemuxMedia::startAudioVideoThreads() +void DemuxMedia::updateMediaPos() { - if (threadsStarted) - return; - - playVideoThread->start(); - playAudioThread->start(); - threadsStarted = true; + posMutex.lock(); + if (la_seekPos >= 0) + { + xrdpvr_seek_media(la_seekPos, 0); + elapsedTime = av_gettime() - la_seekPos * 1000000; + la_seekPos = -1; + } + posMutex.unlock(); } diff --git a/vrplayer/demuxmedia.h b/vrplayer/demuxmedia.h index b83a8857..0b3935d7 100644 --- a/vrplayer/demuxmedia.h +++ b/vrplayer/demuxmedia.h @@ -37,33 +37,39 @@ 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); + explicit DemuxMedia(QObject *parent = 0, QQueue<MediaPacket *> *videoQueue = 0, + void *channel = 0, int stream_id = 101); void setVcrOp(int op); public slots: void startDemuxing(); - PlayVideo *getPlayVideoInstance(); + void onMediaSeek(int value); private: - QQueue<MediaPacket *> *audioQueue; + QMutex vcrMutex; + int vcrFlag; + void *channel; + int stream_id; + QMutex sendMutex; + QMutex posMutex; + int64_t elapsedTime; /* elapsed time in usecs since play started */ + int64_t pausedTime; /* time at which stream was paused */ + int64_t la_seekPos; /* locked access; must hold posMutex */ + bool isStopped; + 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(); + void updateMediaPos(); signals: void onMediaRestarted(); + +signals: + void onElapsedtime(int val); /* in hundredth of a sec */ + }; #endif // DEMUXMEDIA_H diff --git a/vrplayer/dlgabout.ui b/vrplayer/dlgabout.ui index 8b2c38e5..beb5d837 100644 --- a/vrplayer/dlgabout.ui +++ b/vrplayer/dlgabout.ui @@ -23,7 +23,7 @@ </rect> </property> <property name="text"> - <string>VRPlayer v1.2</string> + <string>VRPlayer v1.4</string> </property> </widget> <widget class="QPushButton" name="okButton"> diff --git a/vrplayer/main.cpp b/vrplayer/main.cpp index d951345f..5e4821ab 100644 --- a/vrplayer/main.cpp +++ b/vrplayer/main.cpp @@ -1,11 +1,12 @@ + #include <QtGui/QApplication> #include "mainwindow.h" int main(int argc, char *argv[]) { + QApplication::setGraphicsSystem(QLatin1String("native")); QApplication a(argc, argv); MainWindow w; w.show(); - return a.exec(); } diff --git a/vrplayer/mainwindow.cpp b/vrplayer/mainwindow.cpp index 1782f710..0ce04674 100644 --- a/vrplayer/mainwindow.cpp +++ b/vrplayer/mainwindow.cpp @@ -66,8 +66,8 @@ MainWindow::~MainWindow() { delete ui; - if (moveResizeTimer) - delete moveResizeTimer; + //if (moveResizeTimer) + // delete moveResizeTimer; } void MainWindow::closeEvent(QCloseEvent *event) @@ -86,56 +86,56 @@ void MainWindow::closeEvent(QCloseEvent *event) void MainWindow::resizeEvent(QResizeEvent *) { - if (vcrFlag != VCR_PLAY) + //if (vcrFlag != VCR_PLAY) { QRect rect; getVdoGeometry(&rect); interface->sendGeometry(rect); - return; + //return; } - interface->setVcrOp(VCR_PAUSE); - vcrFlag = VCR_PAUSE; - - if (!moveResizeTimer) - { - moveResizeTimer = new QTimer; - connect(moveResizeTimer, SIGNAL(timeout()), - this, SLOT(onMoveCompleted())); - } - lblVideo->setStyleSheet("QLabel { background-color : black; color : blue; }"); - moveResizeTimer->start(1000); + //interface->setVcrOp(VCR_PAUSE); + //vcrFlag = VCR_PAUSE; + + //if (!moveResizeTimer) + //{ + // moveResizeTimer = new QTimer; + // connect(moveResizeTimer, SIGNAL(timeout()), + // this, SLOT(onMoveCompleted())); + //} + //lblVideo->setStyleSheet("QLabel { background-color : black; color : blue; }"); + //moveResizeTimer->start(1000); } void MainWindow::moveEvent(QMoveEvent *) { - if (vcrFlag != VCR_PLAY) + //if (vcrFlag != VCR_PLAY) { QRect rect; getVdoGeometry(&rect); interface->sendGeometry(rect); - return; + //return; } - interface->setVcrOp(VCR_PAUSE); - vcrFlag = VCR_PAUSE; - - if (!moveResizeTimer) - { - moveResizeTimer = new QTimer; - connect(moveResizeTimer, SIGNAL(timeout()), - this, SLOT(onMoveCompleted())); - } - lblVideo->setStyleSheet("QLabel { background-color : black; color : blue; }"); - moveResizeTimer->start(1000); + //interface->setVcrOp(VCR_PAUSE); + //vcrFlag = VCR_PAUSE; + + //if (!moveResizeTimer) + //{ + // moveResizeTimer = new QTimer; + // connect(moveResizeTimer, SIGNAL(timeout()), + // this, SLOT(onMoveCompleted())); + //} + //lblVideo->setStyleSheet("QLabel { background-color : black; color : blue; }"); + //moveResizeTimer->start(1000); } void MainWindow::onVolSliderValueChanged(int value) { int volume; - + volume = (value * 0xffff) / 100; if (interface != 0) { @@ -153,8 +153,8 @@ void MainWindow::setupUI() lblVideo->setMinimumWidth(320); lblVideo->setMinimumHeight(200); QPalette palette = lblVideo->palette(); - palette.setColor(lblVideo->backgroundRole(), Qt::black); - palette.setColor(lblVideo->foregroundRole(), Qt::black); + palette.setColor(lblVideo->backgroundRole(), QColor(0x00, 0x00, 0x01, 0xff)); + palette.setColor(lblVideo->foregroundRole(), QColor(0x00, 0x00, 0x01, 0xff)); lblVideo->setAutoFillBackground(true); lblVideo->setPalette(palette); hboxLayoutTop = new QHBoxLayout; @@ -253,10 +253,17 @@ void MainWindow::openMediaFile() if (filename.length() == 0) { + /* no previous selection - open user's home folder TODO */ // TODO filename = QFileDialog::getOpenFileName(this, "Select Media File", "/"); + //filename = QFileDialog::getOpenFileName(this, "Select Media File", + // QDir::currentPath()); + filename = QFileDialog::getOpenFileName(this, "Select Media File", - QDir::currentPath()); + QDir::currentPath(), + "Media *.mov *.mp4 *.mkv (*.mov *.mp4 *.mkv)"); + + } else { @@ -302,13 +309,19 @@ void MainWindow::clearDisplay() void MainWindow::on_actionOpen_Media_File_triggered() { if (vcrFlag != 0) + { onBtnStopClicked(true); + } /* if media was specified on cmd line, use it just once */ if (gotMediaOnCmdline) + { gotMediaOnCmdline = false; + } else + { openMediaFile(); + } if (filename.length() == 0) { @@ -327,10 +340,10 @@ void MainWindow::on_actionOpen_Media_File_triggered() interface->initRemoteClient(); } - playVideo = interface->getPlayVideoInstance(); - if (playVideo) + demuxMedia = interface->getDemuxMediaInstance(); + if (demuxMedia) { - connect(playVideo, SIGNAL(onElapsedtime(int)), + connect(demuxMedia, SIGNAL(onElapsedtime(int)), this, SLOT(onElapsedTime(int))); } @@ -355,7 +368,7 @@ void MainWindow::onBtnPlayClicked(bool) { if (vcrFlag == 0) { - /* first time play button has been clicked */ + /* first time play button3 has been clicked */ on_actionOpen_Media_File_triggered(); btnPlay->setText("Pause"); vcrFlag = VCR_PLAY; @@ -385,8 +398,8 @@ void MainWindow::onBtnPlayClicked(bool) void MainWindow::onBtnRewindClicked(bool) { - if (playVideo) - playVideo->onMediaSeek(0); + //if (playVideo) + // playVideo->onMediaSeek(0); } void MainWindow::onBtnStopClicked(bool) @@ -401,6 +414,8 @@ void MainWindow::onBtnStopClicked(bool) /* clear screen by filling it with black */ clearDisplay(); + + btnPlay->setChecked(false); } void MainWindow::onMediaDurationInSeconds(int duration) @@ -479,8 +494,10 @@ void MainWindow::onSliderValueChanged(int value) if (acceptSliderMove) { acceptSliderMove = false; - if (playVideo) - playVideo->onMediaSeek(value / 100); + if (demuxMedia != NULL) + { + demuxMedia->onMediaSeek(value / 100); + } } } @@ -503,6 +520,7 @@ void MainWindow::onSliderActionTriggered(int action) } } +// not called void MainWindow::onMoveCompleted() { QRect rect; @@ -512,7 +530,7 @@ void MainWindow::onMoveCompleted() interface->setVcrOp(VCR_PLAY); vcrFlag = VCR_PLAY; - moveResizeTimer->stop(); + //moveResizeTimer->stop(); } void MainWindow::on_actionAbout_triggered() diff --git a/vrplayer/mainwindow.h b/vrplayer/mainwindow.h index 4fef0d60..f0383098 100644 --- a/vrplayer/mainwindow.h +++ b/vrplayer/mainwindow.h @@ -111,7 +111,8 @@ private: /* private stuff */ OurInterface *interface; - PlayVideo *playVideo; + //PlayVideo *playVideo; + DemuxMedia *demuxMedia; QString filename; bool oneTimeInitSuccess; bool remoteClientInited; diff --git a/vrplayer/ourinterface.cpp b/vrplayer/ourinterface.cpp index cee66691..e13e6e8b 100644 --- a/vrplayer/ourinterface.cpp +++ b/vrplayer/ourinterface.cpp @@ -1,3 +1,4 @@ + #include "ourinterface.h" OurInterface::OurInterface(QObject *parent) : @@ -59,11 +60,11 @@ void OurInterface::initRemoteClient() /* LK_TODO this needs to be undone in deinitRemoteClient() */ if (!demuxMedia) { - demuxMedia = new DemuxMedia(NULL, &audioQueue, &videoQueue, channel, stream_id); + demuxMedia = new DemuxMedia(NULL, &videoQueue, channel, stream_id); demuxMediaThread = new QThread(this); connect(demuxMediaThread, SIGNAL(started()), demuxMedia, SLOT(startDemuxing())); demuxMedia->moveToThread(demuxMediaThread); - playVideo = demuxMedia->getPlayVideoInstance(); + //playVideo = demuxMedia->getPlayVideoInstance(); } } @@ -84,6 +85,7 @@ int OurInterface::openVirtualChannel() if (channel) return -1; + printf("OurInterface::openVirtualChannel:\n"); /* open a virtual channel and connect to remote client */ channel = WTSVirtualChannelOpenEx(WTS_CURRENT_SESSION, "xrdpvr", 0); if (channel == NULL) @@ -116,37 +118,46 @@ int OurInterface::closeVirtualChannel() ******************************************************************************/ int OurInterface::sendMetadataFile() { + + if (xrdpvr_init_player(channel, 101, filename.toAscii().data())) + { + fprintf(stderr, "failed to initialize the player\n"); + return -1; + } +#if 0 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; } - +#endif return 0; } int OurInterface::sendVideoFormat() { +#if 0 if (xrdpvr_set_video_format(channel, stream_id)) { emit on_ErrorMsg("I/O Error", "Error sending video format to remote client"); return -1; } - +#endif return 0; } int OurInterface::sendAudioFormat() { +#if 0 if (xrdpvr_set_audio_format(channel, stream_id)) { emit on_ErrorMsg("I/O Error", "Error sending audio format to remote client"); return -1; } - +#endif return 0; } @@ -205,11 +216,17 @@ void OurInterface::playMedia() demuxMediaThread->start(); } -PlayVideo * OurInterface::getPlayVideoInstance() +//PlayVideo * OurInterface::getPlayVideoInstance() +//{ +// return this->playVideo; +//} + +DemuxMedia * OurInterface::getDemuxMediaInstance() { - return this->playVideo; + return this->demuxMedia; } + void OurInterface::setVcrOp(int op) { if (demuxMedia) diff --git a/vrplayer/ourinterface.h b/vrplayer/ourinterface.h index 86352001..51f88e6b 100644 --- a/vrplayer/ourinterface.h +++ b/vrplayer/ourinterface.h @@ -40,7 +40,8 @@ public: int sendGeometry(QRect rect); void setFilename(QString filename); void playMedia(); - PlayVideo *getPlayVideoInstance(); + //PlayVideo *getPlayVideoInstance(); + DemuxMedia *getDemuxMediaInstance(); void setVcrOp(int op); int setVolume(int volume); @@ -54,12 +55,12 @@ signals: private: /* private stuff */ - QQueue<MediaPacket *> audioQueue; + QQueue<MediaPacket *> videoQueue; DemuxMedia *demuxMedia; QThread *demuxMediaThread; - PlayVideo *playVideo; + //PlayVideo *playVideo; QString filename; void *channel; int stream_id; diff --git a/vrplayer/playaudio.cpp b/vrplayer/playaudio.cpp index fee98f9d..042b7e26 100644 --- a/vrplayer/playaudio.cpp +++ b/vrplayer/playaudio.cpp @@ -54,13 +54,15 @@ void PlayAudio::play() label1: + printf("audio\n"); if (audioQueue->isEmpty()) { qDebug() << "PlayAudio::play: GOT EMPTY"; - usleep(1000 * 100); + usleep(1000 * 10); continue; } + printf(""); pkt = audioQueue->dequeue(); sendMutex->lock(); send_audio_pkt(channel, stream_id, pkt->av_pkt); diff --git a/vrplayer/playvideo.cpp b/vrplayer/playvideo.cpp index 24ef492d..71fbcda9 100644 --- a/vrplayer/playvideo.cpp +++ b/vrplayer/playvideo.cpp @@ -1,5 +1,6 @@ #include <unistd.h> +#include <sys/time.h> #include "playvideo.h" #include <QDebug> @@ -8,179 +9,58 @@ PlayVideo::PlayVideo(QObject *parent, QQueue<MediaPacket *> *videoQueue, QMutex *sendMutex, void *channel, - int stream_id) : + int stream_id, int fps) : 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; + this->fps = fps; +} + +/** + ******************************************************************************/ +static int +get_mstime(void) +{ + struct timeval tp; + + gettimeofday(&tp, 0); + return (tp.tv_sec * 1000) + (tp.tv_usec / 1000); } void PlayVideo::play() { MediaPacket *pkt; - int usl; + int now_time; + int sleep_time; + int last_display_time; + last_display_time = 0; 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: - + sendMutex->lock(); if (videoQueue->isEmpty()) { + sendMutex->unlock(); + usleep(10 * 1000); continue; } pkt = videoQueue->dequeue(); - sendMutex->lock(); send_video_pkt(channel, stream_id, pkt->av_pkt); sendMutex->unlock(); - usl = pkt->delay_in_us; - if (usl < 0) + now_time = get_mstime(); + sleep_time = now_time - last_display_time; + if (sleep_time > (1000 / fps)) { - usl = 0; + sleep_time = (1000 / fps); } - if (usl > 100 * 1000) + if (sleep_time > 0) { - usl = 100 * 1000; + usleep(sleep_time * 1000); } - usleep(usl); - delete pkt; - 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::onMediaRestarted() -{ - elapsedTime = av_gettime(); -} - -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); + last_display_time = now_time; 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 diff --git a/vrplayer/playvideo.h b/vrplayer/playvideo.h index 2ae183b5..e2300f24 100644 --- a/vrplayer/playvideo.h +++ b/vrplayer/playvideo.h @@ -39,34 +39,36 @@ public: QQueue<MediaPacket *> *videoQueue = 0, QMutex *sendMutex = 0, void *channel = 0, - int stream_id = 101); + int stream_id = 101, + int fps = 24); - void onMediaSeek(int value); - void setVcrOp(int op); - void onMediaRestarted(); + //void onMediaSeek(int value); + //void setVcrOp(int op); + //void onMediaRestarted(); public slots: void play(); -signals: - void onElapsedtime(int val); /* in hundredth of a sec */ +//signals: +// void onElapsedtime(int val); /* in hundredth of a sec */ private: QQueue<MediaPacket *> *videoQueue; - int vcrFlag; - QMutex vcrMutex; +// int vcrFlag; +// QMutex vcrMutex; QMutex *sendMutex; - QMutex posMutex; - int64_t la_seekPos; /* locked access; must hold posMutex */ +// 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; + int fps; +// 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(); +// void updateMediaPos(); +// void clearVideoQ(); }; #endif // PLAYVIDEO_H diff --git a/xorg/server/module/rdp.h b/xorg/server/module/rdp.h index c3533e98..4c6511e0 100644 --- a/xorg/server/module/rdp.h +++ b/xorg/server/module/rdp.h @@ -65,6 +65,26 @@ struct _rdpKeyboard }; typedef struct _rdpKeyboard rdpKeyboard; + +struct _rdpPixmapRec +{ + int status; + int rdpindex; + int con_number; + int is_dirty; + int is_scratch; + int is_alpha_dirty_not; + /* number of times used in a remote operation + if this gets above XRDP_USE_COUNT_THRESHOLD + then we force remote the pixmap */ + int use_count; + int kind_width; + struct rdp_draw_item *draw_item_head; + struct rdp_draw_item *draw_item_tail; +}; +typedef struct _rdpPixmapRec rdpPixmapRec; +typedef struct _rdpPixmapRec * rdpPixmapPtr; + /* move this to common header */ struct _rdpRec { @@ -75,6 +95,8 @@ struct _rdpRec int sizeInBytes; int num_modes; int bitsPerPixel; + int Bpp; + int Bpp_mask; char *pfbMemory; ScreenPtr pScreen; rdpDevPrivateKey privateKeyRecGC; @@ -114,6 +136,20 @@ struct _rdpRec char uds_data[256]; rdpClientCon *clientConHead; rdpClientCon *clientConTail; + + rdpPixmapRec screenPriv; + int sendUpdateScheduled; /* boolean */ + OsTimerPtr sendUpdateTimer; + + int do_dirty_ons; /* boolean */ + int disconnect_scheduled; /* boolean */ + int do_kill_disconnected; /* boolean */ + + OsTimerPtr disconnectTimer; + int disconnectScheduled; /* boolean */ + int disconnect_timeout_s; + int disconnect_time_ms; + }; typedef struct _rdpRec rdpRec; typedef struct _rdpRec * rdpPtr; @@ -127,11 +163,73 @@ struct _rdpGCRec typedef struct _rdpGCRec rdpGCRec; typedef struct _rdpGCRec * rdpGCPtr; -struct _rdpPixmapRec +#define RDI_FILL 1 +#define RDI_IMGLL 2 /* lossless */ +#define RDI_IMGLY 3 /* lossy */ +#define RDI_LINE 4 +#define RDI_SCRBLT 5 +#define RDI_TEXT 6 + +struct urdp_draw_item_fill { - int i1; + int opcode; + int fg_color; + int bg_color; + int pad0; +}; + +struct urdp_draw_item_img +{ + int opcode; + int pad0; +}; + +struct urdp_draw_item_line +{ + int opcode; + int fg_color; + int bg_color; + int width; + xSegment* segs; + int nseg; + int flags; +}; + +struct urdp_draw_item_scrblt +{ + int srcx; + int srcy; + int dstx; + int dsty; + int cx; + int cy; +}; + +struct urdp_draw_item_text +{ + int opcode; + int fg_color; + struct rdp_text* rtext; /* in rdpglyph.h */ +}; + +union urdp_draw_item +{ + struct urdp_draw_item_fill fill; + struct urdp_draw_item_img img; + struct urdp_draw_item_line line; + struct urdp_draw_item_scrblt scrblt; + struct urdp_draw_item_text text; +}; + +struct rdp_draw_item +{ + int type; /* RDI_FILL, RDI_IMGLL, ... */ + int flags; + struct rdp_draw_item* prev; + struct rdp_draw_item* next; + RegionPtr reg; + union urdp_draw_item u; }; -typedef struct _rdpPixmapRec rdpPixmapRec; -typedef struct _rdpPixmapRec * rdpPixmapPtr; +#define XRDP_USE_COUNT_THRESHOLD 1 #endif diff --git a/xorg/server/module/rdpClientCon.c b/xorg/server/module/rdpClientCon.c index 3edd1e0c..b0ca3776 100644 --- a/xorg/server/module/rdpClientCon.c +++ b/xorg/server/module/rdpClientCon.c @@ -24,6 +24,8 @@ Client connection to xrdp #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <signal.h> +#include <sys/types.h> /* this should be before all X11 .h files */ #include <xorg-server.h> @@ -43,6 +45,53 @@ Client connection to xrdp #define LTOUI32(_in) ((unsigned int)(_in)) +#define USE_MAX_OS_BYTES 1 +#define MAX_OS_BYTES (16 * 1024 * 1024) + +/* +0 GXclear, 0 +1 GXnor, DPon +2 GXandInverted, DPna +3 GXcopyInverted, Pn +4 GXandReverse, PDna +5 GXinvert, Dn +6 GXxor, DPx +7 GXnand, DPan +8 GXand, DPa +9 GXequiv, DPxn +a GXnoop, D +b GXorInverted, DPno +c GXcopy, P +d GXorReverse, PDno +e GXor, DPo +f GXset 1 +*/ + +static int g_rdp_opcodes[16] = +{ + 0x00, /* GXclear 0x0 0 */ + 0x88, /* GXand 0x1 src AND dst */ + 0x44, /* GXandReverse 0x2 src AND NOT dst */ + 0xcc, /* GXcopy 0x3 src */ + 0x22, /* GXandInverted 0x4 NOT src AND dst */ + 0xaa, /* GXnoop 0x5 dst */ + 0x66, /* GXxor 0x6 src XOR dst */ + 0xee, /* GXor 0x7 src OR dst */ + 0x11, /* GXnor 0x8 NOT src AND NOT dst */ + 0x99, /* GXequiv 0x9 NOT src XOR dst */ + 0x55, /* GXinvert 0xa NOT dst */ + 0xdd, /* GXorReverse 0xb src OR NOT dst */ + 0x33, /* GXcopyInverted 0xc NOT src */ + 0xbb, /* GXorInverted 0xd NOT src OR dst */ + 0x77, /* GXnand 0xe NOT src OR NOT dst */ + 0xff /* GXset 0xf 1 */ +}; + +static int +rdpClientConSendPending(rdpPtr dev, rdpClientCon *clientCon); +static int +rdpClientConSendMsg(rdpPtr dev, rdpClientCon *clientCon); + /******************************************************************************/ static int rdpClientConGotConnection(ScreenPtr pScreen, rdpPtr dev) @@ -219,13 +268,13 @@ rdpClientConInit(rdpPtr dev) if (dev->listen_sck == 0) { unlink(dev->uds_data); - dev->listen_sck = g_tcp_local_socket_stream(); - if (g_tcp_local_bind(dev->listen_sck, dev->uds_data) != 0) + dev->listen_sck = g_sck_local_socket_stream(); + if (g_sck_local_bind(dev->listen_sck, dev->uds_data) != 0) { LLOGLN(0, ("rdpClientConInit: g_tcp_local_bind failed")); return 1; } - g_tcp_listen(dev->listen_sck); + g_sck_listen(dev->listen_sck); AddEnabledDevice(dev->listen_sck); } return 0; @@ -243,3 +292,1048 @@ rdpClientConDeinit(rdpPtr dev) } return 0; } + +/******************************************************************************/ +static CARD32 +rdpClientConDeferredDisconnectCallback(OsTimerPtr timer, CARD32 now, + pointer arg) +{ + CARD32 lnow_ms; + rdpPtr dev; + + LLOGLN(10, ("rdpClientConDeferredDisconnectCallback")); + dev = (rdpPtr) arg; + if (dev->clientConHead != NULL) /* is there any connection ? */ + { + LLOGLN(0, ("rdpClientConDeferredDisconnectCallback: one connected")); + if (dev->disconnectTimer != NULL) + { + LLOGLN(0, ("rdpClientConDeferredDisconnectCallback: " + "canceling disconnectTimer")); + TimerCancel(dev->disconnectTimer); + TimerFree(dev->disconnectTimer); + dev->disconnectTimer = NULL; + } + dev->disconnectScheduled = FALSE; + return 0; + } + else + { + LLOGLN(10, ("rdpClientConDeferredDisconnectCallback: not connected")); + } + lnow_ms = GetTimeInMillis(); + if (lnow_ms - dev->disconnect_time_ms > dev->disconnect_timeout_s * 1000) + { + LLOGLN(0, ("rdpClientConDeferredDisconnectCallback: exit X11rdp")); + kill(getpid(), SIGTERM); + return 0; + } + dev->disconnectTimer = TimerSet(dev->disconnectTimer, 0, 1000 * 10, + rdpClientConDeferredDisconnectCallback, + dev); + return 0; +} + + +/*****************************************************************************/ +static int +rdpClientConDisconnect(rdpPtr dev, rdpClientCon *clientCon) +{ + //int index; + + LLOGLN(0, ("rdpClientConDisconnect:")); + if (dev->do_kill_disconnected) + { + if (dev->disconnect_scheduled == FALSE) + { + LLOGLN(0, ("rdpClientConDisconnect: starting g_dis_timer")); + dev->disconnectTimer = TimerSet(dev->disconnectTimer, 0, 1000 * 10, + rdpClientConDeferredDisconnectCallback, dev); + dev->disconnect_scheduled = TRUE; + } + dev->disconnect_time_ms = GetTimeInMillis(); + } + + //rdpClientConDelete(dev, clientCon); + +#if 0 + + // TODO + + RemoveEnabledDevice(clientCon->sck); + clientCon->connected = FALSE; + g_sck_close(clientCon->sck); + clientCon->sck = 0; + clientCon->sckClosed = TRUE; + clientCon->osBitmapNumUsed = 0; + clientCon->rdpIndex = -1; + + if (clientCon->maxOsBitmaps > 0) + { + for (index = 0; index < clientCon->maxOsBitmaps; index++) + { + if (clientCon->osBitmaps[index].used) + { + if (g_os_bitmaps[index].priv != 0) + { + g_os_bitmaps[index].priv->status = 0; + } + } + } + } + g_os_bitmap_alloc_size = 0; + + g_max_os_bitmaps = 0; + g_free(g_os_bitmaps); + g_os_bitmaps = 0; + g_use_rail = 0; + g_do_glyph_cache = 0; + g_do_composite = 0; + +#endif + + return 0; +} + +/******************************************************************************/ +int +rdpClientConBeginUpdate(rdpPtr dev, rdpClientCon *clientCon) +{ + LLOGLN(10, ("rdpClientConBeginUpdate:")); + + if (clientCon->connected) + { + if (clientCon->begin) + { + return 0; + } + init_stream(clientCon->out_s, 0); + s_push_layer(clientCon->out_s, iso_hdr, 8); + out_uint16_le(clientCon->out_s, 1); /* begin update */ + out_uint16_le(clientCon->out_s, 4); /* size */ + clientCon->begin = TRUE; + clientCon->count = 1; + } + + return 0; +} + +/******************************************************************************/ +int +rdpClientConEndUpdate(rdpPtr dev, rdpClientCon *clientCon) +{ + LLOGLN(10, ("rdpClientConEndUpdate")); + + if (clientCon->connected && clientCon->begin) + { + if (dev->do_dirty_ons) + { + /* in this mode, end update is only called in check dirty */ + rdpClientConSendPending(dev, clientCon); + } + else + { + rdpClientConScheduleDeferredUpdate(dev); + } + } + + return 0; +} + +/******************************************************************************/ +int +rdpClientConPreCheck(rdpPtr dev, rdpClientCon *clientCon, int in_size) +{ + int rv; + + rv = 0; + if (clientCon->begin == FALSE) + { + rdpClientConBeginUpdate(dev, clientCon); + } + + if ((clientCon->out_s->p - clientCon->out_s->data) > + (clientCon->out_s->size - (in_size + 20))) + { + s_mark_end(clientCon->out_s); + if (rdpClientConSendMsg(dev, clientCon) != 0) + { + LLOGLN(0, ("rdpClientConPreCheck: rdpup_send_msg failed")); + rv = 1; + } + clientCon->count = 0; + init_stream(clientCon->out_s, 0); + s_push_layer(clientCon->out_s, iso_hdr, 8); + } + + return rv; +} + +/******************************************************************************/ +int +rdpClientConFillRect(rdpPtr dev, rdpClientCon *clientCon, + short x, short y, int cx, int cy) +{ + if (clientCon->connected) + { + LLOGLN(10, ("rdpClientConFillRect:")); + rdpClientConPreCheck(dev, clientCon, 12); + out_uint16_le(clientCon->out_s, 3); /* fill rect */ + out_uint16_le(clientCon->out_s, 12); /* size */ + clientCon->count++; + out_uint16_le(clientCon->out_s, x); + out_uint16_le(clientCon->out_s, y); + out_uint16_le(clientCon->out_s, cx); + out_uint16_le(clientCon->out_s, cy); + } + + return 0; +} + +/******************************************************************************/ +int +rdpClientConScreenBlt(rdpPtr dev, rdpClientCon *clientCon, + short x, short y, int cx, int cy, short srcx, short srcy) +{ + if (clientCon->connected) + { + LLOGLN(10, ("rdpClientConScreenBlt: x %d y %d cx %d cy %d " + "srcx %d srcy %d", + x, y, cx, cy, srcx, srcy)); + rdpClientConPreCheck(dev, clientCon, 16); + out_uint16_le(clientCon->out_s, 4); /* screen blt */ + out_uint16_le(clientCon->out_s, 16); /* size */ + clientCon->count++; + out_uint16_le(clientCon->out_s, x); + out_uint16_le(clientCon->out_s, y); + out_uint16_le(clientCon->out_s, cx); + out_uint16_le(clientCon->out_s, cy); + out_uint16_le(clientCon->out_s, srcx); + out_uint16_le(clientCon->out_s, srcy); + } + + return 0; +} + +/******************************************************************************/ +int +rdpClientConSetClip(rdpPtr dev, rdpClientCon *clientCon, + short x, short y, int cx, int cy) +{ + if (clientCon->connected) + { + LLOGLN(10, ("rdpClientConSetClip:")); + rdpClientConPreCheck(dev, clientCon, 12); + out_uint16_le(clientCon->out_s, 10); /* set clip */ + out_uint16_le(clientCon->out_s, 12); /* size */ + clientCon->count++; + out_uint16_le(clientCon->out_s, x); + out_uint16_le(clientCon->out_s, y); + out_uint16_le(clientCon->out_s, cx); + out_uint16_le(clientCon->out_s, cy); + } + + return 0; +} + +/******************************************************************************/ +int +rdpClientConResetClip(rdpPtr dev, rdpClientCon *clientCon) +{ + if (clientCon->connected) + { + LLOGLN(10, ("rdpClientConResetClip:")); + rdpClientConPreCheck(dev, clientCon, 4); + out_uint16_le(clientCon->out_s, 11); /* reset clip */ + out_uint16_le(clientCon->out_s, 4); /* size */ + clientCon->count++; + } + + return 0; +} + +#define COLOR8(r, g, b) \ + ((((r) >> 5) << 0) | (((g) >> 5) << 3) | (((b) >> 6) << 6)) +#define COLOR15(r, g, b) \ + ((((r) >> 3) << 10) | (((g) >> 3) << 5) | (((b) >> 3) << 0)) +#define COLOR16(r, g, b) \ + ((((r) >> 3) << 11) | (((g) >> 2) << 5) | (((b) >> 3) << 0)) +#define COLOR24(r, g, b) \ + ((((r) >> 0) << 0) | (((g) >> 0) << 8) | (((b) >> 0) << 16)) +#define SPLITCOLOR32(r, g, b, c) \ + { \ + r = ((c) >> 16) & 0xff; \ + g = ((c) >> 8) & 0xff; \ + b = (c) & 0xff; \ + } + +/******************************************************************************/ +int +rdpClientConConvertPixel(rdpPtr dev, rdpClientCon *clientCon, int in_pixel) +{ + int red; + int green; + int blue; + int rv; + + rv = 0; + + if (dev->depth == 24) + { + if (clientCon->rdp_bpp == 24) + { + rv = in_pixel; + SPLITCOLOR32(red, green, blue, rv); + rv = COLOR24(red, green, blue); + } + else if (clientCon->rdp_bpp == 16) + { + rv = in_pixel; + SPLITCOLOR32(red, green, blue, rv); + rv = COLOR16(red, green, blue); + } + else if (clientCon->rdp_bpp == 15) + { + rv = in_pixel; + SPLITCOLOR32(red, green, blue, rv); + rv = COLOR15(red, green, blue); + } + else if (clientCon->rdp_bpp == 8) + { + rv = in_pixel; + SPLITCOLOR32(red, green, blue, rv); + rv = COLOR8(red, green, blue); + } + } + else if (dev->depth == clientCon->rdp_bpp) + { + return in_pixel; + } + + return rv; +} + +/******************************************************************************/ +int +rdpClientConConvertPixels(rdpPtr dev, rdpClientCon *clientCon, + void *src, void *dst, int num_pixels) +{ + unsigned int pixel; + unsigned int red; + unsigned int green; + unsigned int blue; + unsigned int *src32; + unsigned int *dst32; + unsigned short *dst16; + unsigned char *dst8; + int index; + + if (dev->depth == clientCon->rdp_bpp) + { + memcpy(dst, src, num_pixels * dev->Bpp); + return 0; + } + + if (dev->depth == 24) + { + src32 = (unsigned int *)src; + + if (clientCon->rdp_bpp == 24) + { + dst32 = (unsigned int *)dst; + + for (index = 0; index < num_pixels; index++) + { + pixel = *src32; + *dst32 = pixel; + dst32++; + src32++; + } + } + else if (clientCon->rdp_bpp == 16) + { + dst16 = (unsigned short *)dst; + + for (index = 0; index < num_pixels; index++) + { + pixel = *src32; + SPLITCOLOR32(red, green, blue, pixel); + pixel = COLOR16(red, green, blue); + *dst16 = pixel; + dst16++; + src32++; + } + } + else if (clientCon->rdp_bpp == 15) + { + dst16 = (unsigned short *)dst; + + for (index = 0; index < num_pixels; index++) + { + pixel = *src32; + SPLITCOLOR32(red, green, blue, pixel); + pixel = COLOR15(red, green, blue); + *dst16 = pixel; + dst16++; + src32++; + } + } + else if (clientCon->rdp_bpp == 8) + { + dst8 = (unsigned char *)dst; + + for (index = 0; index < num_pixels; index++) + { + pixel = *src32; + SPLITCOLOR32(red, green, blue, pixel); + pixel = COLOR8(red, green, blue); + *dst8 = pixel; + dst8++; + src32++; + } + } + } + + return 0; +} + +/******************************************************************************/ +int +rdpClientConAlphaPixels(void* src, void* dst, int num_pixels) +{ + unsigned int* src32; + unsigned char* dst8; + int index; + + src32 = (unsigned int*)src; + dst8 = (unsigned char*)dst; + for (index = 0; index < num_pixels; index++) + { + *dst8 = (*src32) >> 24; + dst8++; + src32++; + } + return 0; +} + +/******************************************************************************/ +int +rdpClientConSetFgcolor(rdpPtr dev, rdpClientCon *clientCon, int fgcolor) +{ + if (clientCon->connected) + { + LLOGLN(10, ("rdpClientConSetFgcolor:")); + rdpClientConPreCheck(dev, clientCon, 8); + out_uint16_le(clientCon->out_s, 12); /* set fgcolor */ + out_uint16_le(clientCon->out_s, 8); /* size */ + clientCon->count++; + fgcolor = fgcolor & dev->Bpp_mask; + fgcolor = rdpClientConConvertPixel(dev, clientCon, fgcolor) & + clientCon->rdp_Bpp_mask; + out_uint32_le(clientCon->out_s, fgcolor); + } + + return 0; +} + +/******************************************************************************/ +int +rdpClientConSetBgcolor(rdpPtr dev, rdpClientCon *clientCon, int bgcolor) +{ + if (clientCon->connected) + { + LLOGLN(10, ("rdpClientConSetBgcolor:")); + rdpClientConPreCheck(dev, clientCon, 8); + out_uint16_le(clientCon->out_s, 13); /* set bg color */ + out_uint16_le(clientCon->out_s, 8); /* size */ + clientCon->count++; + bgcolor = bgcolor & dev->Bpp_mask; + bgcolor = rdpClientConConvertPixel(dev, clientCon, bgcolor) & + clientCon->rdp_Bpp_mask; + out_uint32_le(clientCon->out_s, bgcolor); + } + + return 0; +} + +/******************************************************************************/ +int +rdpClientConSetOpcode(rdpPtr dev, rdpClientCon *clientCon, int opcode) +{ + if (clientCon->connected) + { + LLOGLN(10, ("rdpClientConSetOpcode:")); + rdpClientConPreCheck(dev, clientCon, 6); + out_uint16_le(clientCon->out_s, 14); /* set opcode */ + out_uint16_le(clientCon->out_s, 6); /* size */ + clientCon->count++; + out_uint16_le(clientCon->out_s, g_rdp_opcodes[opcode & 0xf]); + } + + return 0; +} + +/******************************************************************************/ +int +rdpClientConSetPen(rdpPtr dev, rdpClientCon *clientCon, int style, int width) +{ + if (clientCon->connected) + { + LLOGLN(10, ("rdpClientConSetPen:")); + rdpClientConPreCheck(dev, clientCon, 8); + out_uint16_le(clientCon->out_s, 17); /* set pen */ + out_uint16_le(clientCon->out_s, 8); /* size */ + clientCon->count++; + out_uint16_le(clientCon->out_s, style); + out_uint16_le(clientCon->out_s, width); + } + + return 0; +} + +/******************************************************************************/ +int +rdpClientConDrawLine(rdpPtr dev, rdpClientCon *clientCon, + short x1, short y1, short x2, short y2) +{ + if (clientCon->connected) + { + LLOGLN(10, ("rdpClientConDrawLine:")); + rdpClientConPreCheck(dev, clientCon, 12); + out_uint16_le(clientCon->out_s, 18); /* draw line */ + out_uint16_le(clientCon->out_s, 12); /* size */ + clientCon->count++; + out_uint16_le(clientCon->out_s, x1); + out_uint16_le(clientCon->out_s, y1); + out_uint16_le(clientCon->out_s, x2); + out_uint16_le(clientCon->out_s, y2); + } + + return 0; +} + +/******************************************************************************/ +int +rdpClientConSetCursor(rdpPtr dev, rdpClientCon *clientCon, + short x, short y, char *cur_data, char *cur_mask) +{ + int size; + + if (clientCon->connected) + { + LLOGLN(10, ("rdpClientConSetCursor:")); + size = 8 + 32 * (32 * 3) + 32 * (32 / 8); + rdpClientConPreCheck(dev, clientCon, size); + out_uint16_le(clientCon->out_s, 19); /* set cursor */ + out_uint16_le(clientCon->out_s, size); /* size */ + clientCon->count++; + x = RDPMAX(0, x); + x = RDPMIN(31, x); + y = RDPMAX(0, y); + y = RDPMIN(31, y); + out_uint16_le(clientCon->out_s, x); + out_uint16_le(clientCon->out_s, y); + out_uint8a(clientCon->out_s, cur_data, 32 * (32 * 3)); + out_uint8a(clientCon->out_s, cur_mask, 32 * (32 / 8)); + } + + return 0; +} + +/******************************************************************************/ +int +rdpClientConSetCursorEx(rdpPtr dev, rdpClientCon *clientCon, + short x, short y, char *cur_data, + char *cur_mask, int bpp) +{ + int size; + int Bpp; + + if (clientCon->connected) + { + LLOGLN(10, ("rdpClientConSetCursorEx:")); + Bpp = (bpp == 0) ? 3 : (bpp + 7) / 8; + size = 10 + 32 * (32 * Bpp) + 32 * (32 / 8); + rdpClientConPreCheck(dev, clientCon, size); + out_uint16_le(clientCon->out_s, 51); /* set cursor ex */ + out_uint16_le(clientCon->out_s, size); /* size */ + clientCon->count++; + x = RDPMAX(0, x); + x = RDPMIN(31, x); + y = RDPMAX(0, y); + y = RDPMIN(31, y); + out_uint16_le(clientCon->out_s, x); + out_uint16_le(clientCon->out_s, y); + out_uint16_le(clientCon->out_s, bpp); + out_uint8a(clientCon->out_s, cur_data, 32 * (32 * Bpp)); + out_uint8a(clientCon->out_s, cur_mask, 32 * (32 / 8)); + } + + return 0; +} + +/******************************************************************************/ +int +rdpClientConCreateOsSurface(rdpPtr dev, rdpClientCon *clientCon, + int rdpindex, int width, int height) +{ + LLOGLN(10, ("rdpClientConCreateOsSurface:")); + + if (clientCon->connected) + { + LLOGLN(10, ("rdpClientConCreateOsSurface: width %d height %d", width, height)); + rdpClientConPreCheck(dev, clientCon, 12); + out_uint16_le(clientCon->out_s, 20); + out_uint16_le(clientCon->out_s, 12); + clientCon->count++; + out_uint32_le(clientCon->out_s, rdpindex); + out_uint16_le(clientCon->out_s, width); + out_uint16_le(clientCon->out_s, height); + } + + return 0; +} + +/******************************************************************************/ +int +rdpClientConCreateOsSurfaceBpp(rdpPtr dev, rdpClientCon *clientCon, + int rdpindex, int width, int height, int bpp) +{ + LLOGLN(10, ("rdpClientConCreateOsSurfaceBpp:")); + if (clientCon->connected) + { + LLOGLN(10, ("rdpClientConCreateOsSurfaceBpp: width %d height %d " + "bpp %d", width, height, bpp)); + rdpClientConPreCheck(dev, clientCon, 13); + out_uint16_le(clientCon->out_s, 31); + out_uint16_le(clientCon->out_s, 13); + clientCon->count++; + out_uint32_le(clientCon->out_s, rdpindex); + out_uint16_le(clientCon->out_s, width); + out_uint16_le(clientCon->out_s, height); + out_uint8(clientCon->out_s, bpp); + } + return 0; +} + +/******************************************************************************/ +int +rdpClientConSwitchOsSurface(rdpPtr dev, rdpClientCon *clientCon, int rdpindex) +{ + LLOGLN(10, ("rdpClientConSwitchOsSurface:")); + + if (clientCon->connected) + { + if (clientCon->rdpIndex == rdpindex) + { + return 0; + } + + clientCon->rdpIndex = rdpindex; + LLOGLN(10, ("rdpClientConSwitchOsSurface: rdpindex %d", rdpindex)); + /* switch surface */ + rdpClientConPreCheck(dev, clientCon, 8); + out_uint16_le(clientCon->out_s, 21); + out_uint16_le(clientCon->out_s, 8); + out_uint32_le(clientCon->out_s, rdpindex); + clientCon->count++; + } + + return 0; +} + +/******************************************************************************/ +int +rdpClientConDeleteOsSurface(rdpPtr dev, rdpClientCon *clientCon, int rdpindex) +{ + LLOGLN(10, ("rdpClientConDeleteOsSurface: rdpindex %d", rdpindex)); + + if (clientCon->connected) + { + LLOGLN(10, ("rdpClientConDeleteOsSurface: rdpindex %d", rdpindex)); + rdpClientConPreCheck(dev, clientCon, 8); + out_uint16_le(clientCon->out_s, 22); + out_uint16_le(clientCon->out_s, 8); + clientCon->count++; + out_uint32_le(clientCon->out_s, rdpindex); + } + + return 0; +} + +/*****************************************************************************/ +/* returns -1 on error */ +int +rdpClientConAddOsBitmap(rdpPtr dev, rdpClientCon *clientCon, + PixmapPtr pixmap, rdpPixmapPtr priv) +{ + int index; + int rv; + int oldest; + int oldest_index; + int this_bytes; + + LLOGLN(10, ("rdpClientConAddOsBitmap:")); + if (clientCon->connected == FALSE) + { + LLOGLN(10, ("rdpClientConAddOsBitmap: test error 1")); + return -1; + } + + if (clientCon->osBitmaps == NULL) + { + LLOGLN(10, ("rdpClientConAddOsBitmap: test error 2")); + return -1; + } + + this_bytes = pixmap->devKind * pixmap->drawable.height; + if (this_bytes > MAX_OS_BYTES) + { + LLOGLN(10, ("rdpClientConAddOsBitmap: error, too big this_bytes %d " + "width %d height %d", this_bytes, + pixmap->drawable.height, pixmap->drawable.height)); + return -1; + } + + oldest = 0x7fffffff; + oldest_index = -1; + rv = -1; + index = 0; + + while (index < clientCon->maxOsBitmaps) + { + if (clientCon->osBitmaps[index].used == FALSE) + { + clientCon->osBitmaps[index].used = TRUE; + clientCon->osBitmaps[index].pixmap = pixmap; + clientCon->osBitmaps[index].priv = priv; + clientCon->osBitmaps[index].stamp = clientCon->osBitmapStamp; + clientCon->osBitmapStamp++; + clientCon->osBitmapNumUsed++; + rv = index; + break; + } + else + { + if (clientCon->osBitmaps[index].stamp < oldest) + { + oldest = clientCon->osBitmaps[index].stamp; + oldest_index = index; + } + } + index++; + } + + if (rv == -1) + { + if (oldest_index == -1) + { + LLOGLN(0, ("rdpClientConAddOsBitmap: error")); + } + else + { + LLOGLN(10, ("rdpClientConAddOsBitmap: too many pixmaps removing " + "oldest_index %d", oldest_index)); + rdpClientConRemoveOsBitmap(dev, clientCon, oldest_index); + rdpClientConDeleteOsSurface(dev, clientCon, oldest_index); + clientCon->osBitmaps[oldest_index].used = TRUE; + clientCon->osBitmaps[oldest_index].pixmap = pixmap; + clientCon->osBitmaps[oldest_index].priv = priv; + clientCon->osBitmaps[oldest_index].stamp = clientCon->osBitmapStamp; + clientCon->osBitmapStamp++; + clientCon->osBitmapNumUsed++; + rv = oldest_index; + } + } + + if (rv < 0) + { + LLOGLN(10, ("rdpClientConAddOsBitmap: test error 3")); + return rv; + } + + clientCon->osBitmapAllocSize += this_bytes; + LLOGLN(10, ("rdpClientConAddOsBitmap: this_bytes %d " + "clientCon->osBitmapAllocSize %d", + this_bytes, clientCon->osBitmapAllocSize)); +#if USE_MAX_OS_BYTES + while (clientCon->osBitmapAllocSize > MAX_OS_BYTES) + { + LLOGLN(10, ("rdpClientConAddOsBitmap: must delete " + "clientCon->osBitmapNumUsed %d", + clientCon->osBitmapNumUsed)); + /* find oldest */ + oldest = 0x7fffffff; + oldest_index = -1; + index = 0; + while (index < clientCon->maxOsBitmaps) + { + if (clientCon->osBitmaps[index].used && + (clientCon->osBitmaps[index].stamp < oldest)) + { + oldest = clientCon->osBitmaps[index].stamp; + oldest_index = index; + } + index++; + } + if (oldest_index == -1) + { + LLOGLN(0, ("rdpClientConAddOsBitmap: error 1")); + break; + } + if (oldest_index == rv) + { + LLOGLN(0, ("rdpClientConAddOsBitmap: error 2")); + break; + } + rdpClientConRemoveOsBitmap(dev, clientCon, oldest_index); + rdpClientConDeleteOsSurface(dev, clientCon, oldest_index); + } +#endif + LLOGLN(10, ("rdpClientConAddOsBitmap: new bitmap index %d", rv)); + LLOGLN(10, ("rdpClientConAddOsBitmap: clientCon->osBitmapNumUsed %d " + "clientCon->osBitmapStamp 0x%8.8x", + clientCon->osBitmapNumUsed, clientCon->osBitmapStamp)); + return rv; +} + +/*****************************************************************************/ +int +rdpClientConRemoveOsBitmap(rdpPtr dev, rdpClientCon *clientCon, int rdpindex) +{ + PixmapPtr pixmap; + rdpPixmapPtr priv; + int this_bytes; + + if (clientCon->osBitmaps == NULL) + { + LLOGLN(10, ("rdpClientConRemoveOsBitmap: test error 1")); + return 1; + } + + LLOGLN(10, ("rdpClientConRemoveOsBitmap: index %d stamp %d", + rdpindex, clientCon->osBitmaps[rdpindex].stamp)); + + if ((rdpindex < 0) && (rdpindex >= clientCon->maxOsBitmaps)) + { + LLOGLN(10, ("rdpClientConRemoveOsBitmap: test error 2")); + return 1; + } + + if (clientCon->osBitmaps[rdpindex].used) + { + pixmap = clientCon->osBitmaps[rdpindex].pixmap; + priv = clientCon->osBitmaps[rdpindex].priv; + rdpDrawItemRemoveAll(dev, priv); + this_bytes = pixmap->devKind * pixmap->drawable.height; + clientCon->osBitmapAllocSize -= this_bytes; + LLOGLN(10, ("rdpClientConRemoveOsBitmap: this_bytes %d " + "clientCon->osBitmapAllocSize %d", this_bytes, + clientCon->osBitmapAllocSize)); + clientCon->osBitmaps[rdpindex].used = 0; + clientCon->osBitmaps[rdpindex].pixmap = 0; + clientCon->osBitmaps[rdpindex].priv = 0; + clientCon->osBitmapNumUsed--; + priv->status = 0; + priv->con_number = 0; + priv->use_count = 0; + } + else + { + LLOGLN(0, ("rdpup_remove_os_bitmap: error")); + } + + LLOGLN(10, ("rdpup_remove_os_bitmap: clientCon->osBitmapNumUsed %d", + clientCon->osBitmapNumUsed)); + return 0; +} + +/*****************************************************************************/ +int +rdpClientConUpdateOsUse(rdpPtr dev, rdpClientCon *clientCon, int rdpindex) +{ + if (clientCon->osBitmaps == NULL) + { + return 1; + } + + LLOGLN(10, ("rdpClientConUpdateOsUse: index %d stamp %d", + rdpindex, clientCon->osBitmaps[rdpindex].stamp)); + + if ((rdpindex < 0) && (rdpindex >= clientCon->maxOsBitmaps)) + { + return 1; + } + + if (clientCon->osBitmaps[rdpindex].used) + { + clientCon->osBitmaps[rdpindex].stamp = clientCon->osBitmapStamp; + clientCon->osBitmapStamp++; + } + else + { + LLOGLN(0, ("rdpClientConUpdateOsUse: error rdpindex %d", rdpindex)); + } + + return 0; +} + +/*****************************************************************************/ +/* returns error */ +static int +rdpClientConSend(rdpPtr dev, rdpClientCon *clientCon, char *data, int len) +{ + int sent; + + LLOGLN(10, ("rdpClientConSend - sending %d bytes", len)); + + if (clientCon->sckClosed) + { + return 1; + } + + while (len > 0) + { + sent = g_sck_send(clientCon->sck, data, len, 0); + + if (sent == -1) + { + if (g_sck_last_error_would_block(clientCon->sck)) + { + g_sleep(1); + } + else + { + LLOGLN(0, ("rdpClientConSend: g_tcp_send failed(returned -1)")); + rdpClientConDisconnect(dev, clientCon); + return 1; + } + } + else if (sent == 0) + { + LLOGLN(0, ("rdpClientConSend: g_tcp_send failed(returned zero)")); + rdpClientConDisconnect(dev, clientCon); + return 1; + } + else + { + data += sent; + len -= sent; + } + } + + return 0; +} + +/******************************************************************************/ +static int +rdpClientConSendMsg(rdpPtr dev, rdpClientCon *clientCon) +{ + int len; + int rv; + struct stream *s; + + rv = 1; + s = clientCon->out_s; + if (s != NULL) + { + len = (int) (s->end - s->data); + + if (len > s->size) + { + LLOGLN(0, ("rdpClientConSendMsg: overrun error len %d count %d", + len, clientCon->count)); + } + + s_pop_layer(s, iso_hdr); + out_uint16_le(s, 3); + out_uint16_le(s, clientCon->count); + out_uint32_le(s, len - 8); + rv = rdpClientConSend(dev, clientCon, s->data, len); + } + + if (rv != 0) + { + LLOGLN(0, ("rdpClientConSendMsg: error in rdpup_send_msg")); + } + + return rv; +} + +/******************************************************************************/ +static int +rdpClientConSendPending(rdpPtr dev, rdpClientCon *clientCon) +{ + int rv; + + rv = 0; + if (clientCon->connected && clientCon->begin) + { + out_uint16_le(clientCon->out_s, 2); /* XR_SERVER_END_UPDATE */ + out_uint16_le(clientCon->out_s, 4); /* size */ + clientCon->count++; + s_mark_end(clientCon->out_s); + if (rdpClientConSendMsg(dev, clientCon) != 0) + { + LLOGLN(0, ("rdpClientConSendPending: rdpClientConSendMsg failed")); + rv = 1; + } + } + clientCon->count = 0; + clientCon->begin = FALSE; + return rv; +} + +/******************************************************************************/ +static CARD32 +rdpClientConDeferredUpdateCallback(OsTimerPtr timer, CARD32 now, pointer arg) +{ + rdpPtr dev; + rdpClientCon *clientCon; + + LLOGLN(10, ("rdpClientConDeferredUpdateCallback")); + + dev = (rdpPtr) arg; + clientCon = dev->clientConHead; + while (clientCon != NULL) + { + if (dev->do_dirty_ons) + { + if (clientCon->rectId == clientCon->rectIdAck) + { + rdpClientConCheckDirtyScreen(dev, clientCon); + } + else + { + LLOGLN(0, ("rdpClientConDeferredUpdateCallback: skipping")); + } + } + else + { + rdpClientConSendPending(dev, clientCon); + } + clientCon = clientCon->next; + } + dev->sendUpdateScheduled = FALSE; + return 0; +} + +/******************************************************************************/ +void +rdpClientConScheduleDeferredUpdate(rdpPtr dev) +{ + if (dev->sendUpdateScheduled == FALSE) + { + dev->sendUpdateScheduled = TRUE; + dev->sendUpdateTimer = TimerSet(dev->sendUpdateTimer, 0, 40, + rdpClientConDeferredUpdateCallback, + dev); + } +} + +/******************************************************************************/ +int +rdpClientConCheckDirtyScreen(rdpPtr dev, rdpClientCon *clientCon) +{ + return 0; +} diff --git a/xorg/server/module/rdpClientCon.h b/xorg/server/module/rdpClientCon.h index 85a3925a..f288fd7c 100644 --- a/xorg/server/module/rdpClientCon.h +++ b/xorg/server/module/rdpClientCon.h @@ -24,6 +24,15 @@ Client connection to xrdp #ifndef _RDPCLIENTCON_H #define _RDPCLIENTCON_H +struct rdpup_os_bitmap +{ + int used; + PixmapPtr pixmap; + rdpPixmapPtr priv; + int stamp; +}; + +/* one of these for each client */ struct _rdpClientCon { int sck; @@ -31,6 +40,24 @@ struct _rdpClientCon int sckControl; struct stream *out_s; struct stream *in_s; + + int rectIdAck; + int rectId; + int connected; /* boolean */ + int begin; /* boolean */ + int count; + int sckClosed; /* boolean */ + struct rdpup_os_bitmap *osBitmaps; + int maxOsBitmaps; + int osBitmapStamp; + int osBitmapAllocSize; + int osBitmapNumUsed; + + int rdp_bpp; /* client depth */ + int rdp_Bpp_mask; + + int rdpIndex; /* current os target */ + struct _rdpClientCon *next; }; @@ -41,4 +68,16 @@ rdpClientConInit(rdpPtr dev); int rdpClientConDeinit(rdpPtr dev); +int +rdpClientConDeleteOsSurface(rdpPtr dev, rdpClientCon *clientCon, int rdpindex); + +int +rdpClientConRemoveOsBitmap(rdpPtr dev, rdpClientCon *clientCon, int rdpindex); + +void +rdpClientConScheduleDeferredUpdate(rdpPtr dev); +int +rdpClientConCheckDirtyScreen(rdpPtr dev, rdpClientCon *clientCon); + + #endif diff --git a/xorg/server/module/rdpDraw.c b/xorg/server/module/rdpDraw.c index 08fe4b85..cbb7ce75 100644 --- a/xorg/server/module/rdpDraw.c +++ b/xorg/server/module/rdpDraw.c @@ -39,11 +39,100 @@ misc draw calls #include "rdp.h" #include "rdpDraw.h" +#include "rdpClientCon.h" +#include "rdpMisc.h" +#include "rdpGlyphs.h" +#include "rdpReg.h" #define LOG_LEVEL 1 #define LLOGLN(_level, _args) \ do { if (_level < LOG_LEVEL) { ErrorF _args ; ErrorF("\n"); } } while (0) +/******************************************************************************/ +int +rdpDrawItemAdd(rdpPtr dev, rdpPixmapRec *priv, struct rdp_draw_item *di) +{ + priv->is_alpha_dirty_not = FALSE; + + if (priv->draw_item_tail == NULL) + { + priv->draw_item_tail = di; + priv->draw_item_head = di; + } + else + { + di->prev = priv->draw_item_tail; + priv->draw_item_tail->next = di; + priv->draw_item_tail = di; + } + + if (priv == &(dev->screenPriv)) + { + rdpClientConScheduleDeferredUpdate(dev); + } + + return 0; +} + +/******************************************************************************/ +int +rdpDrawItemRemove(rdpPtr dev, rdpPixmapRec *priv, struct rdp_draw_item *di) +{ + if (di->prev != NULL) + { + di->prev->next = di->next; + } + + if (di->next != NULL) + { + di->next->prev = di->prev; + } + + if (priv->draw_item_head == di) + { + priv->draw_item_head = di->next; + } + + if (priv->draw_item_tail == di) + { + priv->draw_item_tail = di->prev; + } + + if (di->type == RDI_LINE) + { + if (di->u.line.segs != NULL) + { + g_free(di->u.line.segs); + } + } + + if (di->type == RDI_TEXT) + { + rdpGlyphDeleteRdpText(di->u.text.rtext); + } + + rdpRegionDestroy(di->reg); + g_free(di); + return 0; +} + +/******************************************************************************/ +int +rdpDrawItemRemoveAll(rdpPtr dev, rdpPixmapRec *priv) +{ + struct rdp_draw_item *di; + + di = priv->draw_item_head; + + while (di != NULL) + { + rdpDrawItemRemove(dev, priv, di); + di = priv->draw_item_head; + } + + return 0; +} + /*****************************************************************************/ void rdpCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr pOldRegion) diff --git a/xorg/server/module/rdpDraw.h b/xorg/server/module/rdpDraw.h index e2711768..2f4aea2f 100644 --- a/xorg/server/module/rdpDraw.h +++ b/xorg/server/module/rdpDraw.h @@ -50,6 +50,12 @@ do { \ extern GCOps g_rdpGCOps; /* in rdpGC.c */ +int +rdpDrawItemAdd(rdpPtr dev, rdpPixmapRec *priv, struct rdp_draw_item *di); +int +rdpDrawItemRemove(rdpPtr dev, rdpPixmapRec *priv, struct rdp_draw_item *di); +int +rdpDrawItemRemoveAll(rdpPtr dev, rdpPixmapRec *priv); void rdpCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr pOldRegion); Bool diff --git a/xorg/server/module/rdpGlyphs.c b/xorg/server/module/rdpGlyphs.c index fc2d347b..71e8a660 100644 --- a/xorg/server/module/rdpGlyphs.c +++ b/xorg/server/module/rdpGlyphs.c @@ -38,6 +38,8 @@ gylph(font) calls #include "rdp.h" #include "rdpGlyphs.h" #include "rdpDraw.h" +#include "rdpMisc.h" +#include "rdpReg.h" /******************************************************************************/ #define LOG_LEVEL 1 @@ -45,6 +47,30 @@ gylph(font) calls do { if (_level < LOG_LEVEL) { ErrorF _args ; ErrorF("\n"); } } while (0) /******************************************************************************/ +int +rdpGlyphDeleteRdpText(struct rdp_text *rtext) +{ + int index; + + if (rtext == NULL) + { + return 0; + } + for (index = 0; index < rtext->num_chars; index++) + { + if (rtext->chars[index] != NULL) + { + g_free(rtext->chars[index]->data); + g_free(rtext->chars[index]); + } + } + rdpRegionDestroy(rtext->reg); + rdpGlyphDeleteRdpText(rtext->next); + g_free(rtext); + return 0; +} + +/******************************************************************************/ static void rdpGlyphsOrg(PictureScreenPtr ps, rdpPtr dev, CARD8 op, PicturePtr pSrc, PicturePtr pDst, diff --git a/xorg/server/module/rdpGlyphs.h b/xorg/server/module/rdpGlyphs.h index d451d9f9..24e978a1 100644 --- a/xorg/server/module/rdpGlyphs.h +++ b/xorg/server/module/rdpGlyphs.h @@ -24,6 +24,35 @@ gylph(font) calls #ifndef _RDPGLYPHS_H #define _RDPGLYPHS_H +struct rdp_font_char +{ + int offset; /* x */ + int baseline; /* y */ + int width; /* cx */ + int height; /* cy */ + int incby; + int bpp; + char *data; + int data_bytes; +}; + +struct rdp_text +{ + RegionPtr reg; + int font; + int x; + int y; + int flags; + int mixmode; + char data[256]; + int data_bytes; + struct rdp_font_char* chars[256]; + int num_chars; + struct rdp_text* next; +}; + +int +rdpGlyphDeleteRdpText(struct rdp_text* rtext); void rdpGlyphs(CARD8 op, PicturePtr pSrc, PicturePtr pDst, PictFormatPtr maskFormat, diff --git a/xorg/server/module/rdpMisc.c b/xorg/server/module/rdpMisc.c index 34e71110..326deff3 100644 --- a/xorg/server/module/rdpMisc.c +++ b/xorg/server/module/rdpMisc.c @@ -67,14 +67,14 @@ rdpBitsPerPixel(int depth) /*****************************************************************************/ int -g_tcp_recv(int sck, void *ptr, int len, int flags) +g_sck_recv(int sck, void *ptr, int len, int flags) { return recv(sck, ptr, len, flags); } /*****************************************************************************/ void -g_tcp_close(int sck) +g_sck_close(int sck) { if (sck == 0) { @@ -87,7 +87,7 @@ g_tcp_close(int sck) /*****************************************************************************/ int -g_tcp_last_error_would_block(int sck) +g_sck_last_error_would_block(int sck) { return (errno == EWOULDBLOCK) || (errno == EINPROGRESS); } @@ -101,7 +101,7 @@ g_sleep(int msecs) /*****************************************************************************/ int -g_tcp_send(int sck, void *ptr, int len, int flags) +g_sck_send(int sck, void *ptr, int len, int flags) { return send(sck, ptr, len, flags); } @@ -146,7 +146,7 @@ g_sprintf(char *dest, char *format, ...) /*****************************************************************************/ int -g_tcp_socket(void) +g_sck_tcp_socket(void) { int rv; int i; @@ -160,14 +160,14 @@ g_tcp_socket(void) /*****************************************************************************/ int -g_tcp_local_socket_dgram(void) +g_sck_local_socket_dgram(void) { return socket(AF_UNIX, SOCK_DGRAM, 0); } /*****************************************************************************/ int -g_tcp_local_socket_stream(void) +g_sck_local_socket_stream(void) { return socket(AF_UNIX, SOCK_STREAM, 0); } @@ -188,7 +188,7 @@ g_memset(void *d_ptr, const unsigned char chr, int size) /*****************************************************************************/ int -g_tcp_set_no_delay(int sck) +g_sck_tcp_set_no_delay(int sck) { int i; @@ -199,7 +199,7 @@ g_tcp_set_no_delay(int sck) /*****************************************************************************/ int -g_tcp_set_non_blocking(int sck) +g_sck_set_non_blocking(int sck) { unsigned long i; @@ -211,7 +211,7 @@ g_tcp_set_non_blocking(int sck) /*****************************************************************************/ int -g_tcp_accept(int sck) +g_sck_accept(int sck) { struct sockaddr_in s; unsigned int i; @@ -223,7 +223,7 @@ g_tcp_accept(int sck) /*****************************************************************************/ int -g_tcp_select(int sck1, int sck2, int sck3) +g_sck_select(int sck1, int sck2, int sck3) { fd_set rfds; struct timeval time; @@ -292,7 +292,7 @@ g_tcp_select(int sck1, int sck2, int sck3) /*****************************************************************************/ int -g_tcp_bind(int sck, char *port) +g_sck_tcp_bind(int sck, char *port) { struct sockaddr_in s; @@ -305,7 +305,7 @@ g_tcp_bind(int sck, char *port) /*****************************************************************************/ int -g_tcp_local_bind(int sck, char *port) +g_sck_local_bind(int sck, char *port) { struct sockaddr_un s; @@ -317,7 +317,7 @@ g_tcp_local_bind(int sck, char *port) /*****************************************************************************/ int -g_tcp_listen(int sck) +g_sck_listen(int sck) { return listen(sck, 2); } diff --git a/xorg/server/module/rdpMisc.h b/xorg/server/module/rdpMisc.h index bed95891..ff54dc0e 100644 --- a/xorg/server/module/rdpMisc.h +++ b/xorg/server/module/rdpMisc.h @@ -29,15 +29,15 @@ the rest int rdpBitsPerPixel(int depth); int -g_tcp_recv(int sck, void *ptr, int len, int flags); +g_sck_recv(int sck, void *ptr, int len, int flags); void -g_tcp_close(int sck); +g_sck_close(int sck); int -g_tcp_last_error_would_block(int sck); +g_sck_last_error_would_block(int sck); void g_sleep(int msecs); int -g_tcp_send(int sck, void *ptr, int len, int flags); +g_sck_send(int sck, void *ptr, int len, int flags); void * g_malloc(int size, int zero); void @@ -45,29 +45,29 @@ g_free(void *ptr); void g_sprintf(char *dest, char *format, ...); int -g_tcp_socket(void); +g_sck_tcp_socket(void); int -g_tcp_local_socket_dgram(void); +g_sck_local_socket_dgram(void); int -g_tcp_local_socket_stream(void); +g_sck_local_socket_stream(void); void g_memcpy(void *d_ptr, const void *s_ptr, int size); void g_memset(void *d_ptr, const unsigned char chr, int size); int -g_tcp_set_no_delay(int sck); +g_sck_tcp_set_no_delay(int sck); int -g_tcp_set_non_blocking(int sck); +g_sck_set_non_blocking(int sck); int -g_tcp_accept(int sck); +g_sck_accept(int sck); int -g_tcp_select(int sck1, int sck2, int sck3); +g_sck_select(int sck1, int sck2, int sck3); int -g_tcp_bind(int sck, char *port); +g_sck_tcp_bind(int sck, char *port); int -g_tcp_local_bind(int sck, char *port); +g_sck_local_bind(int sck, char *port); int -g_tcp_listen(int sck); +g_sck_listen(int sck); int g_create_dir(const char *dirname); int @@ -87,7 +87,6 @@ g_hexdump(unsigned char *p, unsigned int len); # error Unknown endianness in rdp.h #endif /* check if we need to align data */ -/* check if we need to align data */ #if defined(__sparc__) || defined(__alpha__) || defined(__hppa__) || \ defined(__AIX__) || defined(__PPC__) || defined(__mips__) || \ defined(__ia64__) || defined(__ppc__) || defined(__arm__) @@ -97,157 +96,164 @@ g_hexdump(unsigned char *p, unsigned int len); /* parser state */ struct stream { - char* p; - char* end; - char* data; - int size; - /* offsets of various headers */ - char* iso_hdr; - char* mcs_hdr; - char* sec_hdr; - char* rdp_hdr; - char* channel_hdr; - char* next_packet; + char *p; + char *end; + char *data; + int size; + /* offsets of various headers */ + char *iso_hdr; + char *mcs_hdr; + char *sec_hdr; + char *rdp_hdr; + char *channel_hdr; + char *next_packet; }; /******************************************************************************/ #define s_push_layer(s, h, n) \ -{ \ - (s)->h = (s)->p; \ - (s)->p += (n); \ -} +do { \ + (s)->h = (s)->p; \ + (s)->p += (n); \ +} while (0) /******************************************************************************/ #define s_pop_layer(s, h) \ -{ \ - (s)->p = (s)->h; \ -} +do { \ + (s)->p = (s)->h; \ +} while (0) /******************************************************************************/ #if defined(B_ENDIAN) || defined(NEED_ALIGN) -#define out_uint16_le(s, v) \ -{ \ - *((s)->p) = (unsigned char)((v) >> 0); \ - (s)->p++; \ - *((s)->p) = (unsigned char)((v) >> 8); \ - (s)->p++; \ -} +#define out_uint16_le(s, v) \ +do { \ + *((s)->p) = (unsigned char)((v) >> 0); \ + (s)->p++; \ + *((s)->p) = (unsigned char)((v) >> 8); \ + (s)->p++; \ +} while (0) #else -#define out_uint16_le(s, v) \ -{ \ - *((unsigned short*)((s)->p)) = (unsigned short)(v); \ - (s)->p += 2; \ -} +#define out_uint16_le(s, v) \ +do { \ + *((unsigned short*)((s)->p)) = (unsigned short)(v); \ + (s)->p += 2; \ +} while (0) #endif /******************************************************************************/ -#define init_stream(s, v) \ -{ \ - if ((v) > (s)->size) \ - { \ - g_free((s)->data); \ - (s)->data = (char*)g_malloc((v), 0); \ - (s)->size = (v); \ - } \ - (s)->p = (s)->data; \ - (s)->end = (s)->data; \ - (s)->next_packet = 0; \ -} +#define init_stream(s, v) \ +do { \ + if ((v) > (s)->size) \ + { \ + g_free((s)->data); \ + (s)->data = (char*)g_malloc((v), 0); \ + (s)->size = (v); \ + } \ + (s)->p = (s)->data; \ + (s)->end = (s)->data; \ + (s)->next_packet = 0; \ +} while (0) /******************************************************************************/ -#define out_uint8p(s, v, n) \ -{ \ - g_memcpy((s)->p, (v), (n)); \ - (s)->p += (n); \ -} +#define out_uint8p(s, v, n) \ +do { \ + g_memcpy((s)->p, (v), (n)); \ + (s)->p += (n); \ +} while (0) /******************************************************************************/ -#define out_uint8a(s, v, n) \ -{ \ - out_uint8p((s), (v), (n)); \ -} +#define out_uint8a(s, v, n) \ +do { \ + out_uint8p((s), (v), (n)); \ +} while (0) + +/******************************************************************************/ +#define out_uint8(s, v) \ +do { \ + *((s)->p) = (unsigned char)((v) >> 0); \ + (s)->p++; \ +} while (0) /******************************************************************************/ #if defined(B_ENDIAN) || defined(NEED_ALIGN) -#define out_uint32_le(s, v) \ -{ \ - *((s)->p) = (unsigned char)((v) >> 0); \ - (s)->p++; \ - *((s)->p) = (unsigned char)((v) >> 8); \ - (s)->p++; \ - *((s)->p) = (unsigned char)((v) >> 16); \ - (s)->p++; \ - *((s)->p) = (unsigned char)((v) >> 24); \ - (s)->p++; \ -} +#define out_uint32_le(s, v) \ +do { \ + *((s)->p) = (unsigned char)((v) >> 0); \ + (s)->p++; \ + *((s)->p) = (unsigned char)((v) >> 8); \ + (s)->p++; \ + *((s)->p) = (unsigned char)((v) >> 16); \ + (s)->p++; \ + *((s)->p) = (unsigned char)((v) >> 24); \ + (s)->p++; \ +} while (0) #else -#define out_uint32_le(s, v) \ -{ \ - *((unsigned int*)((s)->p)) = (v); \ - (s)->p += 4; \ -} +#define out_uint32_le(s, v) \ +do { \ + *((unsigned int*)((s)->p)) = (v); \ + (s)->p += 4; \ +} while (0) #endif /******************************************************************************/ #if defined(B_ENDIAN) || defined(NEED_ALIGN) -#define in_uint32_le(s, v) \ -{ \ - (v) = (unsigned int) \ - ( \ - (*((unsigned char*)((s)->p + 0)) << 0) | \ - (*((unsigned char*)((s)->p + 1)) << 8) | \ - (*((unsigned char*)((s)->p + 2)) << 16) | \ - (*((unsigned char*)((s)->p + 3)) << 24) \ - ); \ - (s)->p += 4; \ -} +#define in_uint32_le(s, v) \ +do { \ + (v) = (unsigned int) \ + ( \ + (*((unsigned char*)((s)->p + 0)) << 0) | \ + (*((unsigned char*)((s)->p + 1)) << 8) | \ + (*((unsigned char*)((s)->p + 2)) << 16) | \ + (*((unsigned char*)((s)->p + 3)) << 24) \ + ); \ + (s)->p += 4; \ +} while (0) #else -#define in_uint32_le(s, v) \ -{ \ - (v) = *((unsigned int*)((s)->p)); \ - (s)->p += 4; \ -} +#define in_uint32_le(s, v) \ +do { \ + (v) = *((unsigned int*)((s)->p)); \ + (s)->p += 4; \ +} while (0) #endif /******************************************************************************/ #if defined(B_ENDIAN) || defined(NEED_ALIGN) -#define in_uint16_le(s, v) \ -{ \ - (v) = (unsigned short) \ - ( \ - (*((unsigned char*)((s)->p + 0)) << 0) | \ - (*((unsigned char*)((s)->p + 1)) << 8) \ - ); \ - (s)->p += 2; \ -} +#define in_uint16_le(s, v) \ +do { \ + (v) = (unsigned short) \ + ( \ + (*((unsigned char*)((s)->p + 0)) << 0) | \ + (*((unsigned char*)((s)->p + 1)) << 8) \ + ); \ + (s)->p += 2; \ +} while (0) #else -#define in_uint16_le(s, v) \ -{ \ - (v) = *((unsigned short*)((s)->p)); \ - (s)->p += 2; \ -} +#define in_uint16_le(s, v) \ +do { \ + (v) = *((unsigned short*)((s)->p)); \ + (s)->p += 2; \ +} while (0) #endif /******************************************************************************/ -#define s_mark_end(s) \ -{ \ - (s)->end = (s)->p; \ -} +#define s_mark_end(s) \ +do { \ + (s)->end = (s)->p; \ +} while (0) /******************************************************************************/ -#define make_stream(s) \ -{ \ - (s) = (struct stream*)g_malloc(sizeof(struct stream), 1); \ -} +#define make_stream(s) \ +do { \ + (s) = (struct stream*)g_malloc(sizeof(struct stream), 1); \ +} while (0) /******************************************************************************/ -#define free_stream(s) do \ -{ \ - if ((s) != 0) \ - { \ - g_free((s)->data); \ - } \ - g_free((s)); \ +#define free_stream(s) \ +do { \ + if ((s) != 0) \ + { \ + g_free((s)->data); \ + } \ + g_free((s)); \ } while (0) #endif diff --git a/xorg/server/module/rdpPolyFillRect.c b/xorg/server/module/rdpPolyFillRect.c index 1de9cee1..63898e23 100644 --- a/xorg/server/module/rdpPolyFillRect.c +++ b/xorg/server/module/rdpPolyFillRect.c @@ -32,6 +32,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "rdp.h" #include "rdpDraw.h" +#include "rdpClientCon.h" #define LOG_LEVEL 1 #define LLOGLN(_level, _args) \ @@ -39,6 +40,14 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. /******************************************************************************/ static void +rdpPolyFillRectPre(rdpClientCon *clientCon, + DrawablePtr pDrawable, GCPtr pGC, int nrectFill, + xRectangle *prectInit) +{ +} + +/******************************************************************************/ +static void rdpPolyFillRectOrg(DrawablePtr pDrawable, GCPtr pGC, int nrectFill, xRectangle *prectInit) { @@ -50,11 +59,35 @@ rdpPolyFillRectOrg(DrawablePtr pDrawable, GCPtr pGC, int nrectFill, } /******************************************************************************/ +static void +rdpPolyFillRectPost(rdpClientCon *clientCon, + DrawablePtr pDrawable, GCPtr pGC, int nrectFill, + xRectangle *prectInit) +{ +} + +/******************************************************************************/ void rdpPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrectFill, xRectangle *prectInit) { + rdpPtr dev; + rdpClientCon *clientCon; + LLOGLN(10, ("rdpPolyFillRect:")); + dev = rdpGetDevFromScreen(pGC->pScreen); + clientCon = dev->clientConHead; + while (clientCon != NULL) + { + rdpPolyFillRectPre(clientCon, pDrawable, pGC, nrectFill, prectInit); + clientCon = clientCon->next; + } /* do original call */ rdpPolyFillRectOrg(pDrawable, pGC, nrectFill, prectInit); + clientCon = dev->clientConHead; + while (clientCon != NULL) + { + rdpPolyFillRectPost(clientCon, pDrawable, pGC, nrectFill, prectInit); + clientCon = clientCon->next; + } } diff --git a/xrdpvr/xrdpvr.c b/xrdpvr/xrdpvr.c index 09a0a6b8..46326e9e 100644 --- a/xrdpvr/xrdpvr.c +++ b/xrdpvr/xrdpvr.c @@ -28,6 +28,49 @@ PLAYER_STATE_INFO g_psi; int g_video_index = -1; int g_audio_index = -1; +/*****************************************************************************/ +/* produce a hex dump */ +void hexdump(char *p, int len) +{ + unsigned char *line; + int i; + int thisline; + int offset; + + line = (unsigned char *)p; + offset = 0; + + while (offset < len) + { + printf("%04x ", offset); + thisline = len - offset; + + if (thisline > 16) + { + thisline = 16; + } + + for (i = 0; i < thisline; i++) + { + printf("%02x ", line[i]); + } + + for (; i < 16; i++) + { + printf(" "); + } + + for (i = 0; i < thisline; i++) + { + printf("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.'); + } + + printf("\n"); + offset += thisline; + line += thisline; + } +} + /** * initialize the media player * @@ -40,11 +83,15 @@ int g_audio_index = -1; int xrdpvr_init_player(void *channel, int stream_id, char *filename) { + printf("xrdpvr_init_player:\n"); if ((channel == NULL) || (stream_id <= 0) || (filename == NULL)) { return -1; } + xrdpvr_send_init(channel); + +#if 0 /* send metadata from media file to client */ if (xrdpvr_create_metadata_file(channel, filename)) { @@ -68,6 +115,8 @@ xrdpvr_init_player(void *channel, int stream_id, char *filename) printf("xrdpvr_set_audio_format() failed\n"); return 1; } +#endif + } /** @@ -173,7 +222,7 @@ xrdpvr_play_media(void *channel, int stream_id, char *filename) return -1; } -#if 0 +#if 1 /* print media info to standard out */ av_dump_format(g_psi.p_format_ctx, 0, filename, 0); #endif @@ -182,13 +231,15 @@ xrdpvr_play_media(void *channel, int stream_id, char *filename) for (i = 0; i < g_psi.p_format_ctx->nb_streams; i++) { if (g_psi.p_format_ctx->streams[i]->codec->codec_type == CODEC_TYPE_VIDEO && - g_video_index < 0) + g_psi.p_format_ctx->streams[i]->codec->codec_id == CODEC_ID_H264 && + g_video_index < 0) { g_video_index = i; } if (g_psi.p_format_ctx->streams[i]->codec->codec_type == CODEC_TYPE_AUDIO && - g_audio_index < 0) + g_psi.p_format_ctx->streams[i]->codec->codec_id == CODEC_ID_AAC && + g_audio_index < 0) { g_audio_index = i; } @@ -235,6 +286,12 @@ xrdpvr_play_media(void *channel, int stream_id, char *filename) return -1; } + printf("%d\n", g_psi.p_audio_codec_ctx->extradata_size); + hexdump(g_psi.p_audio_codec_ctx->extradata, g_psi.p_audio_codec_ctx->extradata_size); + printf("%d %d %d %d\n", g_psi.p_audio_codec_ctx->sample_rate, + g_psi.p_audio_codec_ctx->bit_rate, g_psi.p_audio_codec_ctx->channels, + g_psi.p_audio_codec_ctx->block_align); + /* open decoder for video stream */ //if (avcodec_open2(g_psi.p_video_codec_ctx, g_psi.p_video_codec, // NULL) < 0) @@ -244,17 +301,45 @@ xrdpvr_play_media(void *channel, int stream_id, char *filename) return -1; } + g_psi.bsfc = av_bitstream_filter_init("h264_mp4toannexb"); + printf("g_psi.bsfc %p\n", g_psi.bsfc); + + if (xrdpvr_set_video_format(channel, 101)) + { + printf("xrdpvr_set_video_format() failed\n"); + return -1; + } + + printf("xrdpvr_play_media: calling xrdpvr_set_audio_format\n"); + if (xrdpvr_set_audio_format(channel, 101, + g_psi.p_audio_codec_ctx->extradata, + g_psi.p_audio_codec_ctx->extradata_size, + g_psi.p_audio_codec_ctx->sample_rate, + g_psi.p_audio_codec_ctx->bit_rate, + g_psi.p_audio_codec_ctx->channels, + g_psi.p_audio_codec_ctx->block_align)) + { + printf("xrdpvr_set_audio_format() failed\n"); + return 1; + } + return 0; } static int firstAudioPkt = 1; static int firstVideoPkt = 1; -int xrdpvr_get_frame(void **av_pkt_ret, int *is_video_frame, int *delay_in_us) +/******************************************************************************/ +int +xrdpvr_get_frame(void **av_pkt_ret, int *is_video_frame, int *delay_in_us) { - AVPacket *av_pkt; - double dts; + AVPacket *av_pkt; + double dts; + int error; + AVBitStreamFilterContext *bsfc; + AVPacket new_pkt; + //printf("xrdpvr_get_frame:\n"); /* alloc an AVPacket */ if ((av_pkt = (AVPacket *) malloc(sizeof(AVPacket))) == NULL) return -1; @@ -292,6 +377,34 @@ int xrdpvr_get_frame(void **av_pkt_ret, int *is_video_frame, int *delay_in_us) } else if (av_pkt->stream_index == g_video_index) { + + bsfc = g_psi.bsfc; + //printf("hi %p\n", bsfc); + while (bsfc != 0) + { + new_pkt = *av_pkt; + error = av_bitstream_filter_filter(bsfc, g_psi.p_video_codec_ctx, 0, + &new_pkt.data, &new_pkt.size, + av_pkt->data, av_pkt->size, + av_pkt->flags & AV_PKT_FLAG_KEY); + //printf("new size %d\n", new_pkt.size); + //hexdump(new_pkt.data, 32); + //printf("old size %d\n", av_pkt->size); + //hexdump(av_pkt->data, 32); + if (error > 0) + { + av_free_packet(av_pkt); + new_pkt.destruct = av_destruct_packet; + } + else if (error < 0) + { + printf("bitstream filter error\n"); + } + *av_pkt = new_pkt; + bsfc = bsfc->next; + } + + dts = av_pkt->dts; //printf("$$$ video raw_dts=%f raw_pts=%f\n", (double) av_pkt->dts, (double) av_pkt->dts); @@ -324,7 +437,9 @@ int xrdpvr_get_frame(void **av_pkt_ret, int *is_video_frame, int *delay_in_us) return 0; } -int send_audio_pkt(void *channel, int stream_id, void *pkt_p) +/******************************************************************************/ +int +send_audio_pkt(void *channel, int stream_id, void *pkt_p) { AVPacket *av_pkt = (AVPacket *) pkt_p; @@ -333,7 +448,9 @@ int send_audio_pkt(void *channel, int stream_id, void *pkt_p) free(av_pkt); } -int send_video_pkt(void *channel, int stream_id, void *pkt_p) +/******************************************************************************/ +int +send_video_pkt(void *channel, int stream_id, void *pkt_p) { AVPacket *av_pkt = (AVPacket *) pkt_p; @@ -342,11 +459,18 @@ int send_video_pkt(void *channel, int stream_id, void *pkt_p) free(av_pkt); } -int xrdpvr_play_frame(void *channel, int stream_id, int *videoTimeout, int *audioTimeout) +/******************************************************************************/ +int +xrdpvr_play_frame(void *channel, int stream_id, int *videoTimeout, int *audioTimeout) { - AVPacket av_pkt; - double dts; - int delay_in_us; + AVPacket av_pkt; + double dts; + int delay_in_us; + int error; + AVBitStreamFilterContext *bsfc; + AVPacket new_pkt; + + //printf("xrdpvr_play_frame:\n"); if (av_read_frame(g_psi.p_format_ctx, &av_pkt) < 0) { @@ -375,12 +499,34 @@ int xrdpvr_play_frame(void *channel, int stream_id, int *videoTimeout, int *audi g_psi.audioTimeout = dts; } - //printf("audio delay: %d\n", delay_in_us); + printf("audio delay: %d\n", delay_in_us); usleep(delay_in_us); //usleep(1000 * 1); } else if (av_pkt.stream_index == g_video_index) { + bsfc = g_psi.bsfc; + printf("hi %p\n", bsfc); + while (bsfc != 0) + { + new_pkt= av_pkt; + error = av_bitstream_filter_filter(bsfc, g_psi.p_video_codec_ctx, 0, + &new_pkt.data, &new_pkt.size, + av_pkt.data, av_pkt.size, + av_pkt.flags & AV_PKT_FLAG_KEY); + if (error > 0) + { + av_free_packet(&av_pkt); + new_pkt.destruct = av_destruct_packet; + } + else if (error < 0) + { + printf("bitstream filter error\n"); + } + av_pkt = new_pkt; + bsfc = bsfc->next; + } + xrdpvr_send_video_data(channel, stream_id, av_pkt.size, av_pkt.data); dts = av_pkt.dts; @@ -404,7 +550,7 @@ int xrdpvr_play_frame(void *channel, int stream_id, int *videoTimeout, int *audi //printf("xrdpvr_play_frame:video2: saved=%f dts=%f delay_in_us=%d\n", g_psi.videoTimeout, dts, delay_in_us); } - //printf("video delay: %d\n", delay_in_us); + printf("video delay: %d\n", delay_in_us); usleep(delay_in_us); } @@ -412,6 +558,7 @@ int xrdpvr_play_frame(void *channel, int stream_id, int *videoTimeout, int *audi return 0; } +/******************************************************************************/ int xrdpvr_seek_media(int64_t pos, int backward) { @@ -439,6 +586,7 @@ xrdpvr_seek_media(int64_t pos, int backward) return 0; } +/******************************************************************************/ void xrdpvr_get_media_duration(int64_t *start_time, int64_t *duration) { @@ -446,6 +594,7 @@ xrdpvr_get_media_duration(int64_t *start_time, int64_t *duration) *duration = g_psi.p_format_ctx->duration / AV_TIME_BASE; } +/******************************************************************************/ int xrdpvr_set_geometry(void *channel, int stream_id, int xpos, int ypos, int width, int height) { @@ -454,7 +603,7 @@ xrdpvr_set_geometry(void *channel, int stream_id, int xpos, int ypos, int width, int rv; int len; -printf("xrdpvr_set_geometry: entered; x=%d y=%d\n", xpos, ypos); + printf("xrdpvr_set_geometry: entered; x=%d y=%d\n", xpos, ypos); stream_new(s, MAX_PDU_SIZE); @@ -496,7 +645,6 @@ xrdpvr_set_video_format(void *channel, uint32_t stream_id) int len; stream_new(s, MAX_PDU_SIZE); - stream_ins_u32_le(s, 0); /* number of bytes to follow */ stream_ins_u32_le(s, CMD_SET_VIDEO_FORMAT); stream_ins_u32_le(s, stream_id); @@ -523,7 +671,9 @@ xrdpvr_set_video_format(void *channel, uint32_t stream_id) * @return 0 on success, -1 on error *****************************************************************************/ int -xrdpvr_set_audio_format(void *channel, uint32_t stream_id) +xrdpvr_set_audio_format(void *channel, uint32_t stream_id, char *extradata, + int extradata_size, int sample_rate, int bit_rate, + int channels, int block_align) { STREAM *s; char *cptr; @@ -532,9 +682,20 @@ xrdpvr_set_audio_format(void *channel, uint32_t stream_id) stream_new(s, MAX_PDU_SIZE); + printf("extradata_size %d sample_rate %d bit_rate %d channels %d " + "block_align %d\n", extradata_size, sample_rate, bit_rate, + channels, block_align); + stream_ins_u32_le(s, 0); /* number of bytes to follow */ stream_ins_u32_le(s, CMD_SET_AUDIO_FORMAT); stream_ins_u32_le(s, stream_id); + stream_ins_u32_le(s, extradata_size); + memcpy(s->p, extradata, extradata_size); + s->p += extradata_size; + stream_ins_u32_le(s, sample_rate); + stream_ins_u32_le(s, bit_rate); + stream_ins_u32_le(s, channels); + stream_ins_u32_le(s, block_align); /* insert number of bytes in stream */ len = stream_length(s) - 4; @@ -567,6 +728,7 @@ xrdpvr_send_video_data(void *channel, uint32_t stream_id, uint32_t data_len, uin int rv; int len; + //printf("xrdpvr_send_video_data:\n"); stream_new(s, MAX_PDU_SIZE + data_len); stream_ins_u32_le(s, 0); /* number of bytes to follow */ @@ -611,6 +773,7 @@ xrdpvr_send_audio_data(void *channel, uint32_t stream_id, uint32_t data_len, uin int rv; int len; + //printf("xrdpvr_send_audio_data:\n"); stream_new(s, MAX_PDU_SIZE + data_len); stream_ins_u32_le(s, 0); /* number of bytes to follow */ @@ -629,6 +792,7 @@ xrdpvr_send_audio_data(void *channel, uint32_t stream_id, uint32_t data_len, uin /* write data to virtual channel */ rv = xrdpvr_write_to_client(channel, s); stream_free(s); + return rv; } @@ -708,6 +872,33 @@ xrdpvr_create_metadata_file(void *channel, char *filename) } /** + ******************************************************************************/ +static int +xrdpvr_read_from_client(void *channel, STREAM *s, int bytes, int timeout) +{ + unsigned int bytes_read; + int total_read; + int ok; + + //printf("xrdpvr_read_from_client:\n"); + total_read = 0; + while (total_read < bytes) + { + //printf("xrdpvr_read_from_client: loop\n"); + bytes_read = bytes - total_read; + ok = WTSVirtualChannelRead(channel, timeout, s->p, bytes_read, &bytes_read); + //printf("xrdpvr_read_from_client: loop ok %d\n", ok); + if (ok) + { + //printf("xrdpvr_read_from_client: bytes_read %d\n", bytes_read); + total_read += bytes_read; + s->p += bytes_read; + } + } + return 0; +} + +/** * write data to a xrdpvr client * * @param channel opaque handle returned by WTSVirtualChannelOpenEx @@ -785,3 +976,43 @@ xrdpvr_set_volume(void *channel, int volume) stream_free(s); return rv; } + +int +xrdpvr_send_init(void *channel) +{ + STREAM *s; + char *cptr; + int rv; + int len; + + printf("xrdpvr_send_init:\n"); + stream_new(s, MAX_BUFSIZE); + + stream_ins_u32_le(s, 0); /* number of bytes to follow */ + stream_ins_u32_le(s, CMD_INIT_XRDPVR); + + /* insert number of bytes in stream */ + len = stream_length(s) - 4; + cptr = s->p; + s->p = s->data; + stream_ins_u32_le(s, len); + s->p = cptr; + + /* write data to virtual channel */ + rv = xrdpvr_write_to_client(channel, s); + stream_free(s); + return rv; +} + +int +xrdpvr_read_ack(void *channel, int *frame) +{ + STREAM *s; + + stream_new(s, MAX_PDU_SIZE); + xrdpvr_read_from_client(channel, s, 4, 1000); + s->p = s->data; + stream_ext_u32_le(s, *frame); + stream_free(s); + return 0; +} diff --git a/xrdpvr/xrdpvr.h b/xrdpvr/xrdpvr.h index 1324282c..e6ab69e8 100644 --- a/xrdpvr/xrdpvr.h +++ b/xrdpvr/xrdpvr.h @@ -34,7 +34,9 @@ int xrdpvr_deinit_player(void *channel, int stream_id); int xrdpvr_play_media(void *channel, int stream_id, char *filename); int xrdpvr_set_geometry(void *channel, int stream_id, int xpos, int ypos, int width, int height); int xrdpvr_set_video_format(void *channel, uint32_t stream_id); -int xrdpvr_set_audio_format(void *channel, uint32_t stream_id); +int xrdpvr_set_audio_format(void *channel, uint32_t stream_id, char *extradata, + int extradata_size, int sample_rate, int bit_rate, + int channels, int block_align); int xrdpvr_send_video_data(void *channel, uint32_t stream_id, uint32_t data_len, uint8_t *data); int xrdpvr_send_audio_data(void *channel, uint32_t stream_id, uint32_t data_len, uint8_t *data); int xrdpvr_create_metadata_file(void *channel, char *filename); @@ -45,6 +47,8 @@ int xrdpvr_get_frame(void **av_pkt_ret, int *is_video_frame, int *delay_in_us); int send_audio_pkt(void *channel, int stream_id, void *pkt_p); int send_video_pkt(void *channel, int stream_id, void *pkt_p); int xrdpvr_set_volume(void *channel, int volume); +int xrdpvr_send_init(void *channel); +int xrdpvr_read_ack(void *channel, int *frame); #ifdef __cplusplus } diff --git a/xrdpvr/xrdpvr_internal.h b/xrdpvr/xrdpvr_internal.h index ca01941c..0b9ba6c8 100644 --- a/xrdpvr/xrdpvr_internal.h +++ b/xrdpvr/xrdpvr_internal.h @@ -62,6 +62,7 @@ #define CMD_DEINIT_XRDPVR 8 #define CMD_SET_GEOMETRY 9 #define CMD_SET_VOLUME 10 +#define CMD_INIT_XRDPVR 11 /* max number of bytes we can send in one pkt */ #define MAX_PDU_SIZE 1600 @@ -217,8 +218,11 @@ typedef struct _player_state_info AVFrame *frame; AVPacket avpkt; + AVBitStreamFilterContext *bsfc; + } PLAYER_STATE_INFO; +static int xrdpvr_read_from_client(void *channel, STREAM *s, int bytes, int timeout); static int xrdpvr_write_to_client(void *channel, STREAM *s); #endif /* __XRDPVR_INTERNAL_H__ */ |
