na_mpeg2_decoder/
convert.rs1use crate::video::{Frame, PixelFormat};
2
3pub fn frame_to_rgba_bt601_limited(frame: &Frame, out_rgba: &mut [u8]) {
8 debug_assert_eq!(out_rgba.len(), frame.width * frame.height * 4);
9
10 match frame.format {
11 PixelFormat::Yuv420p | PixelFormat::Yuv422p | PixelFormat::Yuv444p => {}
12 }
13
14 let (cx, cy) = frame.chroma_shifts();
15 let w_uv = frame.width >> cx;
16
17 for y in 0..frame.height {
18 let y_row = &frame.data_y[y * frame.linesize_y..][..frame.width];
19 let uv_y = y >> cy;
20 let u_row = &frame.data_u[uv_y * frame.linesize_u..][..w_uv];
21 let v_row = &frame.data_v[uv_y * frame.linesize_v..][..w_uv];
22
23 for x in 0..frame.width {
24 let yv = y_row[x] as i32;
25 let uv_x = x >> cx;
26 let u = u_row[uv_x] as i32;
27 let v = v_row[uv_x] as i32;
28 let (r, g, b) = yuv_to_rgb_bt601_limited(yv, u, v);
29 let o = (y * frame.width + x) * 4;
30 out_rgba[o + 0] = r;
31 out_rgba[o + 1] = g;
32 out_rgba[o + 2] = b;
33 out_rgba[o + 3] = 255;
34 }
35 }
36}
37
38pub fn frame_to_gray_rgba(frame: &Frame, out_rgba: &mut [u8]) {
40 debug_assert_eq!(out_rgba.len(), frame.width * frame.height * 4);
41 for y in 0..frame.height {
42 let src = &frame.data_y[y * frame.linesize_y..][..frame.width];
43 for x in 0..frame.width {
44 let v = src[x];
45 let o = (y * frame.width + x) * 4;
46 out_rgba[o + 0] = v;
47 out_rgba[o + 1] = v;
48 out_rgba[o + 2] = v;
49 out_rgba[o + 3] = 255;
50 }
51 }
52}
53
54#[inline]
55fn yuv_to_rgb_bt601_limited(y: i32, u: i32, v: i32) -> (u8, u8, u8) {
56 let c = (y - 16).max(0);
58 let d = u - 128;
59 let e = v - 128;
60
61 let r = (298 * c + 409 * e + 128) >> 8;
62 let g = (298 * c - 100 * d - 208 * e + 128) >> 8;
63 let b = (298 * c + 516 * d + 128) >> 8;
64
65 (clamp_u8(r), clamp_u8(g), clamp_u8(b))
66}
67
68#[inline]
69fn clamp_u8(v: i32) -> u8 {
70 if v < 0 {
71 0
72 } else if v > 255 {
73 255
74 } else {
75 v as u8
76 }
77}