关闭

[置顶] ffmpeg透明贴图

标签: c++ffmpeg视频video
432人阅读 评论(0) 收藏 举报
分类:
//<span style="font-family: monospace; white-space: pre; background-color: rgb(240, 240, 240);">读取视频每帧的AVFrame,和图片的AVFrame,两个Frame都为RGBA格式,ChangeFMT为转换格式方法(通过sws_scale),通过data中的RGBA的数据进行贴图,alpha 为算出的图片的透明度,下面只写了贴图方法。注:只有RGBA格式中含有透明通道。转换格式方法请用ffmpeg自带的sws_scale</span>
{
AVFrame* fr = NULL;
do {
fr = renew_video_frame(frame);
if (!fr)
break;
int x, y, i, j, n = fr->linesize[0];


std::map<std::string, EffectParam>::iterator its = g_map.begin();
//将视频帧格式由yuv420p转换成RGBA
AVFrame* tempfrm = avcodec_alloc_frame();
tempfrm = ChangeFmt(fr, m_vstream->codec->pix_fmt, PIX_FMT_RGBA, m_vstream->codec->width, m_vstream->codec->height);

if (tempfrm == NULL)
{
printf("Change Format Error");
break;
}
//计算当前视频时间
double d_time = duration*(pcv_frames + 1);


for (its; its != g_map.end(); its++){
if (d_time >= its->second.time_start && d_time <= its->second.time_end)
{
AVFrame* picfr = av_frame_alloc();

int h = its->second.frm->height;
int w = its->second.frm->width;
int sw = m_vstream->codec->width;
int sh = m_vstream->codec->height;
int ofx = its->second.position_x;
int ofy = its->second.position_y;
double width = its->second.width;
double height = its->second.height;

//将读取的图片格式转成RGBA格式
picfr = ChangeFmt(its->second.frm, PIX_FMT_RGBA, PIX_FMT_RGBA, width, height);
if (picfr == NULL)
break;
uint8_t* ftbf = picfr->data[0];
unsigned int ftn = picfr->linesize[0];
unsigned int tempftn = tempfrm->linesize[0];

for (int y = 0; y < picfr->height; y++)
{
for (int x = 0; x < picfr->width; x++)
{
unsigned int ss = y*ftn + x * 4;
uint8_t* inds = &ftbf[ss];

//下面为有透明通道和不透明通道时的一个判断,但是这里用不到
/* if (inds[3] == 0xff)
{
if ((y + ofy) > tempfrm->height || (x + ofx) > tempfrm->width)
break;
i = (y + ofy)*tempftn + (x + ofx) * 4;


tempfrm->data[0][i] = picfr->data[0][ss];
tempfrm->data[0][i + 1] = picfr->data[0][ss + 1];
tempfrm->data[0][i + 2] = picfr->data[0][ss + 2];
tempfrm->data[0][i + 3] = picfr->data[0][ss + 3];
}
else
{*/
//下面为视频和图片的贴图的计算方法,通过RGBA四个通道计算。包含透明通道
int indtemp = picfr->data[0][ss + 3];//十六进制的透明通道的大小
if ((y + ofy) > tempfrm->height || (x + ofx) > tempfrm->width)
break;
double alpha = (double)indtemp / 255;<span style="white-space:pre">	</span>//透明度
i = (y + ofy)*tempftn + (x + ofx) * 4;
tempfrm->data[0][i] = alpha*(picfr->data[0][ss]) + (1 - alpha)*(tempfrm->data[0][i]);
tempfrm->data[0][i + 1] = alpha*(picfr->data[0][ss + 1]) + (1 - alpha)*(tempfrm->data[0][i + 1]);
tempfrm->data[0][i + 2] = alpha*(picfr->data[0][ss + 2]) + (1 - alpha)*(tempfrm->data[0][i + 2]);
tempfrm->data[0][i + 3] = picfr->data[0][ss + 3];
//}
}
}
}
}

//最后将RGBA转化成yuv420p就可以了
fr = ChangeFmt(tempfrm, PIX_FMT_RGBA, m_vstream->codec->pix_fmt, m_vstream->codec->width, m_vstream->codec->height);
if (fr == NULL)
{
printf("Change Format Error");
break;
}

if (fr)
av_frame_free(&fr);
}


0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:4323次
    • 积分:114
    • 等级:
    • 排名:千里之外
    • 原创:6篇
    • 转载:3篇
    • 译文:0篇
    • 评论:0条
    文章分类