// keyframe.cpp : ��������̨Ӧ�ó��������ڵ㡣��ѧϰffmpeg��������Ƶ�ļ���֡�����bmp�����ؼ�֡
//
//#include "stdafx.h"
//int _tmain(int argc, _TCHAR* argv[])
//{
// return 0;
//}
#include "stdafx.h"
#include <windows.h>
#include <WinGDI.h>
#include <iostream>
#include <iosfwd>
#include <fstream>
extern "C"
{
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
#include <libavutil/imgutils.h>
#include <libavutil/opt.h>
#include <libavutil/mathematics.h>
#include <libavutil/samplefmt.h>
}
#pragma comment(lib,"avcodec.lib")
#pragma comment(lib,"avdevice.lib")
#pragma comment(lib,"avfilter.lib")
#pragma comment(lib,"avformat.lib")
#pragma comment(lib,"avutil.lib")
#pragma comment(lib,"swscale.lib")
using namespace std;
#define FILE_OUT
#ifdef FILE_OUT
std::ofstream file_debugout("frameandpacketinfo.txt");
#endif
static int av_create_bmp(char* filename,uint8_t *pRGBBuffer,int width,int height,int bpp)
{
BITMAPFILEHEADER bmpheader;
BITMAPINFO bmpinfo;
FILE *fp;
fp = fopen(filename,"wb");
if(!fp)return -1;
bmpheader.bfType = ('M'<<8)|'B';
bmpheader.bfReserved1 = 0;
bmpheader.bfReserved2 = 0;
bmpheader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
bmpheader.bfSize = bmpheader.bfOffBits + width*height*bpp/8;
bmpinfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmpinfo.bmiHeader.biWidth = width;
/*----ע�⣬������bmpinfo.bmiHeader.biHeight�������������bmp�ļ��Ĵ洢��ʽ������
Ϊ��ֵ����ʾ�����ǵ������*/
bmpinfo.bmiHeader.biHeight = -height;
bmpinfo.bmiHeader.biPlanes = 1;
bmpinfo.bmiHeader.biBitCount = bpp;
bmpinfo.bmiHeader.biCompression = BI_RGB;
bmpinfo.bmiHeader.biSizeImage = 0;
bmpinfo.bmiHeader.biXPelsPerMeter = 100;
bmpinfo.bmiHeader.biYPelsPerMeter = 100;
bmpinfo.bmiHeader.biClrUsed = 0;
bmpinfo.bmiHeader.biClrImportant = 0;
fwrite(&bmpheader,sizeof(BITMAPFILEHEADER),1,fp);
fwrite(&bmpinfo.bmiHeader,sizeof(BITMAPINFOHEADER),1,fp);
fwrite(pRGBBuffer,width*height*bpp/8,1,fp);
fclose(fp);
return 0;
}
static int av_create_bmp(char* filename, AVFrame *pRGBBuffer,int width,int height,int bpp)
{
BITMAPFILEHEADER bmpheader;
BITMAPINFO bmpinfo;
FILE *fp;
fp = fopen(filename, "wb");
if(!fp)return -1;
bmpheader.bfType = ('M'<<8)|'B';
bmpheader.bfReserved1 = 0;
bmpheader.bfReserved2 = 0;
bmpheader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
bmpheader.bfSize = bmpheader.bfOffBits + width*height*bpp/8;
bmpinfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmpinfo.bmiHeader.biWidth = width;
bmpinfo.bmiHeader.biHeight = -height;
bmpinfo.bmiHeader.biPlanes = 1;
bmpinfo.bmiHeader.biBitCount = 24;
bmpinfo.bmiHeader.biCompression = BI_RGB;
bmpinfo.bmiHeader.biSizeImage = 0;
bmpinfo.bmiHeader.biXPelsPerMeter = 100;
bmpinfo.bmiHeader.biYPelsPerMeter = 100;
bmpinfo.bmiHeader.biClrUsed = 0;
bmpinfo.bmiHeader.biClrImportant = 0;
fwrite(&bmpheader,sizeof(BITMAPFILEHEADER),1,fp);
fwrite(&bmpinfo.bmiHeader,sizeof(BITMAPINFOHEADER),1,fp);
//fwrite(pRGBBuffer,width*height*bpp/8,1,fp);
for(int y=0; y<height; y++)
fwrite(pRGBBuffer->data[0] + y*pRGBBuffer->linesize[0], 1, width*3, fp);
fclose(fp);
return 0;
}
static void print_packet_info(AVPacket info)
{
#ifdef FILE_OUT
file_debugout << "print_packet_info" << " convergence_duration:" << info.convergence_duration
<< " dts:" << info.dts
<< " duration:" << info.duration
<< " flags:" << info.flags
<< " pos:" << info.pos
<< " pts:" << info.pts
<< " size:" << info.size
<< " stream_index:" << info.stream_index << endl;
#else
cout << "print_packet_info" << " convergence_duration:" << info.convergence_duration
<< " dts:" << info.dts
<< " duration:" << info.duration
<< " flags:" << info.flags
<< " pos:" << info.pos
<< " pts:" << info.pts
<< " size:" << info.size
<< " stream_index:" << info.stream_index << endl;
#endif
}
static void print_frame_info(AVFrame* pinfo)
{
#ifdef FILE_OUT
file_debugout << "print_frame_info" << " coded_picture_number:" << pinfo->coded_picture_number
<< " display_picture_number:" << pinfo->display_picture_number
<< " type:" << pinfo->type << endl;
#else
cout << "print_frame_info" << " coded_picture_number:" << pinfo->coded_picture_number
<< " display_picture_number:" << pinfo->display_picture_number
<< " type:" << pinfo->type << endl;
#endif
}
int decode_video_packet(AVFormatContext* fmt_ctx_for_decode, \
AVCodecContext* dec_ctx, int video_stream_index)
{
int ret = 0;
AVFrame* pFrame=avcodec_alloc_frame();
AVFrame* pFrameRGB = avcodec_alloc_frame();
int numBytes=avpicture_get_size(PIX_FMT_BGR24, dec_ctx->width,dec_ctx->height);
uint8_t* buffer = new(std::nothrow) uint8_t[numBytes];
avpicture_fill((AVPicture *)pFrameRGB, buffer, PIX_FMT_BGR24,\
dec_ctx->width, dec_ctx->height);
SwsContext *pSWSCtx = sws_getContext(dec_ctx->width, dec_ctx->height, \
dec_ctx->pix_fmt, dec_ctx->width, dec_ctx->height, PIX_FMT_BGR24,\
SWS_BICUBIC, NULL, NULL, NULL);
if (NULL == pFrame || NULL == pFrameRGB || NULL == buffer || NULL == pSWSCtx)
{
ret = -1;
goto exit;
}
AVPacket packet;
/*av_init_packet(&packet);*/
int key_frame_picture_count = 0;
while (av_read_frame(fmt_ctx_for_decode, &packet) >= 0)
{
if (packet.stream_index == video_stream_index)
{
int got_frame = 0;
avcodec_decode_video2(dec_ctx, pFrame,&got_frame, &packet);
if (got_frame) //һ��������֡
{
if (pFrame->key_frame)
{
sws_scale(pSWSCtx, pFrame->data, pFrame->linesize,0, \
dec_ctx->height, pFrameRGB->data, pFrameRGB->linesize);
// ���浽����
char pic[200];
sprintf_s(pic,"keyframe%d.bmp", ++key_frame_picture_count);
av_create_bmp(pic,pFrameRGB->data[0],dec_ctx->width,dec_ctx->height,24);
//av_create_bmp(pic, pFrameRGB, dec_ctx->width,dec_ctx->height,24);
}
print_frame_info(pFrame);
}
print_packet_info(packet);
}
/*av_free_packet(&packet);
i++;*/
}
//av_free_packet(&packet);
exit:
avcodec_free_frame(&pFrame);
avcodec_free_frame(&pFrameRGB);
delete [] buffer;
sws_freeContext(pSWSCtx);
return ret;
}
static int open_input_file(const char *filename)
{
int ret;
bool video_codec_init = false;
int video_stream_index = -1;
AVCodecContext* suitable_dec_ctx = NULL;
AVFormatContext *video_fmt_ctx = NULL;
if ((ret = avformat_open_input(&video_fmt_ctx, filename, NULL, NULL)) < 0) {
av_log(NULL, AV_LOG_ERROR, "Cannot open input file\n");
return ret;
}
if ((ret = avformat_find_stream_info(video_fmt_ctx, NULL)) < 0) {
av_log(NULL, AV_LOG_ERROR, "Cannot find stream information\n");
avformat_close_input(&video_fmt_ctx);
return ret;
}
for (int i = 0; i < video_fmt_ctx ->nb_streams; i++)
{
// �ҵ���Ƶ����
if (video_fmt_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
{
video_stream_index = i;
// ��ʼ����������Ϣ
if (!video_codec_init)
{
suitable_dec_ctx = video_fmt_ctx->streams[i]->codec;
AVCodec* pcodec = avcodec_find_decoder(suitable_dec_ctx->codec_id);
if (NULL == pcodec)
{
printf("cannot find decoder");
avformat_close_input(&video_fmt_ctx);
return 1;
}
if(0 != avcodec_open2(suitable_dec_ctx, pcodec, NULL))
{
printf("open codecer failed");
avformat_close_input(&video_fmt_ctx);
return 1;
}
video_codec_init = true;
}
}
}
// ������Ƶ
if (video_codec_init && suitable_dec_ctx)
{
decode_video_packet(video_fmt_ctx, suitable_dec_ctx, video_stream_index);
}
// �ر��ļ�
avformat_close_input(&video_fmt_ctx);
return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
//avcodec_init() ;
// ע���������п������õ��ļ���ʽ�ͱ�����
av_register_all();
avcodec_register_all() ;
open_input_file("D:\\test.264");
#ifdef FILE_OUT
file_debugout.close();
#endif
return 0;
}
ffmpeg 获取视频关键帧
最新推荐文章于 2024-08-26 14:04:47 发布
该博客介绍了一个C++程序,用于使用ffmpeg库从视频文件中提取关键帧,并将其保存为BMP图像。通过调用ffmpeg的相关API,实现了解码视频、判断关键帧并保存图像的功能。
摘要由CSDN通过智能技术生成