6
6
#include <drm/imx-ipu-v3-ioctls.h>
7
7
#include <png.h>
8
8
9
-
9
+ // default width/height of input files
10
10
#define WIDTH 640
11
11
#define HEIGHT 360
12
12
13
+ // png creation helper functions
13
14
#include "ipukms_png.c"
14
15
16
+ // structure to hold DRM framebuffer information
15
17
struct csc_bo {
16
18
uint32_t handle ;
17
19
uint32_t size ;
@@ -21,6 +23,7 @@ struct csc_bo {
21
23
uint32_t pitch ;
22
24
};
23
25
26
+ // framebuffer creation function
24
27
struct csc_bo * csc_bo_create (int fd ,
25
28
const unsigned width , const unsigned height ,
26
29
const unsigned bpp )
@@ -54,6 +57,7 @@ struct csc_bo *csc_bo_create(int fd,
54
57
return NULL ;
55
58
}
56
59
60
+ // framebuffer userspace mapping function
57
61
static int csc_bo_map (int fd , struct csc_bo * bo )
58
62
{
59
63
struct drm_mode_map_dumb arg ;
@@ -81,6 +85,7 @@ static int csc_bo_map(int fd, struct csc_bo *bo)
81
85
return 0 ;
82
86
}
83
87
88
+ // framebuffer destruction function
84
89
static int csc_bo_destroy (int fd , struct csc_bo * bo )
85
90
{
86
91
struct drm_mode_destroy_dumb arg ;
@@ -101,38 +106,44 @@ static int csc_bo_destroy(int fd, struct csc_bo *bo)
101
106
return 0 ;
102
107
}
103
108
109
+ // main function
104
110
int main (void )
105
111
{
106
112
struct csc_bo * input_bo ;
107
113
struct csc_bo * output_bo ;
108
114
int ret , fd ;
109
115
110
- if ((fd = drmOpen ("imx-drm" , NULL )) < 0 ) {
116
+ // open DRM device
117
+ if ((fd = drmOpen ("imx-drm" , "platform:imx-drm:00" )) < 0 ) {
111
118
printf ("drmOpen failed.\n" );
112
119
return -1 ;
113
120
}
114
121
115
- //create buffer for csc in/out
122
+ // create buffer for csc input
116
123
input_bo = csc_bo_create (fd , WIDTH , HEIGHT , 32 );
117
124
if (!input_bo ) {
118
125
printf ("Couldn't create input gem bo\n" );
119
126
return -1 ;
120
127
}
128
+
129
+ // map the input buffer
121
130
if (csc_bo_map (fd , input_bo )) {
122
131
printf ("Couldn't map input bo\n" );
123
132
return -1 ;
124
133
}
125
134
135
+ // create buffer for csc output
126
136
output_bo = csc_bo_create (fd , WIDTH , HEIGHT , 32 );
127
137
if (!output_bo ) {
128
138
printf ("Couldn't create output gem bo\n" );
129
139
return -1 ;
130
140
}
131
141
142
+ // create ipu csc request
132
143
struct drm_imx_ipu_queue req = {
133
144
.task = IPU_TASK_CSC ,
134
145
.input = {
135
- .phys = input_bo -> phys , //id of gem_cma object
146
+ .phys = input_bo -> phys ,
136
147
.pix = {
137
148
.pixelformat = V4L2_PIX_FMT_UYVY ,
138
149
.bytesperline = 2 * WIDTH ,
@@ -145,12 +156,10 @@ int main(void)
145
156
},
146
157
},
147
158
.output = {
148
- .phys = output_bo -> phys , //id of gem_cma object
159
+ .phys = output_bo -> phys ,
149
160
.pix = {
150
161
.pixelformat = V4L2_PIX_FMT_RGB32 ,
151
162
.bytesperline = 4 * WIDTH ,
152
- //.pixelformat = V4L2_PIX_FMT_YUV420,
153
- //.bytesperline = 1 * WIDTH,
154
163
.width = WIDTH ,
155
164
.height = HEIGHT ,
156
165
},
@@ -159,58 +168,82 @@ int main(void)
159
168
.height = HEIGHT ,
160
169
},
161
170
},
162
- #if 0
163
- .csc_coeffs [4 ][3 ] = {
164
- {149 , 0 , 0 }, /* C00, C01, C02 */
165
- {149 , 0 , 0 }, /* C10, C11, C12 */
166
- {149 , 0 , 0 }, /* C20, C21, C22 */
167
- {0 , 0 , 0 }, /* A0, A1, A2 */
168
- },
169
- #endif
170
171
};
172
+
173
+ // color-space conversion (csc) coefficient matrix values
171
174
uint32_t * c0 , * c1 , * c2 , * a0 ;
172
- c0 = calloc (3 , sizeof (uint32_t ));
175
+
176
+ /* i.MX6 Reference Manual (Chapter 36: Table 36-18)
177
+ * Z0 = X0*C00 + X1*C01 +X2*C02+A0;
178
+ * Z1 = X0*C10 + X1*C11 +X2*C12+A1;
179
+ * Z2 = X0*C20 + X1*C21 +X2*C22+A2;
180
+ *
181
+ * Where c0[0] == C00, c0[1] == C01, c0[2] == C02
182
+ */
183
+
184
+ // allocate csc coefficients for kernel task
185
+ c0 = calloc (3 , sizeof (uint32_t ));
173
186
c1 = calloc (3 , sizeof (uint32_t ));
174
187
c2 = calloc (3 , sizeof (uint32_t ));
175
188
a0 = calloc (3 , sizeof (uint32_t ));
176
189
177
- printf ("%p %p %p %p\n" , c0 , c1 , c2 , a0 );
178
-
179
- c0 [0 ] = 149 ;
180
- c1 [0 ] = 149 ;
181
- c2 [0 ] = 149 ;
182
-
190
+ // converting grayscale to RGB32 R = G = B = Y (dropping chroma)
191
+ // Z0 = R = X0 * C00
192
+ // Z1 = G = X0 * C10
193
+ // Z2 = B = X0 * C20
194
+ //
195
+ // C00, C10, C20 = 0.99
196
+ c0 [0 ] = 255 ;
197
+ c1 [0 ] = 255 ;
198
+ c2 [0 ] = 255 ;
199
+
200
+ // set coefficients for kernel ioctl request
183
201
req .csc_coeffs [0 ] = c0 ;
184
202
req .csc_coeffs [1 ] = c1 ;
185
203
req .csc_coeffs [2 ] = c2 ;
186
204
req .csc_coeffs [3 ] = a0 ;
187
205
188
- /* Open YUV420P sample file */
206
+ // open grayscale sample input file
189
207
FILE * fp = fopen ("output.gray" , "r" );
190
- srand (time (NULL ));
191
- //fseek(fp, WIDTH*HEIGHT*3/2*(rand()%87), 0);
208
+
209
+ // another version using a larger sample
210
+ // FILE *fp = fopen("BigBuckBunny_640x360_small.yuv", "r");
211
+ // srand(time(NULL));
212
+ // fseek(fp, WIDTH*HEIGHT*3/2*(rand()%87), 0);
213
+
214
+ // read input into input framebuffer
192
215
fread (input_bo -> ptr , 1 , WIDTH * HEIGHT * 2 , fp );
216
+
217
+ // close read file
193
218
fclose (fp );
194
219
195
- //convert to YUV420
220
+ // convert to input framebuffer RGB32
196
221
if (drmCommandWriteRead (fd , DRM_IMX_IPU_QUEUE , & req , sizeof (req ))) {
197
222
printf ("drmCommandWriteRead failed. [%s]. (%d)\n" , strerror (errno ), sizeof (req ));
198
223
return - errno ;
199
224
}
200
225
226
+ // map the output framebuffer to userspace
201
227
if (csc_bo_map (fd , output_bo )) {
202
228
printf ("Couldn't map output bo\n" );
203
229
return -1 ;
204
230
}
205
231
206
- //let's see it!
232
+ // let's see it!
233
+ // save output framebuffer to png (png only supports rgb24)
234
+
235
+ // allocate the rgb24 output array
207
236
char * rgb_matrix = (char * ) malloc (WIDTH * HEIGHT * 3 );
208
237
const char * rgb = (const char * )output_bo -> ptr ;
209
238
210
- //rgba565_to_rgb888(rgb, rgb_matrix, WIDTH*HEIGHT);
239
+ // convert rgb32 to rgb24 using helper function
211
240
rgba8888_to_rgb888 (rgb , rgb_matrix , WIDTH * HEIGHT );
212
241
242
+ // save output png using helper function
213
243
save_png ("output.png" , rgb_matrix , WIDTH , HEIGHT );
244
+
245
+ // free the allocated rgb24 matrix
214
246
free (rgb_matrix );
247
+
215
248
return 0 ;
216
249
}
0 commit comments