Python&C++相互混合调用编程全面实战-34完成扩展库pyffmpeg尺寸转换空间申请释放和处理

Python&C++ xuhss 368℃ 0评论

作者:虚坏叔叔
博客: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;
}

解码到尺寸格式转换就成功了。

58cbfc986d9a47b99356bd73a6bff57c - Python&C++相互混合调用编程全面实战-34完成扩展库pyffmpeg尺寸转换空间申请释放和处理

转载请注明:xuhss » Python&C++相互混合调用编程全面实战-34完成扩展库pyffmpeg尺寸转换空间申请释放和处理

喜欢 (2)

您必须 登录 才能发表评论!