Chinaunix首页 | 论坛 | 博客
  • 博客访问: 9408964
  • 博文数量: 1748
  • 博客积分: 12961
  • 博客等级: 上将
  • 技术积分: 20070
  • 用 户 组: 普通用户
  • 注册时间: 2009-01-09 11:25
个人简介

偷得浮生半桶水(半日闲), 好记性不如抄下来(烂笔头). 信息爆炸的时代, 学习是一项持续的工作.

文章分类

全部博文(1748)

文章存档

2024年(24)

2023年(26)

2022年(112)

2021年(217)

2020年(157)

2019年(192)

2018年(81)

2017年(78)

2016年(70)

2015年(52)

2014年(40)

2013年(51)

2012年(85)

2011年(45)

2010年(231)

2009年(287)

分类: Android平台

2017-11-23 14:16:48


点击(此处)折叠或打开

  1. extern "C"{
  2.     #include "libavcodec/avcodec.h"
  3.     #include "libavformat/avformat.h"
  4.     #include "libavutil/pixfmt.h"
  5.     #include "libavutil/imgutils.h"
  6.     #include "libswscale/swscale.h"
  7. }
  8.  
  9. #include <stdio.h>
  10.  
  11. ///现在我们需要做的是让SaveFrame函数能把RGB信息定稿到一个PPM格式的文件中。
  12. ///我们将生成一个简单的PPM格式文件,请相信,它是可以工作的。
  13. void SaveFrame(AVFrame *pFrame, int width, int height,int index)
  14. {
  15.  
  16.   FILE *pFile;
  17.   char szFilename[32];
  18.   int y;
  19.  
  20.   // Open file
  21.   sprintf(szFilename, "frame%d.ppm", index);
  22.   pFile=fopen(szFilename, "wb");
  23.  
  24.   if(pFile==NULL)
  25.     return;
  26.  
  27.   // Write header
  28.   fprintf(pFile, "P6 %d %d 255 ", width, height);
  29.  
  30.   // Write pixel data
  31.   for(y=0; y<height; y++)
  32.   {
  33.     fwrite(pFrame->data[0]+y*pFrame->linesize[0], 1, width*3, pFile);
  34.   }
  35.  
  36.   // Close file
  37.   fclose(pFile);
  38.  
  39. }
  40.  
  41.  
  42. int main(int argc, char *argv[])
  43. {
  44.     char file_path[] = "./test.mp4";
  45.  
  46.     AVFormatContext *pFormatCtx;
  47.     AVCodecContext *pCodecCtx;
  48.     AVCodec *pCodec;
  49.     AVFrame *pFrame, *pFrameRGB;
  50.     AVPacket *packet;
  51.     uint8_t *out_buffer;
  52.  
  53.     static struct SwsContext *img_convert_ctx;
  54.  
  55.     uint32_t i, numBytes;
  56.     int videoStreamIndex, ret;
  57.  
  58.     av_register_all(); //初始化FFMPEG 调用了这个才能正常适用编码器和解码器
  59.  
  60.     //Allocate an AVFormatContext.
  61.     pFormatCtx = avformat_alloc_context();
  62.  
  63.     if (avformat_open_input(&pFormatCtx, file_path, NULL, NULL) != 0) {
  64.         printf("can't open the file. ");
  65.         return -1;
  66.     }
  67.  
  68.     if (avformat_find_stream_info(pFormatCtx, NULL) < 0) {
  69.         printf("Could't find stream infomation.");
  70.         return -1;
  71.     }
  72.  
  73.     videoStreamIndex = -1;
  74.  
  75.     ///循环查找视频中包含的流信息,直到找到视频类型的流
  76.     ///便将其记录下来 保存到videoStream变量中
  77.     ///这里我们现在只处理视频流 音频流先不管他
  78.     for (i = 0; i < pFormatCtx->nb_streams; i++) {
  79.         if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
  80.             videoStreamIndex = i;
  81.         }
  82.     }
  83.  
  84.     ///如果videoStream为-1 说明没有找到视频流
  85.     if (videoStreamIndex == -1) {
  86.         printf("Didn't find a video stream.");
  87.         return -1;
  88.     }
  89.  
  90.     ///查找解码器
  91.     pCodecCtx = avcodec_alloc_context3(NULL);
  92.     avcodec_parameters_to_context(pCodecCtx, pFormatCtx->streams[videoStreamIndex]->codecpar);
  93.     pCodec = avcodec_find_decoder(pCodecCtx->codec_id);

  94.     if (pCodec == NULL) {
  95.         printf("Codec not found.");
  96.         return -1;
  97.     }
  98.  
  99.     ///打开解码器
  100.     if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) {
  101.         printf("Could not open codec.");
  102.         return -1;
  103.     }
  104.  
  105.     pFrame = av_frame_alloc();
  106.     pFrameRGB = av_frame_alloc();
  107.  
  108.     img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height,
  109.             pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height,
  110.             AV_PIX_FMT_RGB24, SWS_BICUBIC, NULL, NULL, NULL);
  111.  
  112.     numBytes = av_image_get_buffer_size(AV_PIX_FMT_RGB24, pCodecCtx->width,pCodecCtx->height, 1);
  113.     
  114.  
  115.     out_buffer = (uint8_t *) av_malloc(numBytes * sizeof(uint8_t));
  116.     av_image_fill_arrays(pFrameRGB->data, pFrameRGB->linesize, out_buffer, AV_PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height, 1);
  117.  
  118.     int y_size = pCodecCtx->width * pCodecCtx->height;
  119.  
  120.     packet = (AVPacket *) malloc(sizeof(AVPacket)); //分配一个packet
  121.     av_new_packet(packet, y_size); //分配packet的数据
  122.  
  123.     av_dump_format(pFormatCtx, 0, file_path, 0); //输出视频信息
  124.  
  125.     int index = 0, cnt=0;
  126.  
  127.     while (1)
  128.     {
  129.         if (av_read_frame(pFormatCtx, packet) < 0)
  130.         {
  131.             break; //这里认为视频读取完了
  132.         }
  133.  
  134.         if (packet->stream_index == videoStreamIndex) {
  135.             ret = avcodec_send_packet(pCodecCtx, packet);
  136.             if (ret != 0) continue;
  137.             
  138.             ret = avcodec_receive_frame(pCodecCtx, pFrame);
  139.             if (ret != 0) continue;
  140.             
  141.             {//处理获得视频帧
  142.                 sws_scale(img_convert_ctx,
  143.                         (uint8_t const * const *) pFrame->data,
  144.                         pFrame->linesize, 0, pCodecCtx->height, pFrameRGB->data,
  145.                         pFrameRGB->linesize);
  146.          if (cnt ++ > 20) {
  147.                             SaveFrame(pFrameRGB, pCodecCtx->width,pCodecCtx->height,index++); //保存图片
  148.              cnt = 0;
  149.          }
  150.                 if (index > 50) return 0; //这里我们就保存50张图片
  151.             }
  152.         }
  153.         av_packet_unref(packet);
  154.     }
  155.     av_free(out_buffer);
  156.     av_free(pFrameRGB);
  157.     av_free(pFrame);
  158.     avcodec_close(pCodecCtx);
  159.     avformat_close_input(&pFormatCtx);
  160.  
  161.     return 0;
  162. }

阅读(4117) | 评论(0) | 转发(0) |
0

上一篇:音视频基础教程

下一篇:GTK+3.10 系统学习

给主人留下些什么吧!~~