Skip to content

Commit beb76fe

Browse files
committed
more changes.
1 parent d6fdad6 commit beb76fe

5 files changed

Lines changed: 813 additions & 3 deletions

File tree

webrtc-sys/build.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -142,9 +142,8 @@ fn main() {
142142
.file("src/nvidia/NvCodec/NvCodec/NvDecoder/NvDecoder.cpp")
143143
.file("src/nvidia/NvCodec/NvCodec/NvEncoder/NvEncoder.cpp")
144144
.file("src/nvidia/NvCodec/NvCodec/NvEncoder/NvEncoderCuda.cpp")
145-
.file("src/nvidia/CreateVideoCodecFactory.cpp")
146-
.file("src/nvidia/SimulcastEncoderFactory.cpp")
147-
.file("src/nvidia/H264ProfileLevelId.cpp")
145+
.file("src/nvidia/h264_encoder_impl.cpp")
146+
.file("src/nvidia/NvEncoderCudaWithCUarray.cpp")
148147
.flag("-std=c++2a")
149148
.flag("-Wno-deprecated-declarations");
150149
}
Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
#include "NvEncoderCudaWithCUarray.h"
2+
3+
#include "NvEncoder/NvEncoder.h"
4+
#include "NvEncoder/NvEncoderCuda.h"
5+
6+
namespace webrtc {
7+
8+
static CUresult CreateCUarray(CUarray* pDstArray,
9+
uint32_t width,
10+
uint32_t height,
11+
CUarray_format format,
12+
int numChannels) {
13+
CUDA_ARRAY3D_DESCRIPTOR arrayDesc = CUDA_ARRAY3D_DESCRIPTOR();
14+
arrayDesc.Width = width;
15+
arrayDesc.Height = height;
16+
arrayDesc.Depth = 0; /* CUDA 2D arrays are defined to have depth 0 */
17+
arrayDesc.Format = format;
18+
arrayDesc.NumChannels = static_cast<uint32_t>(numChannels);
19+
arrayDesc.Flags = CUDA_ARRAY3D_SURFACE_LDST;
20+
21+
return cuArray3DCreate(pDstArray, &arrayDesc);
22+
}
23+
24+
NvEncoderCudaWithCUarray::NvEncoderCudaWithCUarray(
25+
CUcontext cuContext,
26+
uint32_t nWidth,
27+
uint32_t nHeight,
28+
NV_ENC_BUFFER_FORMAT eBufferFormat,
29+
uint32_t nExtraOutputDelay,
30+
bool bMotionEstimationOnly,
31+
bool bOutputInVideoMemory)
32+
: NvEncoder(NV_ENC_DEVICE_TYPE_CUDA,
33+
cuContext,
34+
nWidth,
35+
nHeight,
36+
eBufferFormat,
37+
nExtraOutputDelay,
38+
bMotionEstimationOnly,
39+
bOutputInVideoMemory),
40+
m_cuContext(cuContext) {
41+
if (!m_hEncoder) {
42+
NVENC_THROW_ERROR("Encoder Initialization failed",
43+
NV_ENC_ERR_INVALID_DEVICE);
44+
}
45+
46+
if (!m_cuContext) {
47+
NVENC_THROW_ERROR("Invalid Cuda Context", NV_ENC_ERR_INVALID_DEVICE);
48+
}
49+
}
50+
51+
NvEncoderCudaWithCUarray::~NvEncoderCudaWithCUarray() {
52+
ReleaseCudaResources();
53+
}
54+
55+
void NvEncoderCudaWithCUarray::AllocateInputBuffers(int32_t numInputBuffers) {
56+
if (!IsHWEncoderInitialized()) {
57+
NVENC_THROW_ERROR("Encoder intialization failed",
58+
NV_ENC_ERR_ENCODER_NOT_INITIALIZED);
59+
}
60+
61+
// for MEOnly mode we need to allocate seperate set of buffers for reference
62+
// frame
63+
int numCount = m_bMotionEstimationOnly ? 2 : 1;
64+
65+
for (int count = 0; count < numCount; count++) {
66+
CUDA_DRVAPI_CALL(cuCtxPushCurrent(m_cuContext));
67+
std::vector<void*> inputFrames;
68+
for (int i = 0; i < numInputBuffers; i++) {
69+
CUarray frame;
70+
CUDA_DRVAPI_CALL(CreateCUarray(&frame, GetMaxEncodeWidth(),
71+
GetMaxEncodeHeight(),
72+
CU_AD_FORMAT_UNSIGNED_INT32, 1));
73+
inputFrames.push_back(static_cast<void*>(frame));
74+
}
75+
CUDA_DRVAPI_CALL(cuCtxPopCurrent(NULL));
76+
77+
int encodeWidth = static_cast<int>(GetMaxEncodeWidth());
78+
int encodeHeight = static_cast<int>(GetMaxEncodeHeight());
79+
int widthInBytes = static_cast<int>(
80+
GetWidthInBytes(GetPixelFormat(), GetMaxEncodeWidth()));
81+
82+
RegisterInputResources(inputFrames, NV_ENC_INPUT_RESOURCE_TYPE_CUDAARRAY,
83+
encodeWidth, encodeHeight, widthInBytes,
84+
GetPixelFormat(), (count == 1) ? true : false);
85+
}
86+
}
87+
88+
void NvEncoderCudaWithCUarray::ReleaseInputBuffers() {
89+
ReleaseCudaResources();
90+
}
91+
92+
void NvEncoderCudaWithCUarray::ReleaseCudaResources() {
93+
if (!m_hEncoder) {
94+
return;
95+
}
96+
97+
if (!m_cuContext) {
98+
return;
99+
}
100+
101+
UnregisterInputResources();
102+
103+
cuCtxPushCurrent(m_cuContext);
104+
105+
for (uint32_t i = 0; i < m_vInputFrames.size(); ++i) {
106+
if (m_vInputFrames[i].inputPtr) {
107+
cuMemFree(reinterpret_cast<CUdeviceptr>(m_vInputFrames[i].inputPtr));
108+
}
109+
}
110+
m_vInputFrames.clear();
111+
112+
for (uint32_t i = 0; i < m_vReferenceFrames.size(); ++i) {
113+
if (m_vReferenceFrames[i].inputPtr) {
114+
cuMemFree(reinterpret_cast<CUdeviceptr>(m_vReferenceFrames[i].inputPtr));
115+
}
116+
}
117+
m_vReferenceFrames.clear();
118+
119+
cuCtxPopCurrent(nullptr);
120+
m_cuContext = nullptr;
121+
}
122+
123+
void NvEncoderCudaWithCUarray::CopyToDeviceFrame(
124+
CUcontext device,
125+
void* pSrcArray,
126+
uint32_t nSrcPitch,
127+
CUarray pDstArray,
128+
uint32_t dstPitch,
129+
int width,
130+
int height,
131+
CUmemorytype srcMemoryType,
132+
NV_ENC_BUFFER_FORMAT pixelFormat,
133+
const uint32_t dstChromaOffsets[],
134+
uint32_t numChromaPlanes,
135+
bool bUnAlignedDeviceCopy,
136+
CUstream stream) {
137+
if (srcMemoryType != CU_MEMORYTYPE_HOST &&
138+
srcMemoryType != CU_MEMORYTYPE_ARRAY) {
139+
NVENC_THROW_ERROR("Invalid source memory type for copy",
140+
NV_ENC_ERR_INVALID_PARAM);
141+
}
142+
143+
CUDA_DRVAPI_CALL(cuCtxPushCurrent(device));
144+
145+
uint32_t srcPitch = nSrcPitch
146+
? nSrcPitch
147+
: NvEncoder::GetWidthInBytes(
148+
pixelFormat, static_cast<uint32_t>(width));
149+
CUDA_MEMCPY2D m = CUDA_MEMCPY2D();
150+
m.srcMemoryType = srcMemoryType;
151+
if (srcMemoryType == CU_MEMORYTYPE_HOST) {
152+
m.srcHost = pSrcArray;
153+
} else {
154+
m.srcArray = static_cast<CUarray>(pSrcArray);
155+
}
156+
m.srcPitch = srcPitch;
157+
m.dstMemoryType = CU_MEMORYTYPE_ARRAY;
158+
m.dstArray = pDstArray;
159+
m.dstPitch = dstPitch;
160+
m.WidthInBytes =
161+
NvEncoder::GetWidthInBytes(pixelFormat, static_cast<uint32_t>(width));
162+
m.Height = static_cast<size_t>(height);
163+
if (bUnAlignedDeviceCopy && srcMemoryType == CU_MEMORYTYPE_ARRAY) {
164+
CUDA_DRVAPI_CALL(cuMemcpy2DUnaligned(&m));
165+
} else {
166+
CUDA_DRVAPI_CALL(stream == NULL ? cuMemcpy2D(&m)
167+
: cuMemcpy2DAsync(&m, stream));
168+
}
169+
170+
std::vector<uint32_t> srcChromaOffsets;
171+
NvEncoder::GetChromaSubPlaneOffsets(
172+
pixelFormat, srcPitch, static_cast<uint32_t>(height), srcChromaOffsets);
173+
uint32_t chromaHeight =
174+
NvEncoder::GetChromaHeight(pixelFormat, static_cast<uint32_t>(height));
175+
uint32_t destChromaPitch = NvEncoder::GetChromaPitch(pixelFormat, dstPitch);
176+
uint32_t srcChromaPitch = NvEncoder::GetChromaPitch(pixelFormat, srcPitch);
177+
uint32_t chromaWidthInBytes = NvEncoder::GetChromaWidthInBytes(
178+
pixelFormat, static_cast<uint32_t>(width));
179+
180+
for (uint32_t i = 0; i < numChromaPlanes; ++i) {
181+
if (chromaHeight) {
182+
if (srcMemoryType == CU_MEMORYTYPE_HOST) {
183+
m.srcHost = (static_cast<uint8_t*>(pSrcArray) + srcChromaOffsets[i]);
184+
} else {
185+
m.srcArray =
186+
(CUarray)(static_cast<uint8_t*>(pSrcArray) + srcChromaOffsets[i]);
187+
}
188+
m.srcPitch = srcChromaPitch;
189+
190+
m.dstArray = (CUarray)((uint8_t*)pDstArray + dstChromaOffsets[i]);
191+
m.dstPitch = destChromaPitch;
192+
m.WidthInBytes = chromaWidthInBytes;
193+
m.Height = chromaHeight;
194+
if (bUnAlignedDeviceCopy && srcMemoryType == CU_MEMORYTYPE_ARRAY) {
195+
CUDA_DRVAPI_CALL(cuMemcpy2DUnaligned(&m));
196+
} else {
197+
CUDA_DRVAPI_CALL(stream == NULL ? cuMemcpy2D(&m)
198+
: cuMemcpy2DAsync(&m, stream));
199+
}
200+
}
201+
}
202+
CUDA_DRVAPI_CALL(cuCtxPopCurrent(NULL));
203+
}
204+
205+
} // end namespace webrtc
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
#pragma once
2+
3+
#include <cuda.h>
4+
#include <stdint.h>
5+
6+
#include <mutex>
7+
8+
#include "NvEncoder/NvEncoder.h"
9+
10+
namespace webrtc {
11+
12+
/**
13+
* @brief Encoder for CUDA device memory.
14+
*/
15+
class NvEncoderCudaWithCUarray : public ::NvEncoder {
16+
public:
17+
NvEncoderCudaWithCUarray(CUcontext cuContext,
18+
uint32_t nWidth,
19+
uint32_t nHeight,
20+
NV_ENC_BUFFER_FORMAT eBufferFormat,
21+
uint32_t nExtraOutputDelay = 3,
22+
bool bMotionEstimationOnly = false,
23+
bool bOPInVideoMemory = false);
24+
virtual ~NvEncoderCudaWithCUarray() override;
25+
26+
/**
27+
* @brief This is a static function to copy input data from host memory to
28+
* device memory. This function assumes YUV plane is a single contiguous
29+
* memory segment.
30+
*/
31+
static void CopyToDeviceFrame(CUcontext device,
32+
void* pSrcArray,
33+
uint32_t nSrcPitch,
34+
CUarray pDstArray,
35+
uint32_t dstPitch,
36+
int width,
37+
int height,
38+
CUmemorytype srcMemoryType,
39+
NV_ENC_BUFFER_FORMAT pixelFormat,
40+
const uint32_t dstChromaOffsets[],
41+
uint32_t numChromaPlanes,
42+
bool bUnAlignedDeviceCopy = false,
43+
CUstream stream = nullptr);
44+
45+
protected:
46+
/**
47+
* @brief This function is used to release the input buffers allocated for
48+
* encoding. This function is an override of virtual function
49+
* NvEncoder::ReleaseInputBuffers().
50+
*/
51+
virtual void ReleaseInputBuffers() override;
52+
53+
private:
54+
/**
55+
* @brief This function is used to allocate input buffers for encoding.
56+
* This function is an override of virtual function
57+
* NvEncoder::AllocateInputBuffers().
58+
*/
59+
virtual void AllocateInputBuffers(int32_t numInputBuffers) override;
60+
61+
private:
62+
/**
63+
* @brief This is a private function to release CUDA device memory used for
64+
* encoding.
65+
*/
66+
void ReleaseCudaResources();
67+
68+
protected:
69+
CUcontext m_cuContext;
70+
};
71+
} // end namespace webrtc

0 commit comments

Comments
 (0)