ffmpeg 提取视频文件关键帧

http://blog.csdn.net/fengfeifengfei/article/details/43410205

#include "libavformat/avformat.h"

#include "libavcodec/avcodec.h"
#include "libavutil/avutil.h"
#include "libswscale/swscale.h"
#include <unistd.h>
void SaveFrame(AVFrame *pFrame, int width, int height, int iFrame)
{

printf("-------------------\n");
FILE *pFile;
char szFilename[32];
int  y;
// Open file
sprintf(szFilename, "frame%d.ppm", iFrame);
pFile=fopen(szFilename, "wb");
if(pFile==NULL)
{
return ;
}
printf("P6\n%d %d\n255\n", width, height);
fprintf(pFile, "P6\n%d %d\n255\n", width, height);
for(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();
avformat_network_init();
AVFormatContext *pformat;
AVCodecContext  *pcodec;

AVCodec         *pcc;

//

if(argc<2)
{
printf("please  input  filename !!!\n");
return  -1;
}
//为pformat结构申请空间 打开文件
pformat=avformat_alloc_context();
if(avformat_open_input(&pformat,argv[1],NULL,NULL))
{
printf("avformat_open_input  error!!!\n");
return  -1;
}
//查找输入文件信息
if(avformat_find_stream_info(pformat,NULL) <  0)
{
printf("avformat_find_stream_info error !!!\n");
return -1;
}
//查找视频流
int videoindex=-1;
int i;
for(i=0;i<pformat->nb_streams;i++)
{
if(pformat->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
{
videoindex=i;
    break;
}
}
if(videoindex==-1)
{
printf("can't find video stream in %s\n",pformat->filename);
return  -1;
}
//AVFormatContext  ->AVStream ->AVCodecContext
pcodec=pformat->streams[videoindex]->codec;
printf(" find video stream in %s\n",pformat->filename);

//查找该视频流对应的解码器AVCodec
pcc=avcodec_find_decoder(pcodec->codec_id);
//
if(pcc==NULL)
{
printf("cann't find  decoder in %s\n",pformat->filename);
return  -1;
}
//用该解码器打开该视频文件
if(avcodec_open2(pcodec,pcc,NULL)<0)
{
printf("avcodec_open2  error !!!\n");
return  -1;
}
//AVFrame  是存储视频数据的结构
//pframe  是从数据包中读出来的数据放在其中
//pframeRGB 是通过 sws_scale转化格式之后所要储存的数据结构
AVFrame *pframe,*pframeRGB;
//为pframe 开辟内存空间
pframe=avcodec_alloc_frame();
//为转化视频格式之后的结构开辟内存空间
pframeRGB=avcodec_alloc_frame();
if(pframeRGB==NULL)
{
printf("pframeRGB  alloc error !!!\n");
return -1;
}
//申请空间 通过得到PIX_FMT_RGB24的一个像素所占用的内存(avpicture_get_size())
uint8_t *out_buffer=(uint8_t *)av_malloc(avpicture_get_size(PIX_FMT_RGB24, pcodec->width, pcodec->height));
//将out_buffer 以pframeRGB的形式关联起来
avpicture_fill((AVPicture *)pframeRGB, out_buffer, PIX_FMT_RGB24, pcodec->width, pcodec->height);
struct  SwsContext  *sws;
//转换上下文  
sws = sws_getContext(pcodec->width, pcodec->height, pcodec->pix_fmt,320,240, PIX_FMT_RGB24, SWS_BICUBIC, NULL, NULL, NULL);
int  j=0;
AVPacket *ppacket;//cann*t init 
int got_picture;
while(av_read_frame(pformat,ppacket)>=0)
{
if(ppacket->stream_index==videoindex)
{
int ret=avcodec_decode_video2(pcodec, pframe,&got_picture,ppacket);
if(ret < 0)
{  
printf("Decode Error.(解码错误)\n");
return -1;
}

if(got_picture)
{
//提取i帧
if(pframe->pict_type == AV_PICTURE_TYPE_I)
{
sws_scale(sws , (const uint8_t* const*)pframe->data, pframe->linesize,0, pcodec->height, pframeRGB->data, pframeRGB->linesize);
printf("AV_PICTURE_TYPE_I\n");
SaveFrame(pframeRGB, 320,240, j);
j++;
sleep(1);
}
   
//提取p帧
/* if(pframe->pict_type == AV_PICTURE_TYPE_P)
{
sws_scale(sws , (const uint8_t* const*)pframe->data, pframe->linesize,0, pcodec->height, pframeRGB->data, pframeRGB->linesize);
printf("AV_PICTURE_TYPE_P\n");
SaveFrame(pframeRGB, 320,240, j);
j++;
sleep(1);

}
//提取b帧
if(pframe->pict_type == AV_PICTURE_TYPE_B)
{
sws_scale(sws , (const uint8_t* const*)pframe->data, pframe->linesize,0, pcodec->height, pframeRGB->data, pframeRGB->linesize);
printf("AV_PICTURE_TYPE_B\n");
SaveFrame(pframeRGB, 320,240, j);
j++;
sleep(1);

}
*/

              }

}

}

av_free_packet(ppacket);

return  0;

}


编译选项:

gcc  demux_decode2.c  -omain  -I/home/fengfei/ffmpeg_Bin/include   -L/home/fengfei/ffmpeg_Bin/lib  -lavformat -lavdevice  -lavcodec -lavutil  -lpthread  

-lswscale -lswresample  -lSDL  -lbz2    -lz -lm  -lrt

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值