1 // Copyright (C) 2020 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "host-common/MediaCudaUtils.h"
16 #include <cstdint>
17 #include <string>
18 #include <vector>
19 #include "android/main-emugl.h"
20
21 #ifdef _WIN32
22 #define WIN32_LEAN_AND_MEAN 1
23 #include <windows.h>
24 #include <winioctl.h>
25 #endif
26
27 #include <stdio.h>
28 #include <string.h>
29
30 extern "C" {
31 #define INIT_CUDA_GL 1
32 #include "host-common/dynlink_cuda.h"
33 #include "host-common/dynlink_cudaGL.h"
34 #include "host-common/dynlink_nvcuvid.h"
35 }
36
37 #define MEDIA_CUVID_DEBUG 0
38
39 #if MEDIA_CUVID_DEBUG
40 #define CUVID_DPRINT(fmt, ...) \
41 fprintf(stderr, "cuvid-utils: %s:%d " fmt "\n", __func__, __LINE__, \
42 ##__VA_ARGS__);
43 #else
44 #define CUVID_DPRINT(fmt, ...)
45 #endif
46
47 #define NVDEC_API_CALL(cuvidAPI) \
48 do { \
49 CUresult errorCode = cuvidAPI; \
50 if (errorCode != CUDA_SUCCESS) { \
51 CUVID_DPRINT("%s failed with error code %d\n", #cuvidAPI, \
52 (int)errorCode); \
53 } \
54 } while (0)
55
56 extern "C" {
57
58 #define MEDIA_CUDA_COPY_Y_TEXTURE 1
59 #define MEDIA_CUDA_COPY_UV_TEXTURE 2
60
media_cuda_copy_decoded_frame(void * privData,int mode,uint32_t dest_texture_handle)61 static void media_cuda_copy_decoded_frame(void* privData,
62 int mode,
63 uint32_t dest_texture_handle) {
64 media_cuda_utils_copy_context* copy_context =
65 static_cast<media_cuda_utils_copy_context*>(privData);
66
67 const unsigned int GL_TEXTURE_2D = 0x0DE1;
68 const unsigned int cudaGraphicsMapFlagsNone = 0x0;
69 CUgraphicsResource CudaRes{0};
70 CUVID_DPRINT("cuda copy decoded frame testure %d",
71 (int)dest_texture_handle);
72 NVDEC_API_CALL(cuGraphicsGLRegisterImage(&CudaRes, dest_texture_handle,
73 GL_TEXTURE_2D, 0x0));
74 CUarray texture_ptr;
75 NVDEC_API_CALL(cuGraphicsMapResources(1, &CudaRes, 0));
76 NVDEC_API_CALL(
77 cuGraphicsSubResourceGetMappedArray(&texture_ptr, CudaRes, 0, 0));
78 CUdeviceptr dpSrcFrame = copy_context->src_frame;
79 CUDA_MEMCPY2D m = {0};
80 m.srcMemoryType = CU_MEMORYTYPE_DEVICE;
81 m.srcDevice = dpSrcFrame;
82 m.srcPitch = copy_context->src_pitch;
83 m.dstMemoryType = CU_MEMORYTYPE_ARRAY;
84 m.dstArray = texture_ptr;
85 m.dstPitch = copy_context->dest_width * 1;
86 m.WidthInBytes = copy_context->dest_width * 1;
87 m.Height = copy_context->dest_height;
88 CUVID_DPRINT("dstPitch %d, WidthInBytes %d Height %d surface-height %d",
89 (int)m.dstPitch, (int)m.WidthInBytes, (int)m.Height,
90 (int)copy_context->src_surface_height);
91
92 if (mode == MEDIA_CUDA_COPY_Y_TEXTURE) { // copy Y data
93 NVDEC_API_CALL(cuMemcpy2D(&m));
94 } else if (mode == MEDIA_CUDA_COPY_UV_TEXTURE) { // copy UV data
95 m.srcDevice =
96 (CUdeviceptr)((uint8_t*)dpSrcFrame +
97 m.srcPitch * copy_context->src_surface_height);
98 m.Height = m.Height / 2;
99 NVDEC_API_CALL(cuMemcpy2D(&m));
100 }
101 NVDEC_API_CALL(cuGraphicsUnmapResources(1, &CudaRes, 0));
102 NVDEC_API_CALL(cuGraphicsUnregisterResource(CudaRes));
103 }
104
media_cuda_utils_nv12_updater(void * privData,uint32_t type,uint32_t * textures,void * callerData)105 void media_cuda_utils_nv12_updater(void* privData,
106 uint32_t type,
107 uint32_t* textures,
108 void* callerData) {
109 constexpr uint32_t kFRAMEWORK_FORMAT_NV12 = 3;
110 if (type != kFRAMEWORK_FORMAT_NV12) {
111 return;
112 }
113 CUVID_DPRINT("copyiong Ytex %d", textures[0]);
114 CUVID_DPRINT("copyiong UVtex %d", textures[1]);
115 media_cuda_copy_decoded_frame(privData, MEDIA_CUDA_COPY_Y_TEXTURE,
116 textures[0]);
117 media_cuda_copy_decoded_frame(privData, MEDIA_CUDA_COPY_UV_TEXTURE,
118 textures[1]);
119 }
120
121 } // end extern C
122