• 利用ffmpeg将H264流 解码为RGB 分类: VC++ ffmpeg-SDL-VLC-Live555 2015-08-07 11:39 155人阅读 评论(0) 收藏


    利用H264解码分为几个步骤:

     

    注意一点在添加头文件的时候要添加extern "C",不然会出现错误

    1. extern "C"  
    2. {  
    3. #include <avcodec.h>  
    4. #include <avformat.h>  
    5. #include <avutil.h>  
    6. #include <swscale.h>  
    7. };  


     

     

    这里申明了几个全局变量

    1. AVCodec         *pCodec = NULL;  
    2. AVCodecContext  *pCodecCtx = NULL;  
    3. SwsContext      *img_convert_ctx = NULL;  
    4. AVFrame         *pFrame = NULL;  
    5. AVFrame         *pFrameRGB = NULL;  


     

    1. 初始化

    1. int H264_Init(void)  
    2. {  
    3.     /* must be called before using avcodec lib*/  
    4.     avcodec_init();  
    5.     /* register all the codecs */  
    6.     avcodec_register_all();  
    7.   
    8.     /* find the h264 video decoder */  
    9.     pCodec = avcodec_find_decoder(CODEC_ID_H264);  
    10.     if (!pCodec) {  
    11.         fprintf(stderr, "codec not found ");  
    12.     }  
    13.     pCodecCtx = avcodec_alloc_context();  
    14.   
    15.     /* open the coderc */  
    16.     if (avcodec_open(pCodecCtx, pCodec) < 0) {  
    17.         fprintf(stderr, "could not open codec ");  
    18.     }  
    19.     // Allocate video frame  
    20.     pFrame = avcodec_alloc_frame();  
    21.     if(pFrame == NULL)  
    22.         return -1;  
    23.     // Allocate an AVFrame structure  
    24.     pFrameRGB=avcodec_alloc_frame();  
    25.     if(pFrameRGB == NULL)  
    26.         return -1;  
    27.   
    28.   
    29.       
    30.     return 0;  
    31.   
    32. }  

    在最早使用的时候没有使用全局变量,初始化中也就只有init和regisger这两个函数,而这样做的下场是,非关键帧全部无法解码,只有关键帧才有办法解码。

    2. 解码

    解码的时候avcodec_decode_video函数是进行解码操作,在外部定义outputbuf的大小时,pixes*3,outsize是返回的outputbuf的size,值也是pixes*3。

     

    在解码的时候这几句话的意义是将YUV420P的数据倒置。在原先使用中,发现解出来的图像居然是中心旋转图,后面在网上找了些办法,觉得这个比较实用。解码实时是很重要的,图像转化完之后也可以讲RGB图再次转化,那样也能成为一个正的图,但是那样效率就明显低了。

    1. pFrame->data[0] += pFrame->linesize[0] * (pCodecCtx->height-1);  
    2. pFrame->linesize[0] *= -1;  
    3. pFrame->data[1] += pFrame->linesize[1] * (pCodecCtx->height/2 - 1);;  
    4. pFrame->linesize[1] *= -1;  
    5. pFrame->data[2] += pFrame->linesize[2] * (pCodecCtx->height/2 - 1);;  
    6. pFrame->linesize[2] *= -1;  


     

     

    1. int H264_2_RGB(unsigned char *inputbuf, int frame_size, unsigned char *outputbuf, unsigned int*outsize)  
    2. {  
    3.       
    4.     int             decode_size;  
    5.     int             numBytes;  
    6.     int             av_result;  
    7.     uint8_t         *buffer = NULL;  
    8.   
    9.     printf("Video decoding ");  
    10.   
    11.     av_result = avcodec_decode_video(pCodecCtx, pFrame, &decode_size, inputbuf, frame_size);  
    12.     if (av_result < 0)  
    13.     {  
    14.         fprintf(stderr, "decode failed: inputbuf = 0x%x , input_framesize = %d ", inputbuf, frame_size);  
    15.         return -1;  
    16.     }  
    17.   
    18.     // Determine required buffer size and allocate buffer  
    19.     numBytes=avpicture_get_size(PIX_FMT_BGR24, pCodecCtx->width,  
    20.         pCodecCtx->height);  
    21.     buffer = (uint8_t*)malloc(numBytes * sizeof(uint8_t));  
    22.     // Assign appropriate parts of buffer to image planes in pFrameRGB  
    23.     avpicture_fill((AVPicture *)pFrameRGB, buffer, PIX_FMT_BGR24,  
    24.         pCodecCtx->width, pCodecCtx->height);  
    25.   
    26.     img_convert_ctx = sws_getCachedContext(img_convert_ctx,pCodecCtx->width,pCodecCtx->height,  
    27.         //PIX_FMT_YUV420P,pCodecCtx->width,pCodecCtx->height,pCodecCtx->pix_fmt,  
    28.         pCodecCtx->pix_fmt,pCodecCtx->width,pCodecCtx->height,PIX_FMT_RGB24 ,  
    29.         SWS_X ,NULL,NULL,NULL) ;  
    30.     if (img_convert_ctx == NULL)   
    31.     {  
    32.   
    33.         printf("can't init convert context! ") ;  
    34.         return -1;  
    35.     }  
    36.     pFrame->data[0] += pFrame->linesize[0] * (pCodecCtx->height-1);  
    37.     pFrame->linesize[0] *= -1;  
    38.     pFrame->data[1] += pFrame->linesize[1] * (pCodecCtx->height/2 - 1);;  
    39.     pFrame->linesize[1] *= -1;  
    40.     pFrame->data[2] += pFrame->linesize[2] * (pCodecCtx->height/2 - 1);;  
    41.     pFrame->linesize[2] *= -1;  
    42.     sws_scale(img_convert_ctx, pFrame->data, pFrame->linesize,  
    43.         0, 0 - pCodecCtx->width, pFrameRGB->data, pFrameRGB->linesize);  
    44.       
    45.     if (decode_size)  
    46.     {  
    47.         *outsize = pCodecCtx->width * pCodecCtx->height * 3;  
    48.         memcpy(outputbuf, pFrameRGB->data[0], *outsize);  
    49.     }     
    50.   
    51.   
    52.     free(buffer);  
    53.     return 0;  
    54. }  

    //解码yuv 修改 PIX_FMT_YUV420P	
    memcpy(outputbuf, pFrameRGB->data[2], 720*576/4);
    			memcpy(outputbuf, pFrameRGB->data[1], 720*576/4);
    			memcpy(outputbuf, pFrameRGB->data[0], 720*576);
    



    3. 释放资源

    资源的回收。

    1. void H264_Release(void)  
    2. {  
    3.     avcodec_close(pCodecCtx);  
    4.     av_free(pCodecCtx);  
    5.     av_free(pFrame);  
    6.     av_free(pFrameRGB);  
    7. }  

    版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 相关阅读:
    抽象工厂模式
    工厂方法模式
    assert断言
    非日志警告
    requests获取所有状态码
    在线工具、资料
    重定向、feed输出:控制台输出的内容存放到文件
    正则表达式python
    python提取相对路径
    logger类
  • 原文地址:https://www.cnblogs.com/mao0504/p/4712505.html
Copyright © 2020-2023  润新知