ffmpeg的使用

1 搭建 ffmpeg 环境(windows下)

1 下载

点击这里下载FFMPEG的库,里面包含:

  • Static :静态库版本
  • Shared:动态库版本
  • Dev:提供给开发者用的lib文件

如果只要ffmpeg的库就只需要下载 Shared 和 Dev(使用方法见下一步)
如果想在终端命令下执行ffmpeg就下载 Static(下载完毕后值需要将该目录加入环境变量即可使用 ffmpeg 终端命令);
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XROq9KOr-1609573256270)(http://www.tamray.cn/wp-content/uploads/2020/05/wp_editor_md_e8205364e111efa8c7696f864d1505d9.jpg)]

2 测试(windows Qt环境)

  • 解压下载的文件

  • 将 Shared/bin 文件夹中的 dll 文件,复制到当前qt工程debug文件中(或者将dll所在目录添加至环境变量,重启生效)

    # 该目录下的dll文件
    E:\.ffmpeg\ffmpeg-20200515-b18fd2b-win64-shared\bin
    
  • 创建Qt的.pro文件中链接库文件(在 Dev/lib 文件夹下)

    INCLUDEPATH += E:\.ffmpeg\ffmpeg-20200515-b18fd2b-win64-dev\include
    LIBS += E:\.ffmpeg\ffmpeg-20200515-b18fd2b-win64-dev\lib\avcodec.lib \
            E:\.ffmpeg\ffmpeg-20200515-b18fd2b-win64-dev\lib\avdevice.lib \
            E:\.ffmpeg\ffmpeg-20200515-b18fd2b-win64-dev\lib\avfilter.lib \
            E:\.ffmpeg\ffmpeg-20200515-b18fd2b-win64-dev\lib\avformat.lib \
            E:\.ffmpeg\ffmpeg-20200515-b18fd2b-win64-dev\lib\avutil.lib \
            E:\.ffmpeg\ffmpeg-20200515-b18fd2b-win64-dev\lib\postproc.lib \
            E:\.ffmpeg\ffmpeg-20200515-b18fd2b-win64-dev\lib\swresample.lib \
            E:\.ffmpeg\ffmpeg-20200515-b18fd2b-win64-dev\lib\swscale.lib
    
  • 测试代码

    // 由于 FFMPEG 是 C库,但编译的时候使用的C++的编译器编译,
    // 因此这里需要加上extern "C",否则会提示各种未定义
    extern "C"   
    {
    #include "libavdevice/avdevice.h"
    #include <libavformat/avformat.h>
    #include <libavcodec/avcodec.h>
    #include <libswscale/swscale.h>
    #include <libavutil/imgutils.h>
    #include <libavutil/opt.h>
    #include <libavutil/mathematics.h>
    #include <libavutil/samplefmt.h>
    }
    int main()
    {
        std::cout << "Test FFmpeg!" << std::endl;
        av_register_all();
        unsigned version = avcodec_version();
        std::cout << "version :" << version << std::endl;
    }
    

2 搭建 ffmpeg 环境(unbutu16.04下)

2.1 编译

  • 先安装相关工具

    sudo apt-get install -y autoconf automake build-essential git libass-dev libfreetype6-dev libsdl2-dev libtheora-dev libtool libva-dev libvdpau-dev libvorbis-dev libxcb1-dev libxcb-shm0-dev libxcb-xfixes0-dev pkg-config texinfo wget zlib1g-dev 
    sudo apt-get install -y nasam yasm cmake mercurial 
    
  • 下载 ffmpeg

    下载路径

  • 解压下载文件

    tar jxvf ffmpeg-4.2.tar.bz2
    
  • 进入解压目录并执行:

    cd ffmpeg-4.2/
    ./configure --enable-shared  --prefix=/usr/local/ffmpeg
    

    注:选项 --prefix 是安装目录,这里是安装到/usr/local/ffmpeg;--enable-shared 是指定生成动态库,默认是静态库,静态库不方便后续开发;

  • 编译安装

    sudo make -j8
    sudo make install
    
  • 添加环境变量
    ~/.bashrc 文件中添加以下内容,执行 source ~/.bashrc 生效:

    export FFMPEG_HOME=/usr/local/ffmpeg
    export PATH=$FFMPEG_HOME/bin:$PATH
    

    如果没有安装pkgconfig先自行安装,然后添加环境比变量 PKG_CONFIG_PATH

    export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/local/ffmpeg/lib/pkgconfig:/usr/loal/lib
    
  • 添加ffmpeg库的链接
    在 /etc/ld.so.conf 中 末尾添加 /usr/local/ffmpeg/lib 即可,执行:

    sudo ldconfig 
    

2.2 测试(在 Qt 中测试播放视频)

  • 在 .pro 添加库路径:

      INCLUDEPATH += /usr/local/ffmpeg/include
      LIBS += -L /usr/local/ffmpeg/lib   -lswscale -lswresample -lavformat -lavdevice -lavcodec -lavutil -lavfilter  -lm
    
  • 添加头文件:

      // 源代码是由 C 编写的
      extern "C"{
      #include <libavcodec/avcodec.h>
      #include <libavformat/avformat.h>
      #include <libavutil/avutil.h>
      #include <libswresample/swresample.h>
      #include <libavutil/opt.h>
      #include <libswscale/swscale.h>
      #include <libavutil/imgutils.h>
      }
    
  • 创建两个控件:

    label - QLabel

    pushButton - QPushButton

    其中,label 用于显示,pushButton 用于点击开始;

  • c 代码
    :::details

void Delay(int msec) // 延时函数
{
    QTime dieTime = QTime::currentTime().addMSecs(msec);
    while( QTime::currentTime() < dieTime )
        QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
}

void MainWindow::on_pushButton_clicked() // 按键的槽函数
{
    AVFormatContext   *pFormatCtx;
    int               i, videoindex;
    AVCodecContext    *pCodecCtx;
    AVCodec           *pCodec;
    AVFrame           *pFrame, *pFrameRGB;
    unsigned char     *out_buffer;
    AVPacket          *packet;
    int               ret, got_picture;
    struct SwsContext *img_convert_ctx;

    //    char filepath[] = "E:\\media\\1.avi";
    char filepath[] = "/home/tianru/video/2020-4-10/3.mp4";
     //初始化编解码库
    av_register_all();//创建AVFormatContext对象,与码流相关的结构。
    pFormatCtx = avformat_alloc_context();
    //初始化pFormatCtx结构
    if (avformat_open_input(&pFormatCtx, filepath, NULL, NULL) != 0){
        printf("Couldn't open input stream.\n");
        return ;
    }
    //获取音视频流数据信息
    if (avformat_find_stream_info(pFormatCtx, NULL) < 0){
        printf("Couldn't find stream information.\n");
        return ;
    }
    videoindex = -1;
    //nb_streams视音频流的个数,这里当查找到视频流时就中断了。
    for (i = 0; i < pFormatCtx->nb_streams; i++)
        if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO){
            videoindex = i;
            break;
    }
    if (videoindex == -1){
        printf("Didn't find a video stream.\n");
        return ;
    }
    //获取视频流编码结构
    pCodecCtx = pFormatCtx->streams[videoindex]->codec;
    //查找解码器
    pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
    if (pCodec == NULL){
        printf("Codec not found.\n");
        return ;
    }
    //用于初始化pCodecCtx结构
    if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0){
        printf("Could not open codec.\n");
        return ;
    }
    //创建帧结构,此函数仅分配基本结构空间,图像数据空间需通过av_malloc分配
    pFrame = av_frame_alloc();
    pFrameRGB = av_frame_alloc();
    //创建动态内存,创建存储图像数据的空间
    //av_image_get_buffer_size获取一帧图像需要的大小
    out_buffer = (unsigned char *)av_malloc(av_image_get_buffer_size(AV_PIX_FMT_RGB32, pCodecCtx->width, pCodecCtx->height, 1));
    av_image_fill_arrays(pFrameRGB->data, pFrameRGB->linesize, out_buffer,
                              AV_PIX_FMT_RGB32, pCodecCtx->width, pCodecCtx->height, 1);

    packet = (AVPacket *)av_malloc(sizeof(AVPacket));
    //Output Info-----------------------------
    printf("--------------- File Information ----------------\n");
    //此函数打印输入或输出的详细信息
    av_dump_format(pFormatCtx, 0, filepath, 0);
    printf("-------------------------------------------------\n");
    //初始化img_convert_ctx结构
    img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt,
                           pCodecCtx->width, pCodecCtx->height, AV_PIX_FMT_RGB32, SWS_BICUBIC, NULL, NULL, NULL);
    //av_read_frame读取一帧未解码的数据
    while (av_read_frame(pFormatCtx, packet) >= 0){
        //如果是视频数据
        if (packet->stream_index == videoindex){
            //解码一帧视频数据
            ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, packet);
            if (ret < 0){
                printf("Decode Error.\n");
                return ;
            }
            if (got_picture){
                sws_scale(img_convert_ctx, (const unsigned char* const*)pFrame->data, pFrame->linesize, 0, pCodecCtx->height,
                                               pFrameRGB->data, pFrameRGB->linesize);
                QImage img((uchar*)pFrameRGB->data[0],pCodecCtx->width,pCodecCtx->height,QImage::Format_RGB32);
                ui->label->setPixmap(QPixmap::fromImage(img));
                Delay(10);
            }
        }
        av_free_packet(packet);
    }
    sws_freeContext(img_convert_ctx);
    av_frame_free(&pFrameRGB);
    av_frame_free(&pFrame);
    avcodec_close(pCodecCtx);
    avformat_close_input(&pFormatCtx);
}

:::

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值