FFmpeg 解碼出來(lái) AVFrame 后镰禾,要渲染出來(lái)正確的圖像志群,還是有不少問(wèn)題的,下面來(lái)看看幾種常見(jiàn)的渲染方式吧(以yuv格式為例)。
使用 AVFrame 的 width,height 直接渲染
在 width 和 lineSize 不一樣的情況下奶陈,渲染出來(lái)的圖像會(huì)有亂碼滞时。
int width - frame->width;
int width = frame->height;
glTexImage2D(texture_y, 0, GL_LUMINANCE, width, height, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, frame->data[0]);
glTexImage2D(texture_u, 0, GL_LUMINANCE, width/2, height/2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, frame->data[1]);
glTexImage2D(texture_v, 0, GL_LUMINANCE, width/2, height/2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, frame->data[2]);
使用 AVFrame 的 lineSize狗热,height 直接渲染
在 width 和 lineSize 不一樣的情況下驰怎,渲染出來(lái)的圖像會(huì)有綠邊。
int width - frame->width;
int width = frame->height;
glTexImage2D(texture_y, 0, GL_LUMINANCE, frame->linesize[0], height, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, frame->data[0]);
glTexImage2D(texture_u, 0, GL_LUMINANCE, frame->linesize[1], height/2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, frame->data[1]);
glTexImage2D(texture_v, 0, GL_LUMINANCE, frame->linesize[2], height/2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, frame->data[2]);
裁剪有效數(shù)據(jù)后渲染
直接裁剪內(nèi)存二打,性能開(kāi)銷(xiāo)比較大县忌。
int w - frame->width;
int h = frame->height;
if(y == nullptr){
y = new unsigned char[w*h];
}
if(u == nullptr){
u = new unsigned char[w*h/4];
}
if(v == nullptr){
v = new unsigned char[w*h/4];
}}
int l1 = frame->linesize[0];
int l2 = frame->linesize[1];
int l3 = frame->linesize[2];
for(int i= 0; i < h ; i++)
{
memcpy(y + w*i,frame->data[0] + l1* i, sizeof( unsigned char)*w);
}
for(int i= 0 ; i < h/2 ; i++)
{
memcpy(u + w/2*i,frame->data[1] + l2 * i, sizeof(unsigned char)*w/2);
memcpy(v + w/2*i,frame->data[2] + l3 * i, sizeof(unsigned char)*w/2);
}
glTexImage2D(texture_y, 0, GL_LUMINANCE, w, h, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, y);
glTexImage2D(texture_u, 0, GL_LUMINANCE, w/2, h/2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, u);
glTexImage2D(texture_v, 0, GL_LUMINANCE, w/2, h/2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, v);
渲染后再進(jìn)行裁剪
按 lineSize 去渲染,渲染的時(shí)候需要改變紋理坐標(biāo)继效。
int width - frame->width;
int width = frame->height;
glTexImage2D(texture_y, 0, GL_LUMINANCE, frame->linesize[0], height, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, frame->data[0]);
glTexImage2D(texture_u, 0, GL_LUMINANCE, frame->linesize[1], height/2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, frame->data[1]);
glTexImage2D(texture_v, 0, GL_LUMINANCE, frame->linesize[2], height/2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, frame->data[2]);
float textureCoords[] = {
0.0f, 0.0f, // bottom left
0.0f, 1.0f, // top left
1.0f, 1.0f, // top right
1.0f, 0.0f, // bottom right
};
textureCoords[5] = 1.0f * width/frame->linesize[0];
textureCoords[7] = 1.0f * width/frame->linesize[0];
glBindBuffer(GL_ARRAY_BUFFER, textureVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(textureCoords), textureCoords, GL_STATIC_DRAW);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
通過(guò)對(duì)比上面的四種渲染方式症杏,我們發(fā)現(xiàn)第四種不僅最高效,而且沒(méi)有異常問(wèn)題瑞信,因此值得推薦厉颤。