将h264流存为avi文件

使用ffmpeg存为avi和存为mp4在代码上是一样的,ffmpeg可以通过文件名后缀决定视频文件类型,以下是关键代码:

AviWriter.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#pragma once
 
class AVFormatContext;
class AVStream;
 
class AviWriter
{
public:
	int createFile(const char* filename);
	int setVideoTrack(const char* sps, int spslen, const char* pps, int ppslen, int width, int hight, int rate);
	int writeVideoSample(char* data, int datasize, bool keyframe);
	void closeFile();
 
private:
	AVFormatContext *m_fc;
	AVStream *m_avStream;
	int m_isHeaderWritten;
};

AviWriter.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#include "AviWriter.h"
 
#include <string>
 
#ifdef __cplusplus
extern "C" {
#endif
 
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
 
#ifdef __cplusplus
}
#endif
 
using namespace std;
 
int AviWriter::createFile(const char* filename)
{
	string aviFileName = filename;
	aviFileName = aviFileName.substr(0, aviFileName.length() - strlen(".avi")) + ".avi";
 
	m_isHeaderWritten = 0;
 
	av_log_set_level(AV_LOG_QUIET);
	av_register_all();
	avformat_network_init();
 
	avformat_alloc_output_context2(&m_fc, NULL, NULL, aviFileName.c_str());
 
	m_avStream = avformat_new_stream(m_fc, NULL);
 
	AVCodecContext *c;
	c = m_avStream->codec;
	c->codec_type = AVMEDIA_TYPE_VIDEO;
	c->codec_id = AV_CODEC_ID_H264;
	c->width = 1920;
	c->height = 1080;
	c->pix_fmt = AV_PIX_FMT_YUV420P;
	c->time_base.den = 25;
	c->time_base.num = 1;
	c->extradata = NULL;
 
	if (avio_open(&m_fc->pb, m_fc->filename, 2) < 0)
		return -1;
 
	return 0;
 
}
 
int AviWriter::setVideoTrack(const char* sps, int spslen, const char* pps, int ppslen, int width, int hight, int rate)
{
	unsigned char splitter[4] = { 0, 0, 0, 1 };
	int extraSize = 4 + spslen + 4 + ppslen + FF_INPUT_BUFFER_PADDING_SIZE;
	AVCodecContext *c;
	c = m_avStream->codec;
	av_free(c->extradata);
	c->extradata = (unsigned char *)av_malloc(extraSize);
	memcpy(c->extradata, splitter, 4);
	memcpy(c->extradata + 4, sps, spslen);
	memcpy(c->extradata + 4 + spslen, splitter, 4);
	memcpy(c->extradata + 4 + spslen + 4, pps, ppslen);
	c->extradata_size = 4 + spslen + 4 + ppslen;
 
	m_isHeaderWritten = 1;
 
	if (avformat_write_header(m_fc, NULL) != 0)
		return -1;
	return 0;
}
 
int AviWriter::writeVideoSample(char* data, int datasize, bool keyframe)
{
	if (NULL == m_fc || NULL == m_avStream)
		return -1;
 
	AVPacket pkt;
	av_init_packet(&pkt);
	pkt.stream_index = m_avStream->index;
	pkt.data = (unsigned char *)data;
	pkt.size = datasize;
	pkt.flags = keyframe ? AV_PKT_FLAG_KEY : 0;
 
	av_interleaved_write_frame(m_fc, &pkt);
	av_free_packet(&pkt);
	return 0;
}
 
void AviWriter::closeFile()
{
	if (NULL == m_fc)
		return;
 
	if (m_isHeaderWritten)
		av_write_trailer(m_fc);
 
	avio_close(m_fc->pb);
 
	avformat_free_context(m_fc);
 
	m_fc = NULL;
}

Leave a Comment