diff --git a/system/camerad/cameras/nv12_info.h b/system/camerad/cameras/nv12_info.h index 0f4aee81a0..e8eb117406 100644 --- a/system/camerad/cameras/nv12_info.h +++ b/system/camerad/cameras/nv12_info.h @@ -6,14 +6,17 @@ #include "third_party/linux/include/msm_media_info.h" -// Returns NV12 aligned width, height, and buffer size for the given frame. -inline std::tuple get_nv12_info(int width, int height) { - // the encoder HW tells us the size it wants after setting it up. - // TODO: VENUS_BUFFER_SIZE should give the size, but it's too small. dependent on encoder settings? - const uint32_t nv12_width = VENUS_Y_STRIDE(COLOR_FMT_NV12, width); - const uint32_t nv12_height = VENUS_Y_SCANLINES(COLOR_FMT_NV12, height); - assert(nv12_width == VENUS_UV_STRIDE(COLOR_FMT_NV12, width)); - assert(nv12_height / 2 == VENUS_UV_SCANLINES(COLOR_FMT_NV12, height)); - const uint32_t nv12_buffer_size = (width <= 1344 ? 2900 : 2346)*nv12_width; - return {nv12_width, nv12_height, nv12_buffer_size}; +// Returns NV12 aligned (stride, y_height, uv_height, buffer_size) for the given frame dimensions. +inline std::tuple get_nv12_info(int width, int height) { + const uint32_t stride = VENUS_Y_STRIDE(COLOR_FMT_NV12, width); + const uint32_t y_height = VENUS_Y_SCANLINES(COLOR_FMT_NV12, height); + const uint32_t uv_height = VENUS_UV_SCANLINES(COLOR_FMT_NV12, height); + const uint32_t size = VENUS_BUFFER_SIZE(COLOR_FMT_NV12, width, height); + + // Sanity checks for NV12 format assumptions + assert(stride == VENUS_UV_STRIDE(COLOR_FMT_NV12, width)); + assert(y_height / 2 == uv_height); + assert((stride * y_height) % 0x1000 == 0); // uv_offset must be page-aligned + + return {stride, y_height, uv_height, size}; } diff --git a/system/camerad/cameras/nv12_info.py b/system/camerad/cameras/nv12_info.py new file mode 100644 index 0000000000..bcb6312d2b --- /dev/null +++ b/system/camerad/cameras/nv12_info.py @@ -0,0 +1,21 @@ +# Python version of system/camerad/cameras/nv12_info.h +# Calculations from third_party/linux/include/msm_media_info.h (VENUS_BUFFER_SIZE) + +def align(val: int, alignment: int) -> int: + return ((val + alignment - 1) // alignment) * alignment + +def get_nv12_info(width: int, height: int) -> tuple[int, int, int, int]: + """Returns (stride, y_height, uv_height, buffer_size) for NV12 frame dimensions.""" + stride = align(width, 128) + y_height = align(height, 32) + uv_height = align(height // 2, 16) + + # VENUS_BUFFER_SIZE for NV12 + y_plane = stride * y_height + uv_plane = stride * uv_height + 4096 + size = y_plane + uv_plane + max(16 * 1024, 8 * stride) + size = align(size, 4096) + size += align(width, 512) * 512 # kernel padding for non-aligned frames + size = align(size, 4096) + + return stride, y_height, uv_height, size diff --git a/system/camerad/cameras/spectra.cc b/system/camerad/cameras/spectra.cc index 20f48bb556..5c3e7a9d23 100644 --- a/system/camerad/cameras/spectra.cc +++ b/system/camerad/cameras/spectra.cc @@ -12,11 +12,11 @@ #include "media/cam_isp_ife.h" #include "media/cam_sensor_cmn_header.h" #include "media/cam_sync.h" -#include "third_party/linux/include/msm_media_info.h" #include "common/util.h" #include "common/swaglog.h" #include "system/camerad/cameras/ife.h" +#include "system/camerad/cameras/nv12_info.h" #include "system/camerad/cameras/spectra.h" #include "system/camerad/cameras/bps_blobs.h" @@ -283,12 +283,11 @@ void SpectraCamera::camera_open(VisionIpcServer *v, cl_device_id device_id, cl_c buf.out_img_width = sensor->frame_width / sensor->out_scale; buf.out_img_height = (sensor->hdr_offset > 0 ? (sensor->frame_height - sensor->hdr_offset) / 2 : sensor->frame_height) / sensor->out_scale; - std::tie(stride, y_height, yuv_size) = get_nv12_info(buf.out_img_width, buf.out_img_height); - uv_height = y_height / 2; + + // size is driven by all the HW that handles frames, + // the video encoder has certain alignment requirements in this case + std::tie(stride, y_height, uv_height, yuv_size) = get_nv12_info(buf.out_img_width, buf.out_img_height); uv_offset = stride * y_height; - if (cc.output_type != ISP_RAW_OUTPUT) { - uv_offset = ALIGNED_SIZE(uv_offset, 0x1000); - } open = true; configISP(); diff --git a/system/camerad/cameras/spectra.h b/system/camerad/cameras/spectra.h index 983873c7f8..13cb13f98f 100644 --- a/system/camerad/cameras/spectra.h +++ b/system/camerad/cameras/spectra.h @@ -12,7 +12,6 @@ #include "common/util.h" #include "common/swaglog.h" #include "system/camerad/cameras/hw.h" -#include "system/camerad/cameras/nv12_info.h" #include "system/camerad/cameras/camera_common.h" #include "system/camerad/sensors/sensor.h" diff --git a/system/camerad/snapshot.py b/system/camerad/snapshot.py index b3369891d7..035a4acdcf 100755 --- a/system/camerad/snapshot.py +++ b/system/camerad/snapshot.py @@ -43,9 +43,15 @@ def yuv_to_rgb(y, u, v): def extract_image(buf): + # NV12 format: Y plane followed by interleaved UV plane + # UV plane size is stride * uv_height, where uv_height = align(height/2, 16) + uv_height = ((buf.height // 2) + 15) // 16 * 16 + uv_plane_size = buf.stride * uv_height + y = np.array(buf.data[:buf.uv_offset], dtype=np.uint8).reshape((-1, buf.stride))[:buf.height, :buf.width] - u = np.array(buf.data[buf.uv_offset::2], dtype=np.uint8).reshape((-1, buf.stride//2))[:buf.height//2, :buf.width//2] - v = np.array(buf.data[buf.uv_offset+1::2], dtype=np.uint8).reshape((-1, buf.stride//2))[:buf.height//2, :buf.width//2] + uv_data = buf.data[buf.uv_offset:buf.uv_offset + uv_plane_size] + u = np.array(uv_data[::2], dtype=np.uint8).reshape((-1, buf.stride//2))[:buf.height//2, :buf.width//2] + v = np.array(uv_data[1::2], dtype=np.uint8).reshape((-1, buf.stride//2))[:buf.height//2, :buf.width//2] return yuv_to_rgb(y, u, v) diff --git a/third_party/linux/include/msm_media_info.h b/third_party/linux/include/msm_media_info.h index 39dceb2c49..3fd0c8849a 100644 --- a/third_party/linux/include/msm_media_info.h +++ b/third_party/linux/include/msm_media_info.h @@ -2,7 +2,9 @@ #define __MEDIA_INFO_H__ #ifndef MSM_MEDIA_ALIGN -#define MSM_MEDIA_ALIGN(__sz, __align) (((__sz) + (__align-1)) & (~(__align-1))) +#define MSM_MEDIA_ALIGN(__sz, __align) (((__align) & ((__align) - 1)) ?\ + ((((__sz) + (__align) - 1) / (__align)) * (__align)) :\ + (((__sz) + (__align) - 1) & (~((__align) - 1)))) #endif #ifndef MSM_MEDIA_ROUNDUP @@ -148,7 +150,12 @@ enum color_fmts { * + 2*(UV_Stride * UV_Scanlines) + Extradata), 4096) */ COLOR_FMT_NV12_MVTB, - /* Venus NV12 UBWC: + /* + * The buffer can be of 2 types: + * (1) Venus NV12 UBWC Progressive + * (2) Venus NV12 UBWC Interlaced + * + * (1) Venus NV12 UBWC Progressive Buffer Format: * Compressed Macro-tile format for NV12. * Contains 4 planes in the following order - * (A) Y_Meta_Plane @@ -234,6 +241,186 @@ enum color_fmts { * Total size = align( Y_UBWC_Plane_size + UV_UBWC_Plane_size + * Y_Meta_Plane_size + UV_Meta_Plane_size * + max(Extradata, Y_Stride * 48), 4096) + * + * + * (2) Venus NV12 UBWC Interlaced Buffer Format: + * Compressed Macro-tile format for NV12 interlaced. + * Contains 8 planes in the following order - + * (A) Y_Meta_Top_Field_Plane + * (B) Y_UBWC_Top_Field_Plane + * (C) UV_Meta_Top_Field_Plane + * (D) UV_UBWC_Top_Field_Plane + * (E) Y_Meta_Bottom_Field_Plane + * (F) Y_UBWC_Bottom_Field_Plane + * (G) UV_Meta_Bottom_Field_Plane + * (H) UV_UBWC_Bottom_Field_Plane + * Y_Meta_Top_Field_Plane consists of meta information to decode + * compressed tile data for Y_UBWC_Top_Field_Plane. + * Y_UBWC_Top_Field_Plane consists of Y data in compressed macro-tile + * format for top field of an interlaced frame. + * UBWC decoder block will use the Y_Meta_Top_Field_Plane data together + * with Y_UBWC_Top_Field_Plane data to produce loss-less uncompressed + * 8 bit Y samples for top field of an interlaced frame. + * + * UV_Meta_Top_Field_Plane consists of meta information to decode + * compressed tile data in UV_UBWC_Top_Field_Plane. + * UV_UBWC_Top_Field_Plane consists of UV data in compressed macro-tile + * format for top field of an interlaced frame. + * UBWC decoder block will use UV_Meta_Top_Field_Plane data together + * with UV_UBWC_Top_Field_Plane data to produce loss-less uncompressed + * 8 bit subsampled color difference samples for top field of an + * interlaced frame. + * + * Each tile in Y_UBWC_Top_Field_Plane/UV_UBWC_Top_Field_Plane is + * independently decodable and randomly accessible. There is no + * dependency between tiles. + * + * Y_Meta_Bottom_Field_Plane consists of meta information to decode + * compressed tile data for Y_UBWC_Bottom_Field_Plane. + * Y_UBWC_Bottom_Field_Plane consists of Y data in compressed macro-tile + * format for bottom field of an interlaced frame. + * UBWC decoder block will use the Y_Meta_Bottom_Field_Plane data + * together with Y_UBWC_Bottom_Field_Plane data to produce loss-less + * uncompressed 8 bit Y samples for bottom field of an interlaced frame. + * + * UV_Meta_Bottom_Field_Plane consists of meta information to decode + * compressed tile data in UV_UBWC_Bottom_Field_Plane. + * UV_UBWC_Bottom_Field_Plane consists of UV data in compressed + * macro-tile format for bottom field of an interlaced frame. + * UBWC decoder block will use UV_Meta_Bottom_Field_Plane data together + * with UV_UBWC_Bottom_Field_Plane data to produce loss-less + * uncompressed 8 bit subsampled color difference samples for bottom + * field of an interlaced frame. + * + * Each tile in Y_UBWC_Bottom_Field_Plane/UV_UBWC_Bottom_Field_Plane is + * independently decodable and randomly accessible. There is no + * dependency between tiles. + * + * <-----Y_TF_Meta_Stride----> + * <-------- Width ------> + * M M M M M M M M M M M M . . ^ ^ + * M M M M M M M M M M M M . . | | + * M M M M M M M M M M M M . . Half_height | + * M M M M M M M M M M M M . . | Meta_Y_TF_Scanlines + * M M M M M M M M M M M M . . | | + * M M M M M M M M M M M M . . | | + * M M M M M M M M M M M M . . | | + * M M M M M M M M M M M M . . V | + * . . . . . . . . . . . . . . | + * . . . . . . . . . . . . . . | + * . . . . . . . . . . . . . . -------> Buffer size aligned to 4k + * . . . . . . . . . . . . . . V + * <-Compressed tile Y_TF Stride-> + * <------- Width -------> + * Y* Y* Y* Y* Y* Y* Y* Y* . . . . ^ ^ + * Y* Y* Y* Y* Y* Y* Y* Y* . . . . | | + * Y* Y* Y* Y* Y* Y* Y* Y* . . . . Half_height | + * Y* Y* Y* Y* Y* Y* Y* Y* . . . . | Macro_tile_Y_TF_Scanlines + * Y* Y* Y* Y* Y* Y* Y* Y* . . . . | | + * Y* Y* Y* Y* Y* Y* Y* Y* . . . . | | + * Y* Y* Y* Y* Y* Y* Y* Y* . . . . | | + * Y* Y* Y* Y* Y* Y* Y* Y* . . . . V | + * . . . . . . . . . . . . . . . . | + * . . . . . . . . . . . . . . . . | + * . . . . . . . . . . . . . . . . -------> Buffer size aligned to 4k + * . . . . . . . . . . . . . . . . V + * <----UV_TF_Meta_Stride----> + * M M M M M M M M M M M M . . ^ + * M M M M M M M M M M M M . . | + * M M M M M M M M M M M M . . | + * M M M M M M M M M M M M . . M_UV_TF_Scanlines + * . . . . . . . . . . . . . . | + * . . . . . . . . . . . . . . V + * . . . . . . . . . . . . . . -------> Buffer size aligned to 4k + * <-Compressed tile UV_TF Stride-> + * U* V* U* V* U* V* U* V* . . . . ^ + * U* V* U* V* U* V* U* V* . . . . | + * U* V* U* V* U* V* U* V* . . . . | + * U* V* U* V* U* V* U* V* . . . . UV_TF_Scanlines + * . . . . . . . . . . . . . . . . | + * . . . . . . . . . . . . . . . . V + * . . . . . . . . . . . . . . . . -------> Buffer size aligned to 4k + * <-----Y_BF_Meta_Stride----> + * <-------- Width ------> + * M M M M M M M M M M M M . . ^ ^ + * M M M M M M M M M M M M . . | | + * M M M M M M M M M M M M . . Half_height | + * M M M M M M M M M M M M . . | Meta_Y_BF_Scanlines + * M M M M M M M M M M M M . . | | + * M M M M M M M M M M M M . . | | + * M M M M M M M M M M M M . . | | + * M M M M M M M M M M M M . . V | + * . . . . . . . . . . . . . . | + * . . . . . . . . . . . . . . | + * . . . . . . . . . . . . . . -------> Buffer size aligned to 4k + * . . . . . . . . . . . . . . V + * <-Compressed tile Y_BF Stride-> + * <------- Width -------> + * Y* Y* Y* Y* Y* Y* Y* Y* . . . . ^ ^ + * Y* Y* Y* Y* Y* Y* Y* Y* . . . . | | + * Y* Y* Y* Y* Y* Y* Y* Y* . . . . Half_height | + * Y* Y* Y* Y* Y* Y* Y* Y* . . . . | Macro_tile_Y_BF_Scanlines + * Y* Y* Y* Y* Y* Y* Y* Y* . . . . | | + * Y* Y* Y* Y* Y* Y* Y* Y* . . . . | | + * Y* Y* Y* Y* Y* Y* Y* Y* . . . . | | + * Y* Y* Y* Y* Y* Y* Y* Y* . . . . V | + * . . . . . . . . . . . . . . . . | + * . . . . . . . . . . . . . . . . | + * . . . . . . . . . . . . . . . . -------> Buffer size aligned to 4k + * . . . . . . . . . . . . . . . . V + * <----UV_BF_Meta_Stride----> + * M M M M M M M M M M M M . . ^ + * M M M M M M M M M M M M . . | + * M M M M M M M M M M M M . . | + * M M M M M M M M M M M M . . M_UV_BF_Scanlines + * . . . . . . . . . . . . . . | + * . . . . . . . . . . . . . . V + * . . . . . . . . . . . . . . -------> Buffer size aligned to 4k + * <-Compressed tile UV_BF Stride-> + * U* V* U* V* U* V* U* V* . . . . ^ + * U* V* U* V* U* V* U* V* . . . . | + * U* V* U* V* U* V* U* V* . . . . | + * U* V* U* V* U* V* U* V* . . . . UV_BF_Scanlines + * . . . . . . . . . . . . . . . . | + * . . . . . . . . . . . . . . . . V + * . . . . . . . . . . . . . . . . -------> Buffer size aligned to 4k + * + * Half_height = (Height+1)>>1 + * Y_TF_Stride = align(Width, 128) + * UV_TF_Stride = align(Width, 128) + * Y_TF_Scanlines = align(Half_height, 32) + * UV_TF_Scanlines = align((Half_height+1)/2, 32) + * Y_UBWC_TF_Plane_size = align(Y_TF_Stride * Y_TF_Scanlines, 4096) + * UV_UBWC_TF_Plane_size = align(UV_TF_Stride * UV_TF_Scanlines, 4096) + * Y_TF_Meta_Stride = align(roundup(Width, Y_TileWidth), 64) + * Y_TF_Meta_Scanlines = align(roundup(Half_height, Y_TileHeight), 16) + * Y_TF_Meta_Plane_size = + * align(Y_TF_Meta_Stride * Y_TF_Meta_Scanlines, 4096) + * UV_TF_Meta_Stride = align(roundup(Width, UV_TileWidth), 64) + * UV_TF_Meta_Scanlines = align(roundup(Half_height, UV_TileHeight), 16) + * UV_TF_Meta_Plane_size = + * align(UV_TF_Meta_Stride * UV_TF_Meta_Scanlines, 4096) + * Y_BF_Stride = align(Width, 128) + * UV_BF_Stride = align(Width, 128) + * Y_BF_Scanlines = align(Half_height, 32) + * UV_BF_Scanlines = align((Half_height+1)/2, 32) + * Y_UBWC_BF_Plane_size = align(Y_BF_Stride * Y_BF_Scanlines, 4096) + * UV_UBWC_BF_Plane_size = align(UV_BF_Stride * UV_BF_Scanlines, 4096) + * Y_BF_Meta_Stride = align(roundup(Width, Y_TileWidth), 64) + * Y_BF_Meta_Scanlines = align(roundup(Half_height, Y_TileHeight), 16) + * Y_BF_Meta_Plane_size = + * align(Y_BF_Meta_Stride * Y_BF_Meta_Scanlines, 4096) + * UV_BF_Meta_Stride = align(roundup(Width, UV_TileWidth), 64) + * UV_BF_Meta_Scanlines = align(roundup(Half_height, UV_TileHeight), 16) + * UV_BF_Meta_Plane_size = + * align(UV_BF_Meta_Stride * UV_BF_Meta_Scanlines, 4096) + * Extradata = 8k + * + * Total size = align( Y_UBWC_TF_Plane_size + UV_UBWC_TF_Plane_size + + * Y_TF_Meta_Plane_size + UV_TF_Meta_Plane_size + + * Y_UBWC_BF_Plane_size + UV_UBWC_BF_Plane_size + + * Y_BF_Meta_Plane_size + UV_BF_Meta_Plane_size + + * + max(Extradata, Y_TF_Stride * 48), 4096) */ COLOR_FMT_NV12_UBWC, /* Venus NV12 10-bit UBWC: @@ -399,8 +586,233 @@ enum color_fmts { * Extradata, 4096) */ COLOR_FMT_RGBA8888_UBWC, + /* Venus RGBA1010102 UBWC format: + * Contains 2 planes in the following order - + * (A) Meta plane + * (B) RGBA plane + * + * <--- RGB_Meta_Stride ----> + * <-------- Width ------> + * M M M M M M M M M M M M . . ^ ^ + * M M M M M M M M M M M M . . | | + * M M M M M M M M M M M M . . Height | + * M M M M M M M M M M M M . . | Meta_RGB_Scanlines + * M M M M M M M M M M M M . . | | + * M M M M M M M M M M M M . . | | + * M M M M M M M M M M M M . . | | + * M M M M M M M M M M M M . . V | + * . . . . . . . . . . . . . . | + * . . . . . . . . . . . . . . | + * . . . . . . . . . . . . . . -------> Buffer size aligned to 4k + * . . . . . . . . . . . . . . V + * <-------- RGB_Stride --------> + * <------- Width -------> + * R R R R R R R R R R R R . . . . ^ ^ + * R R R R R R R R R R R R . . . . | | + * R R R R R R R R R R R R . . . . Height | + * R R R R R R R R R R R R . . . . | RGB_Scanlines + * R R R R R R R R R R R R . . . . | | + * R R R R R R R R R R R R . . . . | | + * R R R R R R R R R R R R . . . . | | + * R R R R R R R R R R R R . . . . V | + * . . . . . . . . . . . . . . . . | + * . . . . . . . . . . . . . . . . | + * . . . . . . . . . . . . . . . . -------> Buffer size aligned to 4k + * . . . . . . . . . . . . . . . . V + * + * RGB_Stride = align(Width * 4, 256) + * RGB_Scanlines = align(Height, 16) + * RGB_Plane_size = align(RGB_Stride * RGB_Scanlines, 4096) + * RGB_Meta_Stride = align(roundup(Width, RGB_TileWidth), 64) + * RGB_Meta_Scanline = align(roundup(Height, RGB_TileHeight), 16) + * RGB_Meta_Plane_size = align(RGB_Meta_Stride * + * RGB_Meta_Scanlines, 4096) + * Extradata = 8k + * + * Total size = align(RGB_Meta_Plane_size + RGB_Plane_size + + * Extradata, 4096) + */ + COLOR_FMT_RGBA1010102_UBWC, + /* Venus RGB565 UBWC format: + * Contains 2 planes in the following order - + * (A) Meta plane + * (B) RGB plane + * + * <--- RGB_Meta_Stride ----> + * <-------- Width ------> + * M M M M M M M M M M M M . . ^ ^ + * M M M M M M M M M M M M . . | | + * M M M M M M M M M M M M . . Height | + * M M M M M M M M M M M M . . | Meta_RGB_Scanlines + * M M M M M M M M M M M M . . | | + * M M M M M M M M M M M M . . | | + * M M M M M M M M M M M M . . | | + * M M M M M M M M M M M M . . V | + * . . . . . . . . . . . . . . | + * . . . . . . . . . . . . . . | + * . . . . . . . . . . . . . . -------> Buffer size aligned to 4k + * . . . . . . . . . . . . . . V + * <-------- RGB_Stride --------> + * <------- Width -------> + * R R R R R R R R R R R R . . . . ^ ^ + * R R R R R R R R R R R R . . . . | | + * R R R R R R R R R R R R . . . . Height | + * R R R R R R R R R R R R . . . . | RGB_Scanlines + * R R R R R R R R R R R R . . . . | | + * R R R R R R R R R R R R . . . . | | + * R R R R R R R R R R R R . . . . | | + * R R R R R R R R R R R R . . . . V | + * . . . . . . . . . . . . . . . . | + * . . . . . . . . . . . . . . . . | + * . . . . . . . . . . . . . . . . -------> Buffer size aligned to 4k + * . . . . . . . . . . . . . . . . V + * + * RGB_Stride = align(Width * 2, 128) + * RGB_Scanlines = align(Height, 16) + * RGB_Plane_size = align(RGB_Stride * RGB_Scanlines, 4096) + * RGB_Meta_Stride = align(roundup(Width, RGB_TileWidth), 64) + * RGB_Meta_Scanline = align(roundup(Height, RGB_TileHeight), 16) + * RGB_Meta_Plane_size = align(RGB_Meta_Stride * + * RGB_Meta_Scanlines, 4096) + * Extradata = 8k + * + * Total size = align(RGB_Meta_Plane_size + RGB_Plane_size + + * Extradata, 4096) + */ + COLOR_FMT_RGB565_UBWC, + /* P010 UBWC: + * Compressed Macro-tile format for NV12. + * Contains 4 planes in the following order - + * (A) Y_Meta_Plane + * (B) Y_UBWC_Plane + * (C) UV_Meta_Plane + * (D) UV_UBWC_Plane + * + * Y_Meta_Plane consists of meta information to decode compressed + * tile data in Y_UBWC_Plane. + * Y_UBWC_Plane consists of Y data in compressed macro-tile format. + * UBWC decoder block will use the Y_Meta_Plane data together with + * Y_UBWC_Plane data to produce loss-less uncompressed 10 bit Y samples. + * + * UV_Meta_Plane consists of meta information to decode compressed + * tile data in UV_UBWC_Plane. + * UV_UBWC_Plane consists of UV data in compressed macro-tile format. + * UBWC decoder block will use UV_Meta_Plane data together with + * UV_UBWC_Plane data to produce loss-less uncompressed 10 bit 2x2 + * subsampled color difference samples. + * + * Each tile in Y_UBWC_Plane/UV_UBWC_Plane is independently decodable + * and randomly accessible. There is no dependency between tiles. + * + * <----- Y_Meta_Stride -----> + * <-------- Width ------> + * M M M M M M M M M M M M . . ^ ^ + * M M M M M M M M M M M M . . | | + * M M M M M M M M M M M M . . Height | + * M M M M M M M M M M M M . . | Meta_Y_Scanlines + * M M M M M M M M M M M M . . | | + * M M M M M M M M M M M M . . | | + * M M M M M M M M M M M M . . | | + * M M M M M M M M M M M M . . V | + * . . . . . . . . . . . . . . | + * . . . . . . . . . . . . . . | + * . . . . . . . . . . . . . . -------> Buffer size aligned to 4k + * . . . . . . . . . . . . . . V + * <--Compressed tile Y Stride---> + * <------- Width -------> + * Y* Y* Y* Y* Y* Y* Y* Y* . . . . ^ ^ + * Y* Y* Y* Y* Y* Y* Y* Y* . . . . | | + * Y* Y* Y* Y* Y* Y* Y* Y* . . . . Height | + * Y* Y* Y* Y* Y* Y* Y* Y* . . . . | Macro_tile_Y_Scanlines + * Y* Y* Y* Y* Y* Y* Y* Y* . . . . | | + * Y* Y* Y* Y* Y* Y* Y* Y* . . . . | | + * Y* Y* Y* Y* Y* Y* Y* Y* . . . . | | + * Y* Y* Y* Y* Y* Y* Y* Y* . . . . V | + * . . . . . . . . . . . . . . . . | + * . . . . . . . . . . . . . . . . | + * . . . . . . . . . . . . . . . . -------> Buffer size aligned to 4k + * . . . . . . . . . . . . . . . . V + * <----- UV_Meta_Stride ----> + * M M M M M M M M M M M M . . ^ + * M M M M M M M M M M M M . . | + * M M M M M M M M M M M M . . | + * M M M M M M M M M M M M . . M_UV_Scanlines + * . . . . . . . . . . . . . . | + * . . . . . . . . . . . . . . V + * . . . . . . . . . . . . . . -------> Buffer size aligned to 4k + * <--Compressed tile UV Stride---> + * U* V* U* V* U* V* U* V* . . . . ^ + * U* V* U* V* U* V* U* V* . . . . | + * U* V* U* V* U* V* U* V* . . . . | + * U* V* U* V* U* V* U* V* . . . . UV_Scanlines + * . . . . . . . . . . . . . . . . | + * . . . . . . . . . . . . . . . . V + * . . . . . . . . . . . . . . . . -------> Buffer size aligned to 4k + * + * + * Y_Stride = align(Width * 2, 256) + * UV_Stride = align(Width * 2, 256) + * Y_Scanlines = align(Height, 16) + * UV_Scanlines = align(Height/2, 16) + * Y_UBWC_Plane_Size = align(Y_Stride * Y_Scanlines, 4096) + * UV_UBWC_Plane_Size = align(UV_Stride * UV_Scanlines, 4096) + * Y_Meta_Stride = align(roundup(Width, Y_TileWidth), 64) + * Y_Meta_Scanlines = align(roundup(Height, Y_TileHeight), 16) + * Y_Meta_Plane_size = align(Y_Meta_Stride * Y_Meta_Scanlines, 4096) + * UV_Meta_Stride = align(roundup(Width, UV_TileWidth), 64) + * UV_Meta_Scanlines = align(roundup(Height, UV_TileHeight), 16) + * UV_Meta_Plane_size = align(UV_Meta_Stride * UV_Meta_Scanlines, 4096) + * Extradata = 8k + * + * Total size = align(Y_UBWC_Plane_size + UV_UBWC_Plane_size + + * Y_Meta_Plane_size + UV_Meta_Plane_size + * + max(Extradata, Y_Stride * 48), 4096) + */ + COLOR_FMT_P010_UBWC, + /* Venus P010: + * YUV 4:2:0 image with a plane of 10 bit Y samples followed + * by an interleaved U/V plane containing 10 bit 2x2 subsampled + * colour difference samples. + * + * <-------- Y/UV_Stride --------> + * <------- Width -------> + * Y Y Y Y Y Y Y Y Y Y Y Y . . . . ^ ^ + * Y Y Y Y Y Y Y Y Y Y Y Y . . . . | | + * Y Y Y Y Y Y Y Y Y Y Y Y . . . . Height | + * Y Y Y Y Y Y Y Y Y Y Y Y . . . . | Y_Scanlines + * Y Y Y Y Y Y Y Y Y Y Y Y . . . . | | + * Y Y Y Y Y Y Y Y Y Y Y Y . . . . | | + * Y Y Y Y Y Y Y Y Y Y Y Y . . . . | | + * Y Y Y Y Y Y Y Y Y Y Y Y . . . . V | + * . . . . . . . . . . . . . . . . | + * . . . . . . . . . . . . . . . . | + * . . . . . . . . . . . . . . . . | + * . . . . . . . . . . . . . . . . V + * U V U V U V U V U V U V . . . . ^ + * U V U V U V U V U V U V . . . . | + * U V U V U V U V U V U V . . . . | + * U V U V U V U V U V U V . . . . UV_Scanlines + * . . . . . . . . . . . . . . . . | + * . . . . . . . . . . . . . . . . V + * . . . . . . . . . . . . . . . . --> Buffer size alignment + * + * Y_Stride : Width * 2 aligned to 128 + * UV_Stride : Width * 2 aligned to 128 + * Y_Scanlines: Height aligned to 32 + * UV_Scanlines: Height/2 aligned to 16 + * Extradata: Arbitrary (software-imposed) padding + * Total size = align((Y_Stride * Y_Scanlines + * + UV_Stride * UV_Scanlines + * + max(Extradata, Y_Stride * 8), 4096) + */ + COLOR_FMT_P010, }; +#define COLOR_FMT_RGBA1010102_UBWC COLOR_FMT_RGBA1010102_UBWC +#define COLOR_FMT_RGB565_UBWC COLOR_FMT_RGB565_UBWC +#define COLOR_FMT_P010_UBWC COLOR_FMT_P010_UBWC +#define COLOR_FMT_P010 COLOR_FMT_P010 + static inline unsigned int VENUS_EXTRADATA_SIZE(int width, int height) { (void)height; @@ -413,9 +825,17 @@ static inline unsigned int VENUS_EXTRADATA_SIZE(int width, int height) return 16 * 1024; } +/* + * Function arguments: + * @color_fmt + * @width + * Progressive: width + * Interlaced: width + */ static inline unsigned int VENUS_Y_STRIDE(int color_fmt, int width) { unsigned int alignment, stride = 0; + if (!width) goto invalid_input; @@ -432,6 +852,14 @@ static inline unsigned int VENUS_Y_STRIDE(int color_fmt, int width) stride = MSM_MEDIA_ALIGN(width, 192); stride = MSM_MEDIA_ALIGN(stride * 4/3, alignment); break; + case COLOR_FMT_P010_UBWC: + alignment = 256; + stride = MSM_MEDIA_ALIGN(width * 2, alignment); + break; + case COLOR_FMT_P010: + alignment = 128; + stride = MSM_MEDIA_ALIGN(width*2, alignment); + break; default: break; } @@ -439,9 +867,17 @@ invalid_input: return stride; } +/* + * Function arguments: + * @color_fmt + * @width + * Progressive: width + * Interlaced: width + */ static inline unsigned int VENUS_UV_STRIDE(int color_fmt, int width) { unsigned int alignment, stride = 0; + if (!width) goto invalid_input; @@ -458,6 +894,14 @@ static inline unsigned int VENUS_UV_STRIDE(int color_fmt, int width) stride = MSM_MEDIA_ALIGN(width, 192); stride = MSM_MEDIA_ALIGN(stride * 4/3, alignment); break; + case COLOR_FMT_P010_UBWC: + alignment = 256; + stride = MSM_MEDIA_ALIGN(width * 2, alignment); + break; + case COLOR_FMT_P010: + alignment = 128; + stride = MSM_MEDIA_ALIGN(width*2, alignment); + break; default: break; } @@ -465,9 +909,17 @@ invalid_input: return stride; } +/* + * Function arguments: + * @color_fmt + * @height + * Progressive: height + * Interlaced: (height+1)>>1 + */ static inline unsigned int VENUS_Y_SCANLINES(int color_fmt, int height) { unsigned int alignment, sclines = 0; + if (!height) goto invalid_input; @@ -476,9 +928,11 @@ static inline unsigned int VENUS_Y_SCANLINES(int color_fmt, int height) case COLOR_FMT_NV12: case COLOR_FMT_NV12_MVTB: case COLOR_FMT_NV12_UBWC: + case COLOR_FMT_P010: alignment = 32; break; case COLOR_FMT_NV12_BPP10_UBWC: + case COLOR_FMT_P010_UBWC: alignment = 16; break; default: @@ -489,9 +943,17 @@ invalid_input: return sclines; } +/* + * Function arguments: + * @color_fmt + * @height + * Progressive: height + * Interlaced: (height+1)>>1 + */ static inline unsigned int VENUS_UV_SCANLINES(int color_fmt, int height) { unsigned int alignment, sclines = 0; + if (!height) goto invalid_input; @@ -500,6 +962,8 @@ static inline unsigned int VENUS_UV_SCANLINES(int color_fmt, int height) case COLOR_FMT_NV12: case COLOR_FMT_NV12_MVTB: case COLOR_FMT_NV12_BPP10_UBWC: + case COLOR_FMT_P010_UBWC: + case COLOR_FMT_P010: alignment = 16; break; case COLOR_FMT_NV12_UBWC: @@ -509,12 +973,19 @@ static inline unsigned int VENUS_UV_SCANLINES(int color_fmt, int height) goto invalid_input; } - sclines = MSM_MEDIA_ALIGN(height / 2, alignment); + sclines = MSM_MEDIA_ALIGN((height+1)>>1, alignment); invalid_input: return sclines; } +/* + * Function arguments: + * @color_fmt + * @width + * Progressive: width + * Interlaced: width + */ static inline unsigned int VENUS_Y_META_STRIDE(int color_fmt, int width) { int y_tile_width = 0, y_meta_stride = 0; @@ -524,6 +995,7 @@ static inline unsigned int VENUS_Y_META_STRIDE(int color_fmt, int width) switch (color_fmt) { case COLOR_FMT_NV12_UBWC: + case COLOR_FMT_P010_UBWC: y_tile_width = 32; break; case COLOR_FMT_NV12_BPP10_UBWC: @@ -540,6 +1012,13 @@ invalid_input: return y_meta_stride; } +/* + * Function arguments: + * @color_fmt + * @height + * Progressive: height + * Interlaced: (height+1)>>1 + */ static inline unsigned int VENUS_Y_META_SCANLINES(int color_fmt, int height) { int y_tile_height = 0, y_meta_scanlines = 0; @@ -552,6 +1031,7 @@ static inline unsigned int VENUS_Y_META_SCANLINES(int color_fmt, int height) y_tile_height = 8; break; case COLOR_FMT_NV12_BPP10_UBWC: + case COLOR_FMT_P010_UBWC: y_tile_height = 4; break; default: @@ -565,6 +1045,13 @@ invalid_input: return y_meta_scanlines; } +/* + * Function arguments: + * @color_fmt + * @width + * Progressive: width + * Interlaced: width + */ static inline unsigned int VENUS_UV_META_STRIDE(int color_fmt, int width) { int uv_tile_width = 0, uv_meta_stride = 0; @@ -574,6 +1061,7 @@ static inline unsigned int VENUS_UV_META_STRIDE(int color_fmt, int width) switch (color_fmt) { case COLOR_FMT_NV12_UBWC: + case COLOR_FMT_P010_UBWC: uv_tile_width = 16; break; case COLOR_FMT_NV12_BPP10_UBWC: @@ -583,13 +1071,20 @@ static inline unsigned int VENUS_UV_META_STRIDE(int color_fmt, int width) goto invalid_input; } - uv_meta_stride = MSM_MEDIA_ROUNDUP(width / 2, uv_tile_width); + uv_meta_stride = MSM_MEDIA_ROUNDUP((width+1)>>1, uv_tile_width); uv_meta_stride = MSM_MEDIA_ALIGN(uv_meta_stride, 64); invalid_input: return uv_meta_stride; } +/* + * Function arguments: + * @color_fmt + * @height + * Progressive: height + * Interlaced: (height+1)>>1 + */ static inline unsigned int VENUS_UV_META_SCANLINES(int color_fmt, int height) { int uv_tile_height = 0, uv_meta_scanlines = 0; @@ -602,13 +1097,14 @@ static inline unsigned int VENUS_UV_META_SCANLINES(int color_fmt, int height) uv_tile_height = 8; break; case COLOR_FMT_NV12_BPP10_UBWC: + case COLOR_FMT_P010_UBWC: uv_tile_height = 4; break; default: goto invalid_input; } - uv_meta_scanlines = MSM_MEDIA_ROUNDUP(height / 2, uv_tile_height); + uv_meta_scanlines = MSM_MEDIA_ROUNDUP((height+1)>>1, uv_tile_height); uv_meta_scanlines = MSM_MEDIA_ALIGN(uv_meta_scanlines, 16); invalid_input: @@ -617,7 +1113,8 @@ invalid_input: static inline unsigned int VENUS_RGB_STRIDE(int color_fmt, int width) { - unsigned int alignment = 0, stride = 0; + unsigned int alignment = 0, stride = 0, bpp = 4; + if (!width) goto invalid_input; @@ -625,14 +1122,19 @@ static inline unsigned int VENUS_RGB_STRIDE(int color_fmt, int width) case COLOR_FMT_RGBA8888: alignment = 128; break; + case COLOR_FMT_RGB565_UBWC: + alignment = 256; + bpp = 2; + break; case COLOR_FMT_RGBA8888_UBWC: + case COLOR_FMT_RGBA1010102_UBWC: alignment = 256; break; default: goto invalid_input; } - stride = MSM_MEDIA_ALIGN(width * 4, alignment); + stride = MSM_MEDIA_ALIGN(width * bpp, alignment); invalid_input: return stride; @@ -650,6 +1152,8 @@ static inline unsigned int VENUS_RGB_SCANLINES(int color_fmt, int height) alignment = 32; break; case COLOR_FMT_RGBA8888_UBWC: + case COLOR_FMT_RGBA1010102_UBWC: + case COLOR_FMT_RGB565_UBWC: alignment = 16; break; default: @@ -671,6 +1175,8 @@ static inline unsigned int VENUS_RGB_META_STRIDE(int color_fmt, int width) switch (color_fmt) { case COLOR_FMT_RGBA8888_UBWC: + case COLOR_FMT_RGBA1010102_UBWC: + case COLOR_FMT_RGB565_UBWC: rgb_tile_width = 16; break; default: @@ -693,6 +1199,8 @@ static inline unsigned int VENUS_RGB_META_SCANLINES(int color_fmt, int height) switch (color_fmt) { case COLOR_FMT_RGBA8888_UBWC: + case COLOR_FMT_RGBA1010102_UBWC: + case COLOR_FMT_RGB565_UBWC: rgb_tile_height = 4; break; default: @@ -706,11 +1214,22 @@ invalid_input: return rgb_meta_scanlines; } +/* + * Function arguments: + * @color_fmt + * @width + * Progressive: width + * Interlaced: width + * @height + * Progressive: height + * Interlaced: height + */ static inline unsigned int VENUS_BUFFER_SIZE( int color_fmt, int width, int height) { const unsigned int extra_size = VENUS_EXTRADATA_SIZE(width, height); unsigned int uv_alignment = 0, size = 0; + unsigned int w_alignment = 512; unsigned int y_plane, uv_plane, y_stride, uv_stride, y_sclines, uv_sclines; unsigned int y_ubwc_plane = 0, uv_ubwc_plane = 0; @@ -740,6 +1259,18 @@ static inline unsigned int VENUS_BUFFER_SIZE( size = y_plane + uv_plane + MSM_MEDIA_MAX(extra_size, 8 * y_stride); size = MSM_MEDIA_ALIGN(size, 4096); + + /* Additional size to cover last row of non-aligned frame */ + size += MSM_MEDIA_ALIGN(width, w_alignment) * w_alignment; + size = MSM_MEDIA_ALIGN(size, 4096); + break; + case COLOR_FMT_P010: + uv_alignment = 4096; + y_plane = y_stride * y_sclines; + uv_plane = uv_stride * uv_sclines + uv_alignment; + size = y_plane + uv_plane + + MSM_MEDIA_MAX(extra_size, 8 * y_stride); + size = MSM_MEDIA_ALIGN(size, 4096); break; case COLOR_FMT_NV12_MVTB: uv_alignment = 4096; @@ -750,6 +1281,30 @@ static inline unsigned int VENUS_BUFFER_SIZE( size = MSM_MEDIA_ALIGN(size, 4096); break; case COLOR_FMT_NV12_UBWC: + y_sclines = VENUS_Y_SCANLINES(color_fmt, (height+1)>>1); + y_ubwc_plane = MSM_MEDIA_ALIGN(y_stride * y_sclines, 4096); + uv_sclines = VENUS_UV_SCANLINES(color_fmt, (height+1)>>1); + uv_ubwc_plane = MSM_MEDIA_ALIGN(uv_stride * uv_sclines, 4096); + y_meta_stride = VENUS_Y_META_STRIDE(color_fmt, width); + y_meta_scanlines = + VENUS_Y_META_SCANLINES(color_fmt, (height+1)>>1); + y_meta_plane = MSM_MEDIA_ALIGN( + y_meta_stride * y_meta_scanlines, 4096); + uv_meta_stride = VENUS_UV_META_STRIDE(color_fmt, width); + uv_meta_scanlines = + VENUS_UV_META_SCANLINES(color_fmt, (height+1)>>1); + uv_meta_plane = MSM_MEDIA_ALIGN(uv_meta_stride * + uv_meta_scanlines, 4096); + + size = (y_ubwc_plane + uv_ubwc_plane + y_meta_plane + + uv_meta_plane)*2 + + MSM_MEDIA_MAX(extra_size + 8192, 48 * y_stride); + size = MSM_MEDIA_ALIGN(size, 4096); + + /* Additional size to cover last row of non-aligned frame */ + size += MSM_MEDIA_ALIGN(width, w_alignment) * w_alignment; + size = MSM_MEDIA_ALIGN(size, 4096); + break; case COLOR_FMT_NV12_BPP10_UBWC: y_ubwc_plane = MSM_MEDIA_ALIGN(y_stride * y_sclines, 4096); uv_ubwc_plane = MSM_MEDIA_ALIGN(uv_stride * uv_sclines, 4096); @@ -767,12 +1322,30 @@ static inline unsigned int VENUS_BUFFER_SIZE( MSM_MEDIA_MAX(extra_size + 8192, 48 * y_stride); size = MSM_MEDIA_ALIGN(size, 4096); break; + case COLOR_FMT_P010_UBWC: + y_ubwc_plane = MSM_MEDIA_ALIGN(y_stride * y_sclines, 4096); + uv_ubwc_plane = MSM_MEDIA_ALIGN(uv_stride * uv_sclines, 4096); + y_meta_stride = VENUS_Y_META_STRIDE(color_fmt, width); + y_meta_scanlines = VENUS_Y_META_SCANLINES(color_fmt, height); + y_meta_plane = MSM_MEDIA_ALIGN( + y_meta_stride * y_meta_scanlines, 4096); + uv_meta_stride = VENUS_UV_META_STRIDE(color_fmt, width); + uv_meta_scanlines = VENUS_UV_META_SCANLINES(color_fmt, height); + uv_meta_plane = MSM_MEDIA_ALIGN(uv_meta_stride * + uv_meta_scanlines, 4096); + + size = y_ubwc_plane + uv_ubwc_plane + y_meta_plane + + uv_meta_plane; + size = MSM_MEDIA_ALIGN(size, 4096); + break; case COLOR_FMT_RGBA8888: rgb_plane = MSM_MEDIA_ALIGN(rgb_stride * rgb_scanlines, 4096); size = rgb_plane; size = MSM_MEDIA_ALIGN(size, 4096); break; case COLOR_FMT_RGBA8888_UBWC: + case COLOR_FMT_RGBA1010102_UBWC: + case COLOR_FMT_RGB565_UBWC: rgb_ubwc_plane = MSM_MEDIA_ALIGN(rgb_stride * rgb_scanlines, 4096); rgb_meta_stride = VENUS_RGB_META_STRIDE(color_fmt, width); diff --git a/tools/replay/camera.cc b/tools/replay/camera.cc index 2962195aff..671c0320bb 100644 --- a/tools/replay/camera.cc +++ b/tools/replay/camera.cc @@ -1,14 +1,11 @@ #include "tools/replay/camera.h" -#include #include #include -#include "third_party/linux/include/msm_media_info.h" -#include "tools/replay/util.h" #include "system/camerad/cameras/nv12_info.h" - +#include "tools/replay/util.h" const int BUFFER_COUNT = 40; @@ -43,9 +40,10 @@ void CameraServer::startVipcServer() { if (cam.width > 0 && cam.height > 0) { rInfo("camera[%d] frame size %dx%d", cam.type, cam.width, cam.height); - auto [nv12_width, nv12_height, nv12_buffer_size] = get_nv12_info(cam.width, cam.height); + auto [stride, y_height, uv_height_, buffer_size] = get_nv12_info(cam.width, cam.height); + (void)uv_height_; // unused in replay vipc_server_->create_buffers_with_sizes(cam.stream_type, BUFFER_COUNT, cam.width, cam.height, - nv12_buffer_size, nv12_width, nv12_width * nv12_height); + buffer_size, stride, stride * y_height); if (!cam.thread.joinable()) { cam.thread = std::thread(&CameraServer::cameraThread, this, std::ref(cam)); }