// ffmpegTest.cpp : Defines the entry point for the console application. // //#include "stdafx.h" #include "windows.h" #include "time.h" #include <avformat.h> #include <avutil.h> #include <avcodec.h> #include <swscale.h> #pragma comment(lib, "avcodec.lib") #pragma comment(lib, "avformat.lib") #pragma comment(lib, "avutil.lib") void SaveBmp(AVCodecContext *CodecContex, AVFrame *Picture, int width, int height); #define MAX_BUF_SIZE 256*1024 int main(int argc, char* argv[]) { int ret=-1, i=0, videoindex=-1, nComplete=0, len=0, frame_index=0; unsigned char *pEnCodeBuf = new unsigned char[MAX_BUF_SIZE]; char *sourceFile = "5.avi"; char *destFile = "123.mp4"; av_register_all(); AVFormatContext *pInputFormatContext=NULL; AVCodec *pInputCodec = NULL; AVCodecContext *pInputCodecContext = NULL; AVPacket InPack; int videoWidth, videoHeight; AVOutputFormat *pOutputFmt = NULL; AVFormatContext *pOutFormatContext = NULL; AVCodecContext *pOutCodecContext = NULL; AVCodec *pOutCodec = NULL; AVStream *pOutStream = NULL; AVPacket OutPack; AVFrame OutFrame; if(av_open_input_file(&pInputFormatContext, sourceFile, NULL, 0, NULL) !=0 ) { //打开输入文件 printf("can't open the file %s\n",sourceFile); exit(1); } if(av_find_stream_info(pInputFormatContext)<0) { //查找流信息 printf("can't find suitable codec parameters\n"); goto lk_error; } for(i=0; i<pInputFormatContext->nb_streams; i++) { if(pInputFormatContext->streams[i]->codec->codec_type==CODEC_TYPE_VIDEO) { videoindex=i; break; } } if(-1 == videoindex) { //没有找到视频流 goto lk_error; } pInputCodecContext = pInputFormatContext->streams[videoindex]->codec; pInputCodec = avcodec_find_decoder(pInputCodecContext->codec_id); if(NULL == pInputCodec) { //没有找到解码器 goto lk_error; } if(avcodec_open(pInputCodecContext, pInputCodec) != 0) { //打开解码器失败 goto lk_error; } videoWidth = pInputCodecContext->width; videoHeight = pInputCodecContext->height; pOutputFmt = guess_format(NULL, destFile, NULL); if(NULL == pOutputFmt) { //分析输出文件格式失败 goto lk_error; } pOutFormatContext = av_alloc_format_context(); if(NULL == pOutFormatContext) { goto lk_error; } pOutFormatContext->oformat = pOutputFmt; pOutStream = av_new_stream(pOutFormatContext, 0); if(NULL == pOutStream) { //创建流失败 goto lk_error; } //设定转换编码参数 pOutCodecContext = pOutStream->codec; pOutCodecContext->codec_id = CODEC_ID_MPEG4; pOutCodecContext->codec_type = CODEC_TYPE_VIDEO; pOutCodecContext->bit_rate = 98000; pOutCodecContext->width = videoWidth; pOutCodecContext->height = videoHeight; pOutCodecContext->time_base = pInputCodecContext->time_base; pOutCodecContext->gop_size = pInputCodecContext->gop_size; pOutCodecContext->pix_fmt = pInputCodecContext->pix_fmt; pOutCodecContext->max_b_frames = pInputCodecContext->max_b_frames; pOutCodecContext->time_base.den = 15; pOutCodecContext->time_base.num = 1; pOutStream->r_frame_rate = pInputFormatContext->streams[videoindex]->r_frame_rate; if (av_set_parameters(pOutFormatContext, NULL) < 0) { //转换编码参数设置不正确 goto lk_error; } strcpy(pOutFormatContext->title, pInputFormatContext->title); strcpy(pOutFormatContext->author, pInputFormatContext->author); strcpy(pOutFormatContext->copyright, pInputFormatContext->copyright); strcpy(pOutFormatContext->comment, pInputFormatContext->comment); strcpy(pOutFormatContext->album, pInputFormatContext->album); pOutFormatContext->year = pInputFormatContext->year; pOutFormatContext->track = pInputFormatContext->track; strcpy(pOutFormatContext->genre, pInputFormatContext->genre); pOutCodec = avcodec_find_encoder(CODEC_ID_MPEG4); if(NULL == pOutCodec) { //找不到指定编码器 goto lk_error; } if(avcodec_open(pOutCodecContext, pOutCodec) < 0) { //打开指定编码器错误 goto lk_error; } if (!(pOutFormatContext->flags & AVFMT_NOFILE)) { if(url_fopen(&pOutFormatContext->pb, destFile, URL_WRONLY)<0) { //打开输出文件 goto lk_error; } } if(av_write_header(pOutFormatContext) < 0) { //写入输出文件头失败 goto lk_error; } while(av_read_frame(pInputFormatContext, &InPack) >= 0) { len = avcodec_decode_video(pInputCodecContext, &OutFrame, &nComplete, InPack.data, InPack.size); if(nComplete > 0) { //解码一帧成功 SaveBmp(pInputCodecContext, &OutFrame, videoWidth, videoHeight); memset(pEnCodeBuf, 0, MAX_BUF_SIZE); OutFrame.pts = av_rescale(frame_index, AV_TIME_BASE*(int64_t)pOutCodecContext->time_base.num, pOutCodecContext->time_base.den); OutFrame.pict_type = 0; len = avcodec_encode_video(pOutCodecContext, pEnCodeBuf, MAX_BUF_SIZE, &OutFrame); if (len > 0) { av_init_packet(&OutPack); if(pOutCodecContext->coded_frame && pOutCodecContext->coded_frame->key_frame) { OutPack.flags |= PKT_FLAG_KEY; } OutPack.flags = InPack.flags; OutPack.stream_index = InPack.stream_index; OutPack.data = pEnCodeBuf; OutPack.size = len; ret=av_write_frame(pOutFormatContext, &OutPack); } frame_index++; } av_free_packet(&OutPack); } av_write_trailer(pOutFormatContext); for(i=0; i<pOutFormatContext->nb_streams; i++) { av_freep(&pOutFormatContext->streams[i]->codec); av_freep(&pOutFormatContext->streams[i]); } lk_error: av_free(pOutCodec); av_free(pOutputFmt); avcodec_close(pInputCodecContext); av_free(pInputFormatContext); av_free(pOutFormatContext); return 0; } void SaveBmp(AVCodecContext *CodecContex, AVFrame *Picture, int width, int height) { AVPicture pPictureRGB;//RGB图片 static struct SwsContext *img_convert_ctx; img_convert_ctx = sws_getContext(width, height, CodecContex->pix_fmt, width, height,\ PIX_FMT_RGB24, SWS_BICUBIC, NULL, NULL, NULL); avpicture_alloc(&pPictureRGB, PIX_FMT_RGB24, width, height); sws_scale(img_convert_ctx, Picture->data, Picture->linesize,\ 0, height, pPictureRGB.data, pPictureRGB.linesize); int lineBytes = pPictureRGB.linesize[0], i=0; char fileName[1024]={0}; time_t ltime; time(<ime); sprintf(fileName, "%d.bmp", ltime); FILE *pDestFile = fopen(fileName, "wb"); BITMAPFILEHEADER btfileHeader; btfileHeader.bfType = MAKEWORD(66, 77); btfileHeader.bfSize = lineBytes*height; btfileHeader.bfReserved1 = 0; btfileHeader.bfReserved2 = 0; btfileHeader.bfOffBits = 54; BITMAPINFOHEADER bitmapinfoheader; bitmapinfoheader.biSize = 40; bitmapinfoheader.biWidth = width; bitmapinfoheader.biHeight = height; bitmapinfoheader.biPlanes = 1; bitmapinfoheader.biBitCount = 24; bitmapinfoheader.biCompression = BI_RGB; bitmapinfoheader.biSizeImage = lineBytes*height; bitmapinfoheader.biXPelsPerMeter = 0; bitmapinfoheader.biYPelsPerMeter = 0; bitmapinfoheader.biClrUsed = 0; bitmapinfoheader.biClrImportant = 0; fwrite(&btfileHeader, 14, 1, pDestFile); fwrite(&bitmapinfoheader, 40, 1, pDestFile); for(i=height-1; i>=0; i--) { fwrite(pPictureRGB.data[0]+i*lineBytes, lineBytes, 1, pDestFile); } fclose(pDestFile); avpicture_free(&pPictureRGB); }