NvEncoder.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440
  1. /*
  2. * Copyright 2017-2020 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. #pragma once
  12. #include <vector>
  13. #include "nvEncodeAPI.h"
  14. #include <stdint.h>
  15. #include <mutex>
  16. #include <string>
  17. #include <iostream>
  18. #include <sstream>
  19. #include <string.h>
  20. /**
  21. * @brief Exception class for error reporting from NvEncodeAPI calls.
  22. */
  23. class NVENCException : public std::exception
  24. {
  25. public:
  26. NVENCException(const std::string& errorStr, const NVENCSTATUS errorCode)
  27. : m_errorString(errorStr), m_errorCode(errorCode) {}
  28. virtual ~NVENCException() throw() {}
  29. virtual const char* what() const throw() { return m_errorString.c_str(); }
  30. NVENCSTATUS getErrorCode() const { return m_errorCode; }
  31. const std::string& getErrorString() const { return m_errorString; }
  32. static NVENCException makeNVENCException(const std::string& errorStr, const NVENCSTATUS errorCode,
  33. const std::string& functionName, const std::string& fileName, int lineNo);
  34. private:
  35. std::string m_errorString;
  36. NVENCSTATUS m_errorCode;
  37. };
  38. inline NVENCException NVENCException::makeNVENCException(const std::string& errorStr, const NVENCSTATUS errorCode, const std::string& functionName,
  39. const std::string& fileName, int lineNo)
  40. {
  41. std::ostringstream errorLog;
  42. errorLog << functionName << " : " << errorStr << " at " << fileName << ":" << lineNo << std::endl;
  43. NVENCException exception(errorLog.str(), errorCode);
  44. return exception;
  45. }
  46. #define NVENC_THROW_ERROR( errorStr, errorCode ) \
  47. do \
  48. { \
  49. throw NVENCException::makeNVENCException(errorStr, errorCode, __FUNCTION__, __FILE__, __LINE__); \
  50. } while (0)
  51. #define NVENC_API_CALL( nvencAPI ) \
  52. do \
  53. { \
  54. NVENCSTATUS errorCode = nvencAPI; \
  55. if( errorCode != NV_ENC_SUCCESS) \
  56. { \
  57. std::ostringstream errorLog; \
  58. errorLog << #nvencAPI << " returned error " << errorCode; \
  59. throw NVENCException::makeNVENCException(errorLog.str(), errorCode, __FUNCTION__, __FILE__, __LINE__); \
  60. } \
  61. } while (0)
  62. struct NvEncInputFrame
  63. {
  64. void* inputPtr = nullptr;
  65. uint32_t chromaOffsets[2];
  66. uint32_t numChromaPlanes;
  67. uint32_t pitch;
  68. uint32_t chromaPitch;
  69. NV_ENC_BUFFER_FORMAT bufferFormat;
  70. NV_ENC_INPUT_RESOURCE_TYPE resourceType;
  71. };
  72. /**
  73. * @brief Shared base class for different encoder interfaces.
  74. */
  75. class NvEncoder
  76. {
  77. public:
  78. /**
  79. * @brief This function is used to initialize the encoder session.
  80. * Application must call this function to initialize the encoder, before
  81. * starting to encode any frames.
  82. */
  83. void CreateEncoder(const NV_ENC_INITIALIZE_PARAMS* pEncodeParams);
  84. /**
  85. * @brief This function is used to destroy the encoder session.
  86. * Application must call this function to destroy the encoder session and
  87. * clean up any allocated resources. The application must call EndEncode()
  88. * function to get any queued encoded frames before calling DestroyEncoder().
  89. */
  90. void DestroyEncoder();
  91. /**
  92. * @brief This function is used to reconfigure an existing encoder session.
  93. * Application can use this function to dynamically change the bitrate,
  94. * resolution and other QOS parameters. If the application changes the
  95. * resolution, it must set NV_ENC_RECONFIGURE_PARAMS::forceIDR.
  96. */
  97. bool Reconfigure(const NV_ENC_RECONFIGURE_PARAMS *pReconfigureParams);
  98. /**
  99. * @brief This function is used to get the next available input buffer.
  100. * Applications must call this function to obtain a pointer to the next
  101. * input buffer. The application must copy the uncompressed data to the
  102. * input buffer and then call EncodeFrame() function to encode it.
  103. */
  104. const NvEncInputFrame* GetNextInputFrame();
  105. /**
  106. * @brief This function is used to encode a frame.
  107. * Applications must call EncodeFrame() function to encode the uncompressed
  108. * data, which has been copied to an input buffer obtained from the
  109. * GetNextInputFrame() function.
  110. */
  111. void EncodeFrame(std::vector<std::vector<uint8_t>> &vPacket, NV_ENC_PIC_PARAMS *pPicParams = nullptr);
  112. /**
  113. * @brief This function to flush the encoder queue.
  114. * The encoder might be queuing frames for B picture encoding or lookahead;
  115. * the application must call EndEncode() to get all the queued encoded frames
  116. * from the encoder. The application must call this function before destroying
  117. * an encoder session.
  118. */
  119. void EndEncode(std::vector<std::vector<uint8_t>> &vPacket);
  120. /**
  121. * @brief This function is used to query hardware encoder capabilities.
  122. * Applications can call this function to query capabilities like maximum encode
  123. * dimensions, support for lookahead or the ME-only mode etc.
  124. */
  125. int GetCapabilityValue(GUID guidCodec, NV_ENC_CAPS capsToQuery);
  126. /**
  127. * @brief This function is used to get the current device on which encoder is running.
  128. */
  129. void *GetDevice() const { return m_pDevice; }
  130. /**
  131. * @brief This function is used to get the current device type which encoder is running.
  132. */
  133. NV_ENC_DEVICE_TYPE GetDeviceType() const { return m_eDeviceType; }
  134. /**
  135. * @brief This function is used to get the current encode width.
  136. * The encode width can be modified by Reconfigure() function.
  137. */
  138. int GetEncodeWidth() const { return m_nWidth; }
  139. /**
  140. * @brief This function is used to get the current encode height.
  141. * The encode height can be modified by Reconfigure() function.
  142. */
  143. int GetEncodeHeight() const { return m_nHeight; }
  144. /**
  145. * @brief This function is used to get the current frame size based on pixel format.
  146. */
  147. int GetFrameSize() const;
  148. /**
  149. * @brief This function is used to initialize config parameters based on
  150. * given codec and preset guids.
  151. * The application can call this function to get the default configuration
  152. * for a certain preset. The application can either use these parameters
  153. * directly or override them with application-specific settings before
  154. * using them in CreateEncoder() function.
  155. */
  156. void CreateDefaultEncoderParams(NV_ENC_INITIALIZE_PARAMS* pIntializeParams, GUID codecGuid, GUID presetGuid, NV_ENC_TUNING_INFO tuningInfo = NV_ENC_TUNING_INFO_UNDEFINED);
  157. /**
  158. * @brief This function is used to get the current initialization parameters,
  159. * which had been used to configure the encoder session.
  160. * The initialization parameters are modified if the application calls
  161. * Reconfigure() function.
  162. */
  163. void GetInitializeParams(NV_ENC_INITIALIZE_PARAMS *pInitializeParams);
  164. /**
  165. * @brief This function is used to run motion estimation
  166. * This is used to run motion estimation on a a pair of frames. The
  167. * application must copy the reference frame data to the buffer obtained
  168. * by calling GetNextReferenceFrame(), and copy the input frame data to
  169. * the buffer obtained by calling GetNextInputFrame() before calling the
  170. * RunMotionEstimation() function.
  171. */
  172. void RunMotionEstimation(std::vector<uint8_t> &mvData);
  173. /**
  174. * @brief This function is used to get an available reference frame.
  175. * Application must call this function to get a pointer to reference buffer,
  176. * to be used in the subsequent RunMotionEstimation() function.
  177. */
  178. const NvEncInputFrame* GetNextReferenceFrame();
  179. /**
  180. * @brief This function is used to get sequence and picture parameter headers.
  181. * Application can call this function after encoder is initialized to get SPS and PPS
  182. * nalus for the current encoder instance. The sequence header data might change when
  183. * application calls Reconfigure() function.
  184. */
  185. void GetSequenceParams(std::vector<uint8_t> &seqParams);
  186. /**
  187. * @brief NvEncoder class virtual destructor.
  188. */
  189. virtual ~NvEncoder();
  190. public:
  191. /**
  192. * @brief This a static function to get chroma offsets for YUV planar formats.
  193. */
  194. static void GetChromaSubPlaneOffsets(const NV_ENC_BUFFER_FORMAT bufferFormat, const uint32_t pitch,
  195. const uint32_t height, std::vector<uint32_t>& chromaOffsets);
  196. /**
  197. * @brief This a static function to get the chroma plane pitch for YUV planar formats.
  198. */
  199. static uint32_t GetChromaPitch(const NV_ENC_BUFFER_FORMAT bufferFormat, const uint32_t lumaPitch);
  200. /**
  201. * @brief This a static function to get the number of chroma planes for YUV planar formats.
  202. */
  203. static uint32_t GetNumChromaPlanes(const NV_ENC_BUFFER_FORMAT bufferFormat);
  204. /**
  205. * @brief This a static function to get the chroma plane width in bytes for YUV planar formats.
  206. */
  207. static uint32_t GetChromaWidthInBytes(const NV_ENC_BUFFER_FORMAT bufferFormat, const uint32_t lumaWidth);
  208. /**
  209. * @brief This a static function to get the chroma planes height in bytes for YUV planar formats.
  210. */
  211. static uint32_t GetChromaHeight(const NV_ENC_BUFFER_FORMAT bufferFormat, const uint32_t lumaHeight);
  212. /**
  213. * @brief This a static function to get the width in bytes for the frame.
  214. * For YUV planar format this is the width in bytes of the luma plane.
  215. */
  216. static uint32_t GetWidthInBytes(const NV_ENC_BUFFER_FORMAT bufferFormat, const uint32_t width);
  217. /**
  218. * @brief This function returns the number of allocated buffers.
  219. */
  220. uint32_t GetEncoderBufferCount() const { return m_nEncoderBuffer; }
  221. protected:
  222. /**
  223. * @brief NvEncoder class constructor.
  224. * NvEncoder class constructor cannot be called directly by the application.
  225. */
  226. NvEncoder(NV_ENC_DEVICE_TYPE eDeviceType, void *pDevice, uint32_t nWidth, uint32_t nHeight,
  227. NV_ENC_BUFFER_FORMAT eBufferFormat, uint32_t nOutputDelay, bool bMotionEstimationOnly, bool bOutputInVideoMemory = false);
  228. /**
  229. * @brief This function is used to check if hardware encoder is properly initialized.
  230. */
  231. bool IsHWEncoderInitialized() const { return m_hEncoder != NULL && m_bEncoderInitialized; }
  232. /**
  233. * @brief This function is used to register CUDA, D3D or OpenGL input buffers with NvEncodeAPI.
  234. * This is non public function and is called by derived class for allocating
  235. * and registering input buffers.
  236. */
  237. void RegisterInputResources(std::vector<void*> inputframes, NV_ENC_INPUT_RESOURCE_TYPE eResourceType,
  238. int width, int height, int pitch, NV_ENC_BUFFER_FORMAT bufferFormat, bool bReferenceFrame = false);
  239. /**
  240. * @brief This function is used to unregister resources which had been previously registered for encoding
  241. * using RegisterInputResources() function.
  242. */
  243. void UnregisterInputResources();
  244. /**
  245. * @brief This function is used to register CUDA, D3D or OpenGL input or output buffers with NvEncodeAPI.
  246. */
  247. NV_ENC_REGISTERED_PTR RegisterResource(void *pBuffer, NV_ENC_INPUT_RESOURCE_TYPE eResourceType,
  248. int width, int height, int pitch, NV_ENC_BUFFER_FORMAT bufferFormat, NV_ENC_BUFFER_USAGE bufferUsage = NV_ENC_INPUT_IMAGE);
  249. /**
  250. * @brief This function returns maximum width used to open the encoder session.
  251. * All encode input buffers are allocated using maximum dimensions.
  252. */
  253. uint32_t GetMaxEncodeWidth() const { return m_nMaxEncodeWidth; }
  254. /**
  255. * @brief This function returns maximum height used to open the encoder session.
  256. * All encode input buffers are allocated using maximum dimensions.
  257. */
  258. uint32_t GetMaxEncodeHeight() const { return m_nMaxEncodeHeight; }
  259. /**
  260. * @brief This function returns the completion event.
  261. */
  262. void* GetCompletionEvent(uint32_t eventIdx) { return (m_vpCompletionEvent.size() == m_nEncoderBuffer) ? m_vpCompletionEvent[eventIdx] : nullptr; }
  263. /**
  264. * @brief This function returns the current pixel format.
  265. */
  266. NV_ENC_BUFFER_FORMAT GetPixelFormat() const { return m_eBufferFormat; }
  267. /**
  268. * @brief This function is used to submit the encode commands to the
  269. * NVENC hardware.
  270. */
  271. NVENCSTATUS DoEncode(NV_ENC_INPUT_PTR inputBuffer, NV_ENC_OUTPUT_PTR outputBuffer, NV_ENC_PIC_PARAMS *pPicParams);
  272. /**
  273. * @brief This function is used to submit the encode commands to the
  274. * NVENC hardware for ME only mode.
  275. */
  276. NVENCSTATUS DoMotionEstimation(NV_ENC_INPUT_PTR inputBuffer, NV_ENC_INPUT_PTR inputBufferForReference, NV_ENC_OUTPUT_PTR outputBuffer);
  277. /**
  278. * @brief This function is used to map the input buffers to NvEncodeAPI.
  279. */
  280. void MapResources(uint32_t bfrIdx);
  281. /**
  282. * @brief This function is used to wait for completion of encode command.
  283. */
  284. void WaitForCompletionEvent(int iEvent);
  285. /**
  286. * @brief This function is used to send EOS to HW encoder.
  287. */
  288. void SendEOS();
  289. private:
  290. /**
  291. * @brief This is a private function which is used to check if there is any
  292. buffering done by encoder.
  293. * The encoder generally buffers data to encode B frames or for lookahead
  294. * or pipelining.
  295. */
  296. bool IsZeroDelay() { return m_nOutputDelay == 0; }
  297. /**
  298. * @brief This is a private function which is used to load the encode api shared library.
  299. */
  300. void LoadNvEncApi();
  301. /**
  302. * @brief This is a private function which is used to get the output packets
  303. * from the encoder HW.
  304. * This is called by DoEncode() function. If there is buffering enabled,
  305. * this may return without any output data.
  306. */
  307. void GetEncodedPacket(std::vector<NV_ENC_OUTPUT_PTR> &vOutputBuffer, std::vector<std::vector<uint8_t>> &vPacket, bool bOutputDelay);
  308. /**
  309. * @brief This is a private function which is used to initialize the bitstream buffers.
  310. * This is only used in the encoding mode.
  311. */
  312. void InitializeBitstreamBuffer();
  313. /**
  314. * @brief This is a private function which is used to destroy the bitstream buffers.
  315. * This is only used in the encoding mode.
  316. */
  317. void DestroyBitstreamBuffer();
  318. /**
  319. * @brief This is a private function which is used to initialize MV output buffers.
  320. * This is only used in ME-only Mode.
  321. */
  322. void InitializeMVOutputBuffer();
  323. /**
  324. * @brief This is a private function which is used to destroy MV output buffers.
  325. * This is only used in ME-only Mode.
  326. */
  327. void DestroyMVOutputBuffer();
  328. /**
  329. * @brief This is a private function which is used to destroy HW encoder.
  330. */
  331. void DestroyHWEncoder();
  332. /**
  333. * @brief This function is used to flush the encoder queue.
  334. */
  335. void FlushEncoder();
  336. private:
  337. /**
  338. * @brief This is a pure virtual function which is used to allocate input buffers.
  339. * The derived classes must implement this function.
  340. */
  341. virtual void AllocateInputBuffers(int32_t numInputBuffers) = 0;
  342. /**
  343. * @brief This is a pure virtual function which is used to destroy input buffers.
  344. * The derived classes must implement this function.
  345. */
  346. virtual void ReleaseInputBuffers() = 0;
  347. protected:
  348. bool m_bMotionEstimationOnly = false;
  349. bool m_bOutputInVideoMemory = false;
  350. void *m_hEncoder = nullptr;
  351. NV_ENCODE_API_FUNCTION_LIST m_nvenc;
  352. std::vector<NvEncInputFrame> m_vInputFrames;
  353. std::vector<NV_ENC_REGISTERED_PTR> m_vRegisteredResources;
  354. std::vector<NvEncInputFrame> m_vReferenceFrames;
  355. std::vector<NV_ENC_REGISTERED_PTR> m_vRegisteredResourcesForReference;
  356. std::vector<NV_ENC_INPUT_PTR> m_vMappedInputBuffers;
  357. std::vector<NV_ENC_INPUT_PTR> m_vMappedRefBuffers;
  358. std::vector<void *> m_vpCompletionEvent;
  359. int32_t m_iToSend = 0;
  360. int32_t m_iGot = 0;
  361. int32_t m_nEncoderBuffer = 0;
  362. int32_t m_nOutputDelay = 0;
  363. private:
  364. uint32_t m_nWidth;
  365. uint32_t m_nHeight;
  366. NV_ENC_BUFFER_FORMAT m_eBufferFormat;
  367. void *m_pDevice;
  368. NV_ENC_DEVICE_TYPE m_eDeviceType;
  369. NV_ENC_INITIALIZE_PARAMS m_initializeParams = {};
  370. NV_ENC_CONFIG m_encodeConfig = {};
  371. bool m_bEncoderInitialized = false;
  372. uint32_t m_nExtraOutputDelay = 3; // To ensure encode and graphics can work in parallel, m_nExtraOutputDelay should be set to at least 1
  373. std::vector<NV_ENC_OUTPUT_PTR> m_vBitstreamOutputBuffer;
  374. std::vector<NV_ENC_OUTPUT_PTR> m_vMVDataOutputBuffer;
  375. uint32_t m_nMaxEncodeWidth = 0;
  376. uint32_t m_nMaxEncodeHeight = 0;
  377. };