From bb10af64c0a251072e16c37699c345d0627db434 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 21 Oct 2014 16:12:33 +0200 Subject: [PATCH 1/8] Revert "Disable travis IRC spam until the OSX build is fixed" This reverts commit 841d52f1f78fe78b5b5c56c4985c3b25b4d55660. --- .travis.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.travis.yml b/.travis.yml index f3e7e1760..c35d29201 100644 --- a/.travis.yml +++ b/.travis.yml @@ -24,3 +24,9 @@ notifications: email: on_success: change on_failure: always + irc: + channels: + - "chat.freenode.net#openmw" + on_success: change + on_failure: always + use_notice: true From 681f3fa530f2e1b729804981418c9809458a1015 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 19 Oct 2014 04:04:43 +0200 Subject: [PATCH 2/8] Revert "Removed a warning about comparision between signed and unsigned variable in ffmpeg_decoder." This reverts commit b40c1ff26c7b47a4a8cd27ca50d68b7089ca09d6. --- apps/openmw/mwrender/videoplayer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwrender/videoplayer.cpp b/apps/openmw/mwrender/videoplayer.cpp index 072653898..46d33c86d 100644 --- a/apps/openmw/mwrender/videoplayer.cpp +++ b/apps/openmw/mwrender/videoplayer.cpp @@ -982,9 +982,9 @@ int VideoState::stream_open(int stream_index, AVFormatContext *pFormatCtx) // Get a pointer to the codec context for the video stream codecCtx = pFormatCtx->streams[stream_index]->codec; codec = avcodec_find_decoder(codecCtx->codec_id); -#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(56,1,0) +#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(56,1,0) codecCtx->refcounted_frames = 1; -#endif /* LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(56,1,0) */ +#endif /* LIBAVCODEC_VERSION_INT < AV_VERSION_INT(56,1,0) */ if(!codec || (avcodec_open2(codecCtx, codec, NULL) < 0)) { fprintf(stderr, "Unsupported codec!\n"); From de0e0fedff8e52f5976efcab75470a1a24b544a9 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 19 Oct 2014 04:05:16 +0200 Subject: [PATCH 3/8] Revert "Fix for compiler warnings and deprecated functions usage in videoplayer." This reverts commit f5589b42ea499c3f2ed6b9713d1c05f9377c876b. Conflicts: apps/openmw/mwrender/videoplayer.cpp --- apps/openmw/mwrender/videoplayer.cpp | 46 +++------------------------- 1 file changed, 5 insertions(+), 41 deletions(-) diff --git a/apps/openmw/mwrender/videoplayer.cpp b/apps/openmw/mwrender/videoplayer.cpp index 46d33c86d..4b1a23c31 100644 --- a/apps/openmw/mwrender/videoplayer.cpp +++ b/apps/openmw/mwrender/videoplayer.cpp @@ -32,16 +32,6 @@ extern "C" #include #include - -#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(56,1,0) -#define IS_NOTEQ_NOPTS_VAL(x) ((uint64_t)x != AV_NOPTS_VALUE) -#define IS_NOTEQ_NOPTS_VAL_PTR(x) (*(uint64_t*)x != AV_NOPTS_VALUE) -#else -#define IS_NOTEQ_NOPTS_VAL(x) ((int64_t)x != AV_NOPTS_VALUE) -#define IS_NOTEQ_NOPTS_VAL_PTR(x) (*(int64_t*)x != AV_NOPTS_VALUE) -#endif /* LIBAVCODEC_VERSION_INT < AV_VERSION_INT(56,1,0) */ - - #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(55,28,1) #define av_frame_alloc avcodec_alloc_frame #endif @@ -229,11 +219,8 @@ void PacketQueue::put(AVPacket *pkt) if(!pkt1) throw std::bad_alloc(); pkt1->pkt = *pkt; pkt1->next = NULL; -#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(56,1,0) - if(pkt1->pkt.destruct == NULL) -#else + if(pkt1->pkt.buf == NULL) -#endif /* LIBAVCODEC_VERSION_INT < AV_VERSION_INT(56,1,0) */ { if(av_dup_packet(&pkt1->pkt) < 0) { @@ -438,7 +425,7 @@ class MovieAudioDecoder : public MWSound::Sound_Decoder return -1; /* if update, update the audio clock w/pts */ - if(IS_NOTEQ_NOPTS_VAL(pkt->pts)) + if(pkt->pts != AV_NOPTS_VALUE) mAudioClock = av_q2d(mAVStream->time_base)*pkt->pts; } } @@ -833,22 +820,6 @@ double VideoState::synchronize_video(AVFrame *src_frame, double pts) * a frame at the time it is allocated. */ static uint64_t global_video_pkt_pts = static_cast(AV_NOPTS_VALUE); - -#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(56,1,0) -static int our_get_buffer(struct AVCodecContext *c, AVFrame *pic) -{ - int ret = avcodec_default_get_buffer(c, pic); - uint64_t *pts = (uint64_t*)av_malloc(sizeof(uint64_t)); - *pts = global_video_pkt_pts; - pic->opaque = pts; - return ret; -} -static void our_release_buffer(struct AVCodecContext *c, AVFrame *pic) -{ - if(pic) av_freep(&pic->opaque); - avcodec_default_release_buffer(c, pic); -} -#else static int our_get_buffer2(struct AVCodecContext *c, AVFrame *pic, int flags = AV_GET_BUFFER_FLAG_REF) { int ret = avcodec_default_get_buffer2(c, pic, flags); @@ -857,7 +828,6 @@ static int our_get_buffer2(struct AVCodecContext *c, AVFrame *pic, int flags = A pic->opaque = pts; return ret; } -#endif /* LIBAVCODEC_VERSION_INT < AV_VERSION_INT(56,1,0) */ void VideoState::video_thread_loop(VideoState *self) { @@ -879,9 +849,9 @@ void VideoState::video_thread_loop(VideoState *self) throw std::runtime_error("Error decoding video frame"); double pts = 0; - if(IS_NOTEQ_NOPTS_VAL(packet->dts)) + if(packet->dts != AV_NOPTS_VALUE) pts = packet->dts; - else if(pFrame->opaque && IS_NOTEQ_NOPTS_VAL_PTR(pFrame->opaque)) + else if(pFrame->opaque && *(int64_t*)pFrame->opaque != AV_NOPTS_VALUE) pts = *(uint64_t*)pFrame->opaque; pts *= av_q2d((*self->video_st)->time_base); @@ -982,9 +952,7 @@ int VideoState::stream_open(int stream_index, AVFormatContext *pFormatCtx) // Get a pointer to the codec context for the video stream codecCtx = pFormatCtx->streams[stream_index]->codec; codec = avcodec_find_decoder(codecCtx->codec_id); -#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(56,1,0) codecCtx->refcounted_frames = 1; -#endif /* LIBAVCODEC_VERSION_INT < AV_VERSION_INT(56,1,0) */ if(!codec || (avcodec_open2(codecCtx, codec, NULL) < 0)) { fprintf(stderr, "Unsupported codec!\n"); @@ -1010,12 +978,8 @@ int VideoState::stream_open(int stream_index, AVFormatContext *pFormatCtx) this->video_st = pFormatCtx->streams + stream_index; this->frame_last_delay = 40e-3; -#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(56,1,0) - codecCtx->get_buffer = our_get_buffer; - codecCtx->release_buffer = our_release_buffer; -#else + codecCtx->get_buffer2 = our_get_buffer2; -#endif /* LIBAVCODEC_VERSION_INT < AV_VERSION_INT(56,1,0) */ this->video_thread = boost::thread(video_thread_loop, this); this->refresh_thread = boost::thread(video_refresh, this); break; From 8472695f89a36fe91ae08cddeedff6b7258df852 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 19 Oct 2014 04:05:43 +0200 Subject: [PATCH 4/8] Revert "Fix for compiler warnings and deprecated functions usage in videoplayer." This reverts commit d77546b7dcbd832ba1b977a63aac0d294eae3663. Conflicts: apps/openmw/mwrender/videoplayer.cpp --- apps/openmw/mwrender/videoplayer.cpp | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/apps/openmw/mwrender/videoplayer.cpp b/apps/openmw/mwrender/videoplayer.cpp index 4b1a23c31..f2e9543ae 100644 --- a/apps/openmw/mwrender/videoplayer.cpp +++ b/apps/openmw/mwrender/videoplayer.cpp @@ -220,7 +220,7 @@ void PacketQueue::put(AVPacket *pkt) pkt1->pkt = *pkt; pkt1->next = NULL; - if(pkt1->pkt.buf == NULL) + if(pkt1->pkt.destruct == NULL) { if(av_dup_packet(&pkt1->pkt) < 0) { @@ -425,7 +425,7 @@ class MovieAudioDecoder : public MWSound::Sound_Decoder return -1; /* if update, update the audio clock w/pts */ - if(pkt->pts != AV_NOPTS_VALUE) + if((uint64_t)pkt->pts != AV_NOPTS_VALUE) mAudioClock = av_q2d(mAVStream->time_base)*pkt->pts; } } @@ -820,14 +820,20 @@ double VideoState::synchronize_video(AVFrame *src_frame, double pts) * a frame at the time it is allocated. */ static uint64_t global_video_pkt_pts = static_cast(AV_NOPTS_VALUE); -static int our_get_buffer2(struct AVCodecContext *c, AVFrame *pic, int flags = AV_GET_BUFFER_FLAG_REF) +static int our_get_buffer(struct AVCodecContext *c, AVFrame *pic) { - int ret = avcodec_default_get_buffer2(c, pic, flags); + int ret = avcodec_default_get_buffer(c, pic); uint64_t *pts = (uint64_t*)av_malloc(sizeof(uint64_t)); *pts = global_video_pkt_pts; pic->opaque = pts; return ret; } +static void our_release_buffer(struct AVCodecContext *c, AVFrame *pic) +{ + if(pic) av_freep(&pic->opaque); + avcodec_default_release_buffer(c, pic); +} + void VideoState::video_thread_loop(VideoState *self) { @@ -849,9 +855,9 @@ void VideoState::video_thread_loop(VideoState *self) throw std::runtime_error("Error decoding video frame"); double pts = 0; - if(packet->dts != AV_NOPTS_VALUE) + if((uint64_t)packet->dts != AV_NOPTS_VALUE) pts = packet->dts; - else if(pFrame->opaque && *(int64_t*)pFrame->opaque != AV_NOPTS_VALUE) + else if(pFrame->opaque && *(uint64_t*)pFrame->opaque != AV_NOPTS_VALUE) pts = *(uint64_t*)pFrame->opaque; pts *= av_q2d((*self->video_st)->time_base); @@ -952,7 +958,6 @@ int VideoState::stream_open(int stream_index, AVFormatContext *pFormatCtx) // Get a pointer to the codec context for the video stream codecCtx = pFormatCtx->streams[stream_index]->codec; codec = avcodec_find_decoder(codecCtx->codec_id); - codecCtx->refcounted_frames = 1; if(!codec || (avcodec_open2(codecCtx, codec, NULL) < 0)) { fprintf(stderr, "Unsupported codec!\n"); @@ -979,7 +984,8 @@ int VideoState::stream_open(int stream_index, AVFormatContext *pFormatCtx) this->frame_last_delay = 40e-3; - codecCtx->get_buffer2 = our_get_buffer2; + codecCtx->get_buffer = our_get_buffer; + codecCtx->release_buffer = our_release_buffer; this->video_thread = boost::thread(video_thread_loop, this); this->refresh_thread = boost::thread(video_refresh, this); break; From 290aacd2a6482ff307bed79455f16c41f4772f17 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 19 Oct 2014 23:53:39 +0200 Subject: [PATCH 5/8] Fix videoplayer crash on quit The sound stream thread was trying to update the stream during/after destruction of the video state. --- apps/openmw/mwrender/videoplayer.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/openmw/mwrender/videoplayer.cpp b/apps/openmw/mwrender/videoplayer.cpp index f2e9543ae..b2517251b 100644 --- a/apps/openmw/mwrender/videoplayer.cpp +++ b/apps/openmw/mwrender/videoplayer.cpp @@ -1099,6 +1099,8 @@ void VideoState::deinit() { this->quit = true; + this->AudioTrack.reset(); + this->audioq.cond.notify_one(); this->videoq.cond.notify_one(); From 202cfa879ff998bdd8277e1002c9de70438f2a0a Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 20 Oct 2014 00:27:32 +0200 Subject: [PATCH 6/8] Implement frame drop support in the videoplayer (Fixes #1343) --- apps/openmw/mwrender/videoplayer.cpp | 145 +++++++++------------------ 1 file changed, 50 insertions(+), 95 deletions(-) diff --git a/apps/openmw/mwrender/videoplayer.cpp b/apps/openmw/mwrender/videoplayer.cpp index b2517251b..07a0abcd6 100644 --- a/apps/openmw/mwrender/videoplayer.cpp +++ b/apps/openmw/mwrender/videoplayer.cpp @@ -44,23 +44,15 @@ extern "C" #include #endif - // From libavutil version 52.2.0 and onward the declaration of - // AV_CH_LAYOUT_* is removed from libavcodec/avcodec.h and moved to - // libavutil/channel_layout.h #if AV_VERSION_INT(52, 2, 0) <= AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ LIBAVUTIL_VERSION_MINOR, LIBAVUTIL_VERSION_MICRO) #include #endif - // WARNING: avcodec versions up to 54.54.100 potentially crashes on Windows 64bit. - - // From version 54.56 binkaudio encoding format changed from S16 to FLTP. See: - // https://gitorious.org/ffmpeg/ffmpeg/commit/7bfd1766d1c18f07b0a2dd042418a874d49ea60d - // http://ffmpeg.zeranoe.com/forum/viewtopic.php?f=15&t=872 #ifdef HAVE_LIBSWRESAMPLE #include #else - /* FIXME: remove this section once libswresample is available on all platforms */ + // FIXME: remove this section once libswresample is packaged for Debian #include #include #define SwrContext AVAudioResampleContext @@ -75,12 +67,12 @@ extern "C" #define MAX_VIDEOQ_SIZE (5 * 256 * 1024) #define AV_SYNC_THRESHOLD 0.01 #define AUDIO_DIFF_AVG_NB 20 -#define VIDEO_PICTURE_QUEUE_SIZE 1 +#define VIDEO_PICTURE_QUEUE_SIZE 50 enum { - AV_SYNC_AUDIO_MASTER, - AV_SYNC_VIDEO_MASTER, - AV_SYNC_EXTERNAL_MASTER, + AV_SYNC_AUDIO_MASTER, // Play audio with no frame drops, sync video to audio + AV_SYNC_VIDEO_MASTER, // Play video with no frame drops, sync audio to video + AV_SYNC_EXTERNAL_MASTER, // Sync audio and video to an external clock AV_SYNC_DEFAULT = AV_SYNC_EXTERNAL_MASTER }; @@ -121,10 +113,10 @@ struct VideoState { : format_ctx(NULL), av_sync_type(AV_SYNC_DEFAULT) , external_clock_base(0.0) , audio_st(NULL) - , video_st(NULL), frame_last_pts(0.0), frame_last_delay(0.0), - video_clock(0.0), sws_context(NULL), rgbaFrame(NULL), pictq_size(0), - pictq_rindex(0), pictq_windex(0) - , refresh_rate_ms(10), refresh(false), quit(false), display_ready(false) + , video_st(NULL), frame_last_pts(0.0) + , video_clock(0.0), sws_context(NULL), rgbaFrame(NULL), pictq_size(0) + , pictq_rindex(0), pictq_windex(0) + , quit(false) { // Register all formats and codecs av_register_all(); @@ -143,15 +135,12 @@ struct VideoState { static void video_thread_loop(VideoState *is); static void decode_thread_loop(VideoState *is); - void video_display(); - void video_refresh_timer(); + void video_display(VideoPicture* vp); + void video_refresh(); int queue_picture(AVFrame *pFrame, double pts); double synchronize_video(AVFrame *src_frame, double pts); - static void video_refresh(VideoState *is); - - double get_audio_clock() { return this->AudioTrack->getTimeOffset(); } @@ -189,7 +178,6 @@ struct VideoState { AVStream** video_st; double frame_last_pts; - double frame_last_delay; double video_clock; ///tell(); } - -void VideoState::video_refresh(VideoState* is) +void VideoState::video_display(VideoPicture *vp) { - boost::system_time t = boost::get_system_time(); - while(!is->quit) - { - t += boost::posix_time::milliseconds(is->refresh_rate_ms); - boost::this_thread::sleep(t); - is->refresh = true; - } -} - - -void VideoState::video_display() -{ - VideoPicture *vp = &this->pictq[this->pictq_rindex]; - if((*this->video_st)->codec->width != 0 && (*this->video_st)->codec->height != 0) { @@ -698,55 +666,53 @@ void VideoState::video_display() Ogre::PixelBox pb((*this->video_st)->codec->width, (*this->video_st)->codec->height, 1, Ogre::PF_BYTE_RGBA, &vp->data[0]); Ogre::HardwarePixelBufferSharedPtr buffer = mTexture->getBuffer(); buffer->blitFromMemory(pb); - this->display_ready = true; } } -void VideoState::video_refresh_timer() +void VideoState::video_refresh() { - VideoPicture *vp; - double delay; - if(this->pictq_size == 0) return; - vp = &this->pictq[this->pictq_rindex]; - - delay = vp->pts - this->frame_last_pts; /* the pts from last time */ - if(delay <= 0 || delay >= 1.0) { - /* if incorrect delay, use previous one */ - delay = this->frame_last_delay; - } - /* save for next time */ - this->frame_last_delay = delay; - this->frame_last_pts = vp->pts; - - /* FIXME: Syncing should be done in the decoding stage, where frames can be - * skipped or duplicated as needed. */ - /* update delay to sync to audio if not master source */ - if(this->av_sync_type != AV_SYNC_VIDEO_MASTER) + if (this->av_sync_type == AV_SYNC_VIDEO_MASTER) { - double diff = this->get_video_clock() - this->get_master_clock(); - - /* Skip or repeat the frame. Take delay into account - * FFPlay still doesn't "know if this is the best guess." */ - double sync_threshold = std::max(delay, AV_SYNC_THRESHOLD); - if(diff <= -sync_threshold) - delay = 0; - else if(diff >= sync_threshold) - delay = 2 * delay; + VideoPicture* vp = &this->pictq[this->pictq_rindex]; + this->video_display(vp); + this->pictq_rindex = (pictq_rindex+1) % VIDEO_PICTURE_QUEUE_SIZE; + this->frame_last_pts = vp->pts; + this->pictq_mutex.lock(); + this->pictq_size--; + this->pictq_cond.notify_one(); + this->pictq_mutex.unlock(); } + else + { + const float threshold = 0.03; + if (this->pictq[pictq_rindex].pts > this->get_master_clock() + threshold) + return; // not ready yet to show this picture + int i=0; + for (; ipictq_size-1; ++i) + { + if (this->pictq[pictq_rindex].pts + threshold <= this->get_master_clock()) + this->pictq_rindex = (this->pictq_rindex+1) % VIDEO_PICTURE_QUEUE_SIZE; // not enough time to show this picture + else + break; + } - this->refresh_rate_ms = std::max(1, (int)(delay*1000.0)); - /* show the picture! */ - this->video_display(); + VideoPicture* vp = &this->pictq[this->pictq_rindex]; - /* update queue for next picture! */ - this->pictq_rindex = (this->pictq_rindex+1) % VIDEO_PICTURE_QUEUE_SIZE; - this->pictq_mutex.lock(); - this->pictq_size--; - this->pictq_cond.notify_one(); - this->pictq_mutex.unlock(); + this->video_display(vp); + + this->frame_last_pts = vp->pts; + + this->pictq_mutex.lock(); + this->pictq_size -= i; + // update queue for next picture + this->pictq_size--; + this->pictq_rindex++; + this->pictq_cond.notify_one(); + this->pictq_mutex.unlock(); + } } @@ -916,7 +882,7 @@ void VideoState::decode_thread_loop(VideoState *self) while(!self->quit) { // EOF reached, all packets processed, we can exit now - if(self->audioq.nb_packets == 0 && self->videoq.nb_packets == 0) + if(self->audioq.nb_packets == 0 && self->videoq.nb_packets == 0 && self->pictq_size == 0) break; boost::this_thread::sleep(boost::posix_time::milliseconds(100)); } @@ -937,11 +903,7 @@ bool VideoState::update() if(this->quit) return false; - if(this->refresh) - { - this->refresh = false; - this->video_refresh_timer(); - } + this->video_refresh(); return true; } @@ -982,12 +944,9 @@ int VideoState::stream_open(int stream_index, AVFormatContext *pFormatCtx) case AVMEDIA_TYPE_VIDEO: this->video_st = pFormatCtx->streams + stream_index; - this->frame_last_delay = 40e-3; - codecCtx->get_buffer = our_get_buffer; codecCtx->release_buffer = our_release_buffer; this->video_thread = boost::thread(video_thread_loop, this); - this->refresh_thread = boost::thread(video_refresh, this); break; default: @@ -1004,8 +963,6 @@ void VideoState::init(const std::string& resourceName) unsigned int i; this->av_sync_type = AV_SYNC_DEFAULT; - this->refresh_rate_ms = 10; - this->refresh = false; this->quit = false; this->stream = Ogre::ResourceGroupManager::getSingleton().openResource(resourceName); @@ -1108,8 +1065,6 @@ void VideoState::deinit() this->parse_thread.join(); if (this->video_thread.joinable()) this->video_thread.join(); - if (this->refresh_thread.joinable()) - this->refresh_thread.join(); if(this->audio_st) avcodec_close((*this->audio_st)->codec); From 57111033223f5f35371f78f63170c06c96435794 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 21 Oct 2014 17:51:59 +0200 Subject: [PATCH 7/8] Remove leftover comment --- apps/openmw/mwrender/videoplayer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwrender/videoplayer.cpp b/apps/openmw/mwrender/videoplayer.cpp index 07a0abcd6..01058731d 100644 --- a/apps/openmw/mwrender/videoplayer.cpp +++ b/apps/openmw/mwrender/videoplayer.cpp @@ -1033,10 +1033,10 @@ void VideoState::init(const std::string& resourceName) int height = (*this->video_st)->codec->height; static int i = 0; this->mTexture = Ogre::TextureManager::getSingleton().createManual( - "OpenMW/VideoTexture" + Ogre::StringConverter::toString(++i), + "ffmpeg/VideoTexture" + Ogre::StringConverter::toString(++i), Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::TEX_TYPE_2D, - width, height, // TEST + width, height, 0, Ogre::PF_BYTE_RGBA, Ogre::TU_DYNAMIC_WRITE_ONLY_DISCARDABLE); From bcb2d714c0a9c2668739e5fc40419012ba074af3 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 21 Oct 2014 23:46:04 +0200 Subject: [PATCH 8/8] Add TODO comments for future videoplayer enhancements --- apps/openmw/mwrender/videoplayer.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/apps/openmw/mwrender/videoplayer.cpp b/apps/openmw/mwrender/videoplayer.cpp index 01058731d..16de1bd30 100644 --- a/apps/openmw/mwrender/videoplayer.cpp +++ b/apps/openmw/mwrender/videoplayer.cpp @@ -690,6 +690,9 @@ void VideoState::video_refresh() const float threshold = 0.03; if (this->pictq[pictq_rindex].pts > this->get_master_clock() + threshold) return; // not ready yet to show this picture + + // TODO: the conversion to RGBA is done in the decoding thread, so if a picture is skipped here, then it was + // unnecessarily converted. But we may want to replace the conversion by a pixel shader anyway (see comment in queue_picture) int i=0; for (; ipictq_size-1; ++i) { @@ -733,6 +736,8 @@ int VideoState::queue_picture(AVFrame *pFrame, double pts) vp = &this->pictq[this->pictq_windex]; // Convert the image into RGBA format for Ogre + // TODO: we could do this in a pixel shader instead, if the source format + // matches a commonly used format (ie YUV420P) if(this->sws_context == NULL) { int w = (*this->video_st)->codec->width;