Skip to content

Commit b2a0352

Browse files
ArcaneNibblemarcan
authored andcommitted
jpeg: Implement encoding from planar formats
Signed-off-by: R <[email protected]>
1 parent f2b8054 commit b2a0352

2 files changed

Lines changed: 158 additions & 28 deletions

File tree

proxyclient/experiments/jpeg.py

Lines changed: 157 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -225,51 +225,110 @@ def rgb2yuv(r, g, b):
225225
'RGB565',
226226
'YUV10',
227227
'YUV-linear',
228+
'YUV444-planar',
229+
'YUV422-planar',
230+
'YUV420-planar',
228231
]
229232
pixfmt = args.encode_pixelfmt
230233

234+
# Driver doesn't support this either
231235
if pixfmt == 'YUV-linear' and args.encode_subsampling == '444':
232-
# Driver doesn't support this either
236+
print("WARNING: This combination does not appear to work!!!")
237+
if pixfmt == 'YUV422-planar' and args.encode_subsampling == '444':
238+
print("WARNING: This combination does not appear to work!!!")
239+
if pixfmt == 'YUV420-planar' and args.encode_subsampling == '444':
233240
print("WARNING: This combination does not appear to work!!!")
234241

235242
image_data = b''
243+
image_data_P1 = b''
236244
with Image.open(args.input) as im:
237245
im_W, im_H = im.size
238246

239-
for y in range(im_H):
240-
for x in range(im_W):
241-
r, g, b = im.getpixel((x, y))
242-
if pixfmt == 'RGB888':
243-
image_data += struct.pack("BBBB", r, g, b, 255)
244-
elif pixfmt == 'RGB101010':
245-
image_data += struct.pack("<I", (r << 2) | (g << 12) | (b << 22))
246-
elif pixfmt == 'RGB565':
247-
image_data += struct.pack("<H", (r >> 3) | ((g >> 2) << 5) | ((b >> 3) << 11))
248-
elif pixfmt == 'YUV10':
249-
# absolute garbage color space conversion
250-
# for demonstration purposes only
251-
y_, u_, v_ = rgb2yuv(r, g, b)
252-
image_data += struct.pack("<I", (y_ << 2) | (u_ << 12) | (v_ << 22))
253-
elif pixfmt == 'YUV-linear':
247+
if pixfmt != 'YUV420-planar':
248+
for y in range(im_H):
249+
for x in range(im_W):
250+
r, g, b = im.getpixel((x, y))
251+
if pixfmt == 'RGB888':
252+
image_data += struct.pack("BBBB", r, g, b, 255)
253+
elif pixfmt == 'RGB101010':
254+
image_data += struct.pack("<I", (r << 2) | (g << 12) | (b << 22))
255+
elif pixfmt == 'RGB565':
256+
image_data += struct.pack("<H", (r >> 3) | ((g >> 2) << 5) | ((b >> 3) << 11))
257+
elif pixfmt == 'YUV10':
258+
# absolute garbage color space conversion
259+
# for demonstration purposes only
260+
y_, u_, v_ = rgb2yuv(r, g, b)
261+
image_data += struct.pack("<I", (y_ << 2) | (u_ << 12) | (v_ << 22))
262+
elif pixfmt == 'YUV-linear':
263+
# garbage color space conversion, garbage subsampling
264+
# for demonstration purposes only
265+
y_, u_, v_ = rgb2yuv(r, g, b)
266+
if x & 1 == 0:
267+
color = u_
268+
else:
269+
color = v_
270+
image_data += struct.pack("BB", y_, color)
271+
elif pixfmt == 'YUV444-planar':
272+
# garbage color space conversion
273+
# for demonstration purposes only
274+
y_, u_, v_ = rgb2yuv(r, g, b)
275+
image_data += struct.pack("B", y_)
276+
image_data_P1 += struct.pack("BB", u_, v_)
277+
elif pixfmt == 'YUV422-planar':
278+
# garbage color space conversion, garbage subsampling
279+
# for demonstration purposes only
280+
y_, u_, v_ = rgb2yuv(r, g, b)
281+
if x & 1 == 0:
282+
color = u_
283+
else:
284+
color = v_
285+
image_data += struct.pack("B", y_)
286+
image_data_P1 += struct.pack("B", color)
287+
else:
288+
assert False
289+
else:
290+
for y in range(im_H):
291+
for x in range(im_W):
292+
r, g, b = im.getpixel((x, y))
254293
# garbage color space conversion, garbage subsampling
255294
# for demonstration purposes only
256295
y_, u_, v_ = rgb2yuv(r, g, b)
257296
if x & 1 == 0:
258297
color = u_
259298
else:
260299
color = v_
261-
image_data += struct.pack("BB", y_, color)
262-
else:
263-
assert False
300+
image_data += struct.pack("B", y_)
301+
if y & 1 == 0:
302+
image_data_P1 += struct.pack("B", color)
264303

