Commit 92989af0db1827cabea63ec2a20ff37eb9ac047d
1 parent
372e629f
更新解码器
Showing
35 changed files
with
2765 additions
and
340 deletions
.gitignore
.vscode/launch.json
... | ... | @@ -6,7 +6,7 @@ |
6 | 6 | "type": "cppdbg", |
7 | 7 | "request": "launch", |
8 | 8 | "program": "${workspaceFolder}/bin/lib/test", |
9 | - "args": ["rtsp://122.97.218.170:8604/openUrl/V5nXRHa?params=eyJwcm90b2NhbCI6InJ0c3AiLCJjbGllbnRUeXBlIjoib3Blbl9hcGkiLCJleHByaWVUaW1lIjotMSwicHJvdG9jb2wiOiJydHNwIiwiZXhwaXJlVGltZSI6MzAwLCJlbmFibGVNR0MiOnRydWUsImV4cGFuZCI6InN0YW5kYXJkPXJ0c3Amc3RyZWFtZm9ybT1ydHAiLCJhIjoiMTBjZjM4N2JjY2Y5NDg3YzhjNWYzNjE2M2ViMWUyNTJ8MXwwfDEiLCJ0IjoxfQ==","0"], | |
9 | + "args": ["rtsp","3", "30012"], | |
10 | 10 | "stopAtEntry": false, |
11 | 11 | "cwd": "${workspaceFolder}/bin/lib", |
12 | 12 | "environment": [], | ... | ... |
README.md
... | ... | @@ -4,7 +4,7 @@ |
4 | 4 | 支持 cuvid 需要安装 nv-codec-headers, 进入 nv-codec-headers 文件夹后以sudo权限make && make install即可 |
5 | 5 | 3. 编译ffmpeg |
6 | 6 | ~~~ |
7 | -./configure --enable-debug --extra-cflags=-g --extra-ldflags=-g --disable-optimizations --disable-stripping --enable-cuda --enable-cuvid --enable-nvenc --disable-x86asm --enable-nonfree --enable-libnpp --extra-cflags=-I/usr/local/cuda-11.7/targets/x86_64-linux/include --extra-cflags=-fPIC --extra-ldflags=-L/usr/local/cuda-11.7/targets/x86_64-linux/lib --enable-shared --enable-pic --enable-ffplay --prefix=../bin | |
7 | +./configure --enable-debug --extra-cflags=-g --extra-ldflags=-g --disable-optimizations --disable-stripping --enable-cuda --enable-cuvid --enable-nvenc --disable-x86asm --enable-nonfree --enable-libnpp --disable-vaapi --extra-cflags=-I/usr/local/cuda-11.7/targets/x86_64-linux/include --extra-cflags=-fPIC --extra-ldflags=-L/usr/local/cuda-11.7/targets/x86_64-linux/lib --enable-shared --enable-pic --enable-ffplay --prefix=../bin | |
8 | 8 | ~~~ |
9 | 9 | 其中以下是用于调试的,编译release可以去掉: |
10 | 10 | ~~~ | ... | ... |
src/AbstractDecoder.cpp
0 → 100644
1 | +#include "AbstractDecoder.h" | |
2 | + | |
3 | +#include "logger.hpp" | |
4 | +#include "GpuRgbMemory.hpp" | |
5 | +#include "cuda_kernels.h" | |
6 | + | |
7 | +#include "utiltools.hpp" | |
8 | + | |
9 | + | |
10 | +FFImgInfo* AbstractDecoder::snapshot(){ | |
11 | + | |
12 | + // 锁住停止队列消耗 | |
13 | + std::lock_guard<std::mutex> l(m_snapshot_mutex); | |
14 | + | |
15 | + AVFrame * gpuFrame = nullptr; | |
16 | + | |
17 | + bool bFirst = true; | |
18 | + while(true){ | |
19 | + m_queue_mutex.lock(); | |
20 | + if(mFrameQueue.size() <= 0){ | |
21 | + m_queue_mutex.unlock(); | |
22 | + if(bFirst){ | |
23 | + std::this_thread::sleep_for(std::chrono::milliseconds(100)); | |
24 | + bFirst = false; | |
25 | + continue; | |
26 | + }else{ | |
27 | + // 再进来说明前面已经等了 100 ms | |
28 | + // 100 ms都没有等到解码数据,则退出 | |
29 | + return nullptr; | |
30 | + } | |
31 | + } | |
32 | + | |
33 | + // 队列中数据大于1 | |
34 | + gpuFrame = mFrameQueue.front(); | |
35 | + m_queue_mutex.unlock(); | |
36 | + break; | |
37 | + } | |
38 | + | |
39 | + if (gpuFrame != nullptr && gpuFrame->format == AV_PIX_FMT_CUDA ){ | |
40 | + LOG_DEBUG("decode task: gpuid: {} width: {} height: {}", m_cfg.gpuid, gpuFrame->width, gpuFrame->height); | |
41 | + GpuRgbMemory* gpuMem = new GpuRgbMemory(3, gpuFrame->width, gpuFrame->height, getName(), m_cfg.gpuid , true); | |
42 | + | |
43 | + if (gpuMem->getMem() == nullptr){ | |
44 | + LOG_ERROR("new GpuRgbMemory failed !!!"); | |
45 | + return nullptr; | |
46 | + } | |
47 | + | |
48 | + cudaSetDevice(atoi(m_cfg.gpuid.c_str())); | |
49 | + cuda_common::setColorSpace( ITU_709, 0 ); | |
50 | + cudaError_t cudaStatus = cuda_common::CUDAToBGR((CUdeviceptr)gpuFrame->data[0],(CUdeviceptr)gpuFrame->data[1], gpuFrame->linesize[0], gpuFrame->linesize[1], gpuMem->getMem(), gpuFrame->width, gpuFrame->height); | |
51 | + cudaDeviceSynchronize(); | |
52 | + if (cudaStatus != cudaSuccess) { | |
53 | + LOG_ERROR("CUDAToBGR failed failed !!!"); | |
54 | + return nullptr; | |
55 | + } | |
56 | + | |
57 | + unsigned char * pHwRgb = gpuMem->getMem(); | |
58 | + int channel = gpuMem->getChannel(); | |
59 | + int width = gpuMem->getWidth(); | |
60 | + int height = gpuMem->getHeight(); | |
61 | + | |
62 | + if (pHwRgb != nullptr && channel > 0 && width > 0 && height > 0){ | |
63 | + int nSize = channel * height * width; | |
64 | + | |
65 | + LOG_INFO("channel:{} height:{} width:{}", channel, height, width); | |
66 | + // unsigned char* cpu_data = new unsigned char[nSize]; | |
67 | + | |
68 | + unsigned char* cpu_data = (unsigned char *)av_malloc(nSize * sizeof(unsigned char)); | |
69 | + | |
70 | + cudaMemcpy(cpu_data, pHwRgb, nSize * sizeof(unsigned char), cudaMemcpyDeviceToHost); | |
71 | + cudaDeviceSynchronize(); | |
72 | + | |
73 | + delete gpuMem; | |
74 | + gpuMem = nullptr; | |
75 | + | |
76 | + FFImgInfo* imgInfo = new FFImgInfo(); | |
77 | + imgInfo->dec_name = m_dec_name; | |
78 | + imgInfo->pData = cpu_data; | |
79 | + imgInfo->height = height; | |
80 | + imgInfo->width = width; | |
81 | + imgInfo->timestamp = UtilTools::get_cur_time_ms(); | |
82 | + imgInfo->index = m_index; | |
83 | + | |
84 | + m_index++; | |
85 | + | |
86 | + return imgInfo; | |
87 | + } | |
88 | + | |
89 | + delete gpuMem; | |
90 | + gpuMem = nullptr; | |
91 | + } | |
92 | + | |
93 | + return nullptr; | |
94 | +} | |
95 | + | |
96 | +bool AbstractDecoder::isSnapTime(){ | |
97 | + if(m_snap_time_interval <= 0){ | |
98 | + return false; | |
99 | + } | |
100 | + long cur_time = UtilTools::get_cur_time_ms(); | |
101 | + if(cur_time - m_last_snap_time > m_snap_time_interval){ | |
102 | + return true; | |
103 | + } | |
104 | + return false; | |
105 | +} | |
106 | + | |
107 | +void AbstractDecoder::updateLastSnapTime(){ | |
108 | + m_last_snap_time = UtilTools::get_cur_time_ms(); | |
109 | +} | |
110 | + | |
111 | +void AbstractDecoder::setSnapTimeInterval(long interval){ | |
112 | + m_snap_time_interval = interval; | |
113 | + m_last_snap_time = UtilTools::get_cur_time_ms(); | |
114 | +} | |
0 | 115 | \ No newline at end of file | ... | ... |
src/AbstractDecoder.h
... | ... | @@ -15,6 +15,9 @@ extern "C" |
15 | 15 | #include <libavutil/imgutils.h> |
16 | 16 | } |
17 | 17 | |
18 | +#include <queue> | |
19 | +#include <mutex> | |
20 | + | |
18 | 21 | using namespace std; |
19 | 22 | |
20 | 23 | /************************************************** |
... | ... | @@ -32,7 +35,7 @@ typedef void(*POST_DECODE_CALLBACK)(const void * userPtr, AVFrame * gpuFrame); |
32 | 35 | |
33 | 36 | typedef void(*DECODE_FINISHED_CALLBACK)(const void* userPtr); |
34 | 37 | |
35 | -typedef bool(*DECODE_REQUEST_STREAM_CALLBACK)(); | |
38 | +typedef bool(*DECODE_REQUEST_STREAM_CALLBACK)(const char* deviceId); | |
36 | 39 | |
37 | 40 | struct FFDecConfig{ |
38 | 41 | string uri; // 视频地址 |
... | ... | @@ -51,6 +54,15 @@ enum DECODER_TYPE{ |
51 | 54 | DECODER_TYPE_FFMPEG |
52 | 55 | }; |
53 | 56 | |
57 | +struct FFImgInfo{ | |
58 | + string dec_name; | |
59 | + int width; | |
60 | + int height; | |
61 | + unsigned char * pData; | |
62 | + long timestamp; | |
63 | + long index; | |
64 | +}; | |
65 | + | |
54 | 66 | class AbstractDecoder { |
55 | 67 | public: |
56 | 68 | virtual ~AbstractDecoder(){}; |
... | ... | @@ -83,6 +95,14 @@ public: |
83 | 95 | return m_dec_name; |
84 | 96 | } |
85 | 97 | |
98 | + FFImgInfo* snapshot(); | |
99 | + | |
100 | + bool isSnapTime(); | |
101 | + | |
102 | + void updateLastSnapTime(); | |
103 | + | |
104 | + void setSnapTimeInterval(long interval); | |
105 | + | |
86 | 106 | public: |
87 | 107 | const void * m_postDecArg; |
88 | 108 | POST_DECODE_CALLBACK post_decoded_cbk; |
... | ... | @@ -95,6 +115,14 @@ public: |
95 | 115 | bool m_dec_keyframe; |
96 | 116 | |
97 | 117 | FFDecConfig m_cfg; |
118 | + | |
119 | + queue<AVFrame*> mFrameQueue; | |
120 | + mutex m_queue_mutex; | |
121 | + mutex m_snapshot_mutex; | |
122 | + | |
123 | + long m_snap_time_interval{-1}; | |
124 | + long m_last_snap_time; | |
125 | + long m_index{0}; | |
98 | 126 | }; |
99 | 127 | |
100 | 128 | #endif // _ABSTRACT_DECODER_H_ |
101 | 129 | \ No newline at end of file | ... | ... |
src/DrawImageOnGPU.cu
0 → 100644
1 | +#include "cuda_kernels.h" | |
2 | + | |
3 | +#include "logger.hpp" | |
4 | + | |
5 | +typedef unsigned char uchar; | |
6 | +typedef unsigned int uint32; | |
7 | +typedef int int32; | |
8 | + | |
9 | +namespace cuda_common | |
10 | +{ | |
11 | + __global__ void kernel_drawPixel(float* d_srcRGB, int src_width, int src_height, | |
12 | + int left, int top, int right, int bottom) | |
13 | + { | |
14 | + const int x = blockIdx.x * blockDim.x + threadIdx.x; | |
15 | + const int y = blockIdx.y * blockDim.y + threadIdx.y; | |
16 | + | |
17 | + if (((x == left || x == right) && y >= top && y <= bottom) || ((y == top || y == bottom) && x >= left && x <= right)) | |
18 | + { | |
19 | + d_srcRGB[(y*src_width) + x] = 0; | |
20 | + d_srcRGB[(src_width*src_height) + (y*src_width) + x] = 255; | |
21 | + d_srcRGB[(2 * src_width*src_height) + (y*src_width) + x] = 0; | |
22 | + } | |
23 | + } | |
24 | + | |
25 | + cudaError_t DrawImage(float* d_srcRGB, int src_width, int src_height, int left, int top, int right, int bottom) | |
26 | + { | |
27 | + dim3 block(32, 16, 1); | |
28 | + dim3 grid((src_width + (block.x - 1)) / block.x, (src_height + (block.y - 1)) / block.y, 1); | |
29 | + | |
30 | + kernel_drawPixel << < grid, block >> >(d_srcRGB, src_width, src_height, left, top, right, bottom); | |
31 | + | |
32 | + cudaError_t cudaStatus = cudaGetLastError(); | |
33 | + if (cudaStatus != cudaSuccess) { | |
34 | + LOG_ERROR("Draw 32 kernel_memcopy launch failed:{}",cudaGetErrorString(cudaStatus)); | |
35 | + return cudaStatus; | |
36 | + } | |
37 | + | |
38 | + cudaStatus = cudaDeviceSynchronize(); | |
39 | + if (cudaStatus != cudaSuccess) { | |
40 | + LOG_ERROR("cudaDeviceSynchronize returned error code {} after launching kernel_bilinear!", cudaStatus); | |
41 | + return cudaStatus; | |
42 | + } | |
43 | + | |
44 | + return cudaStatus; | |
45 | + } | |
46 | + | |
47 | + __global__ void kernel_drawPixel(unsigned char* d_srcRGB, int src_width, int src_height, | |
48 | + int left, int top, int right, int bottom) | |
49 | + { | |
50 | + const int x = blockIdx.x * blockDim.x + threadIdx.x; | |
51 | + const int y = blockIdx.y * blockDim.y + threadIdx.y; | |
52 | + | |
53 | + if (((x == left || x == right) && y >= top && y <= bottom) || ((y == top || y == bottom) && x >= left && x <= right)) | |
54 | + { | |
55 | + d_srcRGB[(y*src_width) + x] = 0; | |
56 | + d_srcRGB[(src_width*src_height) + (y*src_width) + x] = 255; | |
57 | + d_srcRGB[(2 * src_width*src_height) + (y*src_width) + x] = 0; | |
58 | + } | |
59 | + } | |
60 | + | |
61 | + cudaError_t DrawImage(unsigned char* d_srcRGB, int src_width, int src_height, int left, int top, int right, int bottom) | |
62 | + { | |
63 | + dim3 block(32, 16, 1); | |
64 | + dim3 grid((src_width + (block.x - 1)) / block.x, (src_height + (block.y - 1)) / block.y, 1); | |
65 | + | |
66 | + kernel_drawPixel << < grid, block >> >(d_srcRGB, src_width, src_height, left, top, right, bottom); | |
67 | + | |
68 | + cudaError_t cudaStatus = cudaGetLastError(); | |
69 | + if (cudaStatus != cudaSuccess) { | |
70 | + LOG_ERROR("Draw 68 kernel_memcopy launch failed: {}",cudaGetErrorString(cudaStatus)); | |
71 | + return cudaStatus; | |
72 | + } | |
73 | + | |
74 | + cudaStatus = cudaDeviceSynchronize(); | |
75 | + if (cudaStatus != cudaSuccess) { | |
76 | + LOG_ERROR("cudaDeviceSynchronize returned error code {} after launching kernel_bilinear!", cudaStatus); | |
77 | + return cudaStatus; | |
78 | + } | |
79 | + | |
80 | + return cudaStatus; | |
81 | + } | |
82 | + | |
83 | + __global__ void kernel_drawLine(float* d_srcRGB, int src_width, int src_height, | |
84 | + int begin_x, int begin_y, int end_x, int end_y) | |
85 | + { | |
86 | + int min_x = end_x < begin_x ? end_x : begin_x; | |
87 | + int max_x = end_x < begin_x ? begin_x : end_x; | |
88 | + | |
89 | + int min_y = end_y < begin_y ? end_y : begin_y; | |
90 | + int max_y = end_y < begin_y ? begin_y : end_y; | |
91 | + | |
92 | + const int x = blockIdx.x * blockDim.x + threadIdx.x; | |
93 | + const int y = blockIdx.y * blockDim.y + threadIdx.y; | |
94 | + | |
95 | + if ((x - begin_x) * (end_y - begin_y) == (end_x - begin_x) * (y - begin_y) | |
96 | + && min_x <= x && x <= max_x | |
97 | + && min_y <= y && y <= max_y) | |
98 | + { | |
99 | + d_srcRGB[(y*src_width) + x] = 0; | |
100 | + d_srcRGB[(src_width*src_height) + (y*src_width) + x] = 255; | |
101 | + d_srcRGB[(2 * src_width*src_height) + (y*src_width) + x] = 0; | |
102 | + } | |
103 | + } | |
104 | + | |
105 | + cudaError_t DrawLine(float* d_srcRGB, int src_width, int src_height, int begin_x, int begin_y, int end_x, int end_y) | |
106 | + { | |
107 | + dim3 block(32, 16, 1); | |
108 | + dim3 grid((src_width + (block.x - 1)) / block.x, (src_height + (block.y - 1)) / block.y, 1); | |
109 | + | |
110 | + kernel_drawLine << < grid, block >> >(d_srcRGB, src_width, src_height, begin_x, begin_y, end_x, end_y); | |
111 | + | |
112 | + cudaError_t cudaStatus = cudaGetLastError(); | |
113 | + if (cudaStatus != cudaSuccess) { | |
114 | + LOG_ERROR("Draw 112 kernel_memcopy launch failed: {}",cudaGetErrorString(cudaStatus)); | |
115 | + return cudaStatus; | |
116 | + } | |
117 | + | |
118 | + cudaStatus = cudaDeviceSynchronize(); | |
119 | + if (cudaStatus != cudaSuccess) { | |
120 | + LOG_ERROR("cudaDeviceSynchronize returned error code {} after launching kernel_bilinear!", cudaStatus); | |
121 | + return cudaStatus; | |
122 | + } | |
123 | + | |
124 | + return cudaStatus; | |
125 | + } | |
126 | +} | |
0 | 127 | \ No newline at end of file | ... | ... |
src/FFCuContextManager.cpp
1 | 1 | #include "FFCuContextManager.h" |
2 | -#include <iostream> | |
2 | + | |
3 | +#include "logger.hpp" | |
3 | 4 | |
4 | 5 | using namespace std; |
5 | 6 | |
... | ... | @@ -19,7 +20,7 @@ AVBufferRef *FFCuContextManager::getCuCtx(string gpuid) |
19 | 20 | // 初始化硬件解码器 |
20 | 21 | if (av_hwdevice_ctx_create(&hw_device_ctx, AV_HWDEVICE_TYPE_CUDA, gpuid.c_str(), nullptr, 0) < 0) |
21 | 22 | { |
22 | - av_log(nullptr, AV_LOG_ERROR, "Failed to create specified HW device ! \n"); | |
23 | + LOG_ERROR("Failed to create specified HW device."); | |
23 | 24 | return nullptr; |
24 | 25 | } |
25 | 26 | ctxMap[gpuid] = hw_device_ctx; | ... | ... |
src/FFNvDecoder.cpp
... | ... | @@ -10,6 +10,8 @@ |
10 | 10 | |
11 | 11 | #include "logger.hpp" |
12 | 12 | |
13 | +#include "utiltools.hpp" | |
14 | + | |
13 | 15 | using namespace std; |
14 | 16 | |
15 | 17 | // 参考博客: https://blog.csdn.net/qq_40116098/article/details/120704340 |
... | ... | @@ -175,18 +177,6 @@ bool FFNvDecoder::start(){ |
175 | 177 | return true; |
176 | 178 | } |
177 | 179 | |
178 | -static long long get_cur_time(){ | |
179 | - // 获取操作系统当前时间点(精确到微秒) | |
180 | - chrono::time_point<chrono::system_clock, chrono::microseconds> tpMicro | |
181 | - = chrono::time_point_cast<chrono::microseconds>(chrono::system_clock::now()); | |
182 | - // (微秒精度的)时间点 => (微秒精度的)时间戳 | |
183 | - time_t totalMicroSeconds = tpMicro.time_since_epoch().count(); | |
184 | - | |
185 | - long long currentTime = ((long long)totalMicroSeconds)/1000; | |
186 | - | |
187 | - return currentTime; | |
188 | -} | |
189 | - | |
190 | 180 | void FFNvDecoder::decode_thread() |
191 | 181 | { |
192 | 182 | AVPacket* pkt ; |
... | ... | @@ -202,7 +192,7 @@ void FFNvDecoder::decode_thread() |
202 | 192 | } |
203 | 193 | ,this); |
204 | 194 | |
205 | - // long start_time = get_cur_time(); | |
195 | + // long start_time = UtilTools::get_cur_time_ms(); | |
206 | 196 | |
207 | 197 | while (m_bRunning) |
208 | 198 | { |
... | ... | @@ -214,13 +204,6 @@ void FFNvDecoder::decode_thread() |
214 | 204 | continue; |
215 | 205 | } |
216 | 206 | } |
217 | - | |
218 | - AVFrame * gpuFrame = mFrameQueue.getTail(); | |
219 | - if (gpuFrame == nullptr) | |
220 | - { | |
221 | - std::this_thread::sleep_for(std::chrono::milliseconds(1)); | |
222 | - continue; | |
223 | - } | |
224 | 207 | |
225 | 208 | int result = av_read_frame(fmt_ctx, pkt); |
226 | 209 | if (result == AVERROR_EOF || result < 0) |
... | ... | @@ -247,25 +230,37 @@ void FFNvDecoder::decode_thread() |
247 | 230 | if (stream_index == pkt->stream_index){ |
248 | 231 | result = avcodec_send_packet(avctx, pkt); |
249 | 232 | if (result < 0){ |
233 | + av_packet_unref(pkt); | |
250 | 234 | LOG_ERROR("{} - Failed to send pkt: {}", m_dec_name, result); |
251 | 235 | continue; |
252 | 236 | } |
253 | 237 | |
238 | + AVFrame* gpuFrame = av_frame_alloc(); | |
254 | 239 | result = avcodec_receive_frame(avctx, gpuFrame); |
255 | 240 | if ((result == AVERROR(EAGAIN) || result == AVERROR_EOF) || result < 0){ |
256 | 241 | LOG_ERROR("{} - Failed to receive frame: {}", m_dec_name, result); |
242 | + av_frame_free(&gpuFrame); | |
243 | + av_packet_unref(pkt); | |
257 | 244 | continue; |
258 | 245 | } |
246 | + av_packet_unref(pkt); | |
259 | 247 | |
260 | - mFrameQueue.addTail(); | |
248 | + if(gpuFrame != nullptr){ | |
249 | + m_queue_mutex.lock(); | |
250 | + if(mFrameQueue.size() <= 10){ | |
251 | + mFrameQueue.push(gpuFrame); | |
252 | + }else{ | |
253 | + av_frame_free(&gpuFrame); | |
254 | + } | |
255 | + m_queue_mutex.unlock(); | |
256 | + } | |
261 | 257 | } |
262 | 258 | av_packet_unref(pkt); |
263 | 259 | } |
264 | 260 | |
265 | 261 | m_bRunning = false; |
266 | 262 | |
267 | - // long end_time = get_cur_time(); | |
268 | - | |
263 | + // long end_time = UtilTools::get_cur_time_ms(); | |
269 | 264 | // cout << "解码用时:" << end_time - start_time << endl; |
270 | 265 | |
271 | 266 | if (m_post_decode_thread != 0) |
... | ... | @@ -277,6 +272,13 @@ void FFNvDecoder::decode_thread() |
277 | 272 | |
278 | 273 | decode_finished(); |
279 | 274 | |
275 | + // 清空队列 | |
276 | + while(mFrameQueue.size() > 0){ | |
277 | + AVFrame * gpuFrame = mFrameQueue.front(); | |
278 | + av_frame_free(&gpuFrame); | |
279 | + mFrameQueue.pop(); | |
280 | + } | |
281 | + | |
280 | 282 | LOG_INFO("{} - decode thread exited.", m_dec_name); |
281 | 283 | } |
282 | 284 | |
... | ... | @@ -302,24 +304,25 @@ void FFNvDecoder::post_decode_thread(){ |
302 | 304 | } |
303 | 305 | |
304 | 306 | int index = 0; |
305 | - while (m_bRunning || mFrameQueue.length() > 0) | |
307 | + while (m_bRunning) | |
306 | 308 | { |
307 | - AVFrame * gpuFrame = mFrameQueue.getHead(); | |
308 | - if (gpuFrame == nullptr) | |
309 | - { | |
310 | - std::this_thread::sleep_for(std::chrono::milliseconds(3)); | |
311 | - continue; | |
312 | - } | |
309 | + if(mFrameQueue.size() > 0){ | |
310 | + std::lock_guard<std::mutex> l(m_snapshot_mutex); | |
311 | + // 取队头数据 | |
312 | + m_queue_mutex.lock(); | |
313 | + AVFrame * gpuFrame = mFrameQueue.front(); | |
314 | + mFrameQueue.pop(); | |
315 | + m_queue_mutex.unlock(); | |
316 | + // 跳帧 | |
317 | + if (skip_frame == 1 || index % skip_frame == 0){ | |
318 | + post_decoded_cbk(m_postDecArg, gpuFrame); | |
319 | + index = 0; | |
320 | + } | |
313 | 321 | |
314 | - // 跳帧 | |
315 | - if (skip_frame == 1 || index % skip_frame == 0){ | |
316 | - post_decoded_cbk(m_postDecArg, gpuFrame); | |
317 | - index = 0; | |
318 | - } | |
319 | - | |
320 | - mFrameQueue.addHead(); | |
322 | + av_frame_free(&gpuFrame); | |
321 | 323 | |
322 | - index++; | |
324 | + index++; | |
325 | + } | |
323 | 326 | } |
324 | 327 | |
325 | 328 | LOG_INFO("post decode thread exited."); |
... | ... | @@ -374,7 +377,10 @@ void FFNvDecoder::setDecKeyframe(bool bKeyframe) |
374 | 377 | } |
375 | 378 | |
376 | 379 | int FFNvDecoder::getCachedQueueLength(){ |
377 | - return mFrameQueue.length(); | |
380 | + m_queue_mutex.lock(); | |
381 | + int queue_size = mFrameQueue.size(); | |
382 | + m_queue_mutex.lock(); | |
383 | + return queue_size; | |
378 | 384 | } |
379 | 385 | |
380 | 386 | float FFNvDecoder::fps(){ | ... | ... |
src/FFNvDecoder.h
1 | 1 | #include<string> |
2 | 2 | #include <pthread.h> |
3 | 3 | |
4 | -#include "FrameQueue.h" | |
5 | - | |
6 | 4 | #include "AbstractDecoder.h" |
7 | 5 | |
6 | +#include <mutex> | |
7 | + | |
8 | 8 | using namespace std; |
9 | 9 | |
10 | 10 | class FFNvDecoder : public AbstractDecoder{ |
... | ... | @@ -55,7 +55,6 @@ private: |
55 | 55 | bool m_bFinished; |
56 | 56 | |
57 | 57 | bool m_bPause; |
58 | - FrameQueue mFrameQueue; | |
59 | 58 | |
60 | 59 | bool m_bReal; // 是否实时流 |
61 | 60 | ... | ... |
src/FFNvDecoderManager.cpp
... | ... | @@ -116,11 +116,12 @@ AbstractDecoder* FFNvDecoderManager::getDecoderByName(const string name) |
116 | 116 | return nullptr; |
117 | 117 | } |
118 | 118 | |
119 | -void FFNvDecoderManager::startDecode(AbstractDecoder* dec){ | |
119 | +bool FFNvDecoderManager::startDecode(AbstractDecoder* dec){ | |
120 | 120 | if (dec != nullptr && !dec->isRunning()) |
121 | 121 | { |
122 | - dec->start(); | |
122 | + return dec->start(); | |
123 | 123 | } |
124 | + return false; | |
124 | 125 | } |
125 | 126 | |
126 | 127 | bool FFNvDecoderManager::startDecodeByName(const string name){ |
... | ... | @@ -486,7 +487,7 @@ FFImgInfo* FFNvDecoderManager::snapshot(const string& uri){ |
486 | 487 | } |
487 | 488 | |
488 | 489 | // 计算解码后原始数据所需缓冲区大小,并分配内存空间 Determine required buffer size and allocate buffer |
489 | - numBytes = av_image_get_buffer_size(AV_PIX_FMT_RGB24, codec_ctx->width, codec_ctx->height, 1); | |
490 | + numBytes = av_image_get_buffer_size(AV_PIX_FMT_BGR24, codec_ctx->width, codec_ctx->height, 1); | |
490 | 491 | buffer = (uint8_t *)av_malloc(numBytes * sizeof(uint8_t)); |
491 | 492 | |
492 | 493 | pFrameRGB = av_frame_alloc(); |
... | ... | @@ -560,3 +561,40 @@ void FFNvDecoderManager::releaseFFImgInfo(FFImgInfo* info){ |
560 | 561 | info = nullptr; |
561 | 562 | } |
562 | 563 | } |
564 | + | |
565 | +FFImgInfo* FFNvDecoderManager::snapshot_in_task(const string name){ | |
566 | + if (name.empty()){ | |
567 | + LOG_ERROR("name 为空!"); | |
568 | + return nullptr; | |
569 | + } | |
570 | + | |
571 | + std::lock_guard<std::mutex> l(m_mutex); | |
572 | + | |
573 | + auto dec = decoderMap.find(name); | |
574 | + if (dec != decoderMap.end()){ | |
575 | + return dec->second->snapshot(); | |
576 | + } | |
577 | + | |
578 | + LOG_ERROR("没有找到name为{}的解码器",name); | |
579 | + return nullptr; | |
580 | +} | |
581 | + | |
582 | +vector<FFImgInfo*> FFNvDecoderManager::timing_snapshot_all(){ | |
583 | + | |
584 | + closeAllFinishedDecoder(); | |
585 | + | |
586 | + std::lock_guard<std::mutex> l(m_mutex); | |
587 | + | |
588 | + vector<FFImgInfo*> vec; | |
589 | + for(auto it = decoderMap.begin(); it != decoderMap.end(); ++it){ | |
590 | + if(it->second->isSnapTime()){ | |
591 | + FFImgInfo* imginfo = it->second->snapshot(); | |
592 | + if(imginfo != nullptr){ | |
593 | + vec.push_back(imginfo); | |
594 | + } | |
595 | + it->second->updateLastSnapTime(); | |
596 | + } | |
597 | + } | |
598 | + | |
599 | + return vec; | |
600 | +} | |
563 | 601 | \ No newline at end of file | ... | ... |
src/FFNvDecoderManager.h
... | ... | @@ -14,14 +14,9 @@ struct MgrDecConfig |
14 | 14 | string name{""}; // 解码器名称 |
15 | 15 | }; |
16 | 16 | |
17 | -struct FFImgInfo{ | |
18 | - int width; | |
19 | - int height; | |
20 | - unsigned char * pData; | |
21 | -}; | |
22 | - | |
23 | 17 | /** |
24 | 18 | * 解码器管理类,单例类 |
19 | + * 谨防死锁 | |
25 | 20 | **/ |
26 | 21 | class FFNvDecoderManager { |
27 | 22 | public: |
... | ... | @@ -90,7 +85,7 @@ public: |
90 | 85 | * 返回:void |
91 | 86 | * 备注: |
92 | 87 | **************************************************/ |
93 | - void startDecode(AbstractDecoder*); | |
88 | + bool startDecode(AbstractDecoder*); | |
94 | 89 | |
95 | 90 | /************************************************** |
96 | 91 | * 接口:startAllDecode |
... | ... | @@ -257,6 +252,10 @@ public: |
257 | 252 | **************************************************/ |
258 | 253 | void releaseFFImgInfo(FFImgInfo* info); |
259 | 254 | |
255 | + FFImgInfo* snapshot_in_task(const string name); | |
256 | + | |
257 | + vector<FFImgInfo*> timing_snapshot_all(); | |
258 | + | |
260 | 259 | private: |
261 | 260 | FFNvDecoderManager(){} |
262 | 261 | ... | ... |
src/FrameQueue.cpp deleted
1 | -#include "FrameQueue.h" | |
2 | - | |
3 | -FrameQueue::FrameQueue(/* args */) | |
4 | -{ | |
5 | - for (size_t i = 0; i < Maxsize; i++) | |
6 | - { | |
7 | - base[i] = av_frame_alloc(); | |
8 | - } | |
9 | - | |
10 | - front = rear = 0;//头指针和尾指针置为零,队列为空 | |
11 | -} | |
12 | - | |
13 | -FrameQueue::~FrameQueue() | |
14 | -{ | |
15 | - if (base) | |
16 | - { | |
17 | - for (size_t i = 0; i < Maxsize; i++) | |
18 | - { | |
19 | - if (base[i]) | |
20 | - { | |
21 | - av_frame_free(&base[i]); | |
22 | - } | |
23 | - } | |
24 | - } | |
25 | - | |
26 | - rear = front = 0; | |
27 | -} | |
28 | - | |
29 | -//循环队列的入队 | |
30 | -AVFrame* FrameQueue::getTail() | |
31 | -{ | |
32 | - //插入一个元素e为Q的新的队尾元素 | |
33 | - if ((rear + 1) % Maxsize == front) | |
34 | - return nullptr;//队满 | |
35 | - return base[rear];//获取队尾元素 | |
36 | -} | |
37 | - | |
38 | -// 将队尾元素添加到队列中 | |
39 | -void FrameQueue::addTail() | |
40 | -{ | |
41 | - rear = (rear + 1) % Maxsize;//队尾指针加1 | |
42 | -} | |
43 | - | |
44 | -//循环队列的出队 | |
45 | -AVFrame* FrameQueue::deQueue() | |
46 | -{ | |
47 | - //删除Q的队头元素,用e返回其值 | |
48 | - if (front == rear) | |
49 | - return nullptr;//队空 | |
50 | - AVFrame* e = base[front];//保存队头元素 | |
51 | - front = (front + 1) % Maxsize;//队头指针加1 | |
52 | - return e; | |
53 | -} | |
54 | - | |
55 | -//取循环队列的队头元素 | |
56 | -AVFrame* FrameQueue::getHead() | |
57 | -{ | |
58 | - //返回Q的队头元素,不修改队头指针 | |
59 | - if (front == rear) | |
60 | - return nullptr;//队列为空,取元素失败 | |
61 | - return base[front]; | |
62 | -} | |
63 | - | |
64 | -void FrameQueue::addHead() | |
65 | -{ | |
66 | - front = (front + 1) % Maxsize;//队头指针加1 | |
67 | -} | |
68 | - | |
69 | -int FrameQueue::length() | |
70 | -{ | |
71 | - return (rear - front + Maxsize) % Maxsize; | |
72 | -} | |
73 | - | |
74 | -bool FrameQueue::isEmpty() | |
75 | -{ | |
76 | - if (front == rear) | |
77 | - return true; | |
78 | - | |
79 | - return false; | |
80 | -} | |
81 | - | |
82 | -void FrameQueue::clearQueue() | |
83 | -{ | |
84 | - rear = front = 0; | |
85 | -} | |
86 | 0 | \ No newline at end of file |
src/FrameQueue.h deleted
1 | -#include <iostream> | |
2 | -#include <atomic> | |
3 | - | |
4 | -extern "C" | |
5 | -{ | |
6 | - #include <libavcodec/avcodec.h> | |
7 | - #include <libavdevice/avdevice.h> | |
8 | - #include <libavformat/avformat.h> | |
9 | - #include <libavfilter/avfilter.h> | |
10 | - #include <libavutil/avutil.h> | |
11 | - #include <libavutil/pixdesc.h> | |
12 | - #include <libswscale/swscale.h> | |
13 | -} | |
14 | - | |
15 | -using namespace std; | |
16 | - | |
17 | -#define Maxsize 5 // 循环队列的大小 | |
18 | - | |
19 | -// 循环队列 | |
20 | -class FrameQueue | |
21 | -{ | |
22 | -private: | |
23 | - /* data */ | |
24 | -public: | |
25 | - FrameQueue(/* args */); | |
26 | - ~FrameQueue(); | |
27 | - | |
28 | - AVFrame* getTail(); | |
29 | - void addTail(); | |
30 | - AVFrame* deQueue(); | |
31 | - AVFrame* getHead(); | |
32 | - void addHead(); | |
33 | - void clearQueue(); | |
34 | - | |
35 | - int length(); | |
36 | - bool isEmpty(); | |
37 | - | |
38 | -private: | |
39 | - AVFrame* base[Maxsize]; | |
40 | - atomic<int> front; | |
41 | - atomic<int> rear; | |
42 | -}; | |
43 | 0 | \ No newline at end of file |
src/GpuRgbMemory.hpp
0 → 100644
1 | +#include<string> | |
2 | + | |
3 | +#include "cuda_kernels.h" | |
4 | +#include "define.hpp" | |
5 | +#include "utiltools.hpp" | |
6 | + | |
7 | +using namespace std; | |
8 | + | |
9 | +class GpuRgbMemory{ | |
10 | + | |
11 | +public: | |
12 | + GpuRgbMemory(int _channel, int _width, int _height, string _id, string _gpuid, bool _isused){ | |
13 | + channel = _channel; | |
14 | + width = _width; | |
15 | + height = _height; | |
16 | + size = channel * width * height; | |
17 | + isused = _isused; | |
18 | + id = _id; | |
19 | + gpuid = _gpuid; | |
20 | + timestamp = UtilTools::get_cur_time_ms(); | |
21 | + | |
22 | + cudaSetDevice(atoi(gpuid.c_str())); | |
23 | + CHECK_CUDA(cudaMalloc((void **)&pHwRgb, size * sizeof(unsigned char))); | |
24 | + } | |
25 | + | |
26 | + ~GpuRgbMemory(){ | |
27 | + if (pHwRgb) { | |
28 | + cudaSetDevice(atoi(gpuid.c_str())); | |
29 | + CHECK_CUDA(cudaFree(pHwRgb)); | |
30 | + pHwRgb = nullptr; | |
31 | + } | |
32 | + } | |
33 | + | |
34 | + int getSize() { | |
35 | + return size; | |
36 | + } | |
37 | + | |
38 | + bool isIsused() { | |
39 | + return isused; | |
40 | + } | |
41 | + | |
42 | + void setIsused(bool _isused) { | |
43 | + isused = _isused; | |
44 | + // 更新时间戳 | |
45 | + timestamp = UtilTools::get_cur_time_ms(); | |
46 | + } | |
47 | + | |
48 | + string getId() { | |
49 | + return id; | |
50 | + } | |
51 | + | |
52 | + string getGpuId() { | |
53 | + return gpuid; | |
54 | + } | |
55 | + | |
56 | + unsigned char* getMem(){ | |
57 | + return pHwRgb; | |
58 | + } | |
59 | + | |
60 | + long long getTimesstamp(){ | |
61 | + return timestamp; | |
62 | + } | |
63 | + | |
64 | + int getWidth(){ | |
65 | + return width; | |
66 | + } | |
67 | + | |
68 | + int getHeight(){ | |
69 | + return height; | |
70 | + } | |
71 | + | |
72 | + int getChannel(){ | |
73 | + return channel; | |
74 | + } | |
75 | + | |
76 | +private: | |
77 | + int size; | |
78 | + bool isused; | |
79 | + string id; | |
80 | + string gpuid; | |
81 | + unsigned char * pHwRgb{nullptr}; | |
82 | + long long timestamp; | |
83 | + int width{0}; | |
84 | + int height{0}; | |
85 | + int channel{3}; | |
86 | +}; | |
0 | 87 | \ No newline at end of file | ... | ... |
src/ImageSaveGPU.cpp
0 → 100644
1 | +#include "cuda_kernels.h" | |
2 | + | |
3 | +#include "logger.hpp" | |
4 | + | |
5 | + | |
6 | +//int saveJPEG(const char *szOutputFile, float* d_srcRGB, int img_width, int img_height) | |
7 | +//{ | |
8 | +// return jpegNPP(szOutputFile, d_srcRGB, img_width, img_height); | |
9 | +// //return 0; | |
10 | +//} | |
11 | +// | |
12 | +//int saveJPEG(const char *szOutputFile, unsigned char* d_srcRGB, int img_width, int img_height) | |
13 | +//{ | |
14 | +// return jpegNPP(szOutputFile, d_srcRGB, img_width, img_height); | |
15 | +// //return 0; | |
16 | +//} | |
17 | +// | |
18 | +//int saveJPEG(const char *szOutputFile, unsigned char* d_srcRGB) | |
19 | +//{ | |
20 | +// return jpegNPP(szOutputFile, d_srcRGB); | |
21 | +//} | |
22 | +// | |
23 | +//int saveJPEG(const char *szOutputFile, float* d_srcRGB) | |
24 | +//{ | |
25 | +// return jpegNPP(szOutputFile, d_srcRGB); | |
26 | +//} | |
27 | + | |
28 | +int resizeFrame(float* d_srcRGB, int src_width, int src_height, float* d_dstRGB, int dst_width, int dst_height) | |
29 | +{ | |
30 | + cudaError_t cudaStatus = cuda_common::ResizeImage(d_srcRGB, src_width, src_height, d_dstRGB, dst_width, dst_height); | |
31 | + if (cudaStatus != cudaSuccess) { | |
32 | + LOG_ERROR("cuda_common::ResizeImage failed: {}",cudaGetErrorString(cudaStatus)); | |
33 | + return -1; | |
34 | + } | |
35 | + | |
36 | + return 0; | |
37 | +} | |
38 | + | |
39 | +//int initTables() | |
40 | +//{ | |
41 | +// initTable(); | |
42 | +// return 0; | |
43 | +//} | |
44 | +// | |
45 | +//int initTables(int flag, int width, int height) | |
46 | +//{ | |
47 | +// initTable(0, width, height); | |
48 | +// return 0; | |
49 | +//} | |
50 | + | |
51 | +int drawImageOnGPU(float* d_srcRGB, int src_width, int src_height, int left, int top, int right, int bottom) | |
52 | +{ | |
53 | + cuda_common::DrawImage(d_srcRGB, src_width, src_height, left, top, right, bottom); | |
54 | + return 0; | |
55 | +} | |
56 | + | |
57 | +int drawImageOnGPU(unsigned char* d_srcRGB, int src_width, int src_height, int left, int top, int right, int bottom) | |
58 | +{ | |
59 | + cuda_common::DrawImage(d_srcRGB, src_width, src_height, left, top, right, bottom); | |
60 | + return 0; | |
61 | +} | |
62 | + | |
63 | +int drawLineOnGPU(float* d_srcRGB, int src_width, int src_height, int begin_x, int begin_y, int end_x, int end_y) | |
64 | +{ | |
65 | + cuda_common::DrawLine(d_srcRGB, src_width, src_height, begin_x, begin_y, end_x, end_y); | |
66 | + return 0; | |
67 | +} | |
68 | + | |
69 | +//int releaseJpegSaver() | |
70 | +//{ | |
71 | +// releaseJpegNPP(); | |
72 | +// return 0; | |
73 | +//} | |
74 | + | |
75 | +int partMemCopy(unsigned char* d_srcRGB, int src_width, int src_height, unsigned char* d_dstRGB, int left, int top, int right, int bottom) | |
76 | +{ | |
77 | + cudaError_t cudaStatus = cuda_common::PartMemCopy(d_srcRGB, src_width, src_height, d_dstRGB, left, top, right, bottom); | |
78 | + if (cudaStatus != cudaSuccess) { | |
79 | + LOG_ERROR("cuda_common::77 PartMemCopy failed: {} {} {} {} {} {} {}",cudaGetErrorString(cudaStatus), left, top, right, bottom, src_height, d_dstRGB); | |
80 | + return -1; | |
81 | + } | |
82 | + | |
83 | + return 0; | |
84 | +} | |
85 | +//#include <fstream> | |
86 | +//extern std::ofstream g_os; | |
87 | +int PartMemResizeBatch(unsigned char * d_srcRGB, int src_width, int src_height, unsigned char** d_dstRGB, | |
88 | + int count, int* vleft, int * vtop, int* vright, int* vbottom, int *dst_w, int *dst_h, | |
89 | + float submeanb, float submeang, float submeanr, | |
90 | + float varianceb, float varianceg, float variancer) | |
91 | +{ | |
92 | + //g_os << "cudaMemcpyHostToDevice begin 9" << std::endl; | |
93 | + cudaError_t cudaStatus = cuda_common::PartMemResizeBatch( | |
94 | + d_srcRGB, src_width, src_height, d_dstRGB, count, vleft, vtop, vright, vbottom, dst_w, dst_h, | |
95 | + submeanb, submeang, submeanr, | |
96 | + varianceb, varianceg, variancer); | |
97 | + //g_os << "cudaMemcpyHostToDevice end 9" << std::endl; | |
98 | + if (cudaStatus != cudaSuccess) { | |
99 | + LOG_ERROR("cuda_common::PartMemResizeBatch failed: {}",cudaGetErrorString(cudaStatus)); | |
100 | + return -1; | |
101 | + } | |
102 | + | |
103 | + return 0; | |
104 | +} | |
105 | + | |
106 | + | |
107 | +//int PartMemResizeBatch(float * d_srcRGB, int src_width, int src_height, unsigned char* d_dstRGB, | |
108 | +// int count, int* vleft, int * vtop, int* vright, int* vbottom, int dst_w, int dst_h, | |
109 | +// float submeanb, float submeang, float submeanr, | |
110 | +// float varianceb, float varianceg, float variancer) | |
111 | +// | |
112 | +//{ | |
113 | +// cudaError_t cudaStatus = cuda_common::PartMemResizeBatch( | |
114 | +// d_srcRGB, src_width, src_height, d_dstRGB, count, vleft, vtop, vright, vbottom, dst_w, dst_h, | |
115 | +// submeanb, submeang, submeanr, | |
116 | +// varianceb, varianceg, variancer); | |
117 | +// if (cudaStatus != cudaSuccess) { | |
118 | +// fprintf(stderr, "cuda_common::PartMemCopy failed: %s\n", cudaGetErrorString(cudaStatus)); | |
119 | +// return -1; | |
120 | +// } | |
121 | +// | |
122 | +// return 0; | |
123 | +//} | |
0 | 124 | \ No newline at end of file | ... | ... |
src/ImageSaveGPU.h
0 → 100644
1 | +/******************************************************************************************* | |
2 | +* Version: VPT_x64_V2.0.0_20170904 | |
3 | +* CopyRight: 中科院自动化研究所模式识别实验室图像视频组 | |
4 | +* UpdateDate: 20170904 | |
5 | +* Content: 人车物监测跟踪 | |
6 | +********************************************************************************************/ | |
7 | + | |
8 | +#ifndef IMAGESAVEGPU_H_ | |
9 | +#define IMAGESAVEGPU_H_ | |
10 | + | |
11 | +#ifdef _MSC_VER | |
12 | + #ifdef IMAGESAVEGPU_EXPORTS | |
13 | + #define IMAGESAVEGPU_API __declspec(dllexport) | |
14 | + #else | |
15 | + #define IMAGESAVEGPU_API __declspec(dllimport) | |
16 | + #endif | |
17 | +#else | |
18 | +#define IMAGESAVEGPU_API __attribute__((visibility ("default"))) | |
19 | +#endif | |
20 | +// 功能:保存成jpeg文件 | |
21 | +// szOutputFile 输出图片路径,如D:\\out.jpg | |
22 | +// d_srcRGB 输入RGB数据,由cudaMalloc分配的显存空间,数据排列形式为:BBBBBB......GGGGGG......RRRRRRRR...... | |
23 | +// img_width RGB数据图片的宽度 | |
24 | +// img_height RGB数据图片的高度 | |
25 | +// | |
26 | +//IMAGESAVEGPU_API int saveJPEG(const char *szOutputFile, float* d_srcRGB, int img_width, int img_height); | |
27 | +//IMAGESAVEGPU_API int saveJPEG(const char *szOutputFile, float* d_srcRGB); | |
28 | +// | |
29 | +//IMAGESAVEGPU_API int saveJPEG(const char *szOutputFile, unsigned char* d_srcRGB, int img_width, int img_height); | |
30 | +//IMAGESAVEGPU_API int saveJPEG(const char *szOutputFile, unsigned char* d_srcRGB); | |
31 | + | |
32 | +// 功能:防缩图像 | |
33 | +IMAGESAVEGPU_API int resizeFrame(float* d_srcRGB, int src_width, int src_height, float* d_dstRGB, int dst_width, int dst_height); | |
34 | + | |
35 | +// 功能:部分拷贝数据 | |
36 | +IMAGESAVEGPU_API int partMemCopy(unsigned char* d_srcRGB, int src_width, int src_height, unsigned char* d_dstRGB, int left, int top, int right, int bottom); | |
37 | + | |
38 | +//IMAGESAVEGPU_API int partMemResizeImage(float * d_srcRGB, int src_width, int src_height, unsigned char** d_dstRGB, | |
39 | +// int* vleft, int * vtop, int* vright, int* vbottom, int *dst_w, int *dst_h, | |
40 | +// float submeanb, float submeang, float submeanr, | |
41 | +// float varianceb, float varianceg, float variancer); | |
42 | + | |
43 | + | |
44 | +IMAGESAVEGPU_API int PartMemResizeBatch(unsigned char * d_srcRGB, int src_width, int src_height, unsigned char** d_dstRGB, | |
45 | + int count, int* vleft, int * vtop, int* vright, int* vbottom, int *dst_w, int *dst_h, | |
46 | + float submeanb, float submeang, float submeanr, | |
47 | + float varianceb, float varianceg, float variancer); | |
48 | + | |
49 | + | |
50 | +//// 功能:初始化GPU保存图像的各种量化表 | |
51 | +//IMAGESAVEGPU_API int initTables(); | |
52 | +//IMAGESAVEGPU_API int initTables(int falg, int width, int height); | |
53 | +// | |
54 | +//// 功能:释放资源 | |
55 | +//IMAGESAVEGPU_API int releaseJpegSaver(); | |
56 | + | |
57 | +// 功能:在GPU中绘制快照包围框 | |
58 | +IMAGESAVEGPU_API int drawImageOnGPU(float* d_srcRGB, int src_width, int src_height, int left, int top, int right, int bottom); | |
59 | + | |
60 | +IMAGESAVEGPU_API int drawImageOnGPU(unsigned char* d_srcRGB, int src_width, int src_height, int left, int top, int right, int bottom); | |
61 | + | |
62 | +// 功能:在GPU中绘制直线 | |
63 | +IMAGESAVEGPU_API int drawLineOnGPU(float* d_srcRGB, int src_width, int src_height, int begin_x, int begin_y, int end_x, int end_y); | |
64 | + | |
65 | +#endif | ... | ... |
src/NV12ToRGB.cu
... | ... | @@ -257,14 +257,13 @@ namespace cuda_common |
257 | 257 | dstImage[width * y * 3 + x * 3 + 5] = clip_v(red[1] * 0.25,0 ,255); |
258 | 258 | } |
259 | 259 | |
260 | - cudaError_t setColorSpace(e_ColorSpace CSC, float hue) | |
260 | + cudaError_t setColorSpace(FF_ColorSpace CSC, float hue) | |
261 | 261 | { |
262 | - | |
263 | 262 | float hueSin = sin(hue); |
264 | 263 | float hueCos = cos(hue); |
265 | 264 | |
266 | 265 | float hueCSC[9]; |
267 | - if (CSC == ITU601) | |
266 | + if (CSC == ITU_601) | |
268 | 267 | { |
269 | 268 | //CCIR 601 |
270 | 269 | hueCSC[0] = 1.1644f; |
... | ... | @@ -277,7 +276,7 @@ namespace cuda_common |
277 | 276 | hueCSC[7] = hueCos * 2.0172f; |
278 | 277 | hueCSC[8] = hueSin * -2.0172f; |
279 | 278 | } |
280 | - else if (CSC == ITU709) | |
279 | + else if (CSC == ITU_709) | |
281 | 280 | { |
282 | 281 | //CCIR 709 |
283 | 282 | hueCSC[0] = 1.0f; | ... | ... |
src/PartMemCopy.cu
0 → 100644
1 | +#include "cuda_kernels.h" | |
2 | +#include <algorithm> | |
3 | +typedef unsigned char uchar; | |
4 | +typedef unsigned int uint32; | |
5 | +typedef int int32; | |
6 | + | |
7 | +#define MAX_SNAPSHOT_WIDTH 320 | |
8 | +#define MAX_SNAPSHOT_HEIGHT 320 | |
9 | + | |
10 | +namespace cuda_common | |
11 | +{ | |
12 | + __global__ void kernel_memcopy(unsigned char* d_srcRGB, int src_width, int src_height, | |
13 | + unsigned char* d_dstRGB, int left, int top, int right, int bottom) | |
14 | + { | |
15 | + const int dst_x = blockIdx.x * blockDim.x + threadIdx.x; | |
16 | + const int dst_y = blockIdx.y * blockDim.y + threadIdx.y; | |
17 | + const int dst_width = right - left; | |
18 | + const int dst_height = bottom - top; | |
19 | + if (dst_x < dst_width && dst_y < dst_height) | |
20 | + { | |
21 | + int src_x = left + dst_x; | |
22 | + int src_y = top + dst_y; | |
23 | + | |
24 | + //bgr...bgr...bgr... | |
25 | + d_dstRGB[(dst_y*dst_width + dst_x) * 3] = (unsigned char)d_srcRGB[(src_y*src_width + src_x) * 3]; | |
26 | + d_dstRGB[(dst_y*dst_width + dst_x) | |
27 | + * 3 + 1] = (unsigned char)d_srcRGB[(src_y*src_width + src_x) * 3 + 1]; | |
28 | + d_dstRGB[(dst_y*dst_width + dst_x) * 3 + 2] = (unsigned char)d_srcRGB[(src_y*src_width + src_x) * 3 + 2]; | |
29 | + | |
30 | + //bbb...ggg...rrr... | |
31 | + //d_dstRGB[(dst_y*dst_width) + dst_x] = (unsigned char)d_srcRGB[(src_y*src_width) + src_x]; | |
32 | + //d_dstRGB[(dst_width*dst_height) + (dst_y*dst_width) + dst_x] = (unsigned char)d_srcRGB[(src_width*src_height) + (src_y*src_width) + src_x]; | |
33 | + //d_dstRGB[(2 * dst_width*dst_height) + (dst_y*dst_width) + dst_x] = (unsigned char)d_srcRGB[(2 * src_width*src_height) + (src_y*src_width) + src_x]; | |
34 | + | |
35 | + /* memcpy(d_dstRGB + (dst_y*src_width) + dst_x, d_srcRGB + (src_y*src_width) + src_x, sizeof(float)); | |
36 | + memcpy(d_dstRGB + (src_width*src_height) + (dst_y*src_width) + dst_x, d_srcRGB + (src_width*src_height) + (src_y*src_width) + src_x, sizeof(float)); | |
37 | + memcpy(d_dstRGB + (2 * src_width*src_height) + (dst_y*src_width) + dst_x, d_srcRGB + (2 * src_width*src_height) + (src_y*src_width) + src_x, sizeof(float));*/ | |
38 | + } | |
39 | + } | |
40 | + | |
41 | + cudaError_t PartMemCopy(unsigned char* d_srcRGB, int src_width, int src_height, unsigned char* d_dstRGB, int left, int top, int right, int bottom) | |
42 | + { | |
43 | + dim3 block(32, 16, 1); | |
44 | + dim3 grid(((right - left) + (block.x - 1)) / block.x, ((bottom - top) + (block.y - 1)) / block.y, 1); | |
45 | + | |
46 | + kernel_memcopy << < grid, block >> > (d_srcRGB, src_width, src_height, d_dstRGB, left, top, right, bottom); | |
47 | + | |
48 | + cudaError_t cudaStatus = cudaGetLastError(); | |
49 | + if (cudaStatus != cudaSuccess) { | |
50 | + fprintf(stderr, "Part 50 kernel_memcopy launch failed: %s\n", cudaGetErrorString(cudaStatus)); | |
51 | + return cudaStatus; | |
52 | + } | |
53 | + cudaStatus = cudaDeviceSynchronize(); | |
54 | + if (cudaStatus != cudaSuccess) { | |
55 | + fprintf(stderr, "cudaDeviceSynchronize returned error code %d after launching kernel_bilinear!\n", cudaStatus); | |
56 | + return cudaStatus; | |
57 | + } | |
58 | + return cudaStatus; | |
59 | + } | |
60 | + | |
61 | + | |
62 | + // __global__ void kernel_memcopy_mean_variance(float* d_srcRGB, int src_width, int src_height, | |
63 | + // unsigned char* vd_dstRGB, int count, int * vleft, int* vtop, int* vright, int * vbottom, float submeanb,float submeang, float submeanr, float varianceb,float varianceg, float variancer) | |
64 | + // { | |
65 | + // const int dst_x = blockIdx.x * blockDim.x + threadIdx.x; | |
66 | + // const int dst_y = blockIdx.y * blockDim.y + threadIdx.y; | |
67 | + // for (int i=0;i<count;i++) | |
68 | + // { | |
69 | + // const int left = vleft[i]; | |
70 | + // const int right = vright[i]; | |
71 | + // const int top = vtop[i]; | |
72 | + // const int bottom = vbottom[i]; | |
73 | + // | |
74 | + // const int dst_width = right - left; | |
75 | + // const int dst_height = bottom - top; | |
76 | + // | |
77 | + // | |
78 | + // unsigned char * d_dstRGB = vd_dstRGB + i * ; | |
79 | + // | |
80 | + // if (dst_x < dst_width && dst_y < dst_height) | |
81 | + // { | |
82 | + // int src_x = left + dst_x; | |
83 | + // int src_y = top + dst_y; | |
84 | + // | |
85 | + // d_dstRGB[(dst_y*dst_width) + dst_x] = (d_srcRGB[(src_y*src_width) + src_x] - submeanb)*varianceb; | |
86 | + // d_dstRGB[(dst_width*dst_height) + (dst_y*dst_width) + dst_x] = (d_srcRGB[(src_width*src_height) + (src_y*src_width) + src_x] -submeang)*varianceg; | |
87 | + // d_dstRGB[(2 * dst_width*dst_height) + (dst_y*dst_width) + dst_x] = (d_srcRGB[(2 * src_width*src_height) + (src_y*src_width) + src_x] - submeanr) * variancer; | |
88 | + // | |
89 | + // } | |
90 | + // } | |
91 | + // } | |
92 | + __global__ void PartCopy_ResizeImgBilinearBGR_Mean_Variance_CUDAKernel( | |
93 | + unsigned char * d_srcRGB, int srcimg_width, int srcimg_height, | |
94 | + int* vleft, int* vtop, int* vright, int * vbottom, | |
95 | + unsigned char** vd_dstRGB, int count, int *dst_width, int *dst_height, | |
96 | + float submeanb, float submeang, float submeanr, | |
97 | + float varianceb, float varianceg, float variancer) | |
98 | + { | |
99 | + int i = blockIdx.z; | |
100 | + | |
101 | + //for (int i = 0; i<count; i++) | |
102 | + { | |
103 | + const int left = vleft[i]; | |
104 | + const int right = vright[i]; | |
105 | + const int top = vtop[i]; | |
106 | + const int bottom = vbottom[i]; | |
107 | + const int cur_dst_width = dst_width[i]; | |
108 | + const int cur_dst_height = dst_height[i]; | |
109 | + | |
110 | + unsigned char* d_dstRGB = vd_dstRGB[i]; | |
111 | + | |
112 | + const int src_width = right - left; | |
113 | + const int src_height = bottom - top; | |
114 | + const int x = blockIdx.x * blockDim.x + threadIdx.x;// + left; | |
115 | + const int y = blockIdx.y * blockDim.y + threadIdx.y;//+ top; | |
116 | + const int dst_x = blockIdx.x * blockDim.x + threadIdx.x; | |
117 | + const int dst_y = blockIdx.y * blockDim.y + threadIdx.y; | |
118 | + | |
119 | + /*if (dst_x == 0 && dst_y == 0) | |
120 | + printf("%d %d %d %d %d\n", i, vleft[i], vright[i], cur_dst_width, cur_dst_height);*/ | |
121 | + | |
122 | + unsigned char * src_img = d_srcRGB; | |
123 | + unsigned char * dst_img = d_dstRGB; | |
124 | + if (dst_x < cur_dst_width && dst_y < cur_dst_height) | |
125 | + { | |
126 | + float fx = (x + 0.5)*src_width / (float)cur_dst_width - 0.5 + left; | |
127 | + float fy = (y + 0.5)*src_height / (float)cur_dst_height - 0.5 + top; | |
128 | + int ax = floor(fx); | |
129 | + int ay = floor(fy); | |
130 | + if (ax < 0) | |
131 | + { | |
132 | + ax = 0; | |
133 | + } | |
134 | + if (ax > srcimg_width - 2) | |
135 | + { | |
136 | + ax = srcimg_width - 2; | |
137 | + } | |
138 | + if (ay < 0) { | |
139 | + ay = 0; | |
140 | + } | |
141 | + if (ay > srcimg_height - 2) | |
142 | + { | |
143 | + ay = srcimg_height - 2; | |
144 | + } | |
145 | + | |
146 | + int A = ax + ay*srcimg_width; | |
147 | + int B = ax + ay*srcimg_width + 1; | |
148 | + int C = ax + ay*srcimg_width + srcimg_width; | |
149 | + int D = ax + ay*srcimg_width + srcimg_width + 1; | |
150 | + | |
151 | + float w1, w2, w3, w4; | |
152 | + w1 = fx - ax; | |
153 | + w2 = 1 - w1; | |
154 | + w3 = fy - ay; | |
155 | + w4 = 1 - w3; | |
156 | + float blue = src_img[A * 3] * w2*w4 + src_img[B * 3] * w1*w4 + src_img[C * 3] * w2*w3 + src_img[D * 3] * w1*w3; | |
157 | + float green = src_img[A * 3 + 1] * w2*w4 + src_img[B * 3 + 1] * w1*w4 | |
158 | + + src_img[C * 3 + 1] * w2*w3 + src_img[D * 3 + 1] * w1*w3; | |
159 | + float red = src_img[A * 3 + 2] * w2*w4 + src_img[B * 3 + 2] * w1*w4 | |
160 | + + src_img[C * 3 + 2] * w2*w3 + src_img[D * 3 + 2] * w1*w3; | |
161 | + | |
162 | + /*dst_img[(dst_y * dst_width + dst_x) * 3] = (unsigned char)(blue - submeanb)*varianceb; | |
163 | + dst_img[(dst_y * dst_width + dst_x) * 3 + 1] =(unsigned char) (green - submeang)*varianceg; | |
164 | + dst_img[(dst_y * dst_width + dst_x) * 3 + 2] = (unsigned char) (red - submeanr)*variancer;*/ | |
165 | + | |
166 | + if (blue < 0) | |
167 | + blue = 0; | |
168 | + else if (blue > 255) | |
169 | + blue = 255; | |
170 | + | |
171 | + if (green < 0) | |
172 | + green = 0; | |
173 | + else if (green > 255) | |
174 | + green = 255; | |
175 | + | |
176 | + if (red < 0) | |
177 | + red = 0; | |
178 | + else if (red > 255) | |
179 | + red = 255; | |
180 | + | |
181 | + dst_img[(dst_y * cur_dst_width + dst_x) * 3] = (unsigned char)blue; | |
182 | + dst_img[(dst_y * cur_dst_width + dst_x) * 3 + 1] = (unsigned char)green; | |
183 | + dst_img[(dst_y * cur_dst_width + dst_x) * 3 + 2] = (unsigned char)red; | |
184 | + | |
185 | + | |
186 | + /*if (src_img[(dst_y * dst_width + dst_x) * 3] < 0) | |
187 | + src_img[(dst_y * dst_width + dst_x) * 3] = 0; | |
188 | + else if (src_img[(dst_y * dst_width + dst_x) * 3] > 255) | |
189 | + src_img[(dst_y * dst_width + dst_x) * 3] = 255; | |
190 | + | |
191 | + if (src_img[(dst_y * dst_width + dst_x) * 3 + 1] < 0) | |
192 | + src_img[(dst_y * dst_width + dst_x) * 3 + 1] = 0; | |
193 | + else if (src_img[(dst_y * dst_width + dst_x) * 3 + 1] > 255) | |
194 | + src_img[(dst_y * dst_width + dst_x) * 3 + 1] = 255; | |
195 | + | |
196 | + if (src_img[(dst_y * dst_width + dst_x) * 3 + 2] < 0) | |
197 | + src_img[(dst_y * dst_width + dst_x) * 3 + 2] = 0; | |
198 | + else if (src_img[(dst_y * dst_width + dst_x) * 3 + 2] > 255) | |
199 | + src_img[(dst_y * dst_width + dst_x) * 3 + 2] = 255; | |
200 | + | |
201 | + | |
202 | + dst_img[(dst_y * dst_width + dst_x) * 3] = (unsigned char)src_img[(dst_y * dst_width + dst_x) * 3]; | |
203 | + dst_img[(dst_y * dst_width + dst_x) * 3 + 1] = (unsigned char)src_img[(dst_y * dst_width + dst_x) * 3 + 1]; | |
204 | + dst_img[(dst_y * dst_width + dst_x) * 3 + 2] = (unsigned char)src_img[(dst_y * dst_width + dst_x) * 3 + 2];*/ | |
205 | + } | |
206 | + } | |
207 | + } | |
208 | + | |
209 | + cudaError_t PartMemResizeBatch(unsigned char* d_srcRGB, int src_width, int src_height, unsigned char** d_dstRGB, int count, int* left, int* top, int* right, int* bottom, int *dst_w, int *dst_h, float submeanb, float submeang, float submeanr, | |
210 | + float varianceb, float varianceg, float variancer) | |
211 | + { | |
212 | + /* cudaEvent_t start, stop; | |
213 | + float time; | |
214 | + cudaEventCreate(&start); | |
215 | + cudaEventCreate(&stop); | |
216 | + cudaEventRecord(start, 0);*/ | |
217 | + | |
218 | + dim3 block(32, 16, 1); | |
219 | + dim3 grid((*std::max_element(dst_w, dst_w+ count) + (block.x - 1)) / block.x, (*std::max_element(dst_h, dst_h + count) + (block.y - 1)) / block.y, count); | |
220 | + | |
221 | + int * gpu_left; | |
222 | + cudaMalloc(&gpu_left, 1000 * sizeof(int)); | |
223 | + cudaMemcpy(gpu_left, left, count * sizeof(int), cudaMemcpyHostToDevice); | |
224 | + | |
225 | + int * gpu_right; | |
226 | + cudaMalloc(&gpu_right, 1000 * sizeof(int)); | |
227 | + cudaMemcpy(gpu_right, right, count * sizeof(int), cudaMemcpyHostToDevice); | |
228 | + | |
229 | + int * gpu_top; | |
230 | + cudaMalloc(&gpu_top, 1000 * sizeof(int)); | |
231 | + cudaMemcpy(gpu_top, top, count * sizeof(int), cudaMemcpyHostToDevice); | |
232 | + | |
233 | + int * gpu_bottom; | |
234 | + cudaMalloc(&gpu_bottom, 1000 * sizeof(int)); | |
235 | + cudaMemcpy(gpu_bottom, bottom, count * sizeof(int), cudaMemcpyHostToDevice); | |
236 | + | |
237 | + int * gpu_dst_w; | |
238 | + cudaMalloc(&gpu_dst_w, 1000 * sizeof(int)); | |
239 | + cudaMemcpy(gpu_dst_w, dst_w, count * sizeof(int), cudaMemcpyHostToDevice); | |
240 | + | |
241 | + int * gpu_dst_h; | |
242 | + cudaMalloc(&gpu_dst_h, 1000 * sizeof(int)); | |
243 | + cudaMemcpy(gpu_dst_h, dst_h, count * sizeof(int), cudaMemcpyHostToDevice); | |
244 | + | |
245 | + unsigned char** gpu_dst_rgb; | |
246 | + cudaMalloc(&gpu_dst_rgb, 1000 * sizeof(unsigned char*)); | |
247 | + cudaMemcpy(gpu_dst_rgb, d_dstRGB, count * sizeof(unsigned char*), cudaMemcpyHostToDevice); | |
248 | + | |
249 | + //cudaMemcpy(cpu_personfloat, d_srcRGB, 112*224*2*sizeof(float), cudaMemcpyDeviceToHost); | |
250 | + // for(int i=0;i<100;i++) | |
251 | + // { | |
252 | + // printf("the score is %f\t",cpu_personfloat[i]); | |
253 | + // } | |
254 | + PartCopy_ResizeImgBilinearBGR_Mean_Variance_CUDAKernel << < grid, block >> > ( | |
255 | + d_srcRGB, src_width, src_height, | |
256 | + gpu_left, gpu_top, gpu_right, gpu_bottom, | |
257 | + gpu_dst_rgb, count, gpu_dst_w, gpu_dst_h, | |
258 | + submeanb, submeang, submeanr, | |
259 | + varianceb, varianceg, variancer); | |
260 | + cudaFree(gpu_top); | |
261 | + cudaFree(gpu_bottom); | |
262 | + cudaFree(gpu_left); | |
263 | + cudaFree(gpu_right); | |
264 | + cudaFree(gpu_dst_w); | |
265 | + cudaFree(gpu_dst_h); | |
266 | + cudaFree(gpu_dst_rgb); | |
267 | + | |
268 | + cudaError_t cudaStatus = cudaGetLastError(); | |
269 | + if (cudaStatus != cudaSuccess) { | |
270 | + fprintf(stderr, "Part 270 kernel_memcopy launch failed: %s\n", cudaGetErrorString(cudaStatus)); | |
271 | + return cudaStatus; | |
272 | + } | |
273 | + cudaStatus = cudaDeviceSynchronize(); | |
274 | + if (cudaStatus != cudaSuccess) { | |
275 | + fprintf(stderr, "cudaDeviceSynchronize returned error code %d after launching kernel_bilinear!\n", cudaStatus); | |
276 | + return cudaStatus; | |
277 | + } | |
278 | + | |
279 | + /*cudaEventRecord(stop, 0); | |
280 | + cudaEventSynchronize(stop); | |
281 | + cudaEventElapsedTime(&time, start, stop); | |
282 | + cudaEventDestroy(start); | |
283 | + cudaEventDestroy(stop); | |
284 | + printf("ºËº¯ÊýÏûºÄʱ¼ä:%f\n", time);*/ | |
285 | + | |
286 | + return cudaStatus; | |
287 | + } | |
288 | + | |
289 | +} | |
0 | 290 | \ No newline at end of file | ... | ... |
src/RGB2YUV.cu
0 → 100644
1 | + | |
2 | + | |
3 | +#include "cuda_kernels.h" | |
4 | + | |
5 | +typedef unsigned char uint8; | |
6 | +typedef unsigned int uint32; | |
7 | +typedef int int32; | |
8 | + | |
9 | +namespace cuda_common | |
10 | +{ | |
11 | + __device__ unsigned char clip_value(unsigned char x, unsigned char min_val, unsigned char max_val){ | |
12 | + if (x>max_val){ | |
13 | + return max_val; | |
14 | + } | |
15 | + else if (x<min_val){ | |
16 | + return min_val; | |
17 | + } | |
18 | + else{ | |
19 | + return x; | |
20 | + } | |
21 | + } | |
22 | + | |
23 | + __global__ void kernel_rgb2yuv(unsigned char *src_img, unsigned char* Y, unsigned char* u, unsigned char* v, | |
24 | + int src_width, int src_height, size_t yPitch) | |
25 | + { | |
26 | + const int x = blockIdx.x * blockDim.x + threadIdx.x; | |
27 | + const int y = blockIdx.y * blockDim.y + threadIdx.y; | |
28 | + | |
29 | + if (x >= src_width) | |
30 | + return; //x = width - 1; | |
31 | + | |
32 | + if (y >= src_height) | |
33 | + return; // y = height - 1; | |
34 | + | |
35 | + int B = src_img[y * src_width * 3 + x * 3]; | |
36 | + int G = src_img[y * src_width * 3 + x * 3 + 1]; | |
37 | + int R = src_img[y * src_width * 3 + x * 3 + 2]; | |
38 | + | |
39 | + /*int B = src_img[y * src_width + x]; | |
40 | + int G = src_img[src_width * src_height + y * src_width + x]; | |
41 | + int R = src_img[src_width * src_height * 2 + y * src_width + x];*/ | |
42 | + | |
43 | + Y[y * yPitch + x] = clip_value((unsigned char)(0.299 * R + 0.587 * G + 0.114 * B), 0, 255); | |
44 | + u[y * src_width + x] = clip_value((unsigned char)(-0.147 * R - 0.289 * G + 0.436 * B + 128), 0, 255); | |
45 | + v[y * src_width + x] = clip_value((unsigned char)(0.615 * R - 0.515 * G - 0.100 * B + 128), 0, 255); | |
46 | + | |
47 | + //Y[y * yPitch + x] = clip_value((unsigned char)(0.257 * R + 0.504 * G + 0.098 * B + 16), 0, 255); | |
48 | + //u[y * src_width + x] = clip_value((unsigned char)(-0.148 * R - 0.291 * G + 0.439 * B + 128), 0, 255); | |
49 | + //v[y * src_width + x] = clip_value((unsigned char)(0.439 * R - 0.368 * G - 0.071 * B + 128), 0, 255); | |
50 | + } | |
51 | + | |
52 | + __global__ void kernel_rgb2yuv(float *src_img, unsigned char* Y, unsigned char* u, unsigned char* v, | |
53 | + int src_width, int src_height, size_t yPitch) | |
54 | + { | |
55 | + const int x = blockIdx.x * blockDim.x + threadIdx.x; | |
56 | + const int y = blockIdx.y * blockDim.y + threadIdx.y; | |
57 | + | |
58 | + if (x >= src_width) | |
59 | + return; //x = width - 1; | |
60 | + | |
61 | + if (y >= src_height) | |
62 | + return; // y = height - 1; | |
63 | + | |
64 | + float B = src_img[y * src_width + x]; | |
65 | + float G = src_img[src_width * src_height + y * src_width + x]; | |
66 | + float R = src_img[src_width * src_height * 2 + y * src_width + x]; | |
67 | + | |
68 | + Y[y * yPitch + x] = clip_value((unsigned char)(0.299 * R + 0.587 * G + 0.114 * B), 0, 255); | |
69 | + u[y * src_width + x] = clip_value((unsigned char)(-0.147 * R - 0.289 * G + 0.436 * B + 128), 0, 255); | |
70 | + v[y * src_width + x] = clip_value((unsigned char)(0.615 * R - 0.515 * G - 0.100 * B + 128), 0, 255); | |
71 | + | |
72 | + //Y[y * yPitch + x] = clip_value((unsigned char)(0.257 * R + 0.504 * G + 0.098 * B + 16), 0, 255); | |
73 | + //u[y * src_width + x] = clip_value((unsigned char)(-0.148 * R - 0.291 * G + 0.439 * B + 128), 0, 255); | |
74 | + //v[y * src_width + x] = clip_value((unsigned char)(0.439 * R - 0.368 * G - 0.071 * B + 128), 0, 255); | |
75 | + } | |
76 | + | |
77 | + extern "C" | |
78 | + __global__ void kernel_resize_UV(unsigned char* src_img, unsigned char *dst_img, | |
79 | + int src_width, int src_height, int dst_width, int dst_height, int nPitch) | |
80 | + { | |
81 | + const int x = blockIdx.x * blockDim.x + threadIdx.x; | |
82 | + const int y = blockIdx.y * blockDim.y + threadIdx.y; | |
83 | + | |
84 | + if (x >= dst_width) | |
85 | + return; //x = width - 1; | |
86 | + | |
87 | + if (y >= dst_height) | |
88 | + return; // y = height - 1; | |
89 | + | |
90 | + float fx = (x + 0.5)*src_width / (float)dst_width - 0.5; | |
91 | + float fy = (y + 0.5)*src_height / (float)dst_height - 0.5; | |
92 | + int ax = floor(fx); | |
93 | + int ay = floor(fy); | |
94 | + if (ax < 0) | |
95 | + { | |
96 | + ax = 0; | |
97 | + } | |
98 | + else if (ax > src_width - 2) | |
99 | + { | |
100 | + ax = src_width - 2; | |
101 | + } | |
102 | + | |
103 | + if (ay < 0){ | |
104 | + ay = 0; | |
105 | + } | |
106 | + else if (ay > src_height - 2) | |
107 | + { | |
108 | + ay = src_height - 2; | |
109 | + } | |
110 | + | |
111 | + int A = ax + ay*src_width; | |
112 | + int B = ax + ay*src_width + 1; | |
113 | + int C = ax + ay*src_width + src_width; | |
114 | + int D = ax + ay*src_width + src_width + 1; | |
115 | + | |
116 | + float w1, w2, w3, w4; | |
117 | + w1 = fx - ax; | |
118 | + w2 = 1 - w1; | |
119 | + w3 = fy - ay; | |
120 | + w4 = 1 - w3; | |
121 | + | |
122 | + unsigned char val = src_img[A] * w2*w4 + src_img[B] * w1*w4 + src_img[C] * w2*w3 + src_img[D] * w1*w3; | |
123 | + | |
124 | + dst_img[y * nPitch + x] = clip_value(val,0,255); | |
125 | + } | |
126 | + | |
127 | + cudaError_t RGB2YUV(float* d_srcRGB, int src_width, int src_height, | |
128 | + unsigned char* Y, size_t yPitch, int yWidth, int yHeight, | |
129 | + unsigned char* U, size_t uPitch, int uWidth, int uHeight, | |
130 | + unsigned char* V, size_t vPitch, int vWidth, int vHeight) | |
131 | + { | |
132 | + unsigned char * u ; | |
133 | + unsigned char * v ; | |
134 | + | |
135 | + cudaError_t cudaStatus; | |
136 | + | |
137 | + cudaStatus = cudaMalloc((void**)&u, src_width * src_height * sizeof(unsigned char)); | |
138 | + cudaStatus = cudaMalloc((void**)&v, src_width * src_height * sizeof(unsigned char)); | |
139 | + | |
140 | + dim3 block(32, 16, 1); | |
141 | + dim3 grid((src_width + (block.x - 1)) / block.x, (src_height + (block.y - 1)) / block.y, 1); | |
142 | + dim3 grid1((uWidth + (block.x - 1)) / block.x, (uHeight + (block.y - 1)) / block.y, 1); | |
143 | + dim3 grid2((vWidth + (block.x - 1)) / block.x, (vHeight + (block.y - 1)) / block.y, 1); | |
144 | + | |
145 | + kernel_rgb2yuv << < grid, block >> >(d_srcRGB, Y, u, v, src_width, src_height, yPitch); | |
146 | + | |
147 | + cudaStatus = cudaGetLastError(); | |
148 | + if (cudaStatus != cudaSuccess) { | |
149 | + fprintf(stderr, "kernel_rgb2yuv launch failed: %s\n", cudaGetErrorString(cudaStatus)); | |
150 | + goto Error; | |
151 | + } | |
152 | + | |
153 | + cudaStatus = cudaDeviceSynchronize(); | |
154 | + if (cudaStatus != cudaSuccess) { | |
155 | + fprintf(stderr, "cudaDeviceSynchronize returned error code %d after launching kernel_rgb2yuv!\n", cudaStatus); | |
156 | + goto Error; | |
157 | + } | |
158 | + | |
159 | + kernel_resize_UV << < grid1, block >> >(u, U, src_width, src_height, uWidth, uHeight, uPitch); | |
160 | + | |
161 | + cudaStatus = cudaGetLastError(); | |
162 | + if (cudaStatus != cudaSuccess) { | |
163 | + fprintf(stderr, "kernel_resize_UV launch failed: %s\n", cudaGetErrorString(cudaStatus)); | |
164 | + goto Error; | |
165 | + } | |
166 | + | |
167 | + cudaStatus = cudaDeviceSynchronize(); | |
168 | + if (cudaStatus != cudaSuccess) { | |
169 | + fprintf(stderr, "cudaDeviceSynchronize returned error code %d after launching kernel_resize_UV!\n", cudaStatus); | |
170 | + goto Error; | |
171 | + } | |
172 | + | |
173 | + kernel_resize_UV << < grid2, block >> >(v, V, src_width, src_height, vWidth, vHeight, vPitch); | |
174 | + | |
175 | + cudaStatus = cudaGetLastError(); | |
176 | + if (cudaStatus != cudaSuccess) { | |
177 | + fprintf(stderr, "kernel_resize_UV launch failed: %s\n", cudaGetErrorString(cudaStatus)); | |
178 | + goto Error; | |
179 | + } | |
180 | + | |
181 | + cudaStatus = cudaDeviceSynchronize(); | |
182 | + if (cudaStatus != cudaSuccess) { | |
183 | + fprintf(stderr, "cudaDeviceSynchronize returned error code %d after launching kernel_resize_UV!\n", cudaStatus); | |
184 | + goto Error; | |
185 | + } | |
186 | + | |
187 | +Error : | |
188 | + cudaFree(u); | |
189 | + cudaFree(v); | |
190 | + | |
191 | + return cudaStatus; | |
192 | + } | |
193 | + | |
194 | + | |
195 | + | |
196 | + cudaError_t RGB2YUV(unsigned char* d_srcRGB, int src_width, int src_height, | |
197 | + unsigned char* Y, size_t yPitch, int yWidth, int yHeight, | |
198 | + unsigned char* U, size_t uPitch, int uWidth, int uHeight, | |
199 | + unsigned char* V, size_t vPitch, int vWidth, int vHeight) | |
200 | + { | |
201 | + unsigned char * u; | |
202 | + unsigned char * v; | |
203 | + | |
204 | + cudaError_t cudaStatus; | |
205 | + | |
206 | + cudaStatus = cudaMalloc((void**)&u, src_width * src_height * sizeof(unsigned char)); | |
207 | + cudaStatus = cudaMalloc((void**)&v, src_width * src_height * sizeof(unsigned char)); | |
208 | + | |
209 | + dim3 block(32, 16, 1); | |
210 | + dim3 grid((src_width + (block.x - 1)) / block.x, (src_height + (block.y - 1)) / block.y, 1); | |
211 | + dim3 grid1((uWidth + (block.x - 1)) / block.x, (uHeight + (block.y - 1)) / block.y, 1); | |
212 | + dim3 grid2((vWidth + (block.x - 1)) / block.x, (vHeight + (block.y - 1)) / block.y, 1); | |
213 | + | |
214 | + kernel_rgb2yuv << < grid, block >> >(d_srcRGB, Y, u, v, src_width, src_height, yPitch); | |
215 | + | |
216 | + cudaStatus = cudaGetLastError(); | |
217 | + if (cudaStatus != cudaSuccess) { | |
218 | + fprintf(stderr, "kernel_rgb2yuv launch failed: %s\n", cudaGetErrorString(cudaStatus)); | |
219 | + goto Error; | |
220 | + } | |
221 | + | |
222 | + cudaStatus = cudaDeviceSynchronize(); | |
223 | + if (cudaStatus != cudaSuccess) { | |
224 | + fprintf(stderr, "cudaDeviceSynchronize returned error code %d after launching kernel_rgb2yuv!\n", cudaStatus); | |
225 | + goto Error; | |
226 | + } | |
227 | + | |
228 | + kernel_resize_UV << < grid1, block >> >(u, U, src_width, src_height, uWidth, uHeight, uPitch); | |
229 | + | |
230 | + cudaStatus = cudaGetLastError(); | |
231 | + if (cudaStatus != cudaSuccess) { | |
232 | + fprintf(stderr, "kernel_resize_UV launch failed: %s\n", cudaGetErrorString(cudaStatus)); | |
233 | + goto Error; | |
234 | + } | |
235 | + | |
236 | + cudaStatus = cudaDeviceSynchronize(); | |
237 | + if (cudaStatus != cudaSuccess) { | |
238 | + fprintf(stderr, "cudaDeviceSynchronize returned error code %d after launching kernel_resize_UV!\n", cudaStatus); | |
239 | + goto Error; | |
240 | + } | |
241 | + | |
242 | + kernel_resize_UV << < grid2, block >> >(v, V, src_width, src_height, vWidth, vHeight, vPitch); | |
243 | + | |
244 | + cudaStatus = cudaGetLastError(); | |
245 | + if (cudaStatus != cudaSuccess) { | |
246 | + fprintf(stderr, "kernel_resize_UV launch failed: %s\n", cudaGetErrorString(cudaStatus)); | |
247 | + goto Error; | |
248 | + } | |
249 | + | |
250 | + cudaStatus = cudaDeviceSynchronize(); | |
251 | + if (cudaStatus != cudaSuccess) { | |
252 | + fprintf(stderr, "cudaDeviceSynchronize returned error code %d after launching kernel_resize_UV!\n", cudaStatus); | |
253 | + goto Error; | |
254 | + } | |
255 | + | |
256 | + Error: | |
257 | + cudaFree(u); | |
258 | + cudaFree(v); | |
259 | + | |
260 | + return cudaStatus; | |
261 | + } | |
262 | +} | |
263 | + | ... | ... |
src/ResizeImage.cu
0 → 100644
1 | +#include "cuda_kernels.h" | |
2 | + | |
3 | +typedef unsigned char uchar; | |
4 | +typedef unsigned int uint32; | |
5 | +typedef int int32; | |
6 | + | |
7 | +namespace cuda_common | |
8 | +{ | |
9 | + __global__ void kernel_bilinear(float *src_img, float *dst_img, | |
10 | + int src_width, int src_height, int dst_width, int dst_height) | |
11 | + { | |
12 | + const int x = blockIdx.x * blockDim.x + threadIdx.x; | |
13 | + const int y = blockIdx.y * blockDim.y + threadIdx.y; | |
14 | + | |
15 | + if (x < dst_width && y < dst_height) | |
16 | + { | |
17 | + float fx = (x + 0.5)*src_width / (float)dst_width - 0.5; | |
18 | + float fy = (y + 0.5)*src_height / (float)dst_height - 0.5; | |
19 | + int ax = floor(fx); | |
20 | + int ay = floor(fy); | |
21 | + if (ax < 0) | |
22 | + { | |
23 | + ax = 0; | |
24 | + } | |
25 | + else if (ax > src_width - 2) | |
26 | + { | |
27 | + ax = src_width - 2; | |
28 | + } | |
29 | + | |
30 | + if (ay < 0){ | |
31 | + ay = 0; | |
32 | + } | |
33 | + else if (ay > src_height - 2) | |
34 | + { | |
35 | + ay = src_height - 2; | |
36 | + } | |
37 | + | |
38 | + int A = ax + ay*src_width; | |
39 | + int B = ax + ay*src_width + 1; | |
40 | + int C = ax + ay*src_width + src_width; | |
41 | + int D = ax + ay*src_width + src_width + 1; | |
42 | + | |
43 | + float w1, w2, w3, w4; | |
44 | + w1 = fx - ax; | |
45 | + w2 = 1 - w1; | |
46 | + w3 = fy - ay; | |
47 | + w4 = 1 - w3; | |
48 | + | |
49 | + float blue = src_img[A] * w2*w4 + src_img[B] * w1*w4 + src_img[C] * w2*w3 + src_img[D] * w1*w3; | |
50 | + | |
51 | + float green = src_img[src_width * src_height + A] * w2*w4 + src_img[src_width * src_height + B] * w1*w4 | |
52 | + + src_img[src_width * src_height + C] * w2*w3 + src_img[src_width * src_height + D] * w1*w3; | |
53 | + | |
54 | + float red = src_img[src_width * src_height * 2 + A] * w2*w4 + src_img[src_width * src_height * 2 + B] * w1*w4 | |
55 | + + src_img[src_width * src_height * 2 + C] * w2*w3 + src_img[src_width * src_height * 2 + D] * w1*w3; | |
56 | + | |
57 | + dst_img[y * dst_width + x] = blue; | |
58 | + dst_img[dst_width * dst_height + y * dst_width + x] = green; | |
59 | + dst_img[dst_width * dst_height * 2 + y * dst_width + x] = red; | |
60 | + } | |
61 | + } | |
62 | + | |
63 | + cudaError_t ResizeImage(float* d_srcRGB, int src_width, int src_height, float* d_dstRGB, int dst_width, int dst_height) | |
64 | + { | |
65 | + dim3 block(32, 16, 1); | |
66 | + dim3 grid((dst_width + (block.x - 1)) / block.x, (dst_height + (block.y - 1)) / block.y, 1); | |
67 | + | |
68 | + kernel_bilinear << < grid, block >> >(d_srcRGB, d_dstRGB, src_width, src_height, dst_width, dst_height); | |
69 | + | |
70 | + cudaError_t cudaStatus = cudaGetLastError(); | |
71 | + if (cudaStatus != cudaSuccess) { | |
72 | + fprintf(stderr, "kernel_bilinear launch failed: %s\n", cudaGetErrorString(cudaStatus)); | |
73 | + return cudaStatus; | |
74 | + } | |
75 | + | |
76 | + cudaStatus = cudaDeviceSynchronize(); | |
77 | + if (cudaStatus != cudaSuccess) { | |
78 | + fprintf(stderr, "cudaDeviceSynchronize returned error code %d after launching kernel_bilinear!\n", cudaStatus); | |
79 | + return cudaStatus; | |
80 | + } | |
81 | + | |
82 | + return cudaStatus; | |
83 | + } | |
84 | +} | |
0 | 85 | \ No newline at end of file | ... | ... |
src/common/inc/helper_cuda_drvapi.h
... | ... | @@ -218,8 +218,7 @@ inline int gpuGetMaxGflopsDeviceIdDRV() |
218 | 218 | // Find the best major SM Architecture GPU device |
219 | 219 | while (current_device < device_count) |
220 | 220 | { |
221 | - checkCudaErrors(cuDeviceGetAttribute(&major, CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MAJOR, current_device)); | |
222 | - checkCudaErrors(cuDeviceGetAttribute(&minor, CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MINOR, current_device)); | |
221 | + checkCudaErrors(cuDeviceComputeCapability(&major, &minor, current_device)); | |
223 | 222 | |
224 | 223 | if (major > 0 && major < 9999) |
225 | 224 | { |
... | ... | @@ -240,9 +239,7 @@ inline int gpuGetMaxGflopsDeviceIdDRV() |
240 | 239 | checkCudaErrors(cuDeviceGetAttribute(&clockRate, |
241 | 240 | CU_DEVICE_ATTRIBUTE_CLOCK_RATE, |
242 | 241 | current_device)); |
243 | - | |
244 | - checkCudaErrors(cuDeviceGetAttribute(&major, CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MAJOR, current_device)); | |
245 | - checkCudaErrors(cuDeviceGetAttribute(&minor, CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MINOR, current_device)); | |
242 | + checkCudaErrors(cuDeviceComputeCapability(&major, &minor, current_device)); | |
246 | 243 | |
247 | 244 | int computeMode; |
248 | 245 | getCudaAttribute<int>(&computeMode, CU_DEVICE_ATTRIBUTE_COMPUTE_MODE, current_device); |
... | ... | @@ -320,9 +317,7 @@ inline int gpuGetMaxGflopsGLDeviceIdDRV() |
320 | 317 | while (current_device < device_count) |
321 | 318 | { |
322 | 319 | checkCudaErrors(cuDeviceGetName(deviceName, 256, current_device)); |
323 | - | |
324 | - checkCudaErrors(cuDeviceGetAttribute(&major, CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MAJOR, current_device)); | |
325 | - checkCudaErrors(cuDeviceGetAttribute(&minor, CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MINOR, current_device)); | |
320 | + checkCudaErrors(cuDeviceComputeCapability(&major, &minor, current_device)); | |
326 | 321 | |
327 | 322 | #if CUDA_VERSION >= 3020 |
328 | 323 | checkCudaErrors(cuDeviceGetAttribute(&bTCC, CU_DEVICE_ATTRIBUTE_TCC_DRIVER, current_device)); |
... | ... | @@ -374,9 +369,7 @@ inline int gpuGetMaxGflopsGLDeviceIdDRV() |
374 | 369 | checkCudaErrors(cuDeviceGetAttribute(&clockRate, |
375 | 370 | CU_DEVICE_ATTRIBUTE_CLOCK_RATE, |
376 | 371 | current_device)); |
377 | - | |
378 | - checkCudaErrors(cuDeviceGetAttribute(&major, CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MAJOR, current_device)); | |
379 | - checkCudaErrors(cuDeviceGetAttribute(&minor, CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MINOR, current_device)); | |
372 | + checkCudaErrors(cuDeviceComputeCapability(&major, &minor, current_device)); | |
380 | 373 | |
381 | 374 | #if CUDA_VERSION >= 3020 |
382 | 375 | checkCudaErrors(cuDeviceGetAttribute(&bTCC, CU_DEVICE_ATTRIBUTE_TCC_DRIVER, current_device)); |
... | ... | @@ -507,9 +500,7 @@ inline bool checkCudaCapabilitiesDRV(int major_version, int minor_version, int d |
507 | 500 | |
508 | 501 | checkCudaErrors(cuDeviceGet(&cuDevice, devID)); |
509 | 502 | checkCudaErrors(cuDeviceGetName(name, 100, cuDevice)); |
510 | - | |
511 | - checkCudaErrors(cuDeviceGetAttribute(&major, CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MAJOR, devID)); | |
512 | - checkCudaErrors(cuDeviceGetAttribute(&minor, CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MINOR, devID)); | |
503 | + checkCudaErrors(cuDeviceComputeCapability(&major, &minor, devID)); | |
513 | 504 | |
514 | 505 | if ((major > major_version) || |
515 | 506 | (major == major_version && minor >= minor_version)) | ... | ... |
src/cuda_kernels.h
... | ... | @@ -12,15 +12,52 @@ |
12 | 12 | |
13 | 13 | typedef enum |
14 | 14 | { |
15 | - ITU601 = 1, | |
16 | - ITU709 = 2 | |
17 | -} e_ColorSpace; | |
15 | + ITU_601 = 1, | |
16 | + ITU_709 = 2 | |
17 | +} FF_ColorSpace; | |
18 | 18 | |
19 | 19 | namespace cuda_common |
20 | 20 | { |
21 | - cudaError_t setColorSpace(e_ColorSpace CSC, float hue); | |
21 | + cudaError_t setColorSpace(FF_ColorSpace CSC, float hue); | |
22 | 22 | |
23 | 23 | cudaError_t NV12ToRGBnot(CUdeviceptr d_srcNV12, size_t nSourcePitch, unsigned char* d_dstRGB, int width, int height); |
24 | 24 | cudaError_t CUDAToBGR(CUdeviceptr dataY, CUdeviceptr dataUV, size_t pitchY, size_t pitchUV, unsigned char* d_dstRGB, int width, int height); |
25 | + | |
26 | + | |
27 | + cudaError_t ResizeImage(float* d_srcRGB, int src_width, int src_height, float* d_dstRGB, int dst_width, int dst_height); | |
28 | + | |
29 | + cudaError_t RGB2YUV(float* d_srcRGB, int src_width, int src_height, | |
30 | + unsigned char* Y, size_t yPitch, int yWidth, int yHeight, | |
31 | + unsigned char* U, size_t uPitch, int uWidth, int uHeight, | |
32 | + unsigned char* V, size_t vPitch, int vWidth, int vHeight); | |
33 | + | |
34 | + cudaError_t RGB2YUV(unsigned char* d_srcRGB, int src_width, int src_height, | |
35 | + unsigned char* Y, size_t yPitch, int yWidth, int yHeight, | |
36 | + unsigned char* U, size_t uPitch, int uWidth, int uHeight, | |
37 | + unsigned char* V, size_t vPitch, int vWidth, int vHeight); | |
38 | + | |
39 | + cudaError_t PartMemCopy(unsigned char* d_srcRGB, int src_width, int src_height, unsigned char* d_dstRGB, int left, int top, int right, int bottom); | |
40 | + // cudaError_t PartMemResize(float* d_srcRGB, int src_width, int src_height, float* d_dstRGB, int left, int top, int right, int bottom); | |
41 | + | |
42 | + cudaError_t PartMemResizeBatch(unsigned char* d_srcRGB, int srcimg_width, int srcimg_height, unsigned char** d_dstRGB, int count, | |
43 | + int* left, int* top, int* right, int* bottom, int *dst_w, int *dst_h, | |
44 | + float submeanb, float submeang, float submeanr, | |
45 | + float varianceb, float varianceg, float variancer); | |
46 | + | |
47 | + cudaError_t DrawImage(float* d_srcRGB, int src_width, int src_height, int left, int top, int right, int bottom); | |
48 | + cudaError_t DrawImage(unsigned char* d_srcRGB, int src_width, int src_height, int left, int top, int right, int bottom); | |
49 | + | |
50 | + cudaError_t DrawLine(float* d_srcRGB, int src_width, int src_height, int begin_x, int begin_y, int end_x, int end_y); | |
25 | 51 | } |
26 | 52 | |
53 | + | |
54 | +int jpegNPP(const char *szOutputFile, float* d_srcRGB, int img_width, int img_height); | |
55 | +int jpegNPP(const char *szOutputFile, unsigned char* d_srcRGB, int img_width, int img_height); | |
56 | + | |
57 | +int jpegNPP(const char *szOutputFile, float* d_srcRGB); | |
58 | +int jpegNPP(const char *szOutputFile, unsigned char* d_srcRGB); | |
59 | + | |
60 | +int initTable(); | |
61 | +int initTable(int flag, int width, int height); | |
62 | +int releaseJpegNPP(); | |
63 | + | ... | ... |
src/define.hpp
... | ... | @@ -5,3 +5,9 @@ |
5 | 5 | #define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__) |
6 | 6 | |
7 | 7 | |
8 | +#define CHECK_CUDA(call) \ | |
9 | +{\ | |
10 | + const cudaError_t error_code = call;\ | |
11 | + if (cudaSuccess != error_code)\ | |
12 | + LOG_ERROR("CUDA error, code: {} reason: {}", error_code, cudaGetErrorString(error_code));\ | |
13 | +} | |
8 | 14 | \ No newline at end of file | ... | ... |
src/gb28181/FFGB28181Decoder.cpp
... | ... | @@ -10,11 +10,13 @@ extern "C" { |
10 | 10 | #include "libswscale/swscale.h" |
11 | 11 | } |
12 | 12 | |
13 | -#include "../logger.hpp" | |
14 | - | |
15 | 13 | #include"RTPTcpReceiver.h" |
16 | 14 | #include"RTPUdpReceiver.h" |
17 | 15 | |
16 | +#include <cuda_runtime.h> | |
17 | + | |
18 | +#include "common_header.h" | |
19 | + | |
18 | 20 | #define ECLOSED 0 |
19 | 21 | #define ECLOSING 1 |
20 | 22 | #define ERUNNING 2 |
... | ... | @@ -36,6 +38,7 @@ FFGB28181Decoder::FFGB28181Decoder() { |
36 | 38 | m_frameSkip = 1; |
37 | 39 | m_port = -1; |
38 | 40 | m_dec_keyframe = false; |
41 | + m_post_decode_thread = 0; | |
39 | 42 | } |
40 | 43 | |
41 | 44 | FFGB28181Decoder::~FFGB28181Decoder() |
... | ... | @@ -47,11 +50,6 @@ FFGB28181Decoder::~FFGB28181Decoder() |
47 | 50 | avcodec_free_context(&m_pAVCodecCtx); |
48 | 51 | } |
49 | 52 | |
50 | - if (m_pAVFrame) { | |
51 | - av_frame_free(&m_pAVFrame); | |
52 | - m_pAVFrame = NULL; | |
53 | - } | |
54 | - | |
55 | 53 | m_dec_keyframe = false; |
56 | 54 | |
57 | 55 | LOG_INFO("destroy OK--{}", m_dec_name); |
... | ... | @@ -74,9 +72,22 @@ void FFGB28181Decoder::close(){ |
74 | 72 | m_rtpPtr = nullptr; |
75 | 73 | } |
76 | 74 | |
77 | - LOG_INFO("解码器关闭成功 --{}", m_dec_name); | |
75 | + if (gpu_options) av_dict_free(&gpu_options); | |
76 | + | |
77 | + if (m_post_decode_thread != 0) | |
78 | + { | |
79 | + pthread_join(m_post_decode_thread,0); | |
80 | + } | |
81 | + | |
82 | + while(mFrameQueue.size() > 0){ | |
83 | + AVFrame * gpuFrame = mFrameQueue.front(); | |
84 | + av_frame_free(&gpuFrame); | |
85 | + mFrameQueue.pop(); | |
86 | + } | |
78 | 87 | |
79 | 88 | m_status = ECLOSED; |
89 | + | |
90 | + LOG_INFO("解码器关闭成功 --{}", m_dec_name); | |
80 | 91 | } |
81 | 92 | |
82 | 93 | bool FFGB28181Decoder::init(FFDecConfig& cfg){ |
... | ... | @@ -124,7 +135,18 @@ bool FFGB28181Decoder::start() { |
124 | 135 | |
125 | 136 | LOG_INFO("start - {} {}: ", m_dec_name, m_port); |
126 | 137 | |
127 | - return m_rtpPtr->Open((uint16_t)m_port); | |
138 | + bool bRet = m_rtpPtr->Open((uint16_t)m_port); | |
139 | + if(bRet){ | |
140 | + pthread_create(&m_post_decode_thread,0, | |
141 | + [](void* arg) | |
142 | + { | |
143 | + FFGB28181Decoder* a=(FFGB28181Decoder*)arg; | |
144 | + a->post_decode_thread(); | |
145 | + return (void*)0; | |
146 | + } | |
147 | + ,this); | |
148 | + } | |
149 | + return bRet; | |
128 | 150 | } |
129 | 151 | |
130 | 152 | void FFGB28181Decoder::setDecKeyframe(bool bKeyframe){ |
... | ... | @@ -151,15 +173,12 @@ void FFGB28181Decoder::stream_callback(int videoType, char* data, int len, int i |
151 | 173 | return; |
152 | 174 | } |
153 | 175 | |
154 | - AVPacket framePacket = {}, mp4Packet = {}; | |
176 | + AVPacket framePacket = {}; | |
155 | 177 | av_init_packet(&framePacket); |
156 | - av_init_packet(&mp4Packet); | |
157 | 178 | |
158 | 179 | framePacket.size = len; |
159 | 180 | framePacket.data = (uint8_t*)data; |
160 | 181 | |
161 | - AVDictionary *gpu_options = nullptr; | |
162 | - | |
163 | 182 | if (m_pAVCodecCtx == nullptr) { |
164 | 183 | LOG_INFO("frame data is zero --{}", m_dec_name); |
165 | 184 | if (VIDEO_TYPE_H264 == videoType) { |
... | ... | @@ -192,7 +211,6 @@ void FFGB28181Decoder::stream_callback(int videoType, char* data, int len, int i |
192 | 211 | } |
193 | 212 | |
194 | 213 | m_pAVCodecCtx = avcodec_alloc_context3(m_pAVCodec); |
195 | - | |
196 | 214 | |
197 | 215 | if (m_gpuid >= 0) { |
198 | 216 | char gpui[8] = { 0 }; |
... | ... | @@ -211,8 +229,6 @@ void FFGB28181Decoder::stream_callback(int videoType, char* data, int len, int i |
211 | 229 | |
212 | 230 | if (avcodec_open2(m_pAVCodecCtx, m_pAVCodec, &gpu_options) < 0) |
213 | 231 | return; |
214 | - | |
215 | - m_pAVFrame = av_frame_alloc(); | |
216 | 232 | } |
217 | 233 | |
218 | 234 | //开始解码 |
... | ... | @@ -220,6 +236,7 @@ void FFGB28181Decoder::stream_callback(int videoType, char* data, int len, int i |
220 | 236 | if (ret < 0) { |
221 | 237 | //send_exception(RunMessageType::E2002, e_msg); |
222 | 238 | LOG_ERROR("Real stream视频解码失败,请检查视频设备{}: avcodec_send_packet failed. ret={}", m_dec_name, ret); |
239 | + av_packet_unref(&framePacket); | |
223 | 240 | return; |
224 | 241 | } |
225 | 242 | |
... | ... | @@ -228,61 +245,67 @@ void FFGB28181Decoder::stream_callback(int videoType, char* data, int len, int i |
228 | 245 | frameH = m_pAVCodecCtx->height; |
229 | 246 | if (frameW <= 0 || frameH <= 0) { |
230 | 247 | LOG_ERROR("[{}] frame W or H is error! ({},{})", m_dec_name, frameW, frameH); |
248 | + av_packet_unref(&framePacket); | |
231 | 249 | return; |
232 | 250 | } |
233 | 251 | } |
234 | 252 | // m_fps = m_pAVCodecCtx->pkt_timebase.den == 0 ? 25.0 : av_q2d(m_pAVCodecCtx->pkt_timebase); |
235 | 253 | m_fps = av_q2d(m_pAVCodecCtx->framerate); |
236 | - LOG_DEBUG("frameW {}--frameH {}", frameW, frameH); | |
237 | - while (ret >= 0) { | |
238 | - ret = avcodec_receive_frame(m_pAVCodecCtx, m_pAVFrame); | |
239 | - if (ret == AVERROR_EOF || ret == AVERROR(EAGAIN)) | |
240 | - return; | |
241 | - else if (ret < 0) { | |
242 | - if (m_frameCount % 10 == 0){ | |
243 | - //send_exception(RunMessageType::E2002, e_msg); | |
244 | - LOG_ERROR("Real stream视频解码失败,请检查视频设备{}: avcodec_receive_frame failed. ret={}", m_dec_name, ret); | |
245 | - } | |
246 | - continue; | |
247 | - } | |
254 | + // LOG_DEBUG("frameW {}--frameH {}", frameW, frameH); | |
255 | + | |
256 | + AVFrame* gpuFrame = av_frame_alloc(); | |
257 | + ret = avcodec_receive_frame(m_pAVCodecCtx, gpuFrame); | |
258 | + if ((ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) || ret < 0){ | |
259 | + LOG_ERROR("{} - Failed to receive frame: {}", m_dec_name, ret); | |
260 | + av_packet_unref(&framePacket); | |
261 | + av_frame_free(&gpuFrame); | |
262 | + return; | |
263 | + } | |
248 | 264 | |
249 | - if (++m_frameCount % m_frameSkip != 0) continue; | |
250 | - | |
251 | - if (m_pAVFrame->width != frameW || m_pAVFrame->height != frameH){ | |
252 | - LOG_INFO("AVFrame is inconsistent: width is {}, height is {}; original frameW is {}, frameH is {}--{}", m_pAVFrame->width, m_pAVFrame->height, frameW, frameH , m_dec_name); | |
253 | - continue; | |
254 | - } | |
255 | - | |
256 | - LOG_DEBUG("curpos is: {}", m_frameCount); | |
257 | - | |
258 | - post_decoded_cbk(m_postDecArg, m_pAVFrame); | |
259 | - | |
260 | - //LOG_count++; | |
261 | - //if (LOG_count > 100000) { | |
262 | - // LOG_INFO("Real frame send_shm_videoframe pts={}-{}", localPts, m_dec_name); | |
263 | - // //LOG_count = 0; | |
264 | - //} | |
265 | - //} | |
266 | - //catch (GeneralException2& e) | |
267 | - //{ | |
268 | - // LOG_ERROR("send_shm_videoframe failed! {}--{}--{}", e.err_code(), e.err_msg(), m_dec_name); | |
269 | - // if (e.err_code() == -666) { | |
270 | - // this->close(); | |
271 | - // } | |
272 | - // | |
273 | - // if (e.err_code() == ERROR_MEMORY) { | |
274 | - // if (m_frameCount % 10 == 0) { | |
275 | - // string e_msg; | |
276 | - // format_string(e_msg, "服务器资源内存分配失败, 在vas模块%s文件%d行出现无法获取内存的情况!", __FILE__, __LINE__); | |
277 | - // send_exception(RunMessageType::F4001, e_msg); | |
278 | - // LOG_ERROR("{}", e_msg); | |
279 | - // } | |
280 | - // } | |
281 | - // return; | |
282 | - //} | |
265 | + av_packet_unref(&framePacket); | |
266 | + | |
267 | + if (gpuFrame->width != frameW || gpuFrame->height != frameH){ | |
268 | + LOG_INFO("AVFrame is inconsistent: width is {}, height is {}; original frameW is {}, frameH is {}--{}", gpuFrame->width, gpuFrame->height, frameW, frameH , m_dec_name); | |
269 | + av_frame_free(&gpuFrame); | |
270 | + return; | |
271 | + } | |
272 | + | |
273 | + m_queue_mutex.lock(); | |
274 | + if(mFrameQueue.size() <= 10){ | |
275 | + mFrameQueue.push(gpuFrame); | |
276 | + }else{ | |
277 | + av_frame_free(&gpuFrame); | |
283 | 278 | } |
279 | + m_queue_mutex.unlock(); | |
280 | +} | |
281 | + | |
282 | +void FFGB28181Decoder::post_decode_thread(){ | |
283 | + | |
284 | + int index = 0; | |
285 | + while (isRunning()) | |
286 | + { | |
287 | + if(mFrameQueue.size() > 0){ | |
288 | + std::lock_guard<std::mutex> l(m_snapshot_mutex); | |
289 | + // 取队头数据 | |
290 | + m_queue_mutex.lock(); | |
291 | + AVFrame * gpuFrame = mFrameQueue.front(); | |
292 | + mFrameQueue.pop(); | |
293 | + m_queue_mutex.unlock(); | |
294 | + // 跳帧 | |
295 | + if (m_frameSkip == 1 || index % m_frameSkip == 0){ | |
296 | + post_decoded_cbk(m_postDecArg, gpuFrame); | |
297 | + } | |
298 | + | |
299 | + av_frame_free(&gpuFrame); | |
300 | + | |
301 | + index++; | |
302 | + if(index >= 100000){ | |
303 | + index = 0; | |
304 | + } | |
305 | + } | |
306 | + } | |
284 | 307 | |
285 | - if (gpu_options) av_dict_free(&gpu_options); | |
308 | + LOG_INFO("post decode thread exited."); | |
286 | 309 | } |
287 | 310 | |
288 | 311 | void FFGB28181Decoder::stream_end_callback() | ... | ... |
src/gb28181/FFGB28181Decoder.h
... | ... | @@ -6,6 +6,7 @@ |
6 | 6 | #include "../AbstractDecoder.h" |
7 | 7 | |
8 | 8 | #include <atomic> |
9 | +#include <mutex> | |
9 | 10 | |
10 | 11 | struct AVFormatContext; |
11 | 12 | struct AVCodecContext; |
... | ... | @@ -14,6 +15,7 @@ struct AVFrame; |
14 | 15 | struct AVPacket; |
15 | 16 | struct SwsContext; |
16 | 17 | |
18 | +using namespace std; | |
17 | 19 | |
18 | 20 | class FFGB28181Decoder: public AbstractDecoder |
19 | 21 | { |
... | ... | @@ -45,19 +47,16 @@ public: |
45 | 47 | public: |
46 | 48 | void stream_callback(int videoType, char* data, int len, int isKey, uint64_t pts, uint64_t localPts); |
47 | 49 | void stream_end_callback(); |
50 | + void post_decode_thread(); | |
48 | 51 | |
49 | 52 | private: |
50 | 53 | AVCodecContext* m_pAVCodecCtx {}; |
51 | 54 | const AVCodec* m_pAVCodec {}; |
52 | - AVFrame* m_pAVFrame {}; | |
53 | 55 | |
54 | 56 | int m_gpuid {-1}; |
55 | 57 | |
56 | 58 | RTPReceiver* m_rtpPtr; |
57 | 59 | int m_port; |
58 | - uint64_t m_frameCount {}; | |
59 | - | |
60 | - AVFrame* pFrameRGB {}; | |
61 | 60 | |
62 | 61 | uint64_t m_startPts {}; |
63 | 62 | uint64_t m_lastPts {}; //上一次pts的值 |
... | ... | @@ -71,6 +70,10 @@ private: |
71 | 70 | int log_count {}; |
72 | 71 | |
73 | 72 | std::atomic_int m_status {}; |
73 | + | |
74 | + AVDictionary *gpu_options = nullptr; | |
75 | + | |
76 | + pthread_t m_post_decode_thread; | |
74 | 77 | }; |
75 | 78 | |
76 | 79 | #endif // _GB28181_DECODER_H_ | ... | ... |
src/gb28181/RTPReceiver.cpp
1 | -#include "RTPReceiver.h" | |
1 | +#include "RTPReceiver.h" | |
2 | 2 | #include "rtppacket.h" |
3 | -#include "../logger.hpp" | |
4 | 3 | #include <thread> |
5 | 4 | |
5 | +#include "common_header.h" | |
6 | + | |
6 | 7 | #define BUFFERSIZE_1024 1024 |
7 | 8 | const int kVideoFrameSize = BUFFERSIZE_1024*BUFFERSIZE_1024*5*2; |
8 | 9 | |
... | ... | @@ -174,7 +175,7 @@ int RTPReceiver::OnPsProcess() |
174 | 175 | LOG_INFO("[{}] started.", m_deviceID); |
175 | 176 | while (!m_bPsExit) { |
176 | 177 | m_psFrameMutex.lock(); |
177 | - LOG_DEBUG("[{}] PS frame size : {}", m_deviceID, m_psVideoFrames.size()); | |
178 | + // LOG_DEBUG("[{}] PS frame size : {}", m_deviceID, m_psVideoFrames.size()); | |
178 | 179 | if (m_psVideoFrames.size() <= 0){ |
179 | 180 | m_psFrameMutex.unlock(); |
180 | 181 | std::this_thread::sleep_for(std::chrono::milliseconds(10)); |
... | ... | @@ -257,7 +258,7 @@ int RTPReceiver::ParsePacket(RTPPacket* packet){ |
257 | 258 | break; |
258 | 259 | } |
259 | 260 | |
260 | - LOG_DEBUG("[{}] ParsePacket GetPayloadLength", m_deviceID); | |
261 | + // LOG_DEBUG("[{}] ParsePacket GetPayloadLength", m_deviceID); | |
261 | 262 | |
262 | 263 | if (mark) |
263 | 264 | { |
... | ... | @@ -271,7 +272,7 @@ int RTPReceiver::ParsePacket(RTPPacket* packet){ |
271 | 272 | std::lock_guard<std::mutex> l(m_psFrameMutex); |
272 | 273 | if (m_psVideoFrames.size() < 100) |
273 | 274 | { |
274 | - LOG_DEBUG("[{}]ParsePacket push", m_deviceID); | |
275 | + // LOG_DEBUG("[{}]ParsePacket push", m_deviceID); | |
275 | 276 | m_psVideoFrames.push(new Frame(frameBuf, offset, false)); |
276 | 277 | } |
277 | 278 | else { | ... | ... |
src/gb28181/RTPReceiver.h
... | ... | @@ -32,7 +32,7 @@ typedef void(*CallBack_VodFileEnd)(void* userdata); |
32 | 32 | /** |
33 | 33 | * 请求流 |
34 | 34 | */ |
35 | -typedef bool(*CallBack_Request_Stream)(); | |
35 | +typedef bool(*CallBack_Request_Stream)(const char* deviceId); | |
36 | 36 | |
37 | 37 | // 标识帧, 注意buffer需要自己开辟和释放 |
38 | 38 | struct Frame { |
... | ... | @@ -85,7 +85,7 @@ class RTPReceiver{ |
85 | 85 | |
86 | 86 | public: |
87 | 87 | RTPReceiver(); |
88 | - ~RTPReceiver(); | |
88 | + virtual ~RTPReceiver(); | |
89 | 89 | |
90 | 90 | virtual bool Open(uint16_t localPort) = 0; |
91 | 91 | virtual bool IsOpened() = 0; | ... | ... |
src/gb28181/RTPTcpReceiver.cpp
1 | 1 | #include"RTPTcpReceiver.h" |
2 | -#include "../logger.hpp" | |
3 | 2 | |
3 | +#include "common_header.h" | |
4 | 4 | |
5 | -static long long get_cur_time() { | |
6 | - | |
7 | - chrono::time_point<chrono::system_clock, chrono::milliseconds> tpMicro | |
8 | - = chrono::time_point_cast<chrono::milliseconds>(chrono::system_clock::now()); | |
9 | - | |
10 | - return tpMicro.time_since_epoch().count(); | |
11 | -} | |
12 | 5 | |
13 | 6 | // class TcpRTPSession : public RTPSession |
14 | 7 | // { |
... | ... | @@ -65,7 +58,7 @@ public: |
65 | 58 | LOG_ERROR("Error sending over socket {}, removing destination", sock); |
66 | 59 | DeleteDestination(RTPTCPAddress(sock)); |
67 | 60 | if(nullptr != tcpReceiver && !tcpReceiver->isClosing()){ |
68 | - tcpReceiver->RequestStream(); | |
61 | + tcpReceiver->ReConnect(); | |
69 | 62 | } |
70 | 63 | } |
71 | 64 | |
... | ... | @@ -90,6 +83,16 @@ static int rtp_revc_thread_(void* param) |
90 | 83 | return self->OnRtpRecv(); |
91 | 84 | } |
92 | 85 | |
86 | +static int listen_finish_thread_(void* param) | |
87 | +{ | |
88 | + if (!param) | |
89 | + { | |
90 | + return -1; | |
91 | + } | |
92 | + | |
93 | + RTPTcpReceiver* self = (RTPTcpReceiver*)param; | |
94 | + return self->ListenFinish(); | |
95 | +} | |
93 | 96 | |
94 | 97 | RTPTcpReceiver::RTPTcpReceiver() |
95 | 98 | : m_bRtpExit(false) |
... | ... | @@ -143,11 +146,19 @@ bool RTPTcpReceiver::IsOpened(){ |
143 | 146 | } |
144 | 147 | |
145 | 148 | void RTPTcpReceiver::Close(){ |
149 | + m_bRtpExit = true; | |
150 | + | |
151 | + if(m_listenFinishThread.joinable()){ | |
152 | + m_listenFinishThread.join(); | |
153 | + } | |
154 | +} | |
155 | + | |
156 | +void RTPTcpReceiver::close_task(){ | |
157 | + m_bRtpExit = true; | |
146 | 158 | |
147 | 159 | m_bClosing = true; |
148 | 160 | |
149 | 161 | m_bAccepted = true; |
150 | - m_bRtpExit = true; | |
151 | 162 | |
152 | 163 | LOG_DEBUG("[{}] 1.", m_deviceID); |
153 | 164 | |
... | ... | @@ -207,20 +218,22 @@ int RTPTcpReceiver::initSession(int localPort){ |
207 | 218 | status = m_rtpSessionPtr->Create(*m_pSessparams, m_pTrans); |
208 | 219 | if (status < 0) |
209 | 220 | { |
210 | - LOG_ERROR("[{}] create session error!!", m_deviceID); | |
221 | + // 若status = -59 ,需运行 export LOGNAME=root ,见 https://blog.csdn.net/m0_37876242/article/details/128588162 | |
222 | + LOG_ERROR("[{}] create session error: {}", m_deviceID, status); | |
211 | 223 | return -1; |
212 | 224 | } |
213 | 225 | |
214 | 226 | m_rtpThread = std::thread(rtp_revc_thread_, this); |
227 | + m_listenFinishThread = std::thread(listen_finish_thread_, this); | |
215 | 228 | |
216 | 229 | InitPS(); |
217 | 230 | |
218 | - bool bRet = RequestStream(); | |
219 | - if (!bRet) | |
220 | - { | |
221 | - LOG_INFO("[{}] 请求流失败!", m_deviceID); | |
222 | - return -1; | |
223 | - } | |
231 | + // bool bRet = RequestStream(); | |
232 | + // if (!bRet) | |
233 | + // { | |
234 | + // LOG_INFO("[{}] 请求流失败!", m_deviceID); | |
235 | + // return -1; | |
236 | + // } | |
224 | 237 | |
225 | 238 | LOG_INFO("[{}] 初始化成功, congratulations !!!", m_deviceID); |
226 | 239 | |
... | ... | @@ -240,17 +253,56 @@ int RTPTcpReceiver::OnRtpRecv() |
240 | 253 | SocketType nServer = -1; |
241 | 254 | |
242 | 255 | LOG_INFO("[{}] Poll started.", m_deviceID); |
243 | - int status = -1; | |
256 | + int reconn_times = 0; | |
257 | + int reaccept_times = 0; | |
258 | + bool bReconn = false; | |
244 | 259 | while(!m_bRtpExit){ |
245 | 260 | while(!m_bAccepted){ |
261 | + if(m_bRtpExit){ | |
262 | + goto end_flag; | |
263 | + } | |
264 | + | |
265 | + while (!bReconn){ | |
266 | + if(m_bRtpExit){ | |
267 | + goto end_flag; | |
268 | + } | |
269 | + | |
270 | + reconn_times++; | |
271 | + if(reconn_times > 10){ | |
272 | + // 10次请求都失败,结束任务 | |
273 | + m_bRtpExit = true; | |
274 | + goto end_flag; | |
275 | + } | |
276 | + LOG_DEBUG("[{}] RequestStream...", m_deviceID); | |
277 | + bReconn = RequestStream(); | |
278 | + if (bReconn){ | |
279 | + LOG_DEBUG("[{}] RequestStream, True", m_deviceID); | |
280 | + continue; | |
281 | + } | |
282 | + LOG_DEBUG("[{}] RequestStream, False", m_deviceID); | |
283 | + | |
284 | + std::this_thread::sleep_for(std::chrono::seconds(3)); | |
285 | + } | |
286 | + | |
246 | 287 | LOG_DEBUG("[{}] accepting...", m_deviceID); |
247 | 288 | nServer = accept(m_nListener, (sockaddr*)&clientAddr, (socklen_t * ) &nLen); |
248 | 289 | if (-1 == nServer){ |
249 | - std::this_thread::sleep_for(std::chrono::milliseconds(10)); | |
290 | + reaccept_times++; | |
291 | + LOG_DEBUG("[{}] reaccept_times = {}", m_deviceID, reaccept_times); | |
292 | + if(reaccept_times > 600){ | |
293 | + LOG_DEBUG("[{}] reaccept_times > 600", m_deviceID); | |
294 | + bReconn = false; | |
295 | + reaccept_times = 0; | |
296 | + } | |
297 | + std::this_thread::sleep_for(std::chrono::milliseconds(50)); | |
250 | 298 | continue; |
251 | 299 | } |
300 | + LOG_DEBUG("[{}] accept success", m_deviceID); | |
252 | 301 | m_rtpSessionPtr->AddDestination(RTPTCPAddress(nServer)); |
253 | 302 | m_bAccepted = true; |
303 | + bReconn = false; | |
304 | + reconn_times = 0; | |
305 | + reaccept_times = 0; | |
254 | 306 | |
255 | 307 | LOG_INFO("[{}] nServer={}", m_deviceID, nServer); |
256 | 308 | break; |
... | ... | @@ -265,7 +317,7 @@ int RTPTcpReceiver::OnRtpRecv() |
265 | 317 | |
266 | 318 | while ((pack = m_rtpSessionPtr->GetNextPacket()) != NULL) |
267 | 319 | { |
268 | - LOG_DEBUG("[{}] time: {} ", m_deviceID, get_cur_time()); | |
320 | + // LOG_DEBUG("[{}] time: {} ", m_deviceID, UtilTools::get_cur_time_ms()); | |
269 | 321 | ParsePacket(pack); |
270 | 322 | |
271 | 323 | m_rtpSessionPtr->DeletePacket(pack); |
... | ... | @@ -279,6 +331,8 @@ int RTPTcpReceiver::OnRtpRecv() |
279 | 331 | std::this_thread::sleep_for(std::chrono::milliseconds(10)); |
280 | 332 | } |
281 | 333 | |
334 | +end_flag: | |
335 | + | |
282 | 336 | m_rtpSessionPtr->Destroy(); |
283 | 337 | |
284 | 338 | if(nServer > 0){ |
... | ... | @@ -293,13 +347,18 @@ int RTPTcpReceiver::OnRtpRecv() |
293 | 347 | return 0; |
294 | 348 | } |
295 | 349 | |
296 | -bool RTPTcpReceiver::RequestStream(){ | |
297 | - bool bConnect = m_callback_request_stream(); | |
298 | - if(!bConnect){ | |
299 | - Close(); | |
300 | - return false; | |
350 | +int RTPTcpReceiver::ListenFinish(){ | |
351 | + while(!m_bRtpExit){ | |
352 | + std::this_thread::sleep_for(std::chrono::seconds(3)); | |
301 | 353 | } |
354 | + | |
355 | + close_task(); | |
356 | +} | |
357 | + | |
358 | +bool RTPTcpReceiver::ReConnect(){ | |
302 | 359 | m_bAccepted = false; |
360 | +} | |
303 | 361 | |
304 | - return true; | |
362 | +bool RTPTcpReceiver::RequestStream(){ | |
363 | + return m_callback_request_stream(m_deviceID.c_str()); | |
305 | 364 | } |
306 | 365 | \ No newline at end of file | ... | ... |
src/gb28181/RTPTcpReceiver.h
... | ... | @@ -57,11 +57,14 @@ public: |
57 | 57 | |
58 | 58 | public: |
59 | 59 | int OnRtpRecv(); |
60 | + bool ReConnect(); | |
61 | + int ListenFinish(); | |
60 | 62 | bool RequestStream(); |
61 | 63 | bool isClosing(); |
62 | 64 | |
63 | 65 | private: |
64 | 66 | int initSession(int localPort); |
67 | + void close_task(); | |
65 | 68 | |
66 | 69 | private: |
67 | 70 | |
... | ... | @@ -77,9 +80,12 @@ private: |
77 | 80 | std::thread m_rtpThread; // RTP接收线程 |
78 | 81 | SocketType m_nListener; |
79 | 82 | |
80 | - RTPSession* m_rtpSessionPtr; // RTP会话 | |
81 | - RTPSessionParams* m_pSessparams; | |
82 | - MyTCPTransmitter* m_pTrans; | |
83 | + RTPSession* m_rtpSessionPtr; // RTP会话 | |
84 | + RTPSessionParams* m_pSessparams; | |
85 | + MyTCPTransmitter* m_pTrans; | |
86 | + | |
87 | + std::thread m_listenFinishThread; // RTP接收线程 | |
88 | + | |
83 | 89 | }; |
84 | 90 | |
85 | 91 | #endif // _RTP_TCP_RECEIVER_H_ | ... | ... |
src/gb28181/RTPUdpReceiver.cpp
... | ... | @@ -6,7 +6,7 @@ |
6 | 6 | #include <thread> |
7 | 7 | #include <chrono> |
8 | 8 | |
9 | -#include "../logger.hpp" | |
9 | +#include "common_header.h" | |
10 | 10 | |
11 | 11 | using namespace std; |
12 | 12 | |
... | ... | @@ -42,15 +42,6 @@ private: |
42 | 42 | } |
43 | 43 | }; |
44 | 44 | |
45 | - | |
46 | -static long long get_cur_time() { | |
47 | - | |
48 | - chrono::time_point<chrono::system_clock, chrono::milliseconds> tpMicro | |
49 | - = chrono::time_point_cast<chrono::milliseconds>(chrono::system_clock::now()); | |
50 | - | |
51 | - return tpMicro.time_since_epoch().count(); | |
52 | -} | |
53 | - | |
54 | 45 | static int rtp_revc_thread_(void* param) |
55 | 46 | { |
56 | 47 | if (!param) |
... | ... | @@ -175,7 +166,7 @@ int RTPUdpReceiver::OnRtpRecv() |
175 | 166 | if (m_rtpSessionPtr->GotoFirstSourceWithData()) |
176 | 167 | { |
177 | 168 | LOG_INFO("OnRtpRecv GotoFirstSourceWithData --{}", m_deviceID); |
178 | - last_recv_ts = get_cur_time(); | |
169 | + last_recv_ts = UtilTools::get_cur_time_ms(); | |
179 | 170 | m_idleCount = 0; |
180 | 171 | m_noDataCount = 0; |
181 | 172 | do |
... | ... | @@ -261,7 +252,7 @@ int RTPUdpReceiver::OnRtpRecv() |
261 | 252 | // //若是30000,时长大约 18s |
262 | 253 | // if(m_idleCount > 30000) |
263 | 254 | // { |
264 | - // uint64_t cts = get_cur_time(); | |
255 | + // uint64_t cts = UtilTools::get_cur_time_ms(); | |
265 | 256 | // float duration_not_recv = (cts - last_recv_ts) / 1000.0; |
266 | 257 | // |
267 | 258 | // //LOG_ERROR("************I haven't got stream from hik gateway exceed {}s,send eof********{}******", duration_not_recv, m_deviceID); | ... | ... |
src/gb28181/common_header.h
0 → 100644
src/gb28181/demuxer.h
src/jpegNPP.cpp-1
0 → 100644
1 | +/* | |
2 | +* Copyright 1993-2015 NVIDIA Corporation. All rights reserved. | |
3 | +* | |
4 | +* NOTICE TO USER: | |
5 | +* | |
6 | +* This source code is subject to NVIDIA ownership rights under U.S. and | |
7 | +* international Copyright laws. | |
8 | +* | |
9 | +* NVIDIA MAKES NO REPRESENTATION ABOUT THE SUITABILITY OF THIS SOURCE | |
10 | +* CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR | |
11 | +* IMPLIED WARRANTY OF ANY KIND. NVIDIA DISCLAIMS ALL WARRANTIES WITH | |
12 | +* REGARD TO THIS SOURCE CODE, INCLUDING ALL IMPLIED WARRANTIES OF | |
13 | +* MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE. | |
14 | +* IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL, | |
15 | +* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS | |
16 | +* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE | |
17 | +* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE | |
18 | +* OR PERFORMANCE OF THIS SOURCE CODE. | |
19 | +* | |
20 | +* U.S. Government End Users. This source code is a "commercial item" as | |
21 | +* that term is defined at 48 C.F.R. 2.101 (OCT 1995), consisting of | |
22 | +* "commercial computer software" and "commercial computer software | |
23 | +* documentation" as such terms are used in 48 C.F.R. 12.212 (SEPT 1995) | |
24 | +* and is provided to the U.S. Government only as a commercial end item. | |
25 | +* Consistent with 48 C.F.R.12.212 and 48 C.F.R. 227.7202-1 through | |
26 | +* 227.7202-4 (JUNE 1995), all U.S. Government End Users acquire the | |
27 | +* source code with only those rights set forth herein. | |
28 | +*/ | |
29 | + | |
30 | +// This sample needs at least CUDA 5.5 and a GPU that has at least Compute Capability 2.0 | |
31 | + | |
32 | +// This sample demonstrates a simple image processing pipeline. | |
33 | +// First, a JPEG file is huffman decoded and inverse DCT transformed and dequantized. | |
34 | +// Then the different planes are resized. Finally, the resized image is quantized, forward | |
35 | +// DCT transformed and huffman encoded. | |
36 | + | |
37 | +#include "cuda_kernels.h" | |
38 | + | |
39 | +#include <npp.h> | |
40 | +#include <cuda_runtime.h> | |
41 | +#include "common/UtilNPP/Exceptions.h" | |
42 | + | |
43 | +#include "Endianess.h" | |
44 | +#include <math.h> | |
45 | + | |
46 | +#include <string.h> | |
47 | +#include <fstream> | |
48 | +#include <iostream> | |
49 | + | |
50 | +#include "common/inc/helper_string.h" | |
51 | +#include "common/inc/helper_cuda.h" | |
52 | +//#include "MacroDef.h" | |
53 | +#include "cuda.h" | |
54 | + | |
55 | +using namespace std; | |
56 | + | |
57 | +struct FrameHeader | |
58 | +{ | |
59 | + unsigned char nSamplePrecision; | |
60 | + unsigned short nHeight; | |
61 | + unsigned short nWidth; | |
62 | + unsigned char nComponents; | |
63 | + unsigned char aComponentIdentifier[3]; | |
64 | + unsigned char aSamplingFactors[3]; | |
65 | + unsigned char aQuantizationTableSelector[3]; | |
66 | +}; | |
67 | + | |
68 | +struct ScanHeader | |
69 | +{ | |
70 | + unsigned char nComponents; | |
71 | + unsigned char aComponentSelector[3]; | |
72 | + unsigned char aHuffmanTablesSelector[3]; | |
73 | + unsigned char nSs; | |
74 | + unsigned char nSe; | |
75 | + unsigned char nA; | |
76 | +}; | |
77 | + | |
78 | +struct QuantizationTable | |
79 | +{ | |
80 | + unsigned char nPrecisionAndIdentifier; | |
81 | + unsigned char aTable[64]; | |
82 | +}; | |
83 | + | |
84 | +struct HuffmanTable | |
85 | +{ | |
86 | + unsigned char nClassAndIdentifier; | |
87 | + unsigned char aCodes[16]; | |
88 | + unsigned char aTable[256]; | |
89 | +}; | |
90 | + | |
91 | +//??准?炼??藕?量??模?? | |
92 | +//unsigned char std_Y_QT[64] = | |
93 | +//{ | |
94 | +// 16, 11, 10, 16, 24, 40, 51, 61, | |
95 | +// 12, 12, 14, 19, 26, 58, 60, 55, | |
96 | +// 14, 13, 16, 24, 40, 57, 69, 56, | |
97 | +// 14, 17, 22, 29, 51, 87, 80, 62, | |
98 | +// 18, 22, 37, 56, 68, 109, 103, 77, | |
99 | +// 24, 35, 55, 64, 81, 104, 113, 92, | |
100 | +// 49, 64, 78, 87, 103, 121, 120, 101, | |
101 | +// 72, 92, 95, 98, 112, 100, 103, 99 | |
102 | +//}; | |
103 | +// | |
104 | +////??准色???藕?量??模?? | |
105 | +//unsigned char std_UV_QT[64] = | |
106 | +//{ | |
107 | +// 17, 18, 24, 47, 99, 99, 99, 99, | |
108 | +// 18, 21, 26, 66, 99, 99, 99, 99, | |
109 | +// 24, 26, 56, 99, 99, 99, 99, 99, | |
110 | +// 47, 66, 99, 99, 99, 99, 99, 99, | |
111 | +// 99, 99, 99, 99, 99, 99, 99, 99, | |
112 | +// 99, 99, 99, 99, 99, 99, 99, 99, | |
113 | +// 99, 99, 99, 99, 99, 99, 99, 99, | |
114 | +// 99, 99, 99, 99, 99, 99, 99, 99 | |
115 | +//}; | |
116 | + | |
117 | +////?炼??藕?量??模?? | |
118 | +//unsigned char std_Y_QT[64] = | |
119 | +//{ | |
120 | +// 6, 4, 5, 6, 5, 4, 6, 6, | |
121 | +// 5, 6, 7, 7, 6, 8, 10, 16, | |
122 | +// 10, 10, 9, 9, 10, 20, 14, 15, | |
123 | +// 12, 16, 23, 20, 24, 24, 23, 20, | |
124 | +// 22, 22, 26, 29, 37, 31, 26, 27, | |
125 | +// 35, 28, 22, 22, 32, 44, 32, 35, | |
126 | +// 38, 39, 41, 42, 41, 25, 31, 45, | |
127 | +// 48, 45, 40, 48, 37, 40, 41, 40 | |
128 | +//}; | |
129 | +// | |
130 | +////色???藕?量??模?? | |
131 | +//unsigned char std_UV_QT[64] = | |
132 | +//{ | |
133 | +// 7, 7, 7, 10, 8, 10, 19, 10, | |
134 | +// 10, 19, 40, 26, 22, 26, 40, 40, | |
135 | +// 40, 40, 40, 40, 40, 40, 40, 40, | |
136 | +// 40, 40, 40, 40, 40, 40, 40, 40, | |
137 | +// 40, 40, 40, 40, 40, 40, 40, 40, | |
138 | +// 40, 40, 40, 40, 40, 40, 40, 40, | |
139 | +// 40, 40, 40, 40, 40, 40, 40, 40, | |
140 | +// 40, 40, 40, 40, 40, 40, 40, 40 | |
141 | +//}; | |
142 | + | |
143 | +//?炼??藕?量??模?? | |
144 | +unsigned char std_Y_QT[64] = | |
145 | +{ | |
146 | + 0.75 * 6, 0.75 * 4, 0.75 * 5, 0.75 * 6, 0.75 * 5, 0.75 * 4, 0.75 * 6, 0.75 * 6, | |
147 | + 0.75 * 5, 0.75 * 6, 0.75 * 7, 0.75 * 7, 0.75 * 6, 0.75 * 8, 0.75 * 10, 0.75 * 16, | |
148 | + 0.75 * 10, 0.75 * 10, 0.75 * 9, 0.75 * 9, 0.75 * 10, 0.75 * 20, 0.75 * 14, 0.75 * 15, | |
149 | + 0.75 * 12, 0.75 * 16, 0.75 * 23, 0.75 * 20, 0.75 * 24, 0.75 * 24, 0.75 * 23, 0.75 * 20, | |
150 | + 0.75 * 22, 0.75 * 22, 0.75 * 26, 0.75 * 29, 0.75 * 37, 0.75 * 31, 0.75 * 26, 0.75 * 27, | |
151 | + 0.75 * 35, 0.75 * 28, 0.75 * 22, 0.75 * 22, 0.75 * 32, 0.75 * 44, 0.75 * 32, 0.75 * 35, | |
152 | + 0.75 * 38, 0.75 * 39, 0.75 * 41, 0.75 * 42, 0.75 * 41, 0.75 * 25, 0.75 * 31, 0.75 * 45, | |
153 | + 0.75 * 48, 0.75 * 45, 0.75 * 40, 0.75 * 48, 0.75 * 37, 0.75 * 40, 0.75 * 41, 0.75 * 40 | |
154 | +}; | |
155 | + | |
156 | +//色???藕?量??模?? | |
157 | +unsigned char std_UV_QT[64] = | |
158 | +{ | |
159 | + 0.75 * 7, 0.75 * 7, 0.75 * 7, 0.75 * 10, 0.75 * 8, 0.75 * 10, 0.75 * 19, 0.75 * 10, | |
160 | + 0.75 * 10, 0.75 * 19, 0.75 * 40, 0.75 * 26, 0.75 * 22, 0.75 * 26, 0.75 * 40, 0.75 * 40, | |
161 | + 30, 30, 30, 30, 30, 30, 30, 30, | |
162 | + 30, 30, 30, 30, 30, 30, 30, 30, | |
163 | + 30, 30, 30, 30, 30, 30, 30, 30, | |
164 | + 30, 30, 30, 30, 30, 30, 30, 30, | |
165 | + 30, 30, 30, 30, 30, 30, 30, 30, | |
166 | + 30, 30, 30, 30, 30, 30, 30, 30 | |
167 | +}; | |
168 | + | |
169 | +unsigned char STD_DC_Y_NRCODES[16] = { 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 }; | |
170 | +unsigned char STD_DC_Y_VALUES[12] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; | |
171 | + | |
172 | +unsigned char STD_DC_UV_NRCODES[16] = { 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 }; | |
173 | +unsigned char STD_DC_UV_VALUES[12] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; | |
174 | + | |
175 | +unsigned char STD_AC_Y_NRCODES[16] = { 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0X7D }; | |
176 | +unsigned char STD_AC_Y_VALUES[162] = | |
177 | +{ | |
178 | + 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, | |
179 | + 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, | |
180 | + 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, | |
181 | + 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, | |
182 | + 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, | |
183 | + 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, | |
184 | + 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, | |
185 | + 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, | |
186 | + 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, | |
187 | + 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, | |
188 | + 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, | |
189 | + 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, | |
190 | + 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, | |
191 | + 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, | |
192 | + 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, | |
193 | + 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, | |
194 | + 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, | |
195 | + 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, | |
196 | + 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, | |
197 | + 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, | |
198 | + 0xf9, 0xfa | |
199 | +}; | |
200 | + | |
201 | +unsigned char STD_AC_UV_NRCODES[16] = { 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0X77 }; | |
202 | +unsigned char STD_AC_UV_VALUES[162] = | |
203 | +{ | |
204 | + 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, | |
205 | + 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, | |
206 | + 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, | |
207 | + 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, | |
208 | + 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, | |
209 | + 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, | |
210 | + 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, | |
211 | + 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, | |
212 | + 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, | |
213 | + 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, | |
214 | + 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, | |
215 | + 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, | |
216 | + 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, | |
217 | + 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, | |
218 | + 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, | |
219 | + 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, | |
220 | + 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, | |
221 | + 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, | |
222 | + 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, | |
223 | + 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, | |
224 | + 0xf9, 0xfa | |
225 | +}; | |
226 | + | |
227 | +int DivUp(int x, int d) | |
228 | +{ | |
229 | + return (x + d - 1) / d; | |
230 | +} | |
231 | + | |
232 | +template<typename T> | |
233 | +void writeAndAdvance(unsigned char *&pData, T nElement) | |
234 | +{ | |
235 | + writeBigEndian<T>(pData, nElement); | |
236 | + pData += sizeof(T); | |
237 | +} | |
238 | + | |
239 | +void writeMarker(unsigned char nMarker, unsigned char *&pData) | |
240 | +{ | |
241 | + *pData++ = 0x0ff; | |
242 | + *pData++ = nMarker; | |
243 | +} | |
244 | + | |
245 | +void writeJFIFTag(unsigned char *&pData) | |
246 | +{ | |
247 | + const char JFIF_TAG[] = | |
248 | + { | |
249 | + 0x4a, 0x46, 0x49, 0x46, 0x00, | |
250 | + 0x01, 0x02, | |
251 | + 0x00, | |
252 | + 0x00, 0x01, 0x00, 0x01, | |
253 | + 0x00, 0x00 | |
254 | + }; | |
255 | + | |
256 | + writeMarker(0x0e0, pData); | |
257 | + writeAndAdvance<unsigned short>(pData, sizeof(JFIF_TAG) + sizeof(unsigned short)); | |
258 | + memcpy(pData, JFIF_TAG, sizeof(JFIF_TAG)); | |
259 | + pData += sizeof(JFIF_TAG); | |
260 | +} | |
261 | + | |
262 | +void writeFrameHeader(const FrameHeader &header, unsigned char *&pData) | |
263 | +{ | |
264 | + unsigned char aTemp[128]; | |
265 | + unsigned char *pTemp = aTemp; | |
266 | + | |
267 | + writeAndAdvance<unsigned char>(pTemp, header.nSamplePrecision); | |
268 | + writeAndAdvance<unsigned short>(pTemp, header.nHeight); | |
269 | + writeAndAdvance<unsigned short>(pTemp, header.nWidth); | |
270 | + writeAndAdvance<unsigned char>(pTemp, header.nComponents); | |
271 | + | |
272 | + for (int c = 0; c<header.nComponents; ++c) | |
273 | + { | |
274 | + writeAndAdvance<unsigned char>(pTemp, header.aComponentIdentifier[c]); | |
275 | + writeAndAdvance<unsigned char>(pTemp, header.aSamplingFactors[c]); | |
276 | + writeAndAdvance<unsigned char>(pTemp, header.aQuantizationTableSelector[c]); | |
277 | + } | |
278 | + | |
279 | + unsigned short nLength = (unsigned short)(pTemp - aTemp); | |
280 | + | |
281 | + writeMarker(0x0C0, pData); | |
282 | + writeAndAdvance<unsigned short>(pData, nLength + 2); | |
283 | + memcpy(pData, aTemp, nLength); | |
284 | + pData += nLength; | |
285 | +} | |
286 | + | |
287 | +void writeScanHeader(const ScanHeader &header, unsigned char *&pData) | |
288 | +{ | |
289 | + unsigned char aTemp[128]; | |
290 | + unsigned char *pTemp = aTemp; | |
291 | + | |
292 | + writeAndAdvance<unsigned char>(pTemp, header.nComponents); | |
293 | + | |
294 | + for (int c = 0; c<header.nComponents; ++c) | |
295 | + { | |
296 | + writeAndAdvance<unsigned char>(pTemp, header.aComponentSelector[c]); | |
297 | + writeAndAdvance<unsigned char>(pTemp, header.aHuffmanTablesSelector[c]); | |
298 | + } | |
299 | + | |
300 | + writeAndAdvance<unsigned char>(pTemp, header.nSs); | |
301 | + writeAndAdvance<unsigned char>(pTemp, header.nSe); | |
302 | + writeAndAdvance<unsigned char>(pTemp, header.nA); | |
303 | + | |
304 | + unsigned short nLength = (unsigned short)(pTemp - aTemp); | |
305 | + | |
306 | + writeMarker(0x0DA, pData); | |
307 | + writeAndAdvance<unsigned short>(pData, nLength + 2); | |
308 | + memcpy(pData, aTemp, nLength); | |
309 | + pData += nLength; | |
310 | +} | |
311 | + | |
312 | +void writeQuantizationTable(const QuantizationTable &table, unsigned char *&pData) | |
313 | +{ | |
314 | + writeMarker(0x0DB, pData); | |
315 | + writeAndAdvance<unsigned short>(pData, sizeof(QuantizationTable) + 2); | |
316 | + memcpy(pData, &table, sizeof(QuantizationTable)); | |
317 | + pData += sizeof(QuantizationTable); | |
318 | +} | |
319 | + | |
320 | +void writeHuffmanTable(const HuffmanTable &table, unsigned char *&pData) | |
321 | +{ | |
322 | + writeMarker(0x0C4, pData); | |
323 | + | |
324 | + // Number of Codes for Bit Lengths [1..16] | |
325 | + int nCodeCount = 0; | |
326 | + | |
327 | + for (int i = 0; i < 16; ++i) | |
328 | + { | |
329 | + nCodeCount += table.aCodes[i]; | |
330 | + } | |
331 | + | |
332 | + writeAndAdvance<unsigned short>(pData, 17 + nCodeCount + 2); | |
333 | + memcpy(pData, &table, 17 + nCodeCount); | |
334 | + pData += 17 + nCodeCount; | |
335 | +} | |
336 | + | |
337 | +bool printfNPPinfo(int cudaVerMajor, int cudaVerMinor) | |
338 | +{ | |
339 | + const NppLibraryVersion *libVer = nppGetLibVersion(); | |
340 | + | |
341 | + printf("NPP Library Version %d.%d.%d\n", libVer->major, libVer->minor, libVer->build); | |
342 | + | |
343 | + int driverVersion, runtimeVersion; | |
344 | + cudaDriverGetVersion(&driverVersion); | |
345 | + cudaRuntimeGetVersion(&runtimeVersion); | |
346 | + | |
347 | + printf(" CUDA Driver Version: %d.%d\n", driverVersion / 1000, (driverVersion % 100) / 10); | |
348 | + printf(" CUDA Runtime Version: %d.%d\n", runtimeVersion / 1000, (runtimeVersion % 100) / 10); | |
349 | + | |
350 | + bool bVal = checkCudaCapabilities(cudaVerMajor, cudaVerMinor); | |
351 | + return bVal; | |
352 | +} | |
353 | + | |
354 | +NppiDCTState *pDCTState; | |
355 | +FrameHeader oFrameHeader; | |
356 | +FrameHeader oFrameHeaderFixedSize; | |
357 | +ScanHeader oScanHeader; | |
358 | +QuantizationTable aQuantizationTables[4]; | |
359 | +Npp8u *pdQuantizationTables; | |
360 | +HuffmanTable aHuffmanTables[4]; | |
361 | +HuffmanTable *pHuffmanDCTables; | |
362 | +HuffmanTable *pHuffmanACTables; | |
363 | +int nMCUBlocksH; | |
364 | +int nMCUBlocksV; | |
365 | +int nMCUBlocksHFixedSize; | |
366 | +int nMCUBlocksVFixedSize; | |
367 | +Npp8u *pdScan; | |
368 | +NppiEncodeHuffmanSpec *apHuffmanDCTable[3]; | |
369 | +NppiEncodeHuffmanSpec *apHuffmanACTable[3]; | |
370 | +unsigned char *pDstJpeg; | |
371 | +unsigned char *pDstOutput; | |
372 | +int nRestartInterval; | |
373 | + | |
374 | +int initTable() | |
375 | +{ | |
376 | + NPP_CHECK_NPP(nppiDCTInitAlloc(&pDCTState)); | |
377 | + | |
378 | + nRestartInterval = -1; | |
379 | + | |
380 | + cudaMalloc(&pdQuantizationTables, 64 * 4); | |
381 | + pHuffmanDCTables = aHuffmanTables; | |
382 | + pHuffmanACTables = &aHuffmanTables[2]; | |
383 | + memset(aQuantizationTables, 0, 4 * sizeof(QuantizationTable)); | |
384 | + memset(aHuffmanTables, 0, 4 * sizeof(HuffmanTable)); | |
385 | + memset(&oFrameHeader, 0, sizeof(FrameHeader)); | |
386 | + | |
387 | + | |
388 | + //????Huffman?? | |
389 | + aHuffmanTables[0].nClassAndIdentifier = 0; | |
390 | + memcpy(aHuffmanTables[0].aCodes, STD_DC_Y_NRCODES, 16); | |
391 | + memcpy(aHuffmanTables[0].aTable, STD_DC_Y_VALUES, 12); | |
392 | + | |
393 | + aHuffmanTables[1].nClassAndIdentifier = 1; | |
394 | + memcpy(aHuffmanTables[1].aCodes, STD_DC_UV_NRCODES, 16); | |
395 | + memcpy(aHuffmanTables[1].aTable, STD_DC_UV_VALUES, 12); | |
396 | + | |
397 | + aHuffmanTables[2].nClassAndIdentifier = 16; | |
398 | + memcpy(aHuffmanTables[2].aCodes, STD_AC_Y_NRCODES, 16); | |
399 | + memcpy(aHuffmanTables[2].aTable, STD_AC_Y_VALUES, 162); | |
400 | + | |
401 | + aHuffmanTables[3].nClassAndIdentifier = 17; | |
402 | + memcpy(aHuffmanTables[3].aCodes, STD_AC_UV_NRCODES, 16); | |
403 | + memcpy(aHuffmanTables[3].aTable, STD_AC_UV_VALUES, 162); | |
404 | + | |
405 | + | |
406 | + //????量???? | |
407 | + aQuantizationTables[0].nPrecisionAndIdentifier = 0; | |
408 | + memcpy(aQuantizationTables[0].aTable, std_Y_QT, 64); | |
409 | + aQuantizationTables[1].nPrecisionAndIdentifier = 1; | |
410 | + memcpy(aQuantizationTables[1].aTable, std_UV_QT, 64); | |
411 | + | |
412 | + NPP_CHECK_CUDA(cudaMemcpyAsync(pdQuantizationTables, aQuantizationTables[0].aTable, 64, cudaMemcpyHostToDevice)); | |
413 | + NPP_CHECK_CUDA(cudaMemcpyAsync(pdQuantizationTables + 64, aQuantizationTables[1].aTable, 64, cudaMemcpyHostToDevice)); | |
414 | + | |
415 | + oFrameHeader.nSamplePrecision = 8; | |
416 | + oFrameHeader.nComponents = 3; | |
417 | + oFrameHeader.aComponentIdentifier[0] = 1; | |
418 | + oFrameHeader.aComponentIdentifier[1] = 2; | |
419 | + oFrameHeader.aComponentIdentifier[2] = 3; | |
420 | + oFrameHeader.aSamplingFactors[0] = 34; | |
421 | + oFrameHeader.aSamplingFactors[1] = 17; | |
422 | + oFrameHeader.aSamplingFactors[2] = 17; | |
423 | + oFrameHeader.aQuantizationTableSelector[0] = 0; | |
424 | + oFrameHeader.aQuantizationTableSelector[1] = 1; | |
425 | + oFrameHeader.aQuantizationTableSelector[2] = 1; | |
426 | + | |
427 | + for (int i = 0; i < oFrameHeader.nComponents; ++i) | |
428 | + { | |
429 | + nMCUBlocksV = max(nMCUBlocksV, oFrameHeader.aSamplingFactors[i] & 0x0f); | |
430 | + nMCUBlocksH = max(nMCUBlocksH, oFrameHeader.aSamplingFactors[i] >> 4); | |
431 | + } | |
432 | + NPP_CHECK_CUDA(cudaMalloc(&pdScan, 4 << 20)); | |
433 | + | |
434 | + | |
435 | + | |
436 | + oScanHeader.nComponents = 3; | |
437 | + oScanHeader.aComponentSelector[0] = 1; | |
438 | + oScanHeader.aComponentSelector[1] = 2; | |
439 | + oScanHeader.aComponentSelector[2] = 3; | |
440 | + oScanHeader.aHuffmanTablesSelector[0] = 0; | |
441 | + oScanHeader.aHuffmanTablesSelector[1] = 17; | |
442 | + oScanHeader.aHuffmanTablesSelector[2] = 17; | |
443 | + oScanHeader.nSs = 0; | |
444 | + oScanHeader.nSe = 63; | |
445 | + oScanHeader.nA = 0; | |
446 | + | |
447 | + | |
448 | + return 0; | |
449 | +} | |
450 | + | |
451 | +NppiSize aSrcSize[3]; | |
452 | +Npp16s *apdDCT[3];// = { 0, 0, 0 }; | |
453 | +Npp32s aDCTStep[3]; | |
454 | + | |
455 | +Npp8u *apSrcImage[3];// = { 0, 0, 0 }; | |
456 | +Npp32s aSrcImageStep[3]; | |
457 | +size_t aSrcPitch[3]; | |
458 | + | |
459 | + | |
460 | +int releaseJpegNPP() | |
461 | +{ | |
462 | + nppiDCTFree(pDCTState); | |
463 | + cudaFree(pdQuantizationTables); | |
464 | + cudaFree(pdScan); | |
465 | + for (int i = 0; i < 3; ++i) | |
466 | + { | |
467 | + cudaFree(apdDCT[i]); | |
468 | + cudaFree(apSrcImage[i]); | |
469 | + } | |
470 | + return 0; | |
471 | +} | |
472 | + | |
473 | + | |
474 | +int initTable(int flag, int width, int height) | |
475 | +{ | |
476 | + //????帧头 | |
477 | + oFrameHeaderFixedSize.nSamplePrecision = 8; | |
478 | + oFrameHeaderFixedSize.nComponents = 3; | |
479 | + oFrameHeaderFixedSize.aComponentIdentifier[0] = 1; | |
480 | + oFrameHeaderFixedSize.aComponentIdentifier[1] = 2; | |
481 | + oFrameHeaderFixedSize.aComponentIdentifier[2] = 3; | |
482 | + oFrameHeaderFixedSize.aSamplingFactors[0] = 34; | |
483 | + oFrameHeaderFixedSize.aSamplingFactors[1] = 17; | |
484 | + oFrameHeaderFixedSize.aSamplingFactors[2] = 17; | |
485 | + oFrameHeaderFixedSize.aQuantizationTableSelector[0] = 0; | |
486 | + oFrameHeaderFixedSize.aQuantizationTableSelector[1] = 1; | |
487 | + oFrameHeaderFixedSize.aQuantizationTableSelector[2] = 1; | |
488 | + oFrameHeaderFixedSize.nWidth = width; | |
489 | + oFrameHeaderFixedSize.nHeight = height; | |
490 | + | |
491 | + for (int i = 0; i < oFrameHeaderFixedSize.nComponents; ++i) | |
492 | + { | |
493 | + nMCUBlocksVFixedSize = max(nMCUBlocksVFixedSize, oFrameHeaderFixedSize.aSamplingFactors[i] & 0x0f); | |
494 | + nMCUBlocksHFixedSize = max(nMCUBlocksHFixedSize, oFrameHeaderFixedSize.aSamplingFactors[i] >> 4); | |
495 | + } | |
496 | + | |
497 | + for (int i = 0; i < oFrameHeaderFixedSize.nComponents; ++i) | |
498 | + { | |
499 | + NppiSize oBlocks; | |
500 | + NppiSize oBlocksPerMCU = { oFrameHeaderFixedSize.aSamplingFactors[i] >> 4, oFrameHeaderFixedSize.aSamplingFactors[i] & 0x0f }; | |
501 | + | |
502 | + oBlocks.width = (int)ceil((oFrameHeaderFixedSize.nWidth + 7) / 8 * | |
503 | + static_cast<float>(oBlocksPerMCU.width) / nMCUBlocksHFixedSize); | |
504 | + oBlocks.width = DivUp(oBlocks.width, oBlocksPerMCU.width) * oBlocksPerMCU.width; | |
505 | + | |
506 | + oBlocks.height = (int)ceil((oFrameHeaderFixedSize.nHeight + 7) / 8 * | |
507 | + static_cast<float>(oBlocksPerMCU.height) / nMCUBlocksVFixedSize); | |
508 | + oBlocks.height = DivUp(oBlocks.height, oBlocksPerMCU.height) * oBlocksPerMCU.height; | |
509 | + | |
510 | + aSrcSize[i].width = oBlocks.width * 8; | |
511 | + aSrcSize[i].height = oBlocks.height * 8; | |
512 | + | |
513 | + // Allocate Memory | |
514 | + size_t nPitch; | |
515 | + NPP_CHECK_CUDA(cudaMallocPitch(&apdDCT[i], &nPitch, oBlocks.width * 64 * sizeof(Npp16s), oBlocks.height)); | |
516 | + aDCTStep[i] = static_cast<Npp32s>(nPitch); | |
517 | + | |
518 | + NPP_CHECK_CUDA(cudaMallocPitch(&apSrcImage[i], &nPitch, aSrcSize[i].width, aSrcSize[i].height)); | |
519 | + | |
520 | + aSrcPitch[i] = nPitch; | |
521 | + aSrcImageStep[i] = static_cast<Npp32s>(nPitch); | |
522 | + } | |
523 | + | |
524 | + return 0; | |
525 | +} | |
526 | + | |
527 | +int jpegNPP(const char *szOutputFile, float* d_srcRGB) | |
528 | +{ | |
529 | + //RGB2YUV | |
530 | + cudaError_t cudaStatus; | |
531 | + cudaStatus = cuda_common::RGB2YUV(d_srcRGB, oFrameHeaderFixedSize.nWidth, oFrameHeaderFixedSize.nHeight, | |
532 | + apSrcImage[0], aSrcPitch[0], aSrcSize[0].width, aSrcSize[0].height, | |
533 | + apSrcImage[1], aSrcPitch[1], aSrcSize[1].width, aSrcSize[1].height, | |
534 | + apSrcImage[2], aSrcPitch[2], aSrcSize[2].width, aSrcSize[2].height); | |
535 | + | |
536 | + /** | |
537 | + * Forward DCT, quantization and level shift part of the JPEG encoding. | |
538 | + * Input is expected in 8x8 macro blocks and output is expected to be in 64x1 | |
539 | + * macro blocks. The new version of the primitive takes the ROI in image pixel size and | |
540 | + * works with DCT coefficients that are in zig-zag order. | |
541 | + */ | |
542 | + int k = 0; | |
543 | + //LOG_INFO("NPP_CHECK_NPP:%d", 1); | |
544 | + if (NPP_SUCCESS != (nppiDCTQuantFwd8x8LS_JPEG_8u16s_C1R_NEW(apSrcImage[0], aSrcImageStep[0], | |
545 | + apdDCT[0], aDCTStep[0], | |
546 | + pdQuantizationTables + k * 64, | |
547 | + aSrcSize[0], | |
548 | + pDCTState))) | |
549 | + { | |
550 | + printf("nppiDCTQuantFwd8x8LS_JPEG_8u16s_C1R_NEW Failed!\n"); | |
551 | + return EXIT_FAILURE; | |
552 | + } | |
553 | + | |
554 | + k = 1; | |
555 | + //LOG_INFO("NPP_CHECK_NPP:%d", 2); | |
556 | + if (NPP_SUCCESS != (nppiDCTQuantFwd8x8LS_JPEG_8u16s_C1R_NEW(apSrcImage[1], aSrcImageStep[1], | |
557 | + apdDCT[1], aDCTStep[1], | |
558 | + pdQuantizationTables + k * 64, | |
559 | + aSrcSize[1], | |
560 | + pDCTState))) | |
561 | + { | |
562 | + printf("nppiDCTQuantFwd8x8LS_JPEG_8u16s_C1R_NEW Failed!\n"); | |
563 | + return EXIT_FAILURE; | |
564 | + } | |
565 | + | |
566 | + //LOG_INFO("NPP_CHECK_NPP:%d", 3); | |
567 | + if (NPP_SUCCESS != (nppiDCTQuantFwd8x8LS_JPEG_8u16s_C1R_NEW(apSrcImage[2], aSrcImageStep[2], | |
568 | + apdDCT[2], aDCTStep[2], | |
569 | + pdQuantizationTables + k * 64, | |
570 | + aSrcSize[2], | |
571 | + pDCTState))) | |
572 | + { | |
573 | + printf("nppiDCTQuantFwd8x8LS_JPEG_8u16s_C1R_NEW Failed!\n"); | |
574 | + return EXIT_FAILURE; | |
575 | + } | |
576 | + | |
577 | + // Huffman Encoding | |
578 | + | |
579 | + Npp32s nScanLength; | |
580 | + Npp8u *pJpegEncoderTemp; | |
581 | + | |
582 | +#if (CUDA_VERSION == 8000) | |
583 | + Npp32s nTempSize; //when using CUDA8 | |
584 | +#else | |
585 | + size_t nTempSize; //when using CUDA9 | |
586 | +#endif | |
587 | + //modified by Junlin 190221 | |
588 | + | |
589 | + //LOG_INFO("NPP_CHECK_NPP:%d",4); | |
590 | + if (NPP_SUCCESS != (nppiEncodeHuffmanGetSize(aSrcSize[0], 3, &nTempSize))) | |
591 | + { | |
592 | + printf("nppiEncodeHuffmanGetSize Failed!\n"); | |
593 | + return EXIT_FAILURE; | |
594 | + } | |
595 | + | |
596 | + //LOG_INFO("NPP_CHECK_CUDA:%d",5); | |
597 | + NPP_CHECK_CUDA(cudaMalloc(&pJpegEncoderTemp, nTempSize)); | |
598 | + | |
599 | + /** | |
600 | + * Allocates memory and creates a Huffman table in a format that is suitable for the encoder. | |
601 | + */ | |
602 | + NppStatus t_status; | |
603 | + t_status = nppiEncodeHuffmanSpecInitAlloc_JPEG(pHuffmanDCTables[0].aCodes, nppiDCTable, &apHuffmanDCTable[0]); | |
604 | + t_status = nppiEncodeHuffmanSpecInitAlloc_JPEG(pHuffmanACTables[0].aCodes, nppiACTable, &apHuffmanACTable[0]); | |
605 | + t_status = nppiEncodeHuffmanSpecInitAlloc_JPEG(pHuffmanDCTables[1].aCodes, nppiDCTable, &apHuffmanDCTable[1]); | |
606 | + t_status = nppiEncodeHuffmanSpecInitAlloc_JPEG(pHuffmanACTables[1].aCodes, nppiACTable, &apHuffmanACTable[1]); | |
607 | + t_status = nppiEncodeHuffmanSpecInitAlloc_JPEG(pHuffmanDCTables[1].aCodes, nppiDCTable, &apHuffmanDCTable[2]); | |
608 | + t_status = nppiEncodeHuffmanSpecInitAlloc_JPEG(pHuffmanACTables[1].aCodes, nppiACTable, &apHuffmanACTable[2]); | |
609 | + | |
610 | + /** | |
611 | + * Huffman Encoding of the JPEG Encoding. | |
612 | + * Input is expected to be 64x1 macro blocks and output is expected as byte stuffed huffman encoded JPEG scan. | |
613 | + */ | |
614 | + Npp32s nSs = 0; | |
615 | + Npp32s nSe = 63; | |
616 | + Npp32s nH = 0; | |
617 | + Npp32s nL = 0; | |
618 | + //LOG_INFO("NPP_CHECK_NPP:%d",6); | |
619 | + if (NPP_SUCCESS != (nppiEncodeHuffmanScan_JPEG_8u16s_P3R(apdDCT, aDCTStep, | |
620 | + 0, nSs, nSe, nH, nL, | |
621 | + pdScan, &nScanLength, | |
622 | + apHuffmanDCTable, | |
623 | + apHuffmanACTable, | |
624 | + aSrcSize, | |
625 | + pJpegEncoderTemp))) | |
626 | + { | |
627 | + printf("nppiEncodeHuffmanScan_JPEG_8u16s_P3R Failed!\n"); | |
628 | + return EXIT_FAILURE; | |
629 | + } | |
630 | + | |
631 | + for (int i = 0; i < 3; ++i) | |
632 | + { | |
633 | + nppiEncodeHuffmanSpecFree_JPEG(apHuffmanDCTable[i]); | |
634 | + nppiEncodeHuffmanSpecFree_JPEG(apHuffmanACTable[i]); | |
635 | + } | |
636 | + // Write JPEG | |
637 | + pDstJpeg = new unsigned char[4 << 20]{}; | |
638 | + pDstOutput = pDstJpeg; | |
639 | + | |
640 | + writeMarker(0x0D8, pDstOutput); | |
641 | + writeJFIFTag(pDstOutput); | |
642 | + writeQuantizationTable(aQuantizationTables[0], pDstOutput); | |
643 | + writeQuantizationTable(aQuantizationTables[1], pDstOutput); | |
644 | + writeHuffmanTable(pHuffmanDCTables[0], pDstOutput); | |
645 | + writeHuffmanTable(pHuffmanACTables[0], pDstOutput); | |
646 | + writeHuffmanTable(pHuffmanDCTables[1], pDstOutput); | |
647 | + writeHuffmanTable(pHuffmanACTables[1], pDstOutput); | |
648 | + writeFrameHeader(oFrameHeaderFixedSize, pDstOutput); | |
649 | + writeScanHeader(oScanHeader, pDstOutput); | |
650 | + | |
651 | + //LOG_INFO("NPP_CHECK_CUDA:%d",7); | |
652 | + NPP_CHECK_CUDA(cudaMemcpy(pDstOutput, pdScan, nScanLength, cudaMemcpyDeviceToHost)); | |
653 | + | |
654 | + pDstOutput += nScanLength; | |
655 | + writeMarker(0x0D9, pDstOutput); | |
656 | + { | |
657 | + // Write result to file. | |
658 | + std::ofstream outputFile(szOutputFile, ios::out | ios::binary); | |
659 | + outputFile.write(reinterpret_cast<const char *>(pDstJpeg), static_cast<int>(pDstOutput - pDstJpeg)); | |
660 | + } | |
661 | + | |
662 | + // Cleanup | |
663 | + cudaFree(pJpegEncoderTemp); | |
664 | + delete[] pDstJpeg; | |
665 | + | |
666 | + | |
667 | + return EXIT_SUCCESS; | |
668 | +} | |
669 | + | |
670 | +int jpegNPP(const char *szOutputFile, unsigned char* d_srcRGB) | |
671 | +{ | |
672 | + //RGB2YUV | |
673 | + cudaError_t cudaStatus; | |
674 | + cudaStatus = cuda_common::RGB2YUV(d_srcRGB, oFrameHeaderFixedSize.nWidth, oFrameHeaderFixedSize.nHeight, | |
675 | + apSrcImage[0], aSrcPitch[0], aSrcSize[0].width, aSrcSize[0].height, | |
676 | + apSrcImage[1], aSrcPitch[1], aSrcSize[1].width, aSrcSize[1].height, | |
677 | + apSrcImage[2], aSrcPitch[2], aSrcSize[2].width, aSrcSize[2].height); | |
678 | + | |
679 | + /** | |
680 | + * Forward DCT, quantization and level shift part of the JPEG encoding. | |
681 | + * Input is expected in 8x8 macro blocks and output is expected to be in 64x1 | |
682 | + * macro blocks. The new version of the primitive takes the ROI in image pixel size and | |
683 | + * works with DCT coefficients that are in zig-zag order. | |
684 | + */ | |
685 | + int k = 0; | |
686 | + //LOG_INFO("NPP_CHECK_NPP:%d", 1); | |
687 | + if (NPP_SUCCESS != (nppiDCTQuantFwd8x8LS_JPEG_8u16s_C1R_NEW(apSrcImage[0], aSrcImageStep[0], | |
688 | + apdDCT[0], aDCTStep[0], | |
689 | + pdQuantizationTables + k * 64, | |
690 | + aSrcSize[0], | |
691 | + pDCTState))) | |
692 | + { | |
693 | + printf("nppiDCTQuantFwd8x8LS_JPEG_8u16s_C1R_NEW Failed!\n"); | |
694 | + return EXIT_FAILURE; | |
695 | + } | |
696 | + | |
697 | + k = 1; | |
698 | + //LOG_INFO("NPP_CHECK_NPP:%d", 2); | |
699 | + if (NPP_SUCCESS != (nppiDCTQuantFwd8x8LS_JPEG_8u16s_C1R_NEW(apSrcImage[1], aSrcImageStep[1], | |
700 | + apdDCT[1], aDCTStep[1], | |
701 | + pdQuantizationTables + k * 64, | |
702 | + aSrcSize[1], | |
703 | + pDCTState))) | |
704 | + { | |
705 | + printf("nppiDCTQuantFwd8x8LS_JPEG_8u16s_C1R_NEW Failed!\n"); | |
706 | + return EXIT_FAILURE; | |
707 | + } | |
708 | + | |
709 | + //LOG_INFO("NPP_CHECK_NPP:%d", 3); | |
710 | + if (NPP_SUCCESS != (nppiDCTQuantFwd8x8LS_JPEG_8u16s_C1R_NEW(apSrcImage[2], aSrcImageStep[2], | |
711 | + apdDCT[2], aDCTStep[2], | |
712 | + pdQuantizationTables + k * 64, | |
713 | + aSrcSize[2], | |
714 | + pDCTState))) | |
715 | + { | |
716 | + printf("nppiDCTQuantFwd8x8LS_JPEG_8u16s_C1R_NEW Failed!\n"); | |
717 | + return EXIT_FAILURE; | |
718 | + } | |
719 | + | |
720 | + // Huffman Encoding | |
721 | + | |
722 | + Npp32s nScanLength; | |
723 | + Npp8u *pJpegEncoderTemp; | |
724 | + | |
725 | +#if (CUDA_VERSION == 8000) | |
726 | + Npp32s nTempSize; //when using CUDA8 | |
727 | +#else | |
728 | + size_t nTempSize; //when using CUDA9 | |
729 | +#endif | |
730 | + //modified by Junlin 190221 | |
731 | + | |
732 | + //LOG_INFO("NPP_CHECK_NPP:%d",4); | |
733 | + if (NPP_SUCCESS != (nppiEncodeHuffmanGetSize(aSrcSize[0], 3, &nTempSize))) | |
734 | + { | |
735 | + printf("nppiEncodeHuffmanGetSize Failed!\n"); | |
736 | + return EXIT_FAILURE; | |
737 | + } | |
738 | + | |
739 | + //LOG_INFO("NPP_CHECK_CUDA:%d",5); | |
740 | + NPP_CHECK_CUDA(cudaMalloc(&pJpegEncoderTemp, nTempSize)); | |
741 | + | |
742 | + /** | |
743 | + * Allocates memory and creates a Huffman table in a format that is suitable for the encoder. | |
744 | + */ | |
745 | + NppStatus t_status; | |
746 | + t_status = nppiEncodeHuffmanSpecInitAlloc_JPEG(pHuffmanDCTables[0].aCodes, nppiDCTable, &apHuffmanDCTable[0]); | |
747 | + t_status = nppiEncodeHuffmanSpecInitAlloc_JPEG(pHuffmanACTables[0].aCodes, nppiACTable, &apHuffmanACTable[0]); | |
748 | + t_status = nppiEncodeHuffmanSpecInitAlloc_JPEG(pHuffmanDCTables[1].aCodes, nppiDCTable, &apHuffmanDCTable[1]); | |
749 | + t_status = nppiEncodeHuffmanSpecInitAlloc_JPEG(pHuffmanACTables[1].aCodes, nppiACTable, &apHuffmanACTable[1]); | |
750 | + t_status = nppiEncodeHuffmanSpecInitAlloc_JPEG(pHuffmanDCTables[1].aCodes, nppiDCTable, &apHuffmanDCTable[2]); | |
751 | + t_status = nppiEncodeHuffmanSpecInitAlloc_JPEG(pHuffmanACTables[1].aCodes, nppiACTable, &apHuffmanACTable[2]); | |
752 | + | |
753 | + /** | |
754 | + * Huffman Encoding of the JPEG Encoding. | |
755 | + * Input is expected to be 64x1 macro blocks and output is expected as byte stuffed huffman encoded JPEG scan. | |
756 | + */ | |
757 | + Npp32s nSs = 0; | |
758 | + Npp32s nSe = 63; | |
759 | + Npp32s nH = 0; | |
760 | + Npp32s nL = 0; | |
761 | + //LOG_INFO("NPP_CHECK_NPP:%d",6); | |
762 | + if (NPP_SUCCESS != (nppiEncodeHuffmanScan_JPEG_8u16s_P3R(apdDCT, aDCTStep, | |
763 | + 0, nSs, nSe, nH, nL, | |
764 | + pdScan, &nScanLength, | |
765 | + apHuffmanDCTable, | |
766 | + apHuffmanACTable, | |
767 | + aSrcSize, | |
768 | + pJpegEncoderTemp))) | |
769 | + { | |
770 | + printf("nppiEncodeHuffmanScan_JPEG_8u16s_P3R Failed!\n"); | |
771 | + return EXIT_FAILURE; | |
772 | + } | |
773 | + | |
774 | + for (int i = 0; i < 3; ++i) | |
775 | + { | |
776 | + nppiEncodeHuffmanSpecFree_JPEG(apHuffmanDCTable[i]); | |
777 | + nppiEncodeHuffmanSpecFree_JPEG(apHuffmanACTable[i]); | |
778 | + } | |
779 | + // Write JPEG | |
780 | + pDstJpeg = new unsigned char[4 << 20]{}; | |
781 | + pDstOutput = pDstJpeg; | |
782 | + | |
783 | + writeMarker(0x0D8, pDstOutput); | |
784 | + writeJFIFTag(pDstOutput); | |
785 | + writeQuantizationTable(aQuantizationTables[0], pDstOutput); | |
786 | + writeQuantizationTable(aQuantizationTables[1], pDstOutput); | |
787 | + writeHuffmanTable(pHuffmanDCTables[0], pDstOutput); | |
788 | + writeHuffmanTable(pHuffmanACTables[0], pDstOutput); | |
789 | + writeHuffmanTable(pHuffmanDCTables[1], pDstOutput); | |
790 | + writeHuffmanTable(pHuffmanACTables[1], pDstOutput); | |
791 | + writeFrameHeader(oFrameHeaderFixedSize, pDstOutput); | |
792 | + writeScanHeader(oScanHeader, pDstOutput); | |
793 | + | |
794 | + //LOG_INFO("NPP_CHECK_CUDA:%d",7); | |
795 | + NPP_CHECK_CUDA(cudaMemcpy(pDstOutput, pdScan, nScanLength, cudaMemcpyDeviceToHost)); | |
796 | + | |
797 | + pDstOutput += nScanLength; | |
798 | + writeMarker(0x0D9, pDstOutput); | |
799 | + { | |
800 | + // Write result to file. | |
801 | + std::ofstream outputFile(szOutputFile, ios::out | ios::binary); | |
802 | + outputFile.write(reinterpret_cast<const char *>(pDstJpeg), static_cast<int>(pDstOutput - pDstJpeg)); | |
803 | + } | |
804 | + | |
805 | + // Cleanup | |
806 | + cudaFree(pJpegEncoderTemp); | |
807 | + delete[] pDstJpeg; | |
808 | + | |
809 | + | |
810 | + return EXIT_SUCCESS; | |
811 | +} | |
812 | + | |
813 | + | |
814 | +int jpegNPP(const char *szOutputFile, float* d_srcRGB, int img_width, int img_height) | |
815 | +{ | |
816 | + NppiSize aSrcSize[3]; | |
817 | + Npp16s *apdDCT[3] = { 0, 0, 0 }; | |
818 | + Npp32s aDCTStep[3]; | |
819 | + | |
820 | + Npp8u *apSrcImage[3] = { 0, 0, 0 }; | |
821 | + Npp32s aSrcImageStep[3]; | |
822 | + size_t aSrcPitch[3]; | |
823 | + | |
824 | + | |
825 | + //????帧头 | |
826 | + oFrameHeader.nWidth = img_width; | |
827 | + oFrameHeader.nHeight = img_height; | |
828 | + | |
829 | + for (int i = 0; i < oFrameHeader.nComponents; ++i) | |
830 | + { | |
831 | + NppiSize oBlocks; | |
832 | + NppiSize oBlocksPerMCU = { oFrameHeader.aSamplingFactors[i] >> 4, oFrameHeader.aSamplingFactors[i] & 0x0f }; | |
833 | + | |
834 | + oBlocks.width = (int)ceil((oFrameHeader.nWidth + 7) / 8 * | |
835 | + static_cast<float>(oBlocksPerMCU.width) / nMCUBlocksH); | |
836 | + oBlocks.width = DivUp(oBlocks.width, oBlocksPerMCU.width) * oBlocksPerMCU.width; | |
837 | + | |
838 | + oBlocks.height = (int)ceil((oFrameHeader.nHeight + 7) / 8 * | |
839 | + static_cast<float>(oBlocksPerMCU.height) / nMCUBlocksV); | |
840 | + oBlocks.height = DivUp(oBlocks.height, oBlocksPerMCU.height) * oBlocksPerMCU.height; | |
841 | + | |
842 | + aSrcSize[i].width = oBlocks.width * 8; | |
843 | + aSrcSize[i].height = oBlocks.height * 8; | |
844 | + | |
845 | + // Allocate Memory | |
846 | + size_t nPitch; | |
847 | + //LOG_INFO("NPP_CHECK_CUDA:%d",1); | |
848 | + NPP_CHECK_CUDA(cudaMallocPitch(&apdDCT[i], &nPitch, oBlocks.width * 64 * sizeof(Npp16s), oBlocks.height)); | |
849 | + aDCTStep[i] = static_cast<Npp32s>(nPitch); | |
850 | + | |
851 | + //LOG_INFO("NPP_CHECK_CUDA:%d",2); | |
852 | + NPP_CHECK_CUDA(cudaMallocPitch(&apSrcImage[i], &nPitch, aSrcSize[i].width, aSrcSize[i].height)); | |
853 | + | |
854 | + aSrcPitch[i] = nPitch; | |
855 | + aSrcImageStep[i] = static_cast<Npp32s>(nPitch); | |
856 | + } | |
857 | + | |
858 | + //RGB2YUV | |
859 | + cudaError_t cudaStatus; | |
860 | + cudaStatus = cuda_common::RGB2YUV(d_srcRGB, img_width, img_height, | |
861 | + apSrcImage[0], aSrcPitch[0], aSrcSize[0].width, aSrcSize[0].height, | |
862 | + apSrcImage[1], aSrcPitch[1], aSrcSize[1].width, aSrcSize[1].height, | |
863 | + apSrcImage[2], aSrcPitch[2], aSrcSize[2].width, aSrcSize[2].height); | |
864 | + | |
865 | + /** | |
866 | + * Forward DCT, quantization and level shift part of the JPEG encoding. | |
867 | + * Input is expected in 8x8 macro blocks and output is expected to be in 64x1 | |
868 | + * macro blocks. The new version of the primitive takes the ROI in image pixel size and | |
869 | + * works with DCT coefficients that are in zig-zag order. | |
870 | + */ | |
871 | + int k = 0; | |
872 | + //LOG_INFO("NPP_CHECK_CUDA:%d",3); | |
873 | + if (NPP_SUCCESS != (nppiDCTQuantFwd8x8LS_JPEG_8u16s_C1R_NEW(apSrcImage[0], aSrcImageStep[0], | |
874 | + apdDCT[0], aDCTStep[0], | |
875 | + pdQuantizationTables + k * 64, | |
876 | + aSrcSize[0], | |
877 | + pDCTState))) | |
878 | + { | |
879 | + printf("nppiDCTQuantFwd8x8LS_JPEG_8u16s_C1R_NEW Failed!\n"); | |
880 | + return EXIT_FAILURE; | |
881 | + } | |
882 | + k = 1; | |
883 | + | |
884 | + //LOG_INFO("NPP_CHECK_CUDA:%d",4); | |
885 | + if (NPP_SUCCESS != (nppiDCTQuantFwd8x8LS_JPEG_8u16s_C1R_NEW(apSrcImage[1], aSrcImageStep[1], | |
886 | + apdDCT[1], aDCTStep[1], | |
887 | + pdQuantizationTables + k * 64, | |
888 | + aSrcSize[1], | |
889 | + pDCTState))) | |
890 | + { | |
891 | + printf("nppiDCTQuantFwd8x8LS_JPEG_8u16s_C1R_NEW Failed!\n"); | |
892 | + return EXIT_FAILURE; | |
893 | + } | |
894 | + | |
895 | + //LOG_INFO("NPP_CHECK_CUDA:%d",5); | |
896 | + if (NPP_SUCCESS != (nppiDCTQuantFwd8x8LS_JPEG_8u16s_C1R_NEW(apSrcImage[2], aSrcImageStep[2], | |
897 | + apdDCT[2], aDCTStep[2], | |
898 | + pdQuantizationTables + k * 64, | |
899 | + aSrcSize[2], | |
900 | + pDCTState))) | |
901 | + { | |
902 | + printf("nppiDCTQuantFwd8x8LS_JPEG_8u16s_C1R_NEW Failed!\n"); | |
903 | + return EXIT_FAILURE; | |
904 | + } | |
905 | + | |
906 | + // Huffman Encoding | |
907 | + | |
908 | + Npp32s nScanLength; | |
909 | + Npp8u *pJpegEncoderTemp; | |
910 | + | |
911 | +#if (CUDA_VERSION == 8000) | |
912 | + Npp32s nTempSize; //when using CUDA8 | |
913 | +#else | |
914 | + size_t nTempSize; //when using CUDA9 | |
915 | +#endif | |
916 | + //modified by Junlin 190221 | |
917 | + | |
918 | + //LOG_INFO("NPP_CHECK_CUDA:%d",6); | |
919 | + if (NPP_SUCCESS != (nppiEncodeHuffmanGetSize(aSrcSize[0], 3, &nTempSize))) | |
920 | + { | |
921 | + printf("nppiEncodeHuffmanGetSize Failed!\n"); | |
922 | + return EXIT_FAILURE; | |
923 | + } | |
924 | + | |
925 | + //LOG_INFO("NPP_CHECK_CUDA:%d",7); | |
926 | + NPP_CHECK_CUDA(cudaMalloc(&pJpegEncoderTemp, nTempSize)); | |
927 | + | |
928 | + /** | |
929 | + * Allocates memory and creates a Huffman table in a format that is suitable for the encoder. | |
930 | + */ | |
931 | + NppStatus t_status; | |
932 | + t_status = nppiEncodeHuffmanSpecInitAlloc_JPEG(pHuffmanDCTables[0].aCodes, nppiDCTable, &apHuffmanDCTable[0]); | |
933 | + t_status = nppiEncodeHuffmanSpecInitAlloc_JPEG(pHuffmanACTables[0].aCodes, nppiACTable, &apHuffmanACTable[0]); | |
934 | + t_status = nppiEncodeHuffmanSpecInitAlloc_JPEG(pHuffmanDCTables[1].aCodes, nppiDCTable, &apHuffmanDCTable[1]); | |
935 | + t_status = nppiEncodeHuffmanSpecInitAlloc_JPEG(pHuffmanACTables[1].aCodes, nppiACTable, &apHuffmanACTable[1]); | |
936 | + t_status = nppiEncodeHuffmanSpecInitAlloc_JPEG(pHuffmanDCTables[1].aCodes, nppiDCTable, &apHuffmanDCTable[2]); | |
937 | + t_status = nppiEncodeHuffmanSpecInitAlloc_JPEG(pHuffmanACTables[1].aCodes, nppiACTable, &apHuffmanACTable[2]); | |
938 | + | |
939 | + /** | |
940 | + * Huffman Encoding of the JPEG Encoding. | |
941 | + * Input is expected to be 64x1 macro blocks and output is expected as byte stuffed huffman encoded JPEG scan. | |
942 | + */ | |
943 | + Npp32s nSs = 0; | |
944 | + Npp32s nSe = 63; | |
945 | + Npp32s nH = 0; | |
946 | + Npp32s nL = 0; | |
947 | + //LOG_INFO("NPP_CHECK_CUDA:%d",8); | |
948 | + if (NPP_SUCCESS != (nppiEncodeHuffmanScan_JPEG_8u16s_P3R(apdDCT, aDCTStep, | |
949 | + 0, nSs, nSe, nH, nL, | |
950 | + pdScan, &nScanLength, | |
951 | + apHuffmanDCTable, | |
952 | + apHuffmanACTable, | |
953 | + aSrcSize, | |
954 | + pJpegEncoderTemp))) | |
955 | + { | |
956 | + printf("nppiEncodeHuffmanScan_JPEG_8u16s_P3R Failed!\n"); | |
957 | + return EXIT_FAILURE; | |
958 | + } | |
959 | + | |
960 | + for (int i = 0; i < 3; ++i) | |
961 | + { | |
962 | + nppiEncodeHuffmanSpecFree_JPEG(apHuffmanDCTable[i]); | |
963 | + nppiEncodeHuffmanSpecFree_JPEG(apHuffmanACTable[i]); | |
964 | + } | |
965 | + // Write JPEG | |
966 | + pDstJpeg = new unsigned char[4 << 20]{}; | |
967 | + pDstOutput = pDstJpeg; | |
968 | + | |
969 | + writeMarker(0x0D8, pDstOutput); | |
970 | + writeJFIFTag(pDstOutput); | |
971 | + writeQuantizationTable(aQuantizationTables[0], pDstOutput); | |
972 | + writeQuantizationTable(aQuantizationTables[1], pDstOutput); | |
973 | + writeHuffmanTable(pHuffmanDCTables[0], pDstOutput); | |
974 | + writeHuffmanTable(pHuffmanACTables[0], pDstOutput); | |
975 | + writeHuffmanTable(pHuffmanDCTables[1], pDstOutput); | |
976 | + writeHuffmanTable(pHuffmanACTables[1], pDstOutput); | |
977 | + writeFrameHeader(oFrameHeader, pDstOutput); | |
978 | + writeScanHeader(oScanHeader, pDstOutput); | |
979 | + | |
980 | + //LOG_INFO("NPP_CHECK_CUDA:%d",9); | |
981 | + NPP_CHECK_CUDA(cudaMemcpy(pDstOutput, pdScan, nScanLength, cudaMemcpyDeviceToHost)); | |
982 | + | |
983 | + pDstOutput += nScanLength; | |
984 | + writeMarker(0x0D9, pDstOutput); | |
985 | + | |
986 | + { | |
987 | + // Write result to file. | |
988 | + std::ofstream outputFile(szOutputFile, ios::out | ios::binary); | |
989 | + outputFile.write(reinterpret_cast<const char *>(pDstJpeg), static_cast<int>(pDstOutput - pDstJpeg)); | |
990 | + } | |
991 | + | |
992 | + // Cleanup | |
993 | + cudaFree(pJpegEncoderTemp); | |
994 | + delete[] pDstJpeg; | |
995 | + for (int i = 0; i < 3; ++i) | |
996 | + { | |
997 | + cudaFree(apdDCT[i]); | |
998 | + cudaFree(apSrcImage[i]); | |
999 | + } | |
1000 | + | |
1001 | + return EXIT_SUCCESS; | |
1002 | +} | |
1003 | + | |
1004 | + | |
1005 | +int jpegNPP(const char *szOutputFile, unsigned char* d_srcRGB, int img_width, int img_height) | |
1006 | +{ | |
1007 | + NppiSize aSrcSize[3]; | |
1008 | + Npp16s *apdDCT[3] = { 0, 0, 0 }; | |
1009 | + Npp32s aDCTStep[3]; | |
1010 | + | |
1011 | + Npp8u *apSrcImage[3] = { 0, 0, 0 }; | |
1012 | + Npp32s aSrcImageStep[3]; | |
1013 | + size_t aSrcPitch[3]; | |
1014 | + | |
1015 | + | |
1016 | + //????帧头 | |
1017 | + oFrameHeader.nWidth = img_width; | |
1018 | + oFrameHeader.nHeight = img_height; | |
1019 | + | |
1020 | + for (int i = 0; i < oFrameHeader.nComponents; ++i) | |
1021 | + { | |
1022 | + NppiSize oBlocks; | |
1023 | + NppiSize oBlocksPerMCU = { oFrameHeader.aSamplingFactors[i] >> 4, oFrameHeader.aSamplingFactors[i] & 0x0f }; | |
1024 | + | |
1025 | + oBlocks.width = (int)ceil((oFrameHeader.nWidth + 7) / 8 * | |
1026 | + static_cast<float>(oBlocksPerMCU.width) / nMCUBlocksH); | |
1027 | + oBlocks.width = DivUp(oBlocks.width, oBlocksPerMCU.width) * oBlocksPerMCU.width; | |
1028 | + | |
1029 | + oBlocks.height = (int)ceil((oFrameHeader.nHeight + 7) / 8 * | |
1030 | + static_cast<float>(oBlocksPerMCU.height) / nMCUBlocksV); | |
1031 | + oBlocks.height = DivUp(oBlocks.height, oBlocksPerMCU.height) * oBlocksPerMCU.height; | |
1032 | + | |
1033 | + aSrcSize[i].width = oBlocks.width * 8; | |
1034 | + aSrcSize[i].height = oBlocks.height * 8; | |
1035 | + | |
1036 | + // Allocate Memory | |
1037 | + size_t nPitch; | |
1038 | + //LOG_INFO("NPP_CHECK_CUDA:%d",1); | |
1039 | + NPP_CHECK_CUDA(cudaMallocPitch(&apdDCT[i], &nPitch, oBlocks.width * 64 * sizeof(Npp16s), oBlocks.height)); | |
1040 | + aDCTStep[i] = static_cast<Npp32s>(nPitch); | |
1041 | + | |
1042 | + //LOG_INFO("NPP_CHECK_CUDA:%d",2); | |
1043 | + NPP_CHECK_CUDA(cudaMallocPitch(&apSrcImage[i], &nPitch, aSrcSize[i].width, aSrcSize[i].height)); | |
1044 | + | |
1045 | + aSrcPitch[i] = nPitch; | |
1046 | + aSrcImageStep[i] = static_cast<Npp32s>(nPitch); | |
1047 | + } | |
1048 | + | |
1049 | + //RGB2YUV | |
1050 | + cudaError_t cudaStatus; | |
1051 | + cudaStatus = cuda_common::RGB2YUV(d_srcRGB, img_width, img_height, | |
1052 | + apSrcImage[0], aSrcPitch[0], aSrcSize[0].width, aSrcSize[0].height, | |
1053 | + apSrcImage[1], aSrcPitch[1], aSrcSize[1].width, aSrcSize[1].height, | |
1054 | + apSrcImage[2], aSrcPitch[2], aSrcSize[2].width, aSrcSize[2].height); | |
1055 | + | |
1056 | + /** | |
1057 | + * Forward DCT, quantization and level shift part of the JPEG encoding. | |
1058 | + * Input is expected in 8x8 macro blocks and output is expected to be in 64x1 | |
1059 | + * macro blocks. The new version of the primitive takes the ROI in image pixel size and | |
1060 | + * works with DCT coefficients that are in zig-zag order. | |
1061 | + */ | |
1062 | + int k = 0; | |
1063 | + //LOG_INFO("NPP_CHECK_CUDA:%d",3); | |
1064 | + if (NPP_SUCCESS != (nppiDCTQuantFwd8x8LS_JPEG_8u16s_C1R_NEW(apSrcImage[0], aSrcImageStep[0], | |
1065 | + apdDCT[0], aDCTStep[0], | |
1066 | + pdQuantizationTables + k * 64, | |
1067 | + aSrcSize[0], | |
1068 | + pDCTState))) | |
1069 | + { | |
1070 | + printf("nppiDCTQuantFwd8x8LS_JPEG_8u16s_C1R_NEW Failed!\n"); | |
1071 | + return EXIT_FAILURE; | |
1072 | + } | |
1073 | + k = 1; | |
1074 | + | |
1075 | + //LOG_INFO("NPP_CHECK_CUDA:%d",4); | |
1076 | + if (NPP_SUCCESS != (nppiDCTQuantFwd8x8LS_JPEG_8u16s_C1R_NEW(apSrcImage[1], aSrcImageStep[1], | |
1077 | + apdDCT[1], aDCTStep[1], | |
1078 | + pdQuantizationTables + k * 64, | |
1079 | + aSrcSize[1], | |
1080 | + pDCTState))) | |
1081 | + { | |
1082 | + printf("nppiDCTQuantFwd8x8LS_JPEG_8u16s_C1R_NEW Failed!\n"); | |
1083 | + return EXIT_FAILURE; | |
1084 | + } | |
1085 | + | |
1086 | + //LOG_INFO("NPP_CHECK_CUDA:%d",5); | |
1087 | + if (NPP_SUCCESS != (nppiDCTQuantFwd8x8LS_JPEG_8u16s_C1R_NEW(apSrcImage[2], aSrcImageStep[2], | |
1088 | + apdDCT[2], aDCTStep[2], | |
1089 | + pdQuantizationTables + k * 64, | |
1090 | + aSrcSize[2], | |
1091 | + pDCTState))) | |
1092 | + { | |
1093 | + printf("nppiDCTQuantFwd8x8LS_JPEG_8u16s_C1R_NEW Failed!\n"); | |
1094 | + return EXIT_FAILURE; | |
1095 | + } | |
1096 | + | |
1097 | + // Huffman Encoding | |
1098 | + | |
1099 | + Npp32s nScanLength; | |
1100 | + Npp8u *pJpegEncoderTemp; | |
1101 | + | |
1102 | +#if (CUDA_VERSION == 8000) | |
1103 | + Npp32s nTempSize; //when using CUDA8 | |
1104 | +#else | |
1105 | + size_t nTempSize; //when using CUDA9 | |
1106 | +#endif | |
1107 | + //modified by Junlin 190221 | |
1108 | + | |
1109 | + //LOG_INFO("NPP_CHECK_CUDA:%d",6); | |
1110 | + if (NPP_SUCCESS != (nppiEncodeHuffmanGetSize(aSrcSize[0], 3, &nTempSize))) | |
1111 | + { | |
1112 | + printf("nppiEncodeHuffmanGetSize Failed!\n"); | |
1113 | + return EXIT_FAILURE; | |
1114 | + } | |
1115 | + | |
1116 | + //LOG_INFO("NPP_CHECK_CUDA:%d",7); | |
1117 | + NPP_CHECK_CUDA(cudaMalloc(&pJpegEncoderTemp, nTempSize)); | |
1118 | + | |
1119 | + /** | |
1120 | + * Allocates memory and creates a Huffman table in a format that is suitable for the encoder. | |
1121 | + */ | |
1122 | + NppStatus t_status; | |
1123 | + t_status = nppiEncodeHuffmanSpecInitAlloc_JPEG(pHuffmanDCTables[0].aCodes, nppiDCTable, &apHuffmanDCTable[0]); | |
1124 | + t_status = nppiEncodeHuffmanSpecInitAlloc_JPEG(pHuffmanACTables[0].aCodes, nppiACTable, &apHuffmanACTable[0]); | |
1125 | + t_status = nppiEncodeHuffmanSpecInitAlloc_JPEG(pHuffmanDCTables[1].aCodes, nppiDCTable, &apHuffmanDCTable[1]); | |
1126 | + t_status = nppiEncodeHuffmanSpecInitAlloc_JPEG(pHuffmanACTables[1].aCodes, nppiACTable, &apHuffmanACTable[1]); | |
1127 | + t_status = nppiEncodeHuffmanSpecInitAlloc_JPEG(pHuffmanDCTables[1].aCodes, nppiDCTable, &apHuffmanDCTable[2]); | |
1128 | + t_status = nppiEncodeHuffmanSpecInitAlloc_JPEG(pHuffmanACTables[1].aCodes, nppiACTable, &apHuffmanACTable[2]); | |
1129 | + | |
1130 | + /** | |
1131 | + * Huffman Encoding of the JPEG Encoding. | |
1132 | + * Input is expected to be 64x1 macro blocks and output is expected as byte stuffed huffman encoded JPEG scan. | |
1133 | + */ | |
1134 | + Npp32s nSs = 0; | |
1135 | + Npp32s nSe = 63; | |
1136 | + Npp32s nH = 0; | |
1137 | + Npp32s nL = 0; | |
1138 | + //LOG_INFO("NPP_CHECK_CUDA:%d",8); | |
1139 | + if (NPP_SUCCESS != (nppiEncodeHuffmanScan_JPEG_8u16s_P3R(apdDCT, aDCTStep, | |
1140 | + 0, nSs, nSe, nH, nL, | |
1141 | + pdScan, &nScanLength, | |
1142 | + apHuffmanDCTable, | |
1143 | + apHuffmanACTable, | |
1144 | + aSrcSize, | |
1145 | + pJpegEncoderTemp))) | |
1146 | + { | |
1147 | + printf("nppiEncodeHuffmanScan_JPEG_8u16s_P3R Failed!\n"); | |
1148 | + return EXIT_FAILURE; | |
1149 | + } | |
1150 | + | |
1151 | + for (int i = 0; i < 3; ++i) | |
1152 | + { | |
1153 | + nppiEncodeHuffmanSpecFree_JPEG(apHuffmanDCTable[i]); | |
1154 | + nppiEncodeHuffmanSpecFree_JPEG(apHuffmanACTable[i]); | |
1155 | + } | |
1156 | + // Write JPEG | |
1157 | + pDstJpeg = new unsigned char[4 << 20]{}; | |
1158 | + pDstOutput = pDstJpeg; | |
1159 | + | |
1160 | + writeMarker(0x0D8, pDstOutput); | |
1161 | + writeJFIFTag(pDstOutput); | |
1162 | + writeQuantizationTable(aQuantizationTables[0], pDstOutput); | |
1163 | + writeQuantizationTable(aQuantizationTables[1], pDstOutput); | |
1164 | + writeHuffmanTable(pHuffmanDCTables[0], pDstOutput); | |
1165 | + writeHuffmanTable(pHuffmanACTables[0], pDstOutput); | |
1166 | + writeHuffmanTable(pHuffmanDCTables[1], pDstOutput); | |
1167 | + writeHuffmanTable(pHuffmanACTables[1], pDstOutput); | |
1168 | + writeFrameHeader(oFrameHeader, pDstOutput); | |
1169 | + writeScanHeader(oScanHeader, pDstOutput); | |
1170 | + | |
1171 | + //LOG_INFO("NPP_CHECK_CUDA:%d",9); | |
1172 | + NPP_CHECK_CUDA(cudaMemcpy(pDstOutput, pdScan, nScanLength, cudaMemcpyDeviceToHost)); | |
1173 | + | |
1174 | + pDstOutput += nScanLength; | |
1175 | + writeMarker(0x0D9, pDstOutput); | |
1176 | + | |
1177 | + { | |
1178 | + // Write result to file. | |
1179 | + std::ofstream outputFile(szOutputFile, ios::out | ios::binary); | |
1180 | + outputFile.write(reinterpret_cast<const char *>(pDstJpeg), static_cast<int>(pDstOutput - pDstJpeg)); | |
1181 | + } | |
1182 | + | |
1183 | + // Cleanup | |
1184 | + cudaFree(pJpegEncoderTemp); | |
1185 | + delete[] pDstJpeg; | |
1186 | + for (int i = 0; i < 3; ++i) | |
1187 | + { | |
1188 | + cudaFree(apdDCT[i]); | |
1189 | + cudaFree(apSrcImage[i]); | |
1190 | + } | |
1191 | + | |
1192 | + return EXIT_SUCCESS; | |
1193 | +} | ... | ... |
src/main.cpp
... | ... | @@ -10,8 +10,6 @@ |
10 | 10 | |
11 | 11 | #include <chrono> |
12 | 12 | |
13 | - | |
14 | - | |
15 | 13 | #include <unistd.h> |
16 | 14 | |
17 | 15 | |
... | ... | @@ -24,6 +22,7 @@ |
24 | 22 | #include "arpa/inet.h" |
25 | 23 | #endif |
26 | 24 | |
25 | +#include "utiltools.hpp" | |
27 | 26 | |
28 | 27 | #define MIN_RTP_PORT 10000 |
29 | 28 | #define MAX_RTP_PORT 60000 |
... | ... | @@ -88,7 +87,7 @@ int sum2 = 0; |
88 | 87 | |
89 | 88 | cudaStream_t stream[2]; |
90 | 89 | |
91 | -string data_home = "/data/tongtu/"; | |
90 | +string data_home = "/mnt/data/cmhu/tmp/"; | |
92 | 91 | |
93 | 92 | |
94 | 93 | #define checkCudaErrors(S) do {CUresult status; \ |
... | ... | @@ -183,7 +182,7 @@ void postDecoded(const void * userPtr, AVFrame * gpuFrame){ |
183 | 182 | cudaError_t cudaStatus; |
184 | 183 | if(pHwRgb[0] == nullptr){ |
185 | 184 | // cudaStreamCreate(&stream[0]); |
186 | - cuda_common::setColorSpace( ITU709, 0 ); | |
185 | + cuda_common::setColorSpace( ITU_709, 0 ); | |
187 | 186 | cudaStatus = cudaMalloc((void **)&pHwRgb[0], 3 * gpuFrame->width * gpuFrame->height * sizeof(unsigned char)); |
188 | 187 | } |
189 | 188 | cudaStatus = cuda_common::CUDAToBGR((CUdeviceptr)gpuFrame->data[0],(CUdeviceptr)gpuFrame->data[1], gpuFrame->linesize[0], gpuFrame->linesize[1], pHwRgb[0], gpuFrame->width, gpuFrame->height); |
... | ... | @@ -208,7 +207,7 @@ void postDecoded(const void * userPtr, AVFrame * gpuFrame){ |
208 | 207 | cudaError_t cudaStatus; |
209 | 208 | if(pHwRgb[1] == nullptr){ |
210 | 209 | // cudaStreamCreate(&stream[1]); |
211 | - cuda_common::setColorSpace( ITU709, 0 ); | |
210 | + cuda_common::setColorSpace( ITU_709, 0 ); | |
212 | 211 | cudaStatus = cudaMalloc((void **)&pHwRgb[1], 3 * gpuFrame->width * gpuFrame->height * sizeof(unsigned char)); |
213 | 212 | } |
214 | 213 | cudaStatus = cuda_common::CUDAToBGR((CUdeviceptr)gpuFrame->data[0],(CUdeviceptr)gpuFrame->data[1], gpuFrame->linesize[0], gpuFrame->linesize[1], pHwRgb[1], gpuFrame->width, gpuFrame->height); |
... | ... | @@ -231,13 +230,6 @@ bool count_flag = false; |
231 | 230 | int count = 0; |
232 | 231 | int count_std = 100; |
233 | 232 | |
234 | -static long long get_cur_time(){ | |
235 | - // 获取操作系统当前时间点(精确到ms) | |
236 | - chrono::time_point<chrono::system_clock, chrono::milliseconds> tpMicro | |
237 | - = chrono::time_point_cast<chrono::milliseconds>(chrono::system_clock::now()); | |
238 | - | |
239 | - return tpMicro.time_since_epoch().count(); | |
240 | -} | |
241 | 233 | |
242 | 234 | static int sum = 0; |
243 | 235 | unsigned char *pHwData = nullptr; |
... | ... | @@ -255,13 +247,13 @@ void postDecoded0(const void * userPtr, AVFrame * gpuFrame){ |
255 | 247 | { |
256 | 248 | count_flag = true; |
257 | 249 | count = 0; |
258 | - end_time = start_time = get_cur_time(); | |
250 | + end_time = start_time = UtilTools::get_cur_time_ms(); | |
259 | 251 | } |
260 | 252 | count++; |
261 | 253 | sum ++ ; |
262 | 254 | if (count >= count_std) |
263 | 255 | { |
264 | - // end_time = get_cur_time(); | |
256 | + // end_time = UtilTools::get_cur_time_ms(); | |
265 | 257 | // long time_using = end_time - start_time; |
266 | 258 | // double time_per_frame = double(time_using)/count_std ; |
267 | 259 | // cout << count_std << "帧用时:" << time_using << "ms 每帧用时:" << time_per_frame << "ms" << endl; |
... | ... | @@ -278,7 +270,7 @@ void postDecoded0(const void * userPtr, AVFrame * gpuFrame){ |
278 | 270 | // cout << "gpu id : " << decoder->m_cfg.gpuid.c_str() << endl; |
279 | 271 | cudaError_t cudaStatus; |
280 | 272 | if(pHwData == nullptr){ |
281 | - cuda_common::setColorSpace( ITU709, 0 ); | |
273 | + cuda_common::setColorSpace( ITU_709, 0 ); | |
282 | 274 | cudaStatus = cudaMalloc((void **)&pHwData, 3 * gpuFrame->width * gpuFrame->height * sizeof(unsigned char)); |
283 | 275 | } |
284 | 276 | cudaStatus = cuda_common::CUDAToBGR((CUdeviceptr)gpuFrame->data[0],(CUdeviceptr)gpuFrame->data[1], gpuFrame->linesize[0], gpuFrame->linesize[1], pHwData, gpuFrame->width, gpuFrame->height); |
... | ... | @@ -296,10 +288,10 @@ void postDecoded0(const void * userPtr, AVFrame * gpuFrame){ |
296 | 288 | } |
297 | 289 | |
298 | 290 | void decode_finished_cbk(const void* userPtr){ |
299 | - cout << "当前时间戳: " << get_cur_time() << endl; | |
291 | + cout << "当前时间戳: " << UtilTools::get_cur_time_ms() << endl; | |
300 | 292 | } |
301 | 293 | |
302 | -bool decode_request_stream_cbk(){ | |
294 | +bool decode_request_stream_cbk(const char* deviceId){ | |
303 | 295 | cout << "需在此请求流" << endl; |
304 | 296 | return true; |
305 | 297 | } |
... | ... | @@ -374,7 +366,7 @@ void logFF(void *, int level, const char *fmt, va_list ap) |
374 | 366 | |
375 | 367 | int main(int argc, char* argv[]){ |
376 | 368 | |
377 | - test_uri = argv[1]; | |
369 | + test_uri = "rtsp://admin:admin@123456@192.168.60.176:554/cam/realmonitor?channel=1&subtype=0";//argv[1]; | |
378 | 370 | char* gpuid = argv[2]; |
379 | 371 | int port = atoi(argv[3]); |
380 | 372 | cout << test_uri << " gpu_id:" << gpuid << " port:" << port << endl; |
... | ... | @@ -393,7 +385,7 @@ int main(int argc, char* argv[]){ |
393 | 385 | std::this_thread::sleep_for(std::chrono::minutes(1)); |
394 | 386 | FFNvDecoderManager* pDecManager = FFNvDecoderManager::getInstance(); |
395 | 387 | int count = pDecManager->count(); |
396 | - cout << "当前时间:" << get_cur_time() << " 当前运行路数: " << pDecManager->count() << endl; | |
388 | + cout << "当前时间:" << UtilTools::get_cur_time_ms() << " 当前运行路数: " << pDecManager->count() << endl; | |
397 | 389 | } |
398 | 390 | |
399 | 391 | return (void*)0; | ... | ... |
src/utiltools.hpp
0 → 100644
1 | +#ifndef _UTIL_TOOLS_HPP_ | |
2 | +#define _UTIL_TOOLS_HPP_ | |
3 | + | |
4 | +#include<chrono> | |
5 | + | |
6 | +using namespace std; | |
7 | + | |
8 | +namespace UtilTools{ | |
9 | + | |
10 | + static long get_cur_time_ms() { | |
11 | + chrono::time_point<chrono::system_clock, chrono::milliseconds> tpMicro | |
12 | + = chrono::time_point_cast<chrono::milliseconds>(chrono::system_clock::now()); | |
13 | + return tpMicro.time_since_epoch().count(); | |
14 | + } | |
15 | + | |
16 | +} | |
17 | + | |
18 | +#endif | |
0 | 19 | \ No newline at end of file | ... | ... |