#include <stdio.h>
extern "C"//包含C文件頭
{
#include "libavformat/avformat.h"
};
#define DATASIZE 2048*2048
AVStream *add_vidio_stream(AVFormatContext *oc, enum AVCodecID codec_id)//用以初始化一個用於輸出的AVFormatContext結構體
{
AVStream *st;
AVCodec *codec;
st = avformat_new_stream(oc, NULL);
if (!st)
{
printf("Could not alloc stream\n");
exit(1);
}
codec = avcodec_find_encoder(codec_id);//查找mjpeg解碼器
if (!codec)
{
printf("codec not found\n");
exit(1);
}
avcodec_get_context_defaults3(st->codec, codec);//申請AVStream->codec(AVCodecContext對象)空間並設置默認值(由avcodec_get_context_defaults3()設置
st->codec->bit_rate = 400000;//設置採樣參數,即比特率
st->codec->width = 1332;//設置視頻寬高,這裏跟圖片的寬高保存一致即可
st->codec->height = 620;
st->codec->time_base.den = 25;//設置幀率
st->codec->time_base.num = 1;
st->codec->pix_fmt = AV_PIX_FMT_YUV420P;//設置像素格式
st->codec->codec_tag = 0;
if (oc->oformat->flags & AVFMT_GLOBALHEADER)//一些格式需要視頻流數據頭分開
st->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;
return st;
}
void main()
{
AVFormatContext *ofmt_ctx = NULL;//其包含碼流參數較多,是一個貫穿始終的數據結構,很多函數都要用到它作爲參數
const char *out_filename = "d:\\out.mp4";//輸出文件路徑,在這裏也可以將mkv改成別的ffmpeg支持的格式,如mp4,flv,avi之類的
int ret;//返回標誌
av_register_all();//初始化解碼器和複用器
avformat_alloc_output_context2(&ofmt_ctx, NULL, NULL, out_filename);//初始化一個用於輸出的AVFormatContext結構體,視頻幀率和寬高在此函數裏面設置
if (!ofmt_ctx)
{
printf("Could not create output context\n");
return;
}
//AVStream *out_stream = add_vidio_stream(ofmt_ctx, AV_CODEC_ID_MJPEG);//創造輸出視頻流
AVStream *out_stream = add_vidio_stream(ofmt_ctx, AV_CODEC_ID_PNG);//創造輸出視頻流(第三個參數指向圖片的格式)
av_dump_format(ofmt_ctx, 0, out_filename, 1);//該函數會打印出視頻流的信息,如果看着不開心可以不要
if (!(ofmt_ctx->oformat->flags & AVFMT_NOFILE))//打開輸出視頻文件
{
ret = avio_open(&ofmt_ctx->pb, out_filename, AVIO_FLAG_WRITE);
if (ret < 0) {
printf("Could not open output file '%s'", out_filename);
return;
}
}
if (avformat_write_header(ofmt_ctx, NULL) < 0)//寫文件頭(Write file header)
{
printf("Error occurred when opening output file\n");
return;
}
int frame_index = 0;//放入視頻的圖像計數
unsigned char *mydata = new unsigned char[DATASIZE];
AVPacket pkt;
av_init_packet(&pkt);
pkt.flags |= AV_PKT_FLAG_KEY;
pkt.stream_index = out_stream->index;//獲取視頻信息,爲壓入幀圖像做準備
char buf[250] = { 0 };
while (frame_index < 626)//將圖像壓入視頻中
{
_snprintf(buf, 255, "1_00%03d.png", frame_index);//1_00000
std::string dir = "F:\\幀轉視頻\\data5\\";
std::string filePath = dir + buf;
FILE *file;//打開一張jpeg圖像並讀取其數據,在這裏圖像最大爲1M,如果超過1M,則需要修改1024*1024這裏
fopen_s(&file, filePath.c_str(), "rb");
pkt.size = fread(mydata, 1, DATASIZE, file);
pkt.data = mydata;
fclose(file);
if (av_interleaved_write_frame(ofmt_ctx, &pkt) < 0) //寫入圖像到視頻
{
printf("Error muxing packet\n");
break;
}
printf("Write %8d frames to output file\n", frame_index);//打印出當前壓入的幀數
frame_index++;
}
av_free_packet(&pkt);//釋放掉幀數據包對象
av_write_trailer(ofmt_ctx);//寫文件尾(Write file trailer)
delete[]mydata;//釋放數據對象
if (ofmt_ctx && !(ofmt_ctx->oformat->flags & AVFMT_NOFILE))
avio_close(ofmt_ctx->pb);//關閉視頻文件
avformat_free_context(ofmt_ctx);//釋放輸出視頻相關數據結構
return;
}