265304
if pixfmt in ['RGB888', 'RGB101010', 'YUV10']:
266305
BYTESPP = 4
306+
BYTESPP_P1 = 0
307+
P1_DIVH = 1
267308
elif pixfmt in ['RGB565', 'YUV-linear']:
268309
BYTESPP = 2
310+
BYTESPP_P1 = 0
311+
P1_DIVH = 1
312+
elif pixfmt == 'YUV444-planar':
313+
BYTESPP = 1
314+
BYTESPP_P1 = 2
315+
P1_DIVH = 1
316+
elif pixfmt == 'YUV422-planar':
317+
BYTESPP = 1
318+
BYTESPP_P1 = 1
319+
P1_DIVH = 1
320+
elif pixfmt == 'YUV420-planar':
321+
BYTESPP = 1
322+
BYTESPP_P1 = 1
323+
P1_DIVH = 2
269324
else:
270325
assert False
271326
surface_stride = im_W * BYTESPP
272327
surface_sz = surface_stride * im_H
328+
surface_P1_off = surface_sz
329+
print(f"Plane 1 offset at {surface_P1_off:08X}")
330+
surface_P1_stride = im_W * BYTESPP_P1
331+
surface_sz += surface_P1_stride * im_H // P1_DIVH
273332
input_mem_sz = align_up(surface_sz)
274333

275334
output_mem_sz = input_mem_sz
@@ -824,6 +883,7 @@ def set_default_regs(param1=0):
824883

825884
if args.encode:
826885
iface.writemem(input_buf_phys, image_data)
886+
iface.writemem(input_buf_phys + surface_P1_off, image_data_P1)
827887
print("Pixel data uploaded")
828888

829889
jpeg.MODE = 0x17f
@@ -842,11 +902,16 @@ def set_default_regs(param1=0):
842902
else:
843903
assert False
844904

845-
jpeg.PX_USE_PLANE1 = 0x0
905+
if BYTESPP_P1 != 0:
906+
jpeg.PX_USE_PLANE1 = 1
907+
jpeg.PX_PLANE1_WIDTH = im_W*BYTESPP_P1 - 1
908+
jpeg.PX_PLANE1_HEIGHT = im_H // P1_DIVH - 1
909+
else:
910+
jpeg.PX_USE_PLANE1 = 0
911+
jpeg.PX_PLANE1_WIDTH = 0xffffffff
912+
jpeg.PX_PLANE1_HEIGHT = 0xffffffff
846913
jpeg.PX_PLANE0_WIDTH = im_W*BYTESPP - 1
847914
jpeg.PX_PLANE0_HEIGHT = im_H - 1
848-
jpeg.PX_PLANE1_WIDTH = 0xffffffff
849-
jpeg.PX_PLANE1_HEIGHT = 0xffffffff
850915
jpeg.TIMEOUT = 266000000
851916

852917
jpeg.PX_TILES_W = divroundup(im_W, macroblock_W)
@@ -905,19 +970,81 @@ def set_default_regs(param1=0):
905970
jpeg.PX_PLANE1_TILING_V = 0
906971
else:
907972
assert False
973+
elif pixfmt == 'YUV444-planar':
974+
if args.encode_subsampling == '444' or args.encode_subsampling == '400':
975+
jpeg.PX_PLANE0_TILING_H = 1
976+
jpeg.PX_PLANE0_TILING_V = 8
977+
jpeg.PX_PLANE1_TILING_H = 2
978+
jpeg.PX_PLANE1_TILING_V = 8
979+
elif args.encode_subsampling == '422':
980+
jpeg.PX_PLANE0_TILING_H = 2
981+
jpeg.PX_PLANE0_TILING_V = 8
982+
jpeg.PX_PLANE1_TILING_H = 4
983+
jpeg.PX_PLANE1_TILING_V = 8
984+
elif args.encode_subsampling == '420':
985+
jpeg.PX_PLANE0_TILING_H = 2
986+
jpeg.PX_PLANE0_TILING_V = 16
987+
jpeg.PX_PLANE1_TILING_H = 4
988+
jpeg.PX_PLANE1_TILING_V = 16
989+
else:
990+
assert False
991+
elif pixfmt == 'YUV422-planar':
992+
if args.encode_subsampling == '444' or args.encode_subsampling == '400':
993+
jpeg.PX_PLANE0_TILING_H = 1
994+
jpeg.PX_PLANE0_TILING_V = 8
995+
jpeg.PX_PLANE1_TILING_H = 1
996+
jpeg.PX_PLANE1_TILING_V = 8
997+
elif args.encode_subsampling == '422':
998+
jpeg.PX_PLANE0_TILING_H = 2
999+
jpeg.PX_PLANE0_TILING_V = 8
1000+
jpeg.PX_PLANE1_TILING_H = 2
1001+
jpeg.PX_PLANE1_TILING_V = 8
1002+
elif args.encode_subsampling == '420':
1003+
jpeg.PX_PLANE0_TILING_H = 2
1004+
jpeg.PX_PLANE0_TILING_V = 16
1005+
jpeg.PX_PLANE1_TILING_H = 2
1006+
jpeg.PX_PLANE1_TILING_V = 16
1007+
else:
1008+
assert False
1009+
elif pixfmt == 'YUV420-planar':
1010+
if args.encode_subsampling == '444' or args.encode_subsampling == '400':
1011+
jpeg.PX_PLANE0_TILING_H = 1
1012+
jpeg.PX_PLANE0_TILING_V = 8
1013+
jpeg.PX_PLANE1_TILING_H = 1
1014+
jpeg.PX_PLANE1_TILING_V = 4
1015+
elif args.encode_subsampling == '422':
1016+
jpeg.PX_PLANE0_TILING_H = 2
1017+
jpeg.PX_PLANE0_TILING_V = 8
1018+
jpeg.PX_PLANE1_TILING_H = 2
1019+
jpeg.PX_PLANE1_TILING_V = 4
1020+
elif args.encode_subsampling == '420':
1021+
jpeg.PX_PLANE0_TILING_H = 2
1022+
jpeg.PX_PLANE0_TILING_V = 16
1023+
jpeg.PX_PLANE1_TILING_H = 2
1024+
jpeg.PX_PLANE1_TILING_V = 8
1025+
elif args.encode_subsampling == '411':
1026+
jpeg.PX_PLANE0_TILING_H = 4
1027+
jpeg.PX_PLANE0_TILING_V = 8
1028+
jpeg.PX_PLANE1_TILING_H = 4
1029+
jpeg.PX_PLANE1_TILING_V = 4
1030+
else:
1031+
assert False
9081032
else:
9091033
assert False
9101034
jpeg.PX_PLANE0_STRIDE = surface_stride
911-
jpeg.PX_PLANE1_STRIDE = 0
1035+
jpeg.PX_PLANE1_STRIDE = surface_P1_stride
9121036

