/* * Copyright 1993-2015 NVIDIA Corporation. All rights reserved. * * Please refer to the NVIDIA end user license agreement (EULA) associated * with this source code for terms and conditions that govern your use of * this software. Any use, reproduction, disclosure, or distribution of * this software and related documentation outside the terms of the EULA * is strictly prohibited. * */ #include "VideoParser.h" #include "VideoDecoder.h" #include "FrameQueue.h" #include #include VideoParser::VideoParser(VideoDecoder *pVideoDecoder, FrameQueue *pFrameQueue): hParser_(0) { assert(0 != pFrameQueue); oParserData_.pFrameQueue = pFrameQueue; assert(0 != pVideoDecoder); oParserData_.pVideoDecoder = pVideoDecoder; CUVIDPARSERPARAMS oVideoParserParameters; memset(&oVideoParserParameters, 0, sizeof(CUVIDPARSERPARAMS)); oVideoParserParameters.CodecType = pVideoDecoder->codec(); oVideoParserParameters.ulMaxNumDecodeSurfaces = pVideoDecoder->maxDecodeSurfaces(); oVideoParserParameters.ulMaxDisplayDelay = 1; // this flag is needed so the parser will push frames out to the decoder as quickly as it can oVideoParserParameters.pUserData = &oParserData_; oVideoParserParameters.pfnSequenceCallback = HandleVideoSequence; // Called before decoding frames and/or whenever there is a format change oVideoParserParameters.pfnDecodePicture = HandlePictureDecode; // Called when a picture is ready to be decoded (decode order) oVideoParserParameters.pfnDisplayPicture = HandlePictureDisplay; // Called whenever a picture is ready to be displayed (display order) CUresult oResult = cuvidCreateVideoParser(&hParser_, &oVideoParserParameters); assert(CUDA_SUCCESS == oResult); } VideoParser::~VideoParser() { if ( hParser_ ) { cuvidDestroyVideoParser( hParser_ ); hParser_ = NULL; } return; } int VideoParser::ParseVideoData( CUVIDSOURCEDATAPACKET * pkt ) { CUresult rlt = CUDA_SUCCESS; rlt = cuvidParseVideoData( hParser_, pkt ); return 0; } int CUDAAPI VideoParser::HandleVideoSequence(void *pUserData, CUVIDEOFORMAT *pFormat) { VideoParserData *pParserData = reinterpret_cast(pUserData); if ((pFormat->codec != pParserData->pVideoDecoder->codec()) // codec-type || (pFormat->coded_width != pParserData->pVideoDecoder->frameWidth()) || (pFormat->coded_height != pParserData->pVideoDecoder->frameHeight()) || (pFormat->chroma_format != pParserData->pVideoDecoder->chromaFormat())) { // We don't deal with dynamic changes in video format return 0; } return 1; } int CUDAAPI VideoParser::HandlePictureDecode(void *pUserData, CUVIDPICPARAMS *pPicParams) { VideoParserData *pParserData = reinterpret_cast(pUserData); bool bFrameAvailable = pParserData->pFrameQueue->waitUntilFrameAvailable(pPicParams->CurrPicIdx); if (!bFrameAvailable) return false; pParserData->pVideoDecoder->decodePicture(pPicParams); return true; } int CUDAAPI VideoParser::HandlePictureDisplay(void *pUserData, CUVIDPARSERDISPINFO *pPicParams) { // std::cout << *pPicParams << std::endl; VideoParserData *pParserData = reinterpret_cast(pUserData); pParserData->pFrameQueue->enqueue(pPicParams); return 1; } std::ostream & operator << (std::ostream &rOutputStream, const CUVIDPARSERDISPINFO &rParserDisplayInfo) { rOutputStream << "Picture Index: " << rParserDisplayInfo.picture_index << "\n"; rOutputStream << "Progressive frame: "; if (rParserDisplayInfo.progressive_frame) rOutputStream << "true\n"; else rOutputStream << "false\n"; rOutputStream << "Top field first: "; if (rParserDisplayInfo.top_field_first) rOutputStream << "true\n"; else rOutputStream << "false\n"; rOutputStream << "Repeat first field: "; if (rParserDisplayInfo.repeat_first_field) rOutputStream << "true\n"; else rOutputStream << "false\n"; rOutputStream << "Time stamp: " << rParserDisplayInfo.timestamp << "\n"; return rOutputStream; }