/*
* 2015-6-16:保存单帧图片
*/
/* This example demonstrates how to use the Video Decode Library with CUDA
* bindings to interop between NVCUVID(CUDA) and OpenGL (PBOs). Post-Processing
* video (de-interlacing) is supported with this sample.
*/
// OpenGL Graphics includes
#include <GL/glew.h>
#if defined(__APPLE__) || defined(__MACOSX)
#include <GLUT/glut.h>
#else
#include <GL/freeglut.h>
#endif
// CUDA Header includes
#include <cuda.h>
#include <cudaGL.h>
// CUDA utilities and system includes
#include <helper_functions.h>
#include <helper_cuda.h>
#include <helper_cuda_drvapi.h>
#include <helper_cuda_gl.h>
// Includes
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <memory>
#include <iostream>
#include <cassert>
// cudaDecodeGL related helper functions
#include "FrameQueue.h"
#include "VideoSource.h"
#include "VideoParser.h"
#include "VideoDecoder.h"
#include "ImageGL.h"
#include "cudaProcessFrame.h"
#include "cudaModuleMgr.h"
const char *sAppName = "CUDA/OpenGL Video Decode";
const char *sAppFilename = "cudaDecodeGL";
const char *sSDKname = "cudaDecodeGL";
//#define VIDEO_SOURCE_FILE "plush1_720p_10s.m2v"
#define VIDEO_SOURCE_FILE "./data/campus.mp4" //2014/6/16修改
//#define VIDEO_SOURCE_FILE "E://video//yj.avi" //2014/6/16修改
#ifdef _DEBUG
#define ENABLE_DEBUG_OUT 0
#else
#define ENABLE_DEBUG_OUT 0
#endif
StopWatchInterface *frame_timer = NULL,
*global_timer = NULL;
/
// RMC ADD
int g_FrameCapCount = 0; // added to capture a specific frame when readback is enabled
// set g_FrameCount to some negative value to disable Frame capture to file
// otherwise set to zero
// g_bUseInterop must also be zero for FrameCap
int g_FrameCapSelect = /*37*/ 144; // select which frame to capture to a file
int g_FrameCapPitch = 0;
int g_FrameCapHeight = 0;
//char g_FrameCapFile[] = "framecap.bmp"; //原始代码
char g_FrameCapFile[] = "G:/SixRoadYUV/single/framecap.bmp"; //2014/6/16
// END RMC ADD
/
int g_DeviceID = 0;
bool g_bWindowed = true;
bool g_bDeviceLost = false;
bool g_bDone = false;
bool g_bRunning = false;
bool g_bAutoQuit = false;
bool g_bUseVsync = false;
bool g_bFrameRepeat= false;
bool g_bFrameStep = false;
bool g_bQAReadback = false;
bool g_bGLVerify = false;
bool g_bFirstFrame = true;
bool g_bLoop = false;
bool g_bUpdateCSC = true;
bool g_bUpdateAll = false;
bool g_bLinearFiltering = false;
//bool g_bUseDisplay = true; // this flag enables/disables video on the window
bool g_bUseDisplay = false; // this flag enables/disables video on the window
//bool g_bUseInterop = true;
bool g_bUseInterop = false; //2014/6/16
bool g_bReadback = false;
bool g_bIsProgressive = true; // assume it is progressive, unless otherwise noted
bool g_bException = false;
bool g_bWaived = false;
int g_iRepeatFactor = 1; // 1:1 assumes no frame repeats
int *pArgc = NULL;
char **pArgv = NULL;
cudaVideoCreateFlags g_eVideoCreateFlags = cudaVideoCreate_PreferCUVID;
CUvideoctxlock g_CtxLock = NULL;
float present_fps, decoded_fps, total_time = 0.0f;
// These are CUDA function pointers to the CUDA kernels
CUmoduleManager *g_pCudaModule;
CUmodule cuModNV12toARGB = 0;
CUfunction g_kernelNV12toARGB = 0;
CUfunction g_kernelPassThru = 0;
CUcontext g_oContext = 0;
CUdevice g_oDevice = 0;
CUstream g_ReadbackSID = 0, g_KernelSID = 0;
eColorSpace g_eColorSpace = ITU601;
float g_nHue = 0.0f;
// System Memory surface we want to readback to
BYTE *g_bFrameData[2] = { 0, 0 };
///
// RMC ADD
BYTE *g_bFrameCapData = 0;
// END RMC ADD
//
FrameQueue *g_pFrameQueue = 0;
VideoSource *g_pVideoSource = 0;
VideoParser *g_pVideoParser = 0;
VideoDecoder *g_pVideoDecoder = 0;
ImageGL *g_pImageGL = 0; // if we're using OpenGL
CUdeviceptr g_pInteropFrame[2] = { 0, 0 }; // if we're using CUDA malloc
std::string sFileName;
char exec_path[256];
unsigned int g_nWindowWidth = 0;
unsigned int g_nWindowHeight = 0;
unsigned int g_nClientAreaWidth = 0;
unsigned int g_nClientAreaHeight = 0;
unsigned int g_nVideoWidth = 0;
unsigned int g_nVideoHeight = 0;
unsigned int g_FrameCount = 0;
unsigned int g_DecodeFrameCount = 0;
unsigned int g_fpsCount = 0; // FPS count for averaging
unsigned int g_fpsLimit = 16; // FPS limit for sampling timer;
/
// Forward declarations
//RMC ADD
void saveFrameCap(BYTE *data, size_t pitch, size_t height);
//END RMC ADD
bool initGL(int argc, char **argv, int *pbTCC);
bool initGLTexture(unsigned int nWidth, unsigned int nHeight);
bool loadVideoSource(const char *video_file,
unsigned int &width, unsigned int &height,
unsigned int &dispWidth, unsigned int &dispHeight);
void initCudaVideo();
void freeCudaResources(bool bDestroyContext);
bool copyDecodedFrameToTexture(unsigned int &nRepeats, int bUseInterop, int *pbIsProgressive);
void cudaPostProcessFrame(CUdeviceptr *ppDecodedFrame, size_t nDecodedPitch,
CUdeviceptr *ppInteropFrame, size_t pFramePitch,
CUmodule cuModNV12toARGB,
CUfunction fpCudaKernel, CUstream streamID);
bool drawScene(int field_num);
bool cleanup(bool bDestroyContext);
bool initCudaResources(int argc, char **argv, int *bTCC);
void renderVideoFrame(int bUseInterop);
#ifdef WIN32
typedef bool (APIENTRY *PFNWGLSWAPINTERVALFARPROC)(int);
PFNWGLSWAPINTERVALFARPROC wglSwapIntervalEXT = 0;
// This allows us to turn off vsync for OpenGL
void setVSync(int interval)
{
const GLubyte *extensions = glGetString(GL_EXTENSIONS);
if (strstr((const char *)extensions, "WGL_EXT_swap_control") == 0)
{
return; // Error: WGL_EXT_swap_control extension not supported on your computer.\n");
}
else
{
wglSwapIntervalEXT = (PFNWGLSWAPINTERVALFARPROC)wglGetProcAddress("wglSwapIntervalEXT");
if (wglSwapIntervalEXT)
{
wglSwapIntervalEXT(interval);
}
}
}
#ifndef STRCASECMP
#define STRCASECMP _stricmp
#endif
#ifndef STRNCASECMP
#define STRNCASECMP _strnicmp
#endif
#else
void setVSync(int interval)
{
}
#ifndef STRCASECMP
#define STRCASECMP strcasecmp
#endif
#ifndef STRNCASECMP
#define STRNCASECMP strncasecmp
#endif
#endif
void printStatistics()
{
int hh, mm, ss, msec;
present_fps = 1.f / (total_time / (g_FrameCount * 1000.f));
decoded_fps = 1.f / (total_time / (g_DecodeFrameCount * 1000.f));
msec = ((int)total_time % 1000);
ss = (int)(total_time/1000) % 60;
mm = (int)(total_time/(1000*60)) % 60;
hh = (int)(total_time/(1000*60*60)) % 60;
printf("\n[%s] statistics\n", sAppFilename);
printf("\t Video Length (hh:mm:ss.msec) = %02d:%02d:%02d.%03d\n", hh, mm, ss, msec);
printf("\t Frames Presented (inc repeats) = %d\n", g_FrameCount);
printf("\t Average Present Rate (fps) = %4.2f\n", present_fps);
printf("\t Frames Decoded (hardware) = %d\n", g_DecodeFrameCount);
printf("\t Average Rate of Decoding (fps) = %4.2f\n", decoded_fps);
}
void computeFPS(int bUseInterop)
{
sdkStopTimer(&frame_timer);
if (g_bRunning)
{
g_fpsCount++;
if (!g_pFrameQueue->isEndOfDecode())
{
g_FrameCount++;
}
}
char sFPS[256];
std::string sDecodeStatus;
if (g_bDeviceLost)
{
sDecodeStatus = "DeviceLost!\0";
sprintf(sFPS, "%s [%s] - [%s %d]",
sSDKname, sDecodeStatus.c_str(),
(g_bIsProgressive ? "Frame" : "Field"),
g_DecodeFrameCount);
if (!g_bQAReadback || g_bGLVerify)
{
glutSetWindowTitle(sFPS);
}
sdkResetTimer(&frame_timer);
g_fpsCount = 0;
return;
}
if (g_pFrameQueue->isEndOfDecode())
{
sDecodeStatus = "STOP (End of File)\0";
// we only want to record this once
if (total_time == 0.0f)
{
total_time = sdkGetTimerValue(&global_timer);
}
sdkStopTimer(&global_timer);
if (g_bAutoQuit)
{
g_bRunning = false;
g_bDone = true;
}
}
else
{
if (!g_bRunning)
{
sDecodeStatus = "PAUSE\0";
sprintf(sFPS, "%s [%s] - [%s %d] - Video Display %s / Vsync %s",
sAppFilename, sDecodeStatus.c_str(),
(g_bIsProgressive ? "Frame" : "Field"),
<