913-
if pixfmt in ['RGB888', 'RGB101010', 'RGB565', 'YUV10']:
1037+
if pixfmt in ['RGB888', 'RGB101010', 'RGB565', 'YUV10', 'YUV444-planar']:
9141038
if args.encode_subsampling in ['422', '420']:
9151039
jpeg.CHROMA_HALVE_H_TYPE1 = 1
9161040
if args.encode_subsampling == '420':
9171041
jpeg.CHROMA_HALVE_V_TYPE1 = 1
918-
elif pixfmt in ['YUV-linear']:
1042+
elif pixfmt in ['YUV-linear', 'YUV422-planar']:
9191043
if args.encode_subsampling == '420':
9201044
jpeg.CHROMA_HALVE_V_TYPE1 = 1
1045+
elif pixfmt == 'YUV420-planar':
1046+
if args.encode_subsampling in ['422', '444']:
1047+
jpeg.CHROMA_DOUBLE_V = 1
9211048
else:
9221049
assert False
9231050

@@ -951,6 +1078,8 @@ def set_default_regs(param1=0):
9511078
jpeg.ENCODE_PIXEL_FORMAT.set(FORMAT=E_ENCODE_PIXEL_FORMAT.YUV10_linear)
9521079
elif pixfmt == 'YUV-linear':
9531080
jpeg.ENCODE_PIXEL_FORMAT.set(FORMAT=E_ENCODE_PIXEL_FORMAT.YUV_linear)
1081+
elif pixfmt in ['YUV444-planar', 'YUV422-planar', 'YUV420-planar']:
1082+
jpeg.ENCODE_PIXEL_FORMAT.set(FORMAT=E_ENCODE_PIXEL_FORMAT.YUV_planar)
9541083
else:
9551084
assert False
9561085
if pixfmt == 'YUV-linear':
@@ -960,12 +1089,12 @@ def set_default_regs(param1=0):
9601089
jpeg.ENCODE_COMPONENT3_POS = 2
9611090
else:
9621091
jpeg.ENCODE_COMPONENT0_POS = 0
963-
jpeg.ENCODE_COMPONENT1_POS = 1
964-
jpeg.ENCODE_COMPONENT2_POS = 2
1092+
jpeg.ENCODE_COMPONENT1_POS = 0
1093+
jpeg.ENCODE_COMPONENT2_POS = 1
9651094
jpeg.ENCODE_COMPONENT3_POS = 3
9661095

9671096
jpeg.INPUT_START1 = input_buf_iova
968-
jpeg.INPUT_START2 = 0xdeadbeef
1097+
jpeg.INPUT_START2 = input_buf_iova + surface_P1_off
9691098
jpeg.INPUT_END = input_buf_iova + input_mem_sz + 7 # NOTE +7
9701099
jpeg.OUTPUT_START1 = output_buf_iova
9711100
jpeg.OUTPUT_START2 = 0xdeadbeef

proxyclient/m1n1/hw/jpeg.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ class JPEGRegs(RegMap):
165165
# RGB565: R, G, B = 0/1/2 = low/mid/high bits
166166
# YUV10: Y, U, V = 0/1/2 = low/mid/high bits
167167
# YUV linear: Y0 Cb Cr Y1 = byte pos
168+
# YUV planar: Y U V = 0 for Y, 0/1 for U/V indicating position somehow
168169
ENCODE_COMPONENT0_POS = 0x104, Register32
169170
ENCODE_COMPONENT1_POS = 0x108, Register32
170171
ENCODE_COMPONENT2_POS = 0x10c, Register32

0 commit comments

Comments
 (0)