diff --git a/vrplayer/demuxmedia.cpp b/vrplayer/demuxmedia.cpp index 0e2091f6..a8de41a1 100644 --- a/vrplayer/demuxmedia.cpp +++ b/vrplayer/demuxmedia.cpp @@ -29,6 +29,18 @@ void DemuxMedia::setVcrOp(int op) vcrMutex.lock(); vcrFlag = op; vcrMutex.unlock(); + if (op == VCR_STOP) + { + clear(); + } +} + +int DemuxMedia::clear() +{ + sendMutex.lock(); + videoQueue->clear(); + sendMutex.unlock(); + return 0; } void DemuxMedia::startDemuxing() diff --git a/vrplayer/demuxmedia.h b/vrplayer/demuxmedia.h index 0b3935d7..742ce525 100644 --- a/vrplayer/demuxmedia.h +++ b/vrplayer/demuxmedia.h @@ -41,6 +41,7 @@ public: void *channel = 0, int stream_id = 101); void setVcrOp(int op); + int clear(); public slots: void startDemuxing(); diff --git a/vrplayer/mainwindow.cpp b/vrplayer/mainwindow.cpp index 0ce04674..e8884726 100644 --- a/vrplayer/mainwindow.cpp +++ b/vrplayer/mainwindow.cpp @@ -295,11 +295,9 @@ void MainWindow::getVdoGeometry(QRect *rect) void MainWindow::clearDisplay() { - QPixmap pixmap(100,100); - pixmap.fill(QColor(0x00, 0x00, 0x00)); - QPainter painter(&pixmap); - painter.setBrush(QBrush(Qt::black)); - lblVideo->setPixmap(pixmap); + /* TODO: this needs to be set after video actually stops + * a few frames come after this */ + lblVideo->update(); } /******************************************************************************* @@ -333,11 +331,21 @@ void MainWindow::on_actionOpen_Media_File_triggered() { remoteClientInited = false; interface->deInitRemoteClient(); - interface->initRemoteClient(); + if (interface->initRemoteClient() != 0) + { + QMessageBox::question(this, "vrplayer", "Unsupported codec", + QMessageBox::Ok); + return; + } } else { - interface->initRemoteClient(); + if (interface->initRemoteClient() != 0) + { + QMessageBox::question(this, "vrplayer", "Unsupported codec", + QMessageBox::Ok); + return; + } } demuxMedia = interface->getDemuxMediaInstance(); @@ -413,6 +421,7 @@ void MainWindow::onBtnStopClicked(bool) lblCurrentPos->setText("00:00:00"); /* clear screen by filling it with black */ + usleep(500 * 1000); clearDisplay(); btnPlay->setChecked(false); diff --git a/vrplayer/ourinterface.cpp b/vrplayer/ourinterface.cpp index e13e6e8b..261ba04d 100644 --- a/vrplayer/ourinterface.cpp +++ b/vrplayer/ourinterface.cpp @@ -32,7 +32,8 @@ void OurInterface::oneTimeDeinit() closeVirtualChannel(); } -void OurInterface::initRemoteClient() +/* returns error */ +int OurInterface::initRemoteClient() { int64_t start_time; int64_t duration; @@ -40,18 +41,21 @@ void OurInterface::initRemoteClient() //elapsedTime = 0; if (sendMetadataFile()) - return; + return 1; if (sendVideoFormat()) - return; + return 1; if (sendAudioFormat()) - return; + return 1; if (sendGeometry(savedGeometry)) - return; + return 1; - xrdpvr_play_media(channel, 101, filename.toAscii().data()); + if (xrdpvr_play_media(channel, 101, filename.toAscii().data()) != 0) + { + return 1; + } xrdpvr_get_media_duration(&start_time, &duration); //qDebug() << "ourInterface:initRemoteClient: emit onMediaDurationInSecs: dur=" << duration; @@ -66,6 +70,7 @@ void OurInterface::initRemoteClient() demuxMedia->moveToThread(demuxMediaThread); //playVideo = demuxMedia->getPlayVideoInstance(); } + return 0; } void OurInterface::deInitRemoteClient() diff --git a/vrplayer/ourinterface.h b/vrplayer/ourinterface.h index 51f88e6b..be354025 100644 --- a/vrplayer/ourinterface.h +++ b/vrplayer/ourinterface.h @@ -31,11 +31,11 @@ class OurInterface : public QObject public: explicit OurInterface(QObject *parent = 0); - + /* public methods */ int oneTimeInit(); void oneTimeDeinit(); - void initRemoteClient(); + int initRemoteClient(); void deInitRemoteClient(); int sendGeometry(QRect rect); void setFilename(QString filename); diff --git a/xrdpvr/xrdpvr.c b/xrdpvr/xrdpvr.c index 46326e9e..6147a66e 100644 --- a/xrdpvr/xrdpvr.c +++ b/xrdpvr/xrdpvr.c @@ -2,6 +2,7 @@ * xrdp: A Remote Desktop Protocol server. * * Copyright (C) Laxmikant Rashinkar 2012-2013 LK.Rashinkar@gmail.com + * Copyright (C) Jay Sorg 2013 jay.sorg@gmail.com * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -30,7 +31,8 @@ int g_audio_index = -1; /*****************************************************************************/ /* produce a hex dump */ -void hexdump(char *p, int len) +void +hexdump(char *p, int len) { unsigned char *line; int i; @@ -90,33 +92,6 @@ xrdpvr_init_player(void *channel, int stream_id, char *filename) } xrdpvr_send_init(channel); - -#if 0 - /* send metadata from media file to client */ - if (xrdpvr_create_metadata_file(channel, filename)) - { - printf("error sending metadata to client\n"); - return -1; - } - - /* ask client to get video format from media file */ - if (xrdpvr_set_video_format(channel, 101)) - { - printf("xrdpvr_set_video_format() failed\n"); - return -1; - } - - /* TODO */ - sleep(3); - - /* ask client to get audio format from media file */ - if (xrdpvr_set_audio_format(channel, 101)) - { - printf("xrdpvr_set_audio_format() failed\n"); - return 1; - } -#endif - } /** @@ -199,7 +174,8 @@ xrdpvr_play_media(void *channel, int stream_id, char *filename) { int i; - printf("$$$$$$ xrdpvr_play_media: setting audioTimeout & videoTimeout to -1\n"); + printf("$$$$$$ xrdpvr_play_media: setting audioTimeout & " + "videoTimeout to -1\n"); g_psi.videoTimeout = -1; g_psi.audioTimeout = -1; @@ -227,25 +203,34 @@ xrdpvr_play_media(void *channel, int stream_id, char *filename) av_dump_format(g_psi.p_format_ctx, 0, filename, 0); #endif + printf("nb_streams %d\n", g_psi.p_format_ctx->nb_streams); + + g_audio_index = -1; + g_video_index = -1; + /* find first audio / video stream */ 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_psi.p_format_ctx->streams[i]->codec->codec_id == CODEC_ID_H264 && + if (g_psi.p_format_ctx->streams[i]->codec->codec_type == + CODEC_TYPE_VIDEO && + 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_psi.p_format_ctx->streams[i]->codec->codec_id == CODEC_ID_AAC && + if (g_psi.p_format_ctx->streams[i]->codec->codec_type == + CODEC_TYPE_AUDIO && + g_psi.p_format_ctx->streams[i]->codec->codec_id == + CODEC_ID_AAC && g_audio_index < 0) { g_audio_index = i; } } - if ((g_audio_index < 0) && (g_video_index < 0)) + if ((g_audio_index < 0) || (g_video_index < 0)) { /* close file and return with error */ printf("ERROR: no audio/video stream found in %s\n", filename); @@ -262,7 +247,8 @@ xrdpvr_play_media(void *channel, int stream_id, char *filename) g_psi.p_video_codec_ctx = g_psi.p_format_ctx->streams[g_video_index]->codec; /* find decoder for audio stream */ - g_psi.p_audio_codec = avcodec_find_decoder(g_psi.p_audio_codec_ctx->codec_id); + g_psi.p_audio_codec = + avcodec_find_decoder(g_psi.p_audio_codec_ctx->codec_id); if (g_psi.p_audio_codec == NULL) { @@ -270,7 +256,8 @@ xrdpvr_play_media(void *channel, int stream_id, char *filename) } /* find decoder for video stream */ - g_psi.p_video_codec = avcodec_find_decoder(g_psi.p_video_codec_ctx->codec_id); + g_psi.p_video_codec = + avcodec_find_decoder(g_psi.p_video_codec_ctx->codec_id); if (g_psi.p_video_codec == NULL) { @@ -287,9 +274,11 @@ xrdpvr_play_media(void *channel, int stream_id, char *filename) } 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); + 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->bit_rate, + g_psi.p_audio_codec_ctx->channels, g_psi.p_audio_codec_ctx->block_align); /* open decoder for video stream */ @@ -304,14 +293,16 @@ xrdpvr_play_media(void *channel, int stream_id, char *filename) 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)) + if (xrdpvr_set_video_format(channel, 101, 0, + g_psi.p_video_codec_ctx->width, + g_psi.p_video_codec_ctx->height)) { 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, + if (xrdpvr_set_audio_format(channel, 101, 0, g_psi.p_audio_codec_ctx->extradata, g_psi.p_audio_codec_ctx->extradata_size, g_psi.p_audio_codec_ctx->sample_rate, @@ -372,25 +363,19 @@ xrdpvr_get_frame(void **av_pkt_ret, int *is_video_frame, int *delay_in_us) if (firstAudioPkt) { firstAudioPkt = 0; - //printf("##### first audio: dts=%f delay_in_ms=%d\n", dts, *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); + av_pkt->flags & PKT_FLAG_KEY); if (error > 0) { av_free_packet(av_pkt); @@ -404,32 +389,25 @@ xrdpvr_get_frame(void **av_pkt_ret, int *is_video_frame, int *delay_in_us) bsfc = bsfc->next; } - dts = av_pkt->dts; - //printf("$$$ video raw_dts=%f raw_pts=%f\n", (double) av_pkt->dts, (double) av_pkt->dts); - dts *= av_q2d(g_psi.p_format_ctx->streams[g_video_index]->time_base); if (g_psi.videoTimeout < 0) { *delay_in_us = 1000 * 5; g_psi.videoTimeout = dts; - //printf("$$$ negative: videoTimeout=%f\n", g_psi.videoTimeout); } else { - //printf("$$$ positive: videoTimeout_b4 =%f\n", g_psi.videoTimeout); *delay_in_us = (int) ((dts - g_psi.videoTimeout) * 1000000); g_psi.videoTimeout = dts; - //printf("$$$ positive: videoTimeout_aft=%f\n", g_psi.videoTimeout); } *is_video_frame = 1; if (firstVideoPkt) { firstVideoPkt = 0; - //printf("$$$ first video: dts=%f delay_in_ms=%d\n", dts, *delay_in_us); } } @@ -461,7 +439,8 @@ send_video_pkt(void *channel, int stream_id, void *pkt_p) /******************************************************************************/ int -xrdpvr_play_frame(void *channel, int stream_id, int *videoTimeout, int *audioTimeout) +xrdpvr_play_frame(void *channel, int stream_id, int *videoTimeout, + int *audioTimeout) { AVPacket av_pkt; double dts; @@ -506,14 +485,13 @@ xrdpvr_play_frame(void *channel, int stream_id, int *videoTimeout, int *audioTim 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); + av_pkt.flags & PKT_FLAG_KEY); if (error > 0) { av_free_packet(&av_pkt); @@ -532,8 +510,6 @@ xrdpvr_play_frame(void *channel, int stream_id, int *videoTimeout, int *audioTim dts = av_pkt.dts; dts *= av_q2d(g_psi.p_format_ctx->streams[g_video_index]->time_base); - //printf("xrdpvr_play_frame:video: saved=%f dts=%f\n", g_psi.videoTimeout, dts); - *videoTimeout = (int) ((dts - g_psi.videoTimeout) * 1000000); *audioTimeout = -1; @@ -541,13 +517,11 @@ xrdpvr_play_frame(void *channel, int stream_id, int *videoTimeout, int *audioTim { g_psi.videoTimeout = dts; delay_in_us = 1000 * 40; - //printf("xrdpvr_play_frame:video1: saved=%f dts=%f delay_in_us=%d\n", g_psi.videoTimeout, dts, delay_in_us); } else { delay_in_us = (int) ((dts - g_psi.videoTimeout) * 1000000); g_psi.videoTimeout = dts; - //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); @@ -574,10 +548,11 @@ xrdpvr_seek_media(int64_t pos, int backward) seek_target = av_rescale_q(pos * AV_TIME_BASE, AV_TIME_BASE_Q, - g_psi.p_format_ctx->streams[g_video_index]->time_base); + g_psi.p_format_ctx->streams[g_video_index]->time_base); - if(av_seek_frame(g_psi.p_format_ctx, g_video_index, seek_target, seek_flag) < 0) + if (av_seek_frame(g_psi.p_format_ctx, g_video_index, seek_target, + seek_flag) < 0) { printf("media seek error\n"); return -1; @@ -596,7 +571,8 @@ xrdpvr_get_media_duration(int64_t *start_time, int64_t *duration) /******************************************************************************/ int -xrdpvr_set_geometry(void *channel, int stream_id, int xpos, int ypos, int width, int height) +xrdpvr_set_geometry(void *channel, int stream_id, int xpos, int ypos, + int width, int height) { STREAM *s; char *cptr; @@ -637,17 +613,22 @@ xrdpvr_set_geometry(void *channel, int stream_id, int xpos, int ypos, int width, * @return 0 on success, -1 on error *****************************************************************************/ int -xrdpvr_set_video_format(void *channel, uint32_t stream_id) +xrdpvr_set_video_format(void *channel, uint32_t stream_id, int format, + int width, int height) { STREAM *s; char *cptr; int rv; int len; + width = (width + 15) & ~15; 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); + stream_ins_u32_le(s, format); + stream_ins_u32_le(s, width); + stream_ins_u32_le(s, height); /* insert number of bytes in stream */ len = stream_length(s) - 4; @@ -671,9 +652,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, char *extradata, - int extradata_size, int sample_rate, int bit_rate, - int channels, int block_align) +xrdpvr_set_audio_format(void *channel, uint32_t stream_id, int format, + char *extradata, int extradata_size, int sample_rate, + int bit_rate, int channels, int block_align) { STREAM *s; char *cptr; @@ -689,6 +670,7 @@ xrdpvr_set_audio_format(void *channel, uint32_t stream_id, char *extradata, 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, format); stream_ins_u32_le(s, extradata_size); memcpy(s->p, extradata, extradata_size); s->p += extradata_size; @@ -721,7 +703,8 @@ xrdpvr_set_audio_format(void *channel, uint32_t stream_id, char *extradata, * @return 0 on success, -1 on error *****************************************************************************/ int -xrdpvr_send_video_data(void *channel, uint32_t stream_id, uint32_t data_len, uint8_t *data) +xrdpvr_send_video_data(void *channel, uint32_t stream_id, + uint32_t data_len, uint8_t *data) { STREAM *s; char *cptr; @@ -766,7 +749,8 @@ xrdpvr_send_video_data(void *channel, uint32_t stream_id, uint32_t data_len, uin * @return 0 on success, -1 on error *****************************************************************************/ int -xrdpvr_send_audio_data(void *channel, uint32_t stream_id, uint32_t data_len, uint8_t *data) +xrdpvr_send_audio_data(void *channel, uint32_t stream_id, uint32_t data_len, + uint8_t *data) { STREAM *s; char *cptr; @@ -886,7 +870,8 @@ xrdpvr_read_from_client(void *channel, STREAM *s, int bytes, int timeout) { //printf("xrdpvr_read_from_client: loop\n"); bytes_read = bytes - total_read; - ok = WTSVirtualChannelRead(channel, timeout, s->p, bytes_read, &bytes_read); + ok = WTSVirtualChannelRead(channel, timeout, s->p, bytes_read, + &bytes_read); //printf("xrdpvr_read_from_client: loop ok %d\n", ok); if (ok) { @@ -923,7 +908,8 @@ xrdpvr_write_to_client(void *channel, STREAM *s) while (1) { - rv = WTSVirtualChannelWrite(channel, &s->data[index], bytes_to_send, &bytes_written); + rv = WTSVirtualChannelWrite(channel, &s->data[index], bytes_to_send, + &bytes_written); if (rv < 0) { diff --git a/xrdpvr/xrdpvr.h b/xrdpvr/xrdpvr.h index e6ab69e8..d7f8ca92 100644 --- a/xrdpvr/xrdpvr.h +++ b/xrdpvr/xrdpvr.h @@ -2,6 +2,7 @@ * xrdp: A Remote Desktop Protocol server. * * Copyright (C) Laxmikant Rashinkar 2012-2013 LK.Rashinkar@gmail.com + * Copyright (C) Jay Sorg 2013 jay.sorg@gmail.com * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -32,18 +33,25 @@ extern "C" { int xrdpvr_init_player(void *channel, int stream_id, char *filename); 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, char *extradata, - int extradata_size, int sample_rate, int bit_rate, +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 format, + int width, int height); +int xrdpvr_set_audio_format(void *channel, uint32_t stream_id, int format, + 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_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); -int xrdpvr_play_frame(void *channel, int stream_id, int *vdoTimeout, int *audioTimeout); +int xrdpvr_play_frame(void *channel, int stream_id, int *vdoTimeout, + int *audioTimeout); void xrdpvr_get_media_duration(int64_t *start_time, int64_t *duration); int xrdpvr_seek_media(int64_t pos, int backward); -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); 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); diff --git a/xrdpvr/xrdpvr_internal.h b/xrdpvr/xrdpvr_internal.h index 0b9ba6c8..90f87361 100644 --- a/xrdpvr/xrdpvr_internal.h +++ b/xrdpvr/xrdpvr_internal.h @@ -48,6 +48,7 @@ #ifdef DISTRO_UBUNTU1204 #define CODEC_TYPE_VIDEO AVMEDIA_TYPE_VIDEO #define CODEC_TYPE_AUDIO AVMEDIA_TYPE_AUDIO +#define PKT_FLAG_KEY AV_PKT_FLAG_KEY #endif #define MAX_BUFSIZE (1024 * 1024 * 8)