ffmpeg解码yuv数据

作者: jeffleefree | 来源:发表于2016-04-14 19:59 被阅读946次

    参与了公司的开发,需要将h264的数据转为yuv,然后再winform里面实时显示,
    再大牛的帮助下,开始明白了一点,我把简单的步骤记一下。
    网上有个博客,<code> http://blog.csdn.net/leixiaohua1020</code>
    里面记录了关于解码,编码方方面面的知识。
    在解码的dll编写有四个部分,加载decoder,卸载decoder,开始解码和将yuv数据转为rgb数据,
    先初始化一些变量,

    AVFormatContext 是储存需要转码的文件的结构体,
    AVCodeContext   是解码器的结构体,
    AVFrame         是转码后一帧数据所存储的结构体,
    uint8_t         指向数据地址的指针,
    AVPacket        存储解码前数据的结构体,
    struct SwsContext *img_convert_ctx   转码所需要的结构体,
    <b>
        av_register_all();   注册所有的编解码器
        avformat_network_init();  初始化
        pFormatCtx = avformat_alloc_context();  这是一个重要的数据对象,存储
    原视频的height,width,timesize,framedata。
    </b>
    avformat_open_input(&pFormatCtx, filepath, NULL, NULL) 打开需要解码的文件
    avformat_find_stream_info(pFormatCtx, NULL)  分析该源文件有可以解码的流码
    pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO 找到视频流的开始点
    pCodecCtx = pFormatCtx->streams[videoindex]->codec; 找到文件流的类型
    pCodec = avcodec_find_decoder(pCodecCtx->codec_id); 找到解码文件的解码器编号
    avcodec_open2(pCodecCtx, pCodec, NULL)<0)  pCodec == NULL 如果没有找到解码器,
    就退出。
    out_buffer = (uint8_t *)av_malloc(avpicture_get_size(AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height)); //一帧大小的缓冲区
    avpicture_fill((AVPicture *)pFrameYUV, out_buffer, AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height);  //将pFrame的大小设为out_buffer
    packet = (AVPacket *)av_malloc(sizeof(AVPacket)); //初始化packet
    img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt,
            pCodecCtx->width, pCodecCtx->height, AV_PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL); // 获取转码的参数
    av_read_frame(pFormatCtx, packet)// 读取一帧数据
    avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, packet);// 如果包中的流是视频数据,就将它转码.
    其中的got_picture可以认为是一个标志,如果解码成功则不为NULL,
    <b>
    sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize, 0, pCodecCtx->height,
                        pFrameYUV->data, pFrameYUV->linesize);// 转码的数据
    </b>
    现在的pFrameYUv里面就是我们需要的yuv数据。
    

    <blockquote>
    1.aviocontext ffmepg管理输入输出的结构体,输入数据的缓存。
    2.avformatcontext 它是FFMPEG解封装(flv,mp4,rmvb,avi)功能的结构体
    3.AVCodec 是存储编解码器信息的结构体
    4.AVInputFormat //音视频文件的解封装器
    5.AVIOContext 管理输入输出数据的结构体
    6.AVStream是存储每一个视频/音频流信息的结构体
    7.muxer是指合并文件,即将视频文件、音频文件和字幕文件合并为某一个视频格式
    //公共操作函数
    8.int(*get_buffer)(struct AVCodecContext *c, AVFrame pic);
    9.void(
    release_buffer)(struct AVCodecContext *c, AVFrame pic);
    10.int(
    reget_buffer)(struct AVCodecContext *c, AVFrame *pic);
    11.av_dump_format文件信息输出到标准错误输出里。
    12.avcodec_alloc_context3():为AVCodecContext分配内存。
    13.avcodec_open2():打开解码器。
    14.avcodec_decode_video2():解码一帧数据。
    15.av_parser_init():初始化AVCodecParserContext。av_parser_parse2():解析获得一个Packet。
    16.AVFrame:存储一帧解码后的像素数据AVPacket:存储一帧(一般情况下)压缩编码数据
    17.avformat_alloc_context():创建AVFormatContext结构体。
    18.avformat_new_stream()创建AVStream结构体
    19.avformat_new_stream()中会调用avcodec_alloc_context3()创建AVCodecContext结构体。
    20.codec 编解码器,parsers 解析器,
    21.ffmpeg进行图像数据格式的转换以及图片的缩放应用中

    sws_getContext 函数可以看做是初始化函数
    int srcW,int srcH 为原始图像数据的高和宽;

      int dstW,int dstH 为输出图像数据的高和宽;
    
      enum AVPixelFormat srcFormat 为输入和输出图片数据的类型;eg:AV_PIX_FMT_YUV420、PAV_PIX_FMT_RGB24;
    
      int flags 为scale算法种类;eg:SWS_BICUBIC、SWS_BICUBLIN、SWS_POINT、SWS_SINC;
    
      SwsFilter *srcFilter ,SwsFilter *dstFilter,const double *param 可以不用管,全为NULL即可;
    

    22.sws_scale 函数则为执行函数,它的参数定义分别为:

      struct SwsContext *c 为sws_getContext函数返回的值;
    
      const uint8_t *const srcSlice[],uint8_t *const dst[] 为输入输出图像数据各颜色通道的buffer指针数组;
    
      const int srcStride[],const int dstStride[] 为输入输出图像数据各颜色通道每行存储的字节数数组;     
    
      int srcSliceY 为从输入图像数据的第多少列开始逐行扫描,通常设为0;
    
      int srcSliceH 为需要扫描多少行,通常为输入图像数据的高度;
    

    23.ffmpeg avpacket每一个包是一个完整的数据帧,来暂存解复用之后、解码之前的媒体数据(一个音/视频帧、一个字幕包等)及附加信息(解码时间戳、显示时间戳、时长等)
    24.avframe存储的是解码后的数据 avpacket是解码前的数据
    ================================================
    25.将yuv数据保存和将它绘制出来是不同的解析过程。

    </blockquote>

    相关文章

      网友评论

        本文标题:ffmpeg解码yuv数据

        本文链接:https://www.haomeiwen.com/subject/tenglttx.html