FFmepg 解码码流数据

FFmepg 解码码流数据

FILE *p = fopen(FileName,"rb+");
int fill_iobuffer(void * opaque,uint8_t *buf,int buf_size)
{
    if(!feof(p))
    {
        int true_size=fread(buf,1,buf_size,p);
        return true_size;
    }
    else
    {
        return -1;
    }
}



int main()
{
	//注册组件
    av_register_all();

    //创建存储视频流信息的结构体
    AVFormatContext *fmatC = avformat_alloc_context();
    //AVFormatContext *fmatC_temp = avformat_alloc_context();

    //开辟缓存区
    unsigned char * iobuffer=(unsigned char *)av_malloc(100000);

    if(iobuffer == NULL)
    {
        qDebug()<<"iobuff is null";
    }

    //AVInputFormat* in_fmt = av_find_input_format("yuv420");
    //查找视频流信息 有h264、avi、mjpeg等
    AVInputFormat* in_fmt = av_find_input_format("mjpeg");

    //数据指针
    //avio_alloc_context(unsigned char *buffer,int buffer_size,int write_flag,void *opaque,
    //int (*read_packet)(void *opaque, uint8_t *buf, int buf_size),
    //int (*write_packet)(void *opaque, uint8_t *buf, int buf_size),
    //int64_t (*seek)(void *opaque, int64_t offset, int whence));
    // param1 为缓存的地址
    // param2 为缓存大小
    // param3 设置缓存区是否可写 可写为1 不可写为1
    // param4 设置用来传给回调的参数 可以把文件指针传过去 但不建议
    // param5 读 回调函数
    // param6 写回调函数
    // param7 查找指定位置的字节的回调函数
    AVIOContext *avio =avio_alloc_context(iobuffer,100000,0,NULL,fill_iobuffer,NULL,NULL);

    int err = -1;
    //把指针赋给fmatC
    fmatC->pb=avio;

    //打开视频流获取信息
    //调用一次fill_iobuffer
    err = avformat_open_input(&fmatC,"",in_fmt,NULL);
    if(err < 0)
    {
        qDebug()<<"open error";
        return 0;
    }
    int ret = -1;

    //查找流媒体信息
    //调用一次fill_iobuffer
    ret = avformat_find_stream_info(fmatC, NULL);
    if(ret < 0)
    {
        qDebug()<<":find stream info failed!";
        return 0;
    }

    int videoIndex = -1;
    //找到视频流
    for(int i = 0; i < fmatC->nb_streams; i++)
        if(fmatC->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
        {
            videoIndex = i;
            break;
        }

    //获取视频流的基本信息
    AVCodecContext *codec = fmatC->streams[0]->codec;
    //找到解码器
    AVCodec *decodec = avcodec_find_decoder(codec->codec_id);
    if(decodec == NULL)
    {
        qDebug()<<":find decodec failed!";
        return 0;
    }

    ret = -1;
    //根据视频流信息初始化解码器
    ret = avcodec_open2(codec,decodec, NULL);
    if(ret != 0)
    {
        qDebug()<<":open decodec failed!";
        return 0;
    }

    uint8_t *buffer;
    SwsContext *sws_context;
    //初始化AVPkt
    AVPacket *pkt = (AVPacket *)malloc(sizeof(AVPacket));//码流数据,GCC编译
    int frameSize = codec->width * codec->height;
    //为pkt分配一个指定大小的内存
    av_new_packet(pkt, frameSize);
    AVFrame *dstFrame;
    AVFrame *picture;
    //初始化Frame
    picture = av_frame_alloc();
    dstFrame = av_frame_alloc();
    //统计RGB32格式帧的大小
    int numByte = avpicture_get_size(AV_PIX_FMT_RGB32, codec->width,codec->height);
    buffer = (uint8_t *)av_malloc(numByte * sizeof(uint8_t));
    //将buffer填充到data里,因为后面需要使用到dstFrame的data
    avpicture_fill((AVPicture *)dstFrame, buffer, AV_PIX_FMT_RGB32,codec->width,codec->height);
    //获取格式转换的结构体
    sws_context = sws_getContext(codec->width,codec->height,codec->pix_fmt,codec->width,codec->height, AV_PIX_FMT_RGB32, SWS_BICUBIC, NULL, NULL, NULL);
    ret = 0;
    int count = 0;
    //读取视频流信息
    //调用fill_iobuffer 直到读取到一帧
    while(av_read_frame(fmatC, pkt) == 0)
    {
        if(pkt->stream_index == 0)//从流媒体中选取视频
        {
            count++;
            int got_picture_ptr = -1;
            //把pkt的数据解码到picture
            avcodec_decode_video2(codec,picture, &got_picture_ptr, pkt);
            if(got_picture_ptr)
            {
                ret = 1;
                //格式转换
                sws_scale(sws_context,picture->data,picture->linesize, 0,picture->height,dstFrame->data,dstFrame->linesize);//剔除无效数据,buffer和data同时修改,0是起始位置,picture->height是处理多少行
                QImage((uchar *)dstFrame->data[0],codec->width, codec->height, QImage::Format_RGB32).save(QString("D://CheckImage/%1.png").arg(QString::number(count)));
            }
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BigProgrambug

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值