项目场景:
接上文:[学习记录:RGBA格式数据加边框](https://blog.csdn.net/weixin_38978427/article/details/121064425) 参考文章:[视音频数据处理入门:RGB、YUV像素数据处理](https://blog.csdn.net/leixiaohua1020/article/details/50534150)问题描述:
实现yuv420p数据添加边框。
实现:
- m_width == m_SwsWidth && m_height == m_SwsHeight:
这个是最简单的,不需要任何处理。 - m_width == m_SwsWidth && m_height > m_SwsHeight:
宽度相同,但是高度不匹配,需要对上下分别填充 m_width * (m_height - m_SwsHeight)/2 边框。
//copy data[start~( start + len)] from src
bool CopyUnsignedChar(unsigned char *dest, int &pos, unsigned char *src, int start, int len)
{
if(start < 0 || len < 0)
{
printf("invalue.\n");
return false;
}
for(int i = start; i < start + len; i ++)
{
dest[pos ++] = src[i];
}
return true;
}
/**
* -------------
* | top |
* -------------
* -------------
* | pic |
* -------------
* -------------
* | buttom |
* -------------
*/
int diff_h = m_height - m_SwsHeight;
int diff_t = diff_h/2;
int diff_b = diff_h - diff_t;
//create top
int top_s = m_width * diff_t;
int top_size = av_image_get_buffer_size(AV_PIX_FMT_YUV420P, m_width, diff_t, 1);
uint8_t *top = (uint8_t*)av_malloc(top_size);
memset(top, 0, m_width * diff_t);//Y:black
memset(top + m_width * diff_t, 128, m_width * diff_t / 2); //UV:设置128 透明
//buttom
int buttom_s = m_width * diff_b;
int buttom_size = av_image_get_buffer_size(AV_PIX_FMT_YUV420P, m_width, diff_b, 1);
uint8_t *buttom = (uint8_t*)av_malloc(buttom_size);
memset(buttom, 0, m_width * diff_b);
memset(buttom + m_width * diff_b, 128, m_width * diff_b / 2);
//pic
int pic_s = m_width * m_SwsHeight;
int pos = 0;//标记图片数据的当前位置
//Y
//top
CopyUnsignedChar(m_picture_buf2, pos, top, 0, top_s);
//pic
CopyUnsignedChar(m_picture_buf2, pos, picture_buf, 0, pic_s);
//buttom
CopyUnsignedChar(m_picture_buf2, pos, buttom, 0, buttom_s);
//U
pos = m_width * m_height;
//top
CopyUnsignedChar(m_picture_buf2, pos, top, top_s, top_s/4);
//pic
CopyUnsignedChar(m_picture_buf2, pos, picture_buf, pic_s, pic_s/4);
//buttom
CopyUnsignedChar(m_picture_buf2, pos, buttom, buttom_s, buttom_s/4);
//V
pos = m_width * m_height * 5/4;
//top
CopyUnsignedChar(m_picture_buf2, pos, top, top_s * 5 / 4, top_s/4);
//pic
CopyUnsignedChar(m_picture_buf2, pos, picture_buf, pic_s * 5 / 4, pic_s/4);
//buttom
CopyUnsignedChar(m_picture_buf2, pos, buttom, buttom_s * 5 / 4, buttom_s/4);
av_free(top);
av_free(buttom);
- m_width > m_SwsWidth && m_height == m_SwsHeight:
高度相同,但是宽度不匹配,需要对左右分别填充 (m_width - m_SwsWidth )/2 * m_height 边框。
/**
* |--left--||--pic--||--right--|
*/
int diff_w = m_width - m_SwsWidth;
int diff_l = diff_w/2;
int diff_r = diff_w - diff_l;
int pos = 0;//记录图片当前位置
//left
int left_uv_w = diff_l/2;
int left_size = av_image_get_buffer_size(AV_PIX_FMT_YUV420P, diff_l, m_height, 1);
uint8_t *left = (uint8_t*)av_malloc(left_size);
memset(left, 0, diff_l * m_height);
memset(left + diff_l * m_height, 128, diff_l * m_height / 2);
//right
int right_uv_w = diff_r/2;
int right_size = av_image_get_buffer_size(AV_PIX_FMT_YUV420P, diff_r, m_height, 1);
uint8_t *right = (uint8_t*)av_malloc(right_size);
memset(right, 0, diff_r * m_height);
memset(right + diff_r * m_height, 128, diff_r * m_height / 2);
//combination:left==>>m_picture==>>right
//Y
for(int i = 0; i < m_height; i ++)
{
//left
CopyUnsignedChar(m_picture_buf2, pos, left, i * diff_l, diff_l);
//picture_buf
CopyUnsignedChar(m_picture_buf2, pos, picture_buf, i * m_SwsWidth, m_SwsWidth);
//right
CopyUnsignedChar(m_picture_buf2, pos, right, i * diff_r, diff_r);
}
printf("pos = %d, total:%d.\n", pos, m_width * m_height);
//U
for(int i = 0; i < m_height / 2; i ++)
{
//left
CopyUnsignedChar(m_picture_buf2, pos, left, i * left_uv_w + diff_l * m_height, left_uv_w);
//picture_buf
CopyUnsignedChar(m_picture_buf2, pos, picture_buf, i * m_SwsWidth/2 + m_SwsWidth * m_height, m_SwsWidth/2);
//right
CopyUnsignedChar(m_picture_buf2, pos, right, i * right_uv_w + diff_r * m_height, right_uv_w);
}
//V
for(int i = 0; i < m_height / 2; i ++)
{
//left
CopyUnsignedChar(m_picture_buf2, pos, left, i * left_uv_w + diff_l * m_height * 5 / 4, left_uv_w);
//m_picture_buf
CopyUnsignedChar(m_picture_buf2, pos, picture_buf, i * m_SwsWidth/2 + m_SwsWidth * m_height * 5 / 4, m_SwsWidth/2);
//right
CopyUnsignedChar(m_picture_buf2, pos, right, i * right_uv_w + diff_r * m_height * 5 / 4, right_uv_w);
}
av_free(left);
av_free(right);
- m_width > m_SwsWidth && m_height > m_SwsHeight:
宽度和高度不匹配,需要对上下m_width * (m_height - m_SwsHeight)/2 边框,左右 (m_width - m_SwsWidth )/2 * m_SwsHeight。
/**
* |----------------------top-----------------------|
* |--left--||------------pic------------||--right--|
* |-------------------buttom-----------------------|
*/
//top & buttom 's height
int diff_h = m_height - m_SwsHeight;
int diff_top = diff_h/2;
int diff_buttom = diff_h - diff_top;
//left & right 's width
int diff_w = m_width - m_SwsWidth;
int diff_left_w = diff_w/2;
int diff_right_w = diff_w - diff_left_w;
//left & right 's height
int diff_left_h = m_SwsHeight;
int diff_right_h = m_SwsHeight;
int row = 0;//pic_buf flag
//for Y
uint8_t* data_y = (uint8_t*)av_malloc(m_width * m_height);
row = 0;
for(int i = 0; i < m_height; i ++)
{
for(int j = 0; j < m_width; j++)
{
if( j < diff_left_w || j >= (diff_left_w + m_SwsWidth) || i < diff_top || i >= (diff_top + m_SwsHeight))
{
data_y[i * m_width + j] = 0;//black
}else
{
data_y[i * m_width + j] = picture_buf[row ++];
}
}
}
//for U
row = m_SwsWidth * m_SwsHeight;
uint8_t *data_u = (uint8_t*)av_malloc(m_width * m_height/4);
for(int i = 0; i < m_height/2; i ++)
{
for(int j = 0 ; j < m_width/2; j ++)
{
if(j < diff_left_w/2 || j >= (diff_left_w/2 + m_SwsWidth/2) || i < diff_top/2 || i >= (diff_top/2 + m_SwsHeight/2))
{
data_u[i * m_width/2 + j] = 128;//透明
}else
{
data_u[i * m_width/2 + j] = picture_buf[row ++];
}
}
}
//for V
row = m_SwsWidth * m_SwsHeight * 5 / 4;
uint8_t *data_v = (uint8_t*)av_malloc(m_width * m_height/4);
for(int i = 0; i < m_height/2; i ++)
{
for(int j = 0 ; j < m_width/2; j ++)
{
if(j < diff_left_w/2 || j >= (diff_left_w/2 + m_SwsWidth/2) || i < diff_top/2 || i >= (diff_top/2 + m_SwsHeight/2))
{
data_v[i * m_width/2 + j] = 128;
}else
{
data_v[i * m_width/2 + j] = picture_buf[row ++];
}
}
}
//copy to m_picture_buf2
memcpy(m_picture_buf2, data_y, m_width * m_height);
memcpy(m_picture_buf2 + m_width * m_height, data_u, m_width * m_height / 4);
memcpy(m_picture_buf2 + m_width * m_height * 5 / 4, data_v, m_width * m_height / 4);
//free
av_free(data_y);
av_free(data_u);
av_free(data_v);