ffmpeg 获取视频关键帧

// keyframe.cpp :
//

//#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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值