• ffmpeg的例子:制作屏幕录像


      最近需要设计一个播放器,然后了解到ffmpeg这个东西,发现这东西应用还挺广泛的。

      在这里要特别提一下CSDN的雷霄骅,关于ffmpeg的博客那是写的真的好,而且还开源了大量的资料。只不过天妒英才啊!听说因为过度劳累而猝死

      本篇博客主要是学习雷神推荐的:如何用FFmpeg编写一个简单播放器

      因为ffmpeg的版本升级,导致版本之间多少有些差异,我的FFmpeg版本为3.2.2,所以在移植第一个代码示例的过程中,出了不少幺蛾子。关于ffmpeg的安装网上到处都是,我就不说明了。

      下面我上我修改后的示例代码:

      开发环境:ubuntu14  64位

      ffmpeg版本:3.2.2

      测试文件:flv格式视频或其他格式视频

      效果:得到5张视频截图

      编译命令:gcc -g main.c -o test -I /usr/local/ffmpeg/include -L /usr/local/ffmpeg/lib -lavutil -lavformat -lavcodec -lz -lavutil -lswscale(说明:-g为加入gdb调试,/usr/local/ffmpeg为我的ffmpeg安装目录,具体目录看你的安装路径来设置)

      1 #ifdef _cplusplus
      2 extern "C" {
      3 #endif
      4 
      5 #include<stdio.h>
      6 #include<libavcodec/avcodec.h>
      7 #include<libavformat/avformat.h>
      8 #include<libavutil/avutil.h>
      9 #include<libswscale/swscale.h>
     10 #include<libavutil/avutil.h>
     11 #include<SDL2/SDL.h>
     12 
     14 
     15 //******************函数声明***********************************
     16 void SaveFrame(AVFrame *pFrame,int width,int height,int iFrame);
     17 
     18 int main(int argc,char **argv)
     19 {
     20     printf("~~~~~~~~design a player!
    ");
     21     AVFormatContext *pFormatCtx;
     22     av_register_all();
     23     avformat_network_init();
     24      pFormatCtx = avformat_alloc_context();
     25     //打开视频文件
     26 //    if(avformat_open_input(&pFormatCtx,"bigbuckbunny_480x272.h265",NULL,NULL)!=0)
     27      if(avformat_open_input(&pFormatCtx,"test.flv",NULL,NULL)!=0)
     28         return -1;//不能打开文件
     29     if(avformat_find_stream_info(pFormatCtx,NULL)<0){
     30             printf("Couldn't find stream information.
    ");
     31             return -1;
     32         }
     33     //丢出一个信息,调试用的
     34 //    av_dump_format(pFormatCtx,0,argv[1],0);
     35     int i,videoStream;
     36     AVCodecContext *pCodecCtx;
     37     //找到第一个视频流
     38     videoStream = -1;
     39     for(i=0;i<pFormatCtx->nb_streams;i++)
     40     {
     41         if(pFormatCtx->streams[i]->codec->codec_type ==AVMEDIA_TYPE_VIDEO)
     42         {
     43             videoStream = i;
     44             break;
     45         }
     46     }
     47     if(videoStream==-1){
     48             printf("Didn't find a video stream.
    ");
     49             return -1;
     50         }
     51     //从视频流中得到一个编解码上下文的指针,里面包含了编解码器的所有信息,包含了一个
     52     //指向真正的编解码的指针
     53     pCodecCtx = pFormatCtx->streams[videoStream]->codec;
     54     AVCodec *pCodec;
     55     //在视频流中找到这个解码器
     56     pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
     57     if(pCodec == NULL)
     58     {
     59         fprintf(stderr,"Unsupported codec !
    ");
     60         return -1;
     61     }
     62     //Open codec
     63     if(avcodec_open2(pCodecCtx,pCodec,NULL)<0){
     64         printf("cann't open the codec!
    ");
     65         return -1;
     66     }
     67     //保存数据
     68     AVFrame *pFrame;
     69     //分配一个视频帧
     70     pFrame = av_frame_alloc();
     71     //分配一帧结构体
     72     AVFrame *pFrameRGB;
     73     pFrameRGB = av_frame_alloc();
     74     if(pFrameRGB == NULL){
     75         return -1;
     76     }
     77     //我们申请了一帧的内存,当转换的时候,我们需要用一个地方来放置原始数据,首先
     78     //我们需要使用avpicture_get_size来获得我们需要的大小,然后手工申请内存
     79     uint8_t *buffer;
     80     int numBytes;
     81     //确定需要的内存大小并分配内存
     82     numBytes = avpicture_get_size(AV_PIX_FMT_RGB24,pCodecCtx->width,pCodecCtx->height);
     83     buffer = (uint8_t*)av_mallocz(numBytes*sizeof(uint8_t));
     84     //指定buffer的适宜的一部分到pFrameRGB的图像平面
     85     //注意pFrameRGB是一个媒体帧,但是该媒体帧是AVPicture的父集
     86     avpicture_fill((AVPicture *)pFrameRGB, buffer, AV_PIX_FMT_RGB24,
     87     pCodecCtx->width, pCodecCtx->height);
     88     //**********读取数据*****************************************
     89     int frameFinished;
     90     AVPacket packet;
     91     struct SwsContext *pSwsCtx;
     92     i=0;
     93     pSwsCtx = sws_getContext(pCodecCtx->width,
     94             pCodecCtx->height,
     95             pCodecCtx->pix_fmt,
     96             pCodecCtx->width,
     97             pCodecCtx->height,
     98             AV_PIX_FMT_RGB24,
     99             SWS_BICUBIC,
    100             NULL,NULL,NULL
    101             );
    102      if(pSwsCtx == NULL)
    103        {
    104             fprintf(stderr, "Cannot initialize the conversion context!
    ");
    105             return -1;
    106         }
    107     while(av_read_frame(pFormatCtx,&packet) >= 0)
    108     {
    109             //如果读取的包来自视频流
    110             if(packet.stream_index == videoStream)
    111             {
    112                 //解码帧数据
    113                 avcodec_decode_video2(pCodecCtx,pFrame,&frameFinished,&packet);
    114                 //我们是否得到一个视频帧
    115                 if(frameFinished){
    116                     //使用RGB格式来将它转换为图片
    117                      sws_scale(pSwsCtx,
    118                                       pFrame->data, pFrame->linesize, 0, pCodecCtx->height,
    119                                       pFrameRGB->data, pFrameRGB->linesize);
    120                      //保存这个帧数据到磁盘
    121                      if(++i<=5)
    122                          SaveFrame(pFrameRGB,pCodecCtx->width,pCodecCtx->height,i);
    123                 }
    124             }
    125             av_free_packet(&packet);
    126     }
    127     //清理操作
    128     av_free(buffer);
    129     av_free(pFrameRGB);
    130     av_free(pFrame);
    131     avcodec_close(pCodecCtx);
    132     avformat_close_input(&pFormatCtx);
    133     return EXIT_SUCCESS;
    134 }
    135 
    136 //*****************函数定义***********************************
    137 void SaveFrame(AVFrame *pFrame,int width,int height,int iFrame)
    138 {
    139     FILE    *pFile;
    140     char szFilename[32];
    141     int y;
    142 
    143     //打开文件
    144     sprintf(szFilename,"frame%d.ppm",iFrame);
    145     pFile = fopen(szFilename,"wb");
    146     if(pFile == NULL)
    147         return;
    148     //写头
    149     fprintf(pFile,"P6
    %d %d
    255
    ",width,height);
    150 
    151     //写 pixel 数据
    152     for(y=0; y<height; y++)
    153         fwrite(pFrame->data[0]+y*pFrame->linesize[0], width*3, 1, pFile);
    154     //关闭文件
    155     fclose(pFile);
    156 }
    157 
    158 #ifdef _cplusplus
    159 }
    160 #endif
  • 相关阅读:
    android 管理wifi
    andriod 剪贴板操作
    andriod绘制图形
    andriod读写XML
    androd 获得wifi列表
    一个小时内学习SQLite数据库
    Android 使用SQLite本地数据库
    Android可伸缩列表ExpandableListView
    三甲医院涉医疗反腐,今年已有 149 位被查!
    2015各地区顶尖中学排行榜
  • 原文地址:https://www.cnblogs.com/xishuichangliu/p/6337175.html
Copyright © 2020-2023  润新知