Home | History | Annotate | Download | only in src
      1 /*M///////////////////////////////////////////////////////////////////////////////////////
      2 //
      3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
      4 //
      5 //  By downloading, copying, installing or using the software you agree to this license.
      6 //  If you do not agree to this license, do not download, install,
      7 //  copy or use the software.
      8 //
      9 //
     10 //                          License Agreement
     11 //                For Open Source Computer Vision Library
     12 //
     13 // Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
     14 // Copyright (C) 2009, Willow Garage Inc., all rights reserved.
     15 // Copyright (C) 2013, OpenCV Foundation, all rights reserved.
     16 // Third party copyrights are property of their respective owners.
     17 //
     18 // Redistribution and use in source and binary forms, with or without modification,
     19 // are permitted provided that the following conditions are met:
     20 //
     21 //   * Redistribution's of source code must retain the above copyright notice,
     22 //     this list of conditions and the following disclaimer.
     23 //
     24 //   * Redistribution's in binary form must reproduce the above copyright notice,
     25 //     this list of conditions and the following disclaimer in the documentation
     26 //     and/or other materials provided with the distribution.
     27 //
     28 //   * The name of the copyright holders may not be used to endorse or promote products
     29 //     derived from this software without specific prior written permission.
     30 //
     31 // This software is provided by the copyright holders and contributors "as is" and
     32 // any express or implied warranties, including, but not limited to, the implied
     33 // warranties of merchantability and fitness for a particular purpose are disclaimed.
     34 // In no event shall the Intel Corporation or contributors be liable for any direct,
     35 // indirect, incidental, special, exemplary, or consequential damages
     36 // (including, but not limited to, procurement of substitute goods or services;
     37 // loss of use, data, or profits; or business interruption) however caused
     38 // and on any theory of liability, whether in contract, strict liability,
     39 // or tort (including negligence or otherwise) arising in any way out of
     40 // the use of this software, even if advised of the possibility of such damage.
     41 //
     42 //M*/
     43 
     44 #include "precomp.hpp"
     45 
     46 #ifdef HAVE_NVCUVID
     47 
     48 cv::cudacodec::detail::VideoParser::VideoParser(VideoDecoder* videoDecoder, FrameQueue* frameQueue) :
     49     videoDecoder_(videoDecoder), frameQueue_(frameQueue), unparsedPackets_(0), hasError_(false)
     50 {
     51     CUVIDPARSERPARAMS params;
     52     std::memset(&params, 0, sizeof(CUVIDPARSERPARAMS));
     53 
     54     params.CodecType              = videoDecoder->codec();
     55     params.ulMaxNumDecodeSurfaces = videoDecoder->maxDecodeSurfaces();
     56     params.ulMaxDisplayDelay      = 1; // this flag is needed so the parser will push frames out to the decoder as quickly as it can
     57     params.pUserData              = this;
     58     params.pfnSequenceCallback    = HandleVideoSequence;    // Called before decoding frames and/or whenever there is a format change
     59     params.pfnDecodePicture       = HandlePictureDecode;    // Called when a picture is ready to be decoded (decode order)
     60     params.pfnDisplayPicture      = HandlePictureDisplay;   // Called whenever a picture is ready to be displayed (display order)
     61 
     62     cuSafeCall( cuvidCreateVideoParser(&parser_, &params) );
     63 }
     64 
     65 bool cv::cudacodec::detail::VideoParser::parseVideoData(const unsigned char* data, size_t size, bool endOfStream)
     66 {
     67     CUVIDSOURCEDATAPACKET packet;
     68     std::memset(&packet, 0, sizeof(CUVIDSOURCEDATAPACKET));
     69 
     70     if (endOfStream)
     71         packet.flags |= CUVID_PKT_ENDOFSTREAM;
     72 
     73     packet.payload_size = static_cast<unsigned long>(size);
     74     packet.payload = data;
     75 
     76     if (cuvidParseVideoData(parser_, &packet) != CUDA_SUCCESS)
     77     {
     78         hasError_ = true;
     79         frameQueue_->endDecode();
     80         return false;
     81     }
     82 
     83     const int maxUnparsedPackets = 15;
     84 
     85     ++unparsedPackets_;
     86     if (unparsedPackets_ > maxUnparsedPackets)
     87     {
     88         hasError_ = true;
     89         frameQueue_->endDecode();
     90         return false;
     91     }
     92 
     93     if (endOfStream)
     94         frameQueue_->endDecode();
     95 
     96     return !frameQueue_->isEndOfDecode();
     97 }
     98 
     99 int CUDAAPI cv::cudacodec::detail::VideoParser::HandleVideoSequence(void* userData, CUVIDEOFORMAT* format)
    100 {
    101     VideoParser* thiz = static_cast<VideoParser*>(userData);
    102 
    103     thiz->unparsedPackets_ = 0;
    104 
    105     if (format->codec         != thiz->videoDecoder_->codec()       ||
    106         format->coded_width   != thiz->videoDecoder_->frameWidth()  ||
    107         format->coded_height  != thiz->videoDecoder_->frameHeight() ||
    108         format->chroma_format != thiz->videoDecoder_->chromaFormat())
    109     {
    110         FormatInfo newFormat;
    111 
    112         newFormat.codec = static_cast<Codec>(format->codec);
    113         newFormat.chromaFormat = static_cast<ChromaFormat>(format->chroma_format);
    114         newFormat.width = format->coded_width;
    115         newFormat.height = format->coded_height;
    116 
    117         try
    118         {
    119             thiz->videoDecoder_->create(newFormat);
    120         }
    121         catch (const cv::Exception&)
    122         {
    123             thiz->hasError_ = true;
    124             return false;
    125         }
    126     }
    127 
    128     return true;
    129 }
    130 
    131 int CUDAAPI cv::cudacodec::detail::VideoParser::HandlePictureDecode(void* userData, CUVIDPICPARAMS* picParams)
    132 {
    133     VideoParser* thiz = static_cast<VideoParser*>(userData);
    134 
    135     thiz->unparsedPackets_ = 0;
    136 
    137     bool isFrameAvailable = thiz->frameQueue_->waitUntilFrameAvailable(picParams->CurrPicIdx);
    138 
    139     if (!isFrameAvailable)
    140         return false;
    141 
    142     if (!thiz->videoDecoder_->decodePicture(picParams))
    143     {
    144         thiz->hasError_ = true;
    145         return false;
    146     }
    147 
    148     return true;
    149 }
    150 
    151 int CUDAAPI cv::cudacodec::detail::VideoParser::HandlePictureDisplay(void* userData, CUVIDPARSERDISPINFO* picParams)
    152 {
    153     VideoParser* thiz = static_cast<VideoParser*>(userData);
    154 
    155     thiz->unparsedPackets_ = 0;
    156 
    157     thiz->frameQueue_->enqueue(picParams);
    158 
    159     return true;
    160 }
    161 
    162 #endif // HAVE_NVCUVID
    163