作者:虚坏叔叔
博客:https://xuhss.com
早餐店不会开到晚上,想吃的人早就来了!?
完成扩展库pyffmpeg尺寸转换空间申请释放和处理
XFFmpeg.h
添加成员变量rgb
用于存储输出的图像数据
// 输出的图像数据
unsigned char *rgb = 0;
在XFFmepg.cpp
中, 分配这块内存
bool XFFmpeg::Open(const char *url)
{
printf("XFFmpeg::open %s\n", url);
// 打开视频 解封装
int re =avformat_open_input(&ic, url, 0, 0);
if (re != 0)
{
char buf[1024] = { 0 };
av_strerror(re, buf, 1023);
printf("avformat open fail:%s\n", buf);
return false;
}
// 获取流
avformat_find_stream_info(ic, 0);
// 获取视频总时长
this->totalms = ic->duration / (AV_TIME_BASE / 1000);
printf("Total Ms =%d\n", totalms);
// 打开解码器 0视频 1音频
AVCodecParameters *para = ic->streams[0]->codecpar;
// 找到解码器
AVCodec * codec = avcodec_find_decoder(para->codec_id);
if (!codec)
{
printf("avcodec_find_decoder %d failed!\n", para->codec_id);
}
// 分配解码器上下文
vcodec = avcodec_alloc_context3(codec);
// 配置解码器上下文
avcodec_parameters_to_context(vcodec, para);
// 多线程解码
vcodec->thread_count = 8;
// 打开上下文
re = avcodec_open2(vcodec, 0, 0);
if (re != 0)
{
avcodec_free_context(&vcodec);
char buf[1024];
av_strerror(re, buf, sizeof(buf) - 1);
printf("avcodec_open2 failec:%s!\n", buf);
}
printf("avcodec_open2 successed \n");
// 空间分多了没事 不能少
rgb = new unsigned char[4096*2160*4];
return true;
}
在Close
函数中释放这块内存
void XFFmpeg::Close()
{
printf("XFFmpeg::Close\n");
if (ic)
{
avformat_close_input(&ic);
}
if (vcodec)
{
avcodec_free_context(&vcodec);
}
if (pkt)
{
av_packet_free(&pkt);
}
if (frame)
{
av_frame_free(&frame);
}
if (rgb)
{
delete rgb;
rgb = NULL;
}
}
然后在Decode
函数中开始尺寸格式转换
bool XFFmpeg::Decode(int outwidth, int outheight) {
if (!vcodec || !pkt) return false;
// 发送到解码线程
int re = avcodec_send_packet(vcodec, pkt);
if (re != 0) return false;
if (!frame)
frame = av_frame_alloc();
// 取到解码后的数据 yuv 前几帧会失败 失败不代表解码失败 只表示解码缓冲没有数据
re = avcodec_receive_frame(vcodec, frame);
if (re != 0) return false;
// 像素格式和尺寸转换上下文
// 将yuv转为rgb 并调整尺寸
sws = sws_getCachedContext(sws,
vcodec->width, vcodec->height, vcodec->pix_fmt, //原宽高/像素格式(YUV420p)
outwidth, outheight, AV_PIX_FMT_BGRA, //目标宽高/像素格式(RGB)
SWS_BICUBIC, // 转换的算法
0, 0, 0
);
if (!sws)
{
// 出错一般都是参数格式有问题
printf("sws_getCachedContext failed\n");
return false;
}
if (!rgb)
{
printf("rgb is null\n");
return false;
}
uint8_t *data[AV_NUM_DATA_POINTERS] = { 0 };
data[0] = rgb;
int linesize[AV_NUM_DATA_POINTERS] = { 0 };
linesize[0] = outwidth * 4;// 一行的大小 width*单像素字节
int h = sws_scale(sws,
frame->data, // 源数据
frame->linesize, // 行大小 行对齐
0,
frame->height,
data, // sws输出数据和行大小
linesize
);
printf("[%d]", h);
return true;
}
解码到尺寸格式转换就成功了。
转载请注明:xuhss » Python&C++相互混合调用编程全面实战-34完成扩展库pyffmpeg尺寸转换空间申请释放和处理