基于ffmpeg 2.8 API 的改写

//
//  main.cpp
//  save_video_to_ppm
//
//  Created by meitu on 15/10/15.
//  Copyright © 2015年 meitu. All rights reserved.
//
#ifdef __cplusplus
extern "C"
{
#endif
#include "libavcodec/avcodec.h"
#include "libavutil/imgutils.h"
#include "libavformat/avformat.h"
#include "libswscale/swscale.h"
#ifdef __cplusplus
}
#endif
static void SaveFrame(AVFrame* pFrame, int width, int height, int iFrame)
{FILE *pFile;char szFilename[32];int y;//Open filesprintf(szFilename, "frame%d.ppm", iFrame);pFile = fopen(szFilename, "wb");if (pFile == NULL) {fprintf(stderr, "Could not open the ppm file.\n");return;}//Write headerfprintf(pFile, "P6\n%d %d\n255\n", width, height);//Write pixel datafor (y = 0; y < height; ++y) {fwrite(pFrame->data[0] + y*pFrame->linesize[0], 1, width*3, pFile);}fclose(pFile);
}
int main(int argc, char *argv[])
{av_register_all();AVFormatContext *pFormatCtx = NULL;//Open video file and allocate format context//读取文件的头部信息,并且保持这些信息到AVFormatContext中//如果AVFormatContext是NULL,这个函数将会同时申请一个空间if (avformat_open_input(&pFormatCtx, argv[1], NULL, NULL) < 0) {av_log(pFormatCtx, AV_LOG_ERROR, "Could not open file.\n");return 1;}//检查在文件的流的信息//这个函数为 pFormatCtx-streams填充正确的信息if (avformat_find_stream_info(pFormatCtx, NULL) < 0) {av_log(pFormatCtx, AV_LOG_ERROR, "Could not find stream info.\n");return 1;}//输出信息av_dump_format(pFormatCtx, 0, argv[1], 0);//找到视频流int videoStream = 0;videoStream = av_find_best_stream(pFormatCtx, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0);if (videoStream == -1) {av_log(pFormatCtx, AV_LOG_ERROR, "Could not find stream index.\n");return 1;}AVCodecContext *pCodecCtx = NULL;pCodecCtx = pFormatCtx->streams[videoStream]->codec;AVCodec *pCodec = NULL;pCodec =avcodec_find_decoder(pCodecCtx->codec_id);if (pCodec == NULL) {av_log(pCodec, AV_LOG_ERROR, "Could not find decoder.\n");return 1;}//open codecif (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) {av_log(pCodecCtx, AV_LOG_ERROR, "Could open decoder.\n");return 1;}AVFrame *pFrameRGB = NULL;pFrameRGB = av_frame_alloc();if (!pFrameRGB) {av_log(pFrameRGB , AV_LOG_ERROR, "Could allocate frame.\n");return 1;}uint8_t *buffer;int numBytes = 0;/*之前我们申请了一个 帧 对象,当转换的时候,我们仍然需要一个地方来放置原始的数据。我们使用avpicture_get_size来获取大小,然后av_malloc申请大小avpicture_fill将申请的帧和我们新申请的内存结合起来*/
//    numBytes = avpicture_get_size(PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height);
//    buffer = (uint8_t *)av_malloc(numBytes);
//    avpicture_fill((AVPicture*)pFrameRGB, buffer, PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height);//使用av_image_alloc代替上面注释的三行代码av_image_alloc(pFrameRGB->data, pFrameRGB->linesize, pCodecCtx->width, pCodecCtx->height, PIX_FMT_RGB24, 1);//接下来,读入整个视频流,然后把它解码成帧,最后转换格式并且保存int frameFinished;AVPacket pkt;//用来存储解码后的原始数据AVFrame *pFrame = av_frame_alloc();int i = 0;auto img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, PIX_FMT_RGB24, SWS_BILINEAR, NULL, NULL, NULL);while (av_read_frame(pFormatCtx, &pkt) >= 0) {//Is this a packet from the video stream?if (pkt.stream_index == videoStream) {//Decode video frame//packet -----> frameavcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &pkt);if (frameFinished) {sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize, 0, pCodecCtx->height, (uint8_t *const *)pFrameRGB->data, pFrameRGB->linesize);if( ++i <= 100 )SaveFrame(pFrameRGB, pCodecCtx->width, pCodecCtx->height, i);}av_free_packet(&pkt);}}sws_freeContext(img_convert_ctx);//free the rgb image//av_free(buffer);av_free(pFrameRGB);//free the yuv frameav_free(pFrame);//close the codecavcodec_close(pCodecCtx);//close the video fileavformat_close_input(&pFormatCtx);return 0;
}

一些具体的解释请看参考文献


ffmpeg2.8将多媒体文件保存为ppm相关推荐

  1. python提取视频帧并保存_python tools实现视频的每一帧提取并保存

    preface 最近在做 video caption 相关,要处理大量视频. method 1 方法 1 是最简单的,用 ffmpeg工具来完成. 具体的网上有很多这方面的资料,本人只是简单了解了一下 ...

  2. 《用两天学习光线追踪》1.项目介绍和ppm图片输出

    本项目参考自教程<Ray Tracing in One Weekend>,在跑通了所有例子之后,加上了自己的理解写成笔记,项目使用CPU多线程提速,并增加了GUI进度显示. 项目链接:ht ...

  3. php将视频流逐帧转图片,ffmpeg sdk解码视频帧后保存成BMP或JPG的方法

    ffmpeg解码视频的例子可以看官方自带的encode_decode.c. 官方解码保存成ppm,这里接下来保存成BMP或JPG. 原理: 保存BMP是解码成功后,从YUV420转成RGB24,然后构 ...

  4. 将bmp图像转换为ppm格式

    实现图像格式的转化,将bmp的彩色图像转化为其他简单格式,便于使用. Cvt_BMP_to_PPM程序说明: 功能:将bmp格式的彩色图像保存为ppm格式:       将bmp格式的灰度图像保存为p ...

  5. ffmpeg API 笔记:使用libavcodec/libavformat/libswscale ffmpeg例子

    ffmpeg API 笔记:使用libavcodec/libavformat/libswscale December 11, 2009 Update 2010.1.5: 其实研究ffmpeg不用找什么 ...

  6. Linux下PDF操作与转换

    Linux下PDF操作与转换 2013-07-02 09:44:58 分类: LINUX 如果说PDF是电子纸张,那么pdftk就是电子起钉器.打孔机.粘合剂.解密指环和 X光镜片.Pdftk是一个简 ...

  7. FFmpeg入门详解之117:视频监控的架构和流程

    几张架构图带您快速了解视频监控 图一 图二 图三 图四 视频监控系统的简介 视频监控 视频监控是安全防范系统的重要组成部分,英文Cameras and Surveillance.传统的监控系统包括前端 ...

  8. ffmpeg API FR NET

    ffmpeg API 笔记:使用libavcodec/libavformat/libswscale December 11, 2009 Update 2010.1.5: 其实研究ffmpeg不用找什么 ...

  9. linux pdf转视频教程,Linux下PDF操作与转换

    如果说PDF是电子纸张,那么pdftk就是电子起钉器.打孔机.粘合剂.解密指环和 X光镜片.Pdftk是一个简单的工具,可以对PDF文档进行各种日常操作.Pdftk可以让你简单而自由地操作PDF.它不 ...

最新文章

  1. 互联网协议 — PPP 点对点协议
  2. 轻量级高精度分割网络推荐
  3. Apache HttpClient库里的日志实现检测原理
  4. mysql查询错误_一个奇怪的MySQL查询错误
  5. MySQL中update一条record的过程
  6. 等式约束的序列二次规划(SQP)
  7. monkeyrunner API接口文档内容
  8. 用递归方法求一个list的最大值
  9. tomcat未自动解压war包原因分析
  10. 电力拖动自动控制系统_教授为你解读“电气工程及其自动化”专业类
  11. java 成员变量存在哪_Java中成员变量、局部变量、全局变量、静态变量存在位置及初始化...
  12. 你可能不知道,你登曾是个气喘小胖子,靠努力逆袭完成梦想
  13. RobotFramework(RF)常用函数库-内置库篇
  14. 面向海洋观监测传感网的移动终端位置隐私保护研究
  15. 五款开源图形处理软件
  16. scons 手册_SCons笔记(详细版)
  17. Buffon投针实验:究竟为什么是pi?
  18. 删除eclipse的SVN/Subclipse插件
  19. AFNetworking 之加载网络图片
  20. 限制性波尔兹曼机RBM and DBN

热门文章

  1. java 打包 根目录_java – Maven在jar文件的根目录中打包图像
  2. ROS入门笔记(十一):编写与测试简单的Service和Client (Python)
  3. win7鼠标指针主题包_Windows10系统用键盘来代替鼠标操作的方法
  4. lm723大电流可调电源电路图_三端稳压模块LM338组成的高精度大电流可调稳压电源,电流可到达5A...
  5. python正则表达式代码_python正则表达式的使用(实验代码)
  6. java tts引擎_Android TTS系列二——如何开发一款系统级tts引擎?
  7. MySQL8单表记录多少_mysql学习笔记之8(单表数据记录查询)_mysql
  8. 3d环形图片展示 js_网易公开课Three.js实践 勋章系统
  9. Hibernate框架ORM的实现原理-不是技术的技术
  10. Spark学习笔记:索引分区映射