zoukankan      html  css  js  c++  java
  • 将 h264 格式转换为YUV数据

    废话少说,直接贴上代码。

    decode_yuv.c

    /*
     * =====================================================================================
     *
     *       Filename:  decode_yuv.c
     *
     *    Description:  
     *
     *        Version:  1.0
     *        Created:  11/15/17 15:26:12
     *       Revision:  none
     *       Compiler:  gcc
     *
     *         Author:  linsheng.pan (), life_is_legend@163.com
     *   Organization:  
     *
     * =====================================================================================
     */
    #include <stdlib.h>
    
    
    #include <libavcodec/avcodec.h>
    #include <libavformat/avformat.h>
    #include <libswscale/swscale.h>
    #include <libavutil/imgutils.h>
    
    
    void usage(void)
    {
        printf("decode_yuv input_file output_file.yuv
    ");
    }
    
    
    int main(int argc, char *argv[])
    {
    
        if(argc != 3)
        {
            usage();
            return -1;
        }
    
    
        char *input_file = argv[1];
        char *output_file = argv[2];
    
    
        AVFormatContext *pFormatCtx = NULL;
        AVCodecContext *pCodecCtx = NULL;
        AVCodec *pCodec = NULL;
        AVFrame *pFrameYUV = NULL;
        AVFrame *pFrame = NULL;
        AVPacket *packet = NULL;
        uint32_t i = 0;
        int videoindex = -1;
        int y_size = -1;
        int ret = 0;
        int got_picture = 0;
        uint8_t *out_buffer = NULL;
        struct SwsContext *img_convert_ctx = NULL;
    
    
        FILE *fp = fopen(output_file, "wb+");
    
    
        av_register_all();
        avformat_network_init();
    
    
        pFormatCtx = avformat_alloc_context();
        if(!pFormatCtx)
        {
            printf("Error: call avformat_alloc_context failed!");
            return -1;
        }
    
    
        //打开视频文件
        if(0 != avformat_open_input(&pFormatCtx, input_file, NULL, NULL))
        {
            printf("Error: call avformat_open_input failed!
    ");
            return -1;
        }
    
    
        //获取视频信息
        if(avformat_find_stream_info(pFormatCtx, NULL) < 0)
        {
            printf("Error: call avformat_find_stream_info failed!
    ");
            return -1;
        }
    
    
        //查找解码器
        videoindex = -1;
        for(i = 0; i < pFormatCtx->nb_streams; ++i)
        {
            if(AVMEDIA_TYPE_VIDEO == pFormatCtx->streams[i]->codec->codec_type)
            {
                videoindex = i;
                break;
            }
        }
        if(-1 == videoindex)
        {
            printf("Error: can't find a video stream!
    ");
            return -1;
        }
        pCodecCtx = pFormatCtx->streams[videoindex]->codec;
        pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
        if(!pCodec)
        {
            printf("Error: Codec not find!
    ");
            return -1;
        }
    
    
        //打开解码器
        if(avcodec_open2(pCodecCtx, pCodec, NULL) < 0)
        {
            printf("Error: Can't open codec!
    ");
            return -1;
        }
    
        printf("width = %d
    ", pCodecCtx->width);
        printf("height = %d
    ", pCodecCtx->height);
    
    
        //将pFrameYUV 和 out_buffer 关联上
        pFrame = av_frame_alloc();
        pFrameYUV = av_frame_alloc();
        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);
    
    
        packet = (AVPacket *)av_malloc(sizeof(AVPacket));
        av_init_packet(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);
    
    
        //打印文件信息
        printf("#------------------------------#
    ");
        av_dump_format(pFormatCtx, 0, input_file, 0);
        printf("#------------------------------#
    ");
    
        while(av_read_frame(pFormatCtx, packet) >= 0)
        {
            if(videoindex == packet->stream_index)
            {
               ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, packet);
               if(ret < 0)
               {
                   printf("Error: Decode failed!
    ");
                   return -1;
               }
    
    
               if(got_picture)
               {
                   sws_scale(img_convert_ctx, (uint8_t *)pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameYUV->data, pFrameYUV->linesize);
    
    
                   y_size = pCodecCtx->width * pCodecCtx->height;
                   fwrite(pFrameYUV->data[0], 1, y_size, fp);
                   fwrite(pFrameYUV->data[1], 1, y_size/4, fp);
                   fwrite(pFrameYUV->data[2], 1, y_size/4, fp);
                   printf("Succeed to decode 1 Frame!
    ");
               }
            }
    
            av_free_packet(packet);
        }
    
    
        //flush decoder
        //当av_read_frame 退出循环的时候,实际上解码器中可能还包含
        //剩余的几帧数据。直接调用avcodec_decode_video2获得AVFrame ,
        //而不再向解码器传递AVPacket
        while(1)
        {
            ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, packet);
            if(ret < 0)
            {
                break;
            }
            if(!got_picture)
            {
                break;
            }
    
    
            sws_scale(img_convert_ctx, (uint8_t *)pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameYUV->data, pFrameYUV->linesize);
    
    
            y_size = pCodecCtx->width * pCodecCtx->height;
            fwrite(pFrameYUV->data[0], 1, y_size, fp);
            fwrite(pFrameYUV->data[1], 1, y_size/4, fp);
            fwrite(pFrameYUV->data[2], 1, y_size/4, fp);
            printf("Succeed to decode 1 Frame!
    ");
    
    
        }
    
    
        sws_freeContext(img_convert_ctx);
        fclose(fp);
        av_frame_free(&pFrame);
        av_frame_free(&pFrameYUV);
        avcodec_close(pCodecCtx);
        avformat_close_input(&pFormatCtx);
    
    
        return 0;
    }

    编译gcc decode_yuv.c -o decode_yuv -lavformat -lavcodec -lavutil -lswscale

  • 相关阅读:
    centos7安装gitlab
    jenkins 部署k8s-jar包项目
    jenkins部署k8s项目-CICD
    pipeline
    jenkins打包
    jenkins 按角色设置管理权限
    1 jenkins的介绍和安装
    PyTables的下载和安装
    解决python报错:ImportError: No module named shutil_get_terminal_size 的方法
    nodejs安装失败
  • 原文地址:https://www.cnblogs.com/standardzero/p/12553173.html
Copyright © 2011-2022 走看看