本文转自:https://blog.csdn.net/yinsui1839/article/details/80519742

/********
*本代码参考自雷神博客
*
**********/
#ifdef __cplusplus
extern "C"
{
#endif
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavdevice/avdevice.h>
#include<libswresample/swresample.h>
#include <libavutil/pixfmt.h>
#include <libswscale/swscale.h>
#ifdef __cplusplus
};
#endif#define MAX_AUDIO_FRAME_SIZE  192000
#define SAMPLE_PRT(fmt...)   \do {\printf("[%s]-%d: ", __FUNCTION__, __LINE__);\printf(fmt);\}while(0)//'1': Use H.264 Bitstream Filter
#define USE_H264BSF 1void save_pnm(AVFrame *pFrame, int w, int h,int index)
{FILE *fl;char szFilename[32];int  y;// Open filesprintf(szFilename, "%d.pnm", index);fl=fopen(szFilename, "wb");if(fl==NULL)return;fprintf(fl, "P6\n%d %d\n255\n", w, h); // 加入pnm文件头// Write pixel datafor(y=0; y<h; y++){fwrite(pFrame->data[0]+y*pFrame->linesize[0], 1, w*3, fl);}// Close filefclose(fl);}int main(int argc, char *argv[])
{char *file_path = "/home/grid/hefang";AVFormatContext *pFormatCtx;AVCodecContext *pCodecCtx;AVCodec *pCodec;AVFrame *pFrame, *pFrameRGB;AVPacket *packet;uint8_t *out_buffer;static struct SwsContext *img_convert_ctx;int videoStream, i, numBytes;int ret, got_picture;av_register_all(); //初始化FFMPEG  调用了这个才能正常适用编码器和解码器//Allocate an AVFormatContext.pFormatCtx = avformat_alloc_context();if (avformat_open_input(&pFormatCtx, file_path, NULL, NULL) != 0) {SAMPLE_PRT("open file error\n");return -1;}if (avformat_find_stream_info(pFormatCtx, NULL) < 0) {SAMPLE_PRT("Could't find stream infomation\n");return -1;}videoStream = -1;for (i = 0; i < pFormatCtx->nb_streams; i++) {if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {videoStream = i;}}if (videoStream == -1) {SAMPLE_PRT("no find vedio_stream");return -1;}///查找解码器pCodecCtx = pFormatCtx->streams[videoStream]->codec;pCodec = avcodec_find_decoder(pCodecCtx->codec_id);if (pCodec == NULL) {SAMPLE_PRT(" not found decodec.\n");return -1;}///打开解码器if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) {SAMPLE_PRT("Could not open decodec.");return -1;}pFrame = av_frame_alloc();pFrameRGB = av_frame_alloc();img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height,pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height,AV_PIX_FMT_RGB24, SWS_BICUBIC, NULL, NULL, NULL);numBytes = avpicture_get_size(AV_PIX_FMT_RGB24, pCodecCtx->width,pCodecCtx->height);out_buffer = (uint8_t *) av_malloc(numBytes * sizeof(uint8_t));avpicture_fill((AVPicture *) pFrameRGB, out_buffer, AV_PIX_FMT_RGB24,pCodecCtx->width, pCodecCtx->height);int y_size = pCodecCtx->width * pCodecCtx->height;packet = (AVPacket *) malloc(sizeof(AVPacket)); //分配一个packetav_new_packet(packet, y_size); //分配packet的数据av_dump_format(pFormatCtx, 0, file_path, 0); //输出视频信息int index = 0;while (av_read_frame(pFormatCtx, packet) >=0){if (packet->stream_index == videoStream) {ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture,packet);if (ret < 0) {SAMPLE_PRT("decode error.");return -1;}if (got_picture) {sws_scale(img_convert_ctx,(uint8_t const * const *) pFrame->data,pFrame->linesize, 0, pCodecCtx->height, pFrameRGB->data,pFrameRGB->linesize);save_pnm(pFrameRGB, pCodecCtx->width,pCodecCtx->height,index++); //保存图片if (index > 100) return 0; //100张}}av_free_packet(packet);}av_free(out_buffer);av_free(pFrameRGB);avcodec_close(pCodecCtx);avformat_close_input(&pFormatCtx);return 0;
}

以下代码转自:https://blog.csdn.net/boonya/article/details/79474754

#include <stdio.h>
#include <stdlib.h>
//编码
#include "libavcodec/avcodec.h"
//封装格式处理
#include "libavformat/avformat.h"
//像素处理
#include "libswscale/swscale.h"int main()
{//获取输入输出文件名const char *input = "test.mp4";const char *output = "test.yuv";//1.注册所有组件av_register_all();//封装格式上下文,统领全局的结构体,保存了视频文件封装格式的相关信息AVFormatContext *pFormatCtx = avformat_alloc_context();//2.打开输入视频文件if (avformat_open_input(&pFormatCtx, input, NULL, NULL) != 0){printf("%s","无法打开输入视频文件");return;}//3.获取视频文件信息if (avformat_find_stream_info(pFormatCtx,NULL) < 0){printf("%s","无法获取视频文件信息");return;}//获取视频流的索引位置//遍历所有类型的流(音频流、视频流、字幕流),找到视频流int v_stream_idx = -1;int i = 0;//number of streamsfor (; i < pFormatCtx->nb_streams; i++){//流的类型if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO){v_stream_idx = i;break;}}if (v_stream_idx == -1){printf("%s","找不到视频流\n");return;}//只有知道视频的编码方式,才能够根据编码方式去找到解码器//获取视频流中的编解码上下文AVCodecContext *pCodecCtx = pFormatCtx->streams[v_stream_idx]->codec;//4.根据编解码上下文中的编码id查找对应的解码AVCodec *pCodec = avcodec_find_decoder(pCodecCtx->codec_id);if (pCodec == NULL){printf("%s","找不到解码器\n");return;}//5.打开解码器if (avcodec_open2(pCodecCtx,pCodec,NULL)<0){printf("%s","解码器无法打开\n");return;}//输出视频信息printf("视频的文件格式:%s",pFormatCtx->iformat->name);printf("视频时长:%d", (pFormatCtx->duration)/1000000);printf("视频的宽高:%d,%d",pCodecCtx->width,pCodecCtx->height);printf("解码器的名称:%s",pCodec->name);//准备读取//AVPacket用于存储一帧一帧的压缩数据(H264)//缓冲区,开辟空间AVPacket *packet = (AVPacket*)av_malloc(sizeof(AVPacket));//AVFrame用于存储解码后的像素数据(YUV)//内存分配AVFrame *pFrame = av_frame_alloc();//YUV420AVFrame *pFrameYUV = av_frame_alloc();//只有指定了AVFrame的像素格式、画面大小才能真正分配内存//缓冲区分配内存uint8_t *out_buffer = (uint8_t *)av_malloc(avpicture_get_size(AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height));//初始化缓冲区avpicture_fill((AVPicture *)pFrameYUV, out_buffer, AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height);//用于转码(缩放)的参数,转之前的宽高,转之后的宽高,格式等struct SwsContext *sws_ctx = sws_getContext(pCodecCtx->width,pCodecCtx->height,pCodecCtx->pix_fmt,pCodecCtx->width, pCodecCtx->height, AV_PIX_FMT_YUV420P,SWS_BICUBIC, NULL, NULL, NULL);int got_picture, ret;FILE *fp_yuv = fopen(output, "wb+");int frame_count = 0;//6.一帧一帧的读取压缩数据while (av_read_frame(pFormatCtx, packet) >= 0){//只要视频压缩数据(根据流的索引位置判断)if (packet->stream_index == v_stream_idx){//7.解码一帧视频压缩数据,得到视频像素数据ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, packet);if (ret < 0){printf("%s","解码错误");return;}//为0说明解码完成,非0正在解码if (got_picture){//AVFrame转为像素格式YUV420,宽高//2 6输入、输出数据//3 7输入、输出画面一行的数据的大小 AVFrame 转换是一行一行转换的//4 输入数据第一列要转码的位置 从0开始//5 输入画面的高度sws_scale(sws_ctx, pFrame->data, pFrame->linesize, 0, pCodecCtx->height,pFrameYUV->data, pFrameYUV->linesize);//输出到YUV文件//AVFrame像素帧写入文件//data解码后的图像像素数据(音频采样数据)//Y 亮度 UV 色度(压缩了) 人对亮度更加敏感//U V 个数是Y的1/4int y_size = pCodecCtx->width * pCodecCtx->height;fwrite(pFrameYUV->data[0], 1, y_size, fp_yuv);fwrite(pFrameYUV->data[1], 1, y_size / 4, fp_yuv);fwrite(pFrameYUV->data[2], 1, y_size / 4, fp_yuv);frame_count++;printf("解码第%d帧\n",frame_count);}}//释放资源av_free_packet(packet);}fclose(fp_yuv);av_frame_free(&pFrame);avcodec_close(pCodecCtx);avformat_free_context(pFormatCtx);
}

Reference:

https://blog.csdn.net/yinsui1839/article/details/80519742

https://blog.csdn.net/boonya/article/details/79474754

https://blog.csdn.net/leixiaohua1020/article/details/8652605

https://blog.csdn.net/u011304970/article/details/72995308

ffmpeg读取本地视频,获取视频帧相关推荐

  1. Java代码实现上传视频获取视频某一帧作为截图封面(二)

    上一个文章讲了Java代码实现上传视频获取视频某一帧作为截图封面的一种方法,现在讲述第二种方法.为什么要在这里讲这种方法呢?第一.这种方法生成的图片占用的空间更小第二.这种方法可以获取很多信息 一.根 ...

  2. 使用ffmpeg读取本地文件,进行推流

    使用ffmpeg读取本地文件,进行推流,跳到指定时间播放. 注意MP4文件h264_mp4toannexb与aac_adtstoasc. 要实现循环播放注意两点: 1.播放到结尾,跳到开始位置重新播放 ...

  3. Android FFmpeg移植总攻略——获取视频帧数(亲测可用)

    第一次尝试使用Android 移植FFmpeg算法,一路坎坷,最终做如下总结,适用于Android手机.Android开发板.亲测可用. 一.下载组件 在Android Studio中下载所需组件:C ...

  4. 【音视频】使用FFMPEG读取本地|网络音视频流(3-4)

    前言:继上一篇推送网络流之后,最近又研究了一下读取网络流(顺便还有本地流)作为音视频源,此篇作为记录. 一.本地|网络视频源 1.初始化视频源 int VStreamCaptor::init(cons ...

  5. android 图片读写,Android读取本地照片和视频相册

    前言 项目中经常要选择本地照片或者视频的需求,如果去扫描整个SD卡就太耗时间,其实Android系统在启动时就已经把整个设备中的多媒体文件信息(文件名,类型,大小等)都存到了数据库,然后提供了Cont ...

  6. vue上传视频获取视频第一帧

    <div class="video" v-show="videoUrl"><video id="upvideo" v-sh ...

  7. uniapp 上传视频获取视频封面图

    // 上传视频或图片 uni.chooseMedia({// 上传数量count: 1,// 限制仅上传视频mediaType: ["video"],// 获取临时储存的信息suc ...

  8. python3读取本地_Python3 获取本机 IP

    通过 UDP 获取本机 IP,没有任何的依赖,也没有去猜测机器上的网络设备信息,而且是利用 UDP 协议来实现的,生成一个UDP包,把自己的 IP 放如到 UDP 协议头中,然后从UDP包中获取本机的 ...

  9. 使用python读取gif,合并gif,视频转换为gif

    一.将视频转换为gif 采用opencv读取gif图并使用imageio转换 import cv2 import imageiodef read_video(video_path):video_cap ...

最新文章

  1. 《转》每天起床时,优秀创业者都会问自己这3个问题
  2. windows 10 安装openssh 0x800f0954 的一种解决方法
  3. 电商网站前台与后台系统架构
  4. EOS Dawn 1.0
  5. 全球及中国语音拾音耳机行主要产品及营销模式分析报告业2022-2028年版
  6. java枚举使用详解
  7. VMware 6.5下载地址及序列号(转,备用)
  8. 关于OpenGL ES中的纹理压缩
  9. mysql中表的约束,主键外键唯一键
  10. Java基础学习总结(175)——分布式ID的9种生成方式总结
  11. MySQL数据库篇之索引原理与慢查询优化之一
  12. LUOGU P3919 【模板】可持久化数组(主席树)
  13. 1.LVS 安装简介
  14. 78. Cookie
  15. 怎样在html中加入计数器?(2),html如何实现计数器以及时钟的功能代码
  16. python 高等数学实验,高等数学以及Python 实现
  17. c语言答案-贾宗璞 许合利,C语言习题答案贾宗璞许合利较全-.doc-资源下载在线文库www.lddoc.cn...
  18. Java中XML运用总结
  19. ERR wrong number of arguments for ‘srem‘ command
  20. 【PTA-训练day6】L2-016 愿天下有情人都是失散多年的兄妹+ L1-011 帅到没朋友

热门文章

  1. J9数字论:什么是DAO模式?DAO发展过程的阻碍
  2. 华为Ebackup模板部署
  3. MEM/MBA数学基础(07)几何
  4. MEM/MBA数学强化(04)方程 函数 不等式
  5. MEM/MBA数学强化(07)几何
  6. 编码员,程序员,黑客,开发人员和计算机科学家走进维恩图
  7. 华为计算机魔术,华为荣耀magic给大家变了一个魔术,想“拆穿”他吗?
  8. 微机原理与接口技术(第6版)第六章习题1、3、10、13
  9. 单片机C语言的“进程调度轮询”
  10. 1502: [NOI2005]月下柠檬树