利用FFmpeg将一系列jpg图片封装成mp4格式

#include "libavformat/avformat.h"
#include "libavutil/timestamp.h"

#define NUMS 33

void saveframe(AVFrame *frame, const char *filename) {
	FILE *file;
	file = fopen(filename, "wb+");
	int width = 320;
	int height = 480;
	unsigned char *buf = (unsigned char*)malloc(width * height * 3 / 2);
	/*
	memcpy(data, frame->data[0], 320 * 480);
	memcpy(data+width*height, frame->data[1], 320 * 480/4);
	memcpy(data + width * height*5/4, frame->data[2], 320 * 480/4);
	*/
	int i;
	int a = 0;
	for (i = 0; i < height; i++)
	{
		memcpy(buf + a, frame->data[0] + i * frame->linesize[0], width);
		a += width;
	}
	for (i = 0; i < height / 2; i++)
	{
		memcpy(buf + a, frame->data[1] + i * frame->linesize[1], width / 2);
		a += width / 2;
	}
	for (i = 0; i < height / 2; i++)
	{
		memcpy(buf + a, frame->data[2] + i * frame->linesize[2], width / 2);
		a += width / 2;
	}
	fwrite(buf, 1, width*height * 3 / 2, file);
	fclose(file);
}

int main()
{
	char input_filename[20];
	const char *output_filename = "out.mp4";

	const char *output_filename111 = "1.yuv";

	AVCodec* pDecodec;
	AVCodecContext* pDecodecCtx;
	AVFrame* pDeFrame;
	AVPacket pDePacket;
	int deCFflag;

	AVCodec* pEncodec;
	AVCodecContext* pEncodecCtx;
	AVFrame* pEnFrame;
	AVPacket pEnPacket;
	AVFormatContext* pOutPutFormatCtx;
	AVStream* pVideoStream;

	//解码器初始化。。。。。。。。。。。。。。。
	//读取jpg用的解码器mjpeg
	pDecodec = avcodec_find_decoder(AV_CODEC_ID_MJPEG);
	//获取解码器上下文
	pDecodecCtx = avcodec_alloc_context3(pDecodec);
	pDecodecCtx->width = 320;
	pDecodecCtx->height = 480;
	pDecodecCtx->pix_fmt = AV_PIX_FMT_YUV420P;
	//打开解码器
	avcodec_open2(pDecodecCtx, pDecodec, NULL);


	//编码器初始化。。。。。。。。。。。。。。。。。
	avformat_alloc_output_context2(&pOutPutFormatCtx, NULL, NULL, output_filename);
	pVideoStream = avformat_new_stream(pOutPutFormatCtx, NULL);
	avio_open(&pOutPutFormatCtx->pb, output_filename, AVIO_FLAG_READ_WRITE);
	av_dump_format(pOutPutFormatCtx, 0, output_filename, 1);

	pEncodecCtx = pVideoStream->codec;
	pEncodecCtx->codec_id = pOutPutFormatCtx->oformat->video_codec;
	pEncodecCtx->codec_type = AVMEDIA_TYPE_VIDEO;
	pEncodecCtx->pix_fmt = AV_PIX_FMT_YUV420P;
	pEncodecCtx->width = 320;
	pEncodecCtx->height = 480;
	//pEncodecCtx->bit_rate = 400000; 码流 适用于网络传输
	pEncodecCtx->gop_size = 1;
	pEncodecCtx->time_base.num = 1;
	pEncodecCtx->time_base.den = 10;
	pEncodecCtx->qmin = 10;
	pEncodecCtx->qmax = 51;
	pEncodecCtx->max_b_frames = 0;
	//质量 文件
	pEncodecCtx->bit_rate = 0;
	av_opt_set_int(pEncodecCtx->priv_data, "crf", 0, 0);
	pEncodecCtx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
	//找一个视频编码器
	pEncodec = avcodec_find_encoder(pEncodecCtx->codec_id);
	//打开编码器
	avcodec_open2(pEncodecCtx, pEncodec, NULL);

	//将编码器的信息与输出的信息属性关联起来
	avcodec_parameters_from_context(pVideoStream->codecpar, pEncodecCtx);
	av_codec_get_tag2(pOutPutFormatCtx->oformat->codec_tag, pEncodecCtx->codec_id, &pVideoStream->codecpar->codec_tag);
	//写输出的文件的头
	avformat_write_header(pOutPutFormatCtx, NULL);

	AVRational rational;
	rational.den = 10;
	rational.num = 1;

	for (int i = 0; i < NUMS; i++) {
		FILE *file;
		sprintf(input_filename, "%d.jpg", i + 1);
		//char *input_filename = "10.jpg";
		file = fopen(input_filename, "rb+");
		printf("%s\n", input_filename);
		fseek(file, 0, SEEK_END);
		int frame_size = ftell(file);
		fseek(file, 0, SEEK_SET);
		unsigned char *jpgdata = (unsigned char *)malloc(frame_size);

		int readlen = fread(jpgdata, 1, frame_size, file);

		// 用一个avstream来接收解码的数据帧
		pDeFrame = av_frame_alloc();
		//pDeFrame->width = 320;
		//pDeFrame->height = 480;
		//初始化一个avpacket数据包
		av_init_packet(&pDePacket);
		pDePacket.data = jpgdata;
		pDePacket.size = frame_size;

		//调用解码器解码,解码成功
		avcodec_decode_video2(pDecodecCtx, pDeFrame, &deCFflag, &pDePacket);
		if (deCFflag == 0) {
			printf("decode false!!!!!!!\n");
			goto end;
		}
		//saveframe(pDeFrame, output_filename111);

		//初始话编码的包
		av_init_packet(&pEnPacket);
		av_new_packet(&pEnPacket, 90 * 1024);

		int gotpicture = 0;
		//pEnFrame->pts = i;

		//编码
		avcodec_encode_video2(pEncodecCtx, &pEnPacket, pDeFrame, &gotpicture);
		if (gotpicture != 1)
			goto end1;
		printf("----encodecresult %d \n",gotpicture);
		pEnPacket.pts = av_rescale_q(pEnPacket.pts, rational, pVideoStream->time_base);
		pEnPacket.stream_index = pVideoStream->index;
		//将编码得到的包写入输出文件
		av_write_frame(pOutPutFormatCtx, &pEnPacket);

end1:
		av_free_packet(&pEnPacket);
end:
		av_frame_free(&pDeFrame);
		//av_free_packet(&pDePacket);
		fclose(file);
	}




	//写文件尾
	av_write_trailer(pOutPutFormatCtx);

	printf("hello,world!!!!\n");

	system("pause");

	return 0;
}

你可能感兴趣的:(音视频,ffmpeg,jpg,mp4)