解码保存全部BMP图像

本文档展示了如何使用CUDA绑定的Video Decode库,将视频解码并保存为BMP图像。示例中包含了CUDA和OpenGL的交互,并支持视频后处理。代码示例解析了视频文件,然后通过CUDA进行NV12到ARGB的颜色空间转换,并将帧保存为BMP图像。
摘要由CSDN通过智能技术生成



/*
 * 2015-6-16:将一个视频全部解码并保存为bmp图片
 */


/* 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/pic/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, size_t g_FrameCount);
//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",
                    sAppFilenam

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值