uint32_t grallocBufHeight = stream.height; uint32_t grallocBufWidth = stream.width; android_ycbcr yCbCr; if (src_buffer != NULL) { AHC_LOGE("%s: srcRect.width=%d, srcRect.height=%d format=%d !", __FUNCTION__, stream.width, stream.height, stream.format); src_buffer->lockYCbCr(GRALLOC_USAGE_SW_READ_OFTEN, &yCbCr); if (yCbCr.y != NULL) { // copy yuv data srcY = (unsigned char*)yCbCr.y; srcCb = (unsigned char*)yCbCr.cb; srcCr = (unsigned char*)yCbCr.cr; srcUV = (unsigned char*)(yCbCr.cr < yCbCr.cb ? yCbCr.cr : yCbCr.cb); // Y高度矩阵范围的Height, yCbCr.ystride是宽 // int srcSlice = ((unsigned char*)yCbCr.cb - (unsigned char*)yCbCr.y) / yCbCr.ystride; // int y_size = yCbCr.ystride * srcSlice; int y_size = srcUV - srcY; int srcSlice = ((unsigned char*)yCbCr.cb - (unsigned char*)yCbCr.y) / yCbCr.ystride; int uv_size = y_size / 2; AHS_LOGE("%s: yCbCr(y=%p cb=%p cr=%p), ySize=%d, uvSize=%d, yH=%d, yStride=%d, cSt
时间: 2025-06-24 22:44:57 浏览: 13
### YUV 数据处理与 `android_ycbcr` 结构分析
#### 1. 关键术语解释
- **YUV**: 颜色空间的一种形式,其中 Y 表示亮度分量,而 U 和 V 表示色度分量。它常用于视频编解码和图像处理。
- **grallocBufHeight**: 这是一个变量,通常代表分配给缓冲区的高度尺寸(单位为像素)。其值可能来源于某个流对象的属性,例如 `stream.height`[^1]。
- **android_ycbcr**: Android 平台上的一个结构体类型,用来描述 YCbCr 图像数据布局。它的主要字段包括指向各个平面的数据指针以及步幅信息。
- **lockYCbCr**: 函数或方法名称,用于锁定共享内存区域并返回对应的 `android_ycbcr` 描述符。
- **srcY**, **srcCb**, **srcCr**: 指向源图片三个通道(Y、Cb、Cr)起始位置的指针数组。
- **ySize**, **uvSize**: 计算得出的 Y 分量和平面 UV 的总字节数。
- **ystride**, **cStride**: 各自对应于 Y 分量和 Cb/Cr 分量的一维水平跨度。
#### 2. `android_ycbcr` 结构详解
在 Android NDK 中定义了一个名为 `android_ycbcr` 的结构体,专门服务于那些采用半透明格式(如 NV12 或者 I420)存储的画面帧。下面给出该结构的一个典型声明:
```c
typedef struct {
uint8_t* y; // Pointer to the Y plane.
uint8_t* cr; // Pointer to the Cr (or V) plane.
uint8_t* cb; // Pointer to the Cb (or U) plane.
size_t stride; // Stride of each row within the Y plane.
size_t chroma_step;// Step between two consecutive pixels inside one line in the same color component.
} android_ycbcr;
```
注意这里的成员变量命名可能会依据实际使用的 API 版本有所差异[^3]。
#### 3. 复制逻辑剖析
当涉及到从某种外部资源复制 YUV 数据到目标缓冲区内时,一般遵循这样的步骤:
- 获取源地址 (`srcY`, `srcCb`, `srcCr`) 及其关联参数;
- 根据分辨率计算所需拷贝长度;
- 循环遍历每一行执行 memcpy 操作。
以下是一段伪代码展示如何实现上述过程:
```c
// Assume all necessary variables have been properly initialized before this point.
size_t rows = grallocBufHeight;
for(size_t r = 0 ; r < rows ; ++r){
memcpy(dstY + r*ystride, srcY + r*src_stride_y, yRowBytes);
}
rows /= 2; // Because usually there's half as many chrominance lines compared with luma ones.
for(size_t r = 0 ; r < rows ; ++r){
memcpy(dstCb + r*cStride, srcCb + r*src_stride_cb, cbRowBytes);
memcpy(dstCr + r*cStride, srcCr + r*src_stride_cr, crRowBytes);
}
```
以上片段假定已经获得了正确的源指针及其各自的跨距值,并且知道每行列所占的实际字节数目[^2]。
#### 4. 实际案例中的注意事项
由于不同的设备制造商可能对内部图形子系统的具体实现存在定制化调整,所以在移植涉及此类低级操作的应用程序之前应当仔细查阅相关文档说明。另外还需留意端序问题可能导致兼容性障碍等情况的发生。
---
###
阅读全文
相关推荐


















