codekingpro/portable-devtools
114k
1/*
2* Copyright 2017-2024 NVIDIA Corporation. All rights reserved.
3*
4* Please refer to the NVIDIA end user license agreement (EULA) associated
5* with this source code for terms and conditions that govern your use of
6* this software. Any use, reproduction, disclosure, or distribution of
7* this software and related documentation outside the terms of the EULA
8* is strictly prohibited.
9*
10*/
11
12//---------------------------------------------------------------------------
13//! \file AppDecLowLatency.cpp
14//! \brief Source file for AppDecLowLatency sample
15//!
16//! This sample application demonstrates low latency decoding feature.
17//! This feature helps to get output frame as soon as it is decoded without any delay.
18//! The feature will work for streams having I and P frames only.
19//---------------------------------------------------------------------------
20
21#include <vector>
22#include <cuda.h>
23#include "NvDecoder/NvDecoder.h"
24#include "../Utils/NvCodecUtils.h"
25#include "../Utils/FFmpegDemuxer.h"
26#include "../Common/AppDecUtils.h"
27
28simplelogger::Logger *logger = simplelogger::LoggerFactory::CreateConsoleLogger();
29
30int main(int argc, char *argv[])
31{
32 char szInFilePath[256] = "", szOutFilePath[256] = "out.yuv";
33 int iGpu = 0;
34 bool bVerbose = false;
35 // With zero latency flag enabled, HandlePictureDisplay() callback happens immediately for
36 // the All-Intra/IPPP streams
37 bool force_zero_latency = false;
38 try
39 {
40 ParseCommandLine(argc, argv, szInFilePath, szOutFilePath, iGpu, &bVerbose, NULL, &force_zero_latency);
41 CheckInputFile(szInFilePath);
42
43 ck(cuInit(0));
44 int nGpu = 0;
45 ck(cuDeviceGetCount(&nGpu));
46 if (iGpu < 0 || iGpu >= nGpu)
47 {
48 std::ostringstream err;
49 err << "GPU ordinal out of range. Should be within [" << 0 << ", " << nGpu - 1 << "]" << std::endl;
50 throw std::invalid_argument(err.str());
51 }
52
53 CUcontext cuContext = NULL;
54 createCudaContext(&cuContext, iGpu, 0);
55
56 FFmpegDemuxer demuxer(szInFilePath);
57 // Here set bLowLatency=true in the constructor.
58 // Please don't use this flag except for low latency, it is harder to get 100% utilization of
59 // hardware decoder with this flag set.
60 NvDecoder dec(cuContext, false, FFmpeg2NvCodecId(demuxer.GetVideoCodec()), true, false, NULL, NULL, false, 0, 0, 1000, force_zero_latency);
61
62 int nFrame = 0;
63 uint8_t *pVideo = NULL;
64 int nVideoBytes = 0;
65 std::ofstream fpOut(szOutFilePath, std::ios::out | std::ios::binary);
66 if (!fpOut)
67 {
68 std::ostringstream err;
69 err << "Unable to open output file: " << szOutFilePath << std::endl;
70 throw std::invalid_argument(err.str());
71 }
72
73 int n = 0;
74 bool bOneInOneOut = true;
75 int nFrameReturned = 0;
76 int64_t timestamp = 0;
77 do {
78 demuxer.Demux(&pVideo, &nVideoBytes);
79 // Set flag CUVID_PKT_ENDOFPICTURE to signal that a complete packet has been sent to decode
80 nFrameReturned = dec.Decode(pVideo, nVideoBytes, CUVID_PKT_ENDOFPICTURE, n++);
81 if (!nFrame && nFrameReturned)
82 LOG(INFO) << dec.GetVideoInfo();
83
84 nFrame += nFrameReturned;
85 // For a stream without B-frames, "one in and one out" is expected, and nFrameReturned should be always 1 for each input packet
86 if (bVerbose)
87 {
88 std::cout << "Decode: nVideoBytes=" << nVideoBytes << ", nFrameReturned=" << nFrameReturned << ", total=" << nFrame << std::endl;
89 }
90 if (nVideoBytes && nFrameReturned != 1)
91 {
92 bOneInOneOut = false;
93 }
94 for (int i = 0; i < nFrameReturned; i++)
95 {
96 fpOut.write(reinterpret_cast<char*>(dec.GetFrame(×tamp)), dec.GetFrameSize());
97 if (bVerbose)
98 {
99 std::cout << "Timestamp: " << timestamp << std::endl;
100 }
101 }
102 } while (nVideoBytes);
103
104 fpOut.close();
105 std::cout << "One packet in and one frame out: " << (bOneInOneOut ? "true" : "false") << std::endl;
106 }
107 catch(const std::exception& ex)
108 {
109 std::cout << ex.what();
110 exit(1);
111 }
112 return 0;
113}
114 