【音视频】FFmpeg打开视频 | 保存图片

1、初始化FFmpeg

av_register_all(); //初始化FFMPEG  调用了这个才能正常使用编码器和解码器

  但是这个函数如今已经没什么用了,它的就是把你定义和系统初始化的编码器和解码器连接起来而已,然后就没有了。

  现在解码器和编码器的初始化都是通过定义全局变量来初始化的。与原来相比,唯一的改变就是使用数组替换链表完成解码器和编码器的初始化。

## 参考文章:https://www.jianshu.com/p/ebb219ec1c0f

 

 2、分配一个AVFormatContext,FFMPEG所有的操作都要通过这个AVFormatContext数据结构来进行

AVFormatContext *pFormatCtx = avformat_alloc_context();

  AVFormatContext是一个贯穿始终的数据结构,很多函数都要用到它作为参数。

  此结构包含了一个视频流的格式内容:AVInputFormat(or AVOutputFormat同一时间AVFormatContext内只能存在其中一个),和AVStream、AVPacket这几个重要的数据结构以及一些其他的相关信息,比如title,author,copyright等。还有一些可能在编解码中会用到的信息,诸如:duration, file_size, bit_rate等。

 

3、打开视频文件:

char *file_path = "./movie/ifwithoutu.mp4";
avformat_open_input(&pFormatCtx, file_path, NULL, NULL);

  

 

4、视频打开之后,查找文件中的视频流

    ///循环查找视频中包含的流信息,直到找到视频类型的流    
    ///便将其记录下来 保存到videoStream变量中
    ///这里我们现在只处理视频流  音频流先不管他
    for (i = 0; i < pFormatCtx->nb_streams; i++) 
    {
        if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) 
        {
            videoStream = i;
        }
    }
 
    ///如果videoStream为-1 说明没有找到视频流
    if (videoStream == -1) 
    {
        printf("Didn't find a video stream.");
        return -1;
    }    

  

5、根据视频流,打开一个解码器来解码

    ///查找解码器    
    pCodecCtx = pFormatCtx->streams[videoStream]->codec;
    pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
 
    if (pCodec == NULL) 
    {
        printf("Codec not found.");
        return -1;
    }
 
    ///打开解码器
    if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) 
    {
        printf("Could not open codec.");
        return -1;
    }

  FFmpeg可以让我们根据查找到的视频流信息获取到解码器,不需要知道实际用到的是什么解码器

 

6、读取视频

     int y_size = pCodecCtx->width * pCodecCtx->height;
    AVPacket *packet = (AVPacket *) malloc(sizeof(AVPacket)); //分配一个packet
    av_new_packet(packet, y_size); //分配packet的数据
 
    if (av_read_frame(pFormatCtx, packet) < 0)
    {
        break; //这里认为视频读取完了
    }

  av_read_frame读取的是一帧视频,并存入一个AVPacket的结构中

 

7、视频里的数据是经过编码压缩的,需要将其解码

   if (packet->stream_index == videoStream) 
    {        
        ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture,packet);
 
        if (ret < 0) 
        {
            printf("decode error.");
            return -1;
        }
    }    

  

8、解码器解码之后得到的图像数据都是YUV420格式的,需要将其保存成图片文件,因此需要转换为RGB格式

    if (got_picture) 
    {        
        sws_scale( img_convert_ctx,
                   (uint8_t const * const *) pFrame->data,
                   pFrame->linesize, 
                   0, 
                   pCodecCtx->height, 
                   pFrameRGB->data,
                   pFrameRGB->linesize
); }

  

9、将RGB图片写入

SaveFrame(pFrameRGB,
                 pCodecCtx->width,
                 pCodecCtx->height,
                 index++
);

  

 

错误:

(1):改成  AV_PIX_FMT_RGB24

 

posted @ 2019-08-28 23:51  XieXinBei0318  阅读(674)  评论(0编辑  收藏  举报