• 视频解析


    参考博客

    step 1

    http://baijiahao.baidu.com/s?id=1651732133043095764&wfr=spider&for=pc&isFailFlag=1

    安装ffmpeg

    step 2

    http://www.qmwxb.com/article/1252981.html

    代码如下

    t.c

    #include <stdio.h>
    #include <assert.h>
    #include "libavcodec/avcodec.h"
    #include <libavformat/avformat.h>
    #include <libswscale/swscale.h>
    
    
    void save_frame(AVFrame *pframe, int width, int height, int iframe){
         char filename[32];
         int y;
    
         sprintf(filename, "frame%d.ppm", iframe);
         FILE *fp = fopen(filename, "w+");
         assert(fp!=NULL);
    
         fprintf(fp, "P6
    %d %d
    255
    ", width, height); // header
    
         for (y=0; y<height;y++) fwrite(pframe->data[0]+y*pframe->linesize[0], 1, width*3, fp);
         fclose(fp);
    }
    
    
    int main(int argc, char *argv[]){
        if(argc<2){
            printf("usage:
    	 %s filename
    ",argv[0]);
        }
        av_register_all();
        AVFormatContext *pctx = NULL;
        if (avformat_open_input(&pctx, argv[1], NULL, NULL)!=0) {
             return -1;
        }
        assert(avformat_find_stream_info(pctx, NULL)>=0);
        av_dump_format(pctx, 0, argv[1], 0);
        int i, video_stream = -1;
        for (i=0; i<pctx->nb_streams; i++) {
         // 查找第一个视频流
             if (pctx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO) {
                 video_stream =i;
                 break;    
             }
         }
         if (-1==video_stream) {
             printf("no video stream detected
    ");
             return -1;
         }
         // pcodec_ctx 指向第一个视频流
         AVCodecContext *pcodec_ctx = pctx->streams[video_stream]->codec;
        AVCodec *pcodec = NULL;
         // 查找视频流对应的解码器
         pcodec = avcodec_find_decoder(pcodec_ctx->codec_id);
         if (NULL == pcodec) {
         printf("unsupported codec.
    ");
         return -1;
         }
         // 拷贝上下文
         AVCodecContext *pcodec_ctx_orig =
         avcodec_alloc_context3(pcodec);
         if (avcodec_copy_context(pcodec_ctx_orig, pcodec_ctx) != 0) {
             printf("couldn't copy codec context
    ");
             return -1;
         }
         // 打开编解码器
         if (avcodec_open2(pcodec_ctx, pcodec, NULL)){
            printf("couldn't open codec
    ");
             return -1;
         }
        AVFrame *pframe = av_frame_alloc();
         AVFrame *pframe_rgb = av_frame_alloc();
         assert(pframe && pframe_rgb);
        int num_bytes = avpicture_get_size(AV_PIX_FMT_RGB24,pcodec_ctx->width, pcodec_ctx->height);
         uint8_t *buffer = av_malloc(num_bytes * sizeof(uint8_t));
        avpicture_fill((AVPicture *)pframe_rgb,buffer,AV_PIX_FMT_RGB24,pcodec_ctx->width,pcodec_ctx->height);
        
        //读取
        int frame_finished;
         AVPacket pkt;
         // 初始化 sws 上下文,用于转换数据格式
         struct SwsContext *sws_ctx = sws_getContext(
         pcodec_ctx->width,
         pcodec_ctx->height,
         pcodec_ctx->pix_fmt,
         pcodec_ctx->width,
         pcodec_ctx->height,
         AV_PIX_FMT_RGB24,
         SWS_BILINEAR,
         NULL,
         NULL,
         NULL
         );
         i = 0; // 作为实例,只保存前 5 帧
         while (av_read_frame(pctx, &pkt) >= 0) {
             if (pkt.stream_index != video_stream) {
             continue;
             }
             avcodec_decode_video2(pcodec_ctx, pframe, &frame_finished, &pkt);
             if (!frame_finished) continue;        
             sws_scale(sws_ctx, pframe->data, pframe->linesize,0, pcodec_ctx->height, pframe_rgb->data, pframe_rgb->linesize);
             if (++i<=5){
                save_frame(pframe_rgb, pcodec_ctx->width, pcodec_ctx->height,i);
             }
    
         }
        
         av_free_packet(&pkt);
        
        // 释放内存
         av_free(buffer);
         av_free(pframe_rgb);
         av_free(pframe);
         // 关闭 codec
         avcodec_close(pcodec_ctx);
         avcodec_close(pcodec_ctx_orig);
         // 关闭打开的文件
         avformat_close_input(&pctx);
    }    

    安装以下两个命令

    sudo apt-get install build-essential
    sudo apt-get install cmake git libgtk2.0-dev pkg-config libavcodec-dev libavformat-dev libswscale-dev

    编译文件 t.c

    gcc t.c -I /include/ -L /lib/ -lavutil -lavformat -lavcodec -lavutil -lm -g -lswscale

    运行
    ./a.out ./test.avi(任意视频格式都可以)

    会生成帧图片
  • 相关阅读:
    深入剖析ASP.NET的编译原理之一:动态编译(Dynamical Compilation)
    ASP.NET Process Model之二:ASP.NET Http Runtime Pipeline Part I
    IIS Server Variables(IIS 服务器变量)
    .Net源码之Page类(二)
    博客改变生活
    目录、路径、虚拟路径
    Windows 7 Beta 1 7000
    《Visual Studio Hacks 》读书笔记 (十二)
    新建XML文件
    另一个分页函数
  • 原文地址:https://www.cnblogs.com/Stephen-Jixing/p/12051286.html
Copyright © 2020-2023  润新知