1793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/*M/////////////////////////////////////////////////////////////////////////////////////// 2793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// 3793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. 4793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// 5793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// By downloading, copying, installing or using the software you agree to this license. 6793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// If you do not agree to this license, do not download, install, 7793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// copy or use the software. 8793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// 9793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// 10793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// License Agreement 11793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// For Open Source Computer Vision Library 12793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// 13793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. 14793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// Copyright (C) 2009, Willow Garage Inc., all rights reserved. 15793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// Third party copyrights are property of their respective owners. 16793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// 17793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// Redistribution and use in source and binary forms, with or without modification, 18793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// are permitted provided that the following conditions are met: 19793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// 20793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// * Redistribution's of source code must retain the above copyright notice, 21793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// this list of conditions and the following disclaimer. 22793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// 23793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// * Redistribution's in binary form must reproduce the above copyright notice, 24793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// this list of conditions and the following disclaimer in the documentation 25793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// and/or other materials provided with the distribution. 26793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// 27793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// * The name of the copyright holders may not be used to endorse or promote products 28793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// derived from this software without specific prior written permission. 29793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// 30793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// This software is provided by the copyright holders and contributors "as is" and 31793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// any express or implied warranties, including, but not limited to, the implied 32793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// warranties of merchantability and fitness for a particular purpose are disclaimed. 33793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// In no event shall the Intel Corporation or contributors be liable for any direct, 34793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// indirect, incidental, special, exemplary, or consequential damages 35793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// (including, but not limited to, procurement of substitute goods or services; 36793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// loss of use, data, or profits; or business interruption) however caused 37793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// and on any theory of liability, whether in contract, strict liability, 38793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// or tort (including negligence or otherwise) arising in any way out of 39793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// the use of this software, even if advised of the possibility of such damage. 40793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// 41793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//M*/ 42793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 43793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include "precomp.hpp" 44793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 45793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerusing namespace cv; 46793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerusing namespace cv::cuda; 47793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerusing namespace cv::cudacodec; 48793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 49793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#ifndef HAVE_NVCUVID 50793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 51793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerPtr<VideoReader> cv::cudacodec::createVideoReader(const String&) { throw_no_cuda(); return Ptr<VideoReader>(); } 52793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerPtr<VideoReader> cv::cudacodec::createVideoReader(const Ptr<RawVideoSource>&) { throw_no_cuda(); return Ptr<VideoReader>(); } 53793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 54793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#else // HAVE_NVCUVID 55793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 56793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslervoid videoDecPostProcessFrame(const GpuMat& decodedFrame, OutputArray _outFrame, int width, int height); 57793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 58793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerusing namespace cv::cudacodec::detail; 59793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 60793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslernamespace 61793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{ 62793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler class VideoReaderImpl : public VideoReader 63793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 64793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler public: 65793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler explicit VideoReaderImpl(const Ptr<VideoSource>& source); 66793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler ~VideoReaderImpl(); 67793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 68793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler bool nextFrame(OutputArray frame); 69793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 70793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler FormatInfo format() const; 71793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 72793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler private: 73793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler Ptr<VideoSource> videoSource_; 74793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 75793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler Ptr<FrameQueue> frameQueue_; 76793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler Ptr<VideoDecoder> videoDecoder_; 77793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler Ptr<VideoParser> videoParser_; 78793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 79793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CUvideoctxlock lock_; 80793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 81793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler std::deque< std::pair<CUVIDPARSERDISPINFO, CUVIDPROCPARAMS> > frames_; 82793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler }; 83793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 84793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler FormatInfo VideoReaderImpl::format() const 85793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 86793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return videoSource_->format(); 87793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 88793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 89793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler VideoReaderImpl::VideoReaderImpl(const Ptr<VideoSource>& source) : 90793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler videoSource_(source), 91793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler lock_(0) 92793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 93793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler // init context 94793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler GpuMat temp(1, 1, CV_8UC1); 95793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler temp.release(); 96793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 97793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CUcontext ctx; 98793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cuSafeCall( cuCtxGetCurrent(&ctx) ); 99793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cuSafeCall( cuvidCtxLockCreate(&lock_, ctx) ); 100793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 101793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler frameQueue_.reset(new FrameQueue); 102793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler videoDecoder_.reset(new VideoDecoder(videoSource_->format(), lock_)); 103793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler videoParser_.reset(new VideoParser(videoDecoder_, frameQueue_)); 104793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 105793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler videoSource_->setVideoParser(videoParser_); 106793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler videoSource_->start(); 107793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 108793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 109793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler VideoReaderImpl::~VideoReaderImpl() 110793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 111793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler frameQueue_->endDecode(); 112793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler videoSource_->stop(); 113793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 114793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 115793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler class VideoCtxAutoLock 116793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 117793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler public: 118793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler VideoCtxAutoLock(CUvideoctxlock lock) : m_lock(lock) { cuSafeCall( cuvidCtxLock(m_lock, 0) ); } 119793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler ~VideoCtxAutoLock() { cuvidCtxUnlock(m_lock, 0); } 120793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 121793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler private: 122793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CUvideoctxlock m_lock; 123793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler }; 124793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 125793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler bool VideoReaderImpl::nextFrame(OutputArray frame) 126793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 127793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if (videoSource_->hasError() || videoParser_->hasError()) 128793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CV_Error(Error::StsUnsupportedFormat, "Unsupported video source"); 129793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 130793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if (!videoSource_->isStarted() || frameQueue_->isEndOfDecode()) 131793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return false; 132793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 133793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if (frames_.empty()) 134793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 135793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CUVIDPARSERDISPINFO displayInfo; 136793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 137793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for (;;) 138793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 139793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if (frameQueue_->dequeue(displayInfo)) 140793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler break; 141793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 142793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if (videoSource_->hasError() || videoParser_->hasError()) 143793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CV_Error(Error::StsUnsupportedFormat, "Unsupported video source"); 144793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 145793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if (frameQueue_->isEndOfDecode()) 146793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return false; 147793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 148793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler // Wait a bit 149793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler Thread::sleep(1); 150793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 151793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 152793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler bool isProgressive = displayInfo.progressive_frame != 0; 153793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler const int num_fields = isProgressive ? 1 : 2 + displayInfo.repeat_first_field; 154793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 155793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for (int active_field = 0; active_field < num_fields; ++active_field) 156793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 157793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CUVIDPROCPARAMS videoProcParams; 158793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler std::memset(&videoProcParams, 0, sizeof(CUVIDPROCPARAMS)); 159793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 160793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler videoProcParams.progressive_frame = displayInfo.progressive_frame; 161793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler videoProcParams.second_field = active_field; 162793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler videoProcParams.top_field_first = displayInfo.top_field_first; 163793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler videoProcParams.unpaired_field = (num_fields == 1); 164793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 165793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler frames_.push_back(std::make_pair(displayInfo, videoProcParams)); 166793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 167793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 168793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 169793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if (frames_.empty()) 170793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return false; 171793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 172793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler std::pair<CUVIDPARSERDISPINFO, CUVIDPROCPARAMS> frameInfo = frames_.front(); 173793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler frames_.pop_front(); 174793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 175793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 176793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler VideoCtxAutoLock autoLock(lock_); 177793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 178793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler // map decoded video frame to CUDA surface 179793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler GpuMat decodedFrame = videoDecoder_->mapFrame(frameInfo.first.picture_index, frameInfo.second); 180793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 181793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler // perform post processing on the CUDA surface (performs colors space conversion and post processing) 182793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler // comment this out if we inclue the line of code seen above 183793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler videoDecPostProcessFrame(decodedFrame, frame, videoDecoder_->targetWidth(), videoDecoder_->targetHeight()); 184793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 185793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler // unmap video frame 186793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler // unmapFrame() synchronizes with the VideoDecode API (ensures the frame has finished decoding) 187793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler videoDecoder_->unmapFrame(decodedFrame); 188793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 189793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 190793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler // release the frame, so it can be re-used in decoder 191793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if (frames_.empty()) 192793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler frameQueue_->releaseFrame(frameInfo.first); 193793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 194793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return true; 195793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 196793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler} 197793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 198793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerPtr<VideoReader> cv::cudacodec::createVideoReader(const String& filename) 199793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{ 200793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CV_Assert( !filename.empty() ); 201793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 202793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler Ptr<VideoSource> videoSource; 203793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 204793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler try 205793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 206793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler videoSource.reset(new CuvidVideoSource(filename)); 207793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 208793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler catch (...) 209793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 210793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler Ptr<RawVideoSource> source(new FFmpegVideoSource(filename)); 211793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler videoSource.reset(new RawVideoSourceWrapper(source)); 212793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 213793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 214793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return makePtr<VideoReaderImpl>(videoSource); 215793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler} 216793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 217793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerPtr<VideoReader> cv::cudacodec::createVideoReader(const Ptr<RawVideoSource>& source) 218793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{ 219793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler Ptr<VideoSource> videoSource(new RawVideoSourceWrapper(source)); 220793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return makePtr<VideoReaderImpl>(videoSource); 221793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler} 222793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 223793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#endif // HAVE_NVCUVID 224