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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
#include "libavexporter.h"
bool libav::Exporter::setup(int w,int h, int bitRate, int frameRate, std::string container){
// Initialize libavcodec, and register all codecs and formats. //
av_register_all();
this->w=w;
this->h=h;
this->bitRate=bitRate;
this->frameRate=frameRate;
this->container=container;
return true;
}
bool libav::Exporter::record(std::string filename){
// allocate the output media context //
avformat_alloc_output_context2(&oc, NULL, NULL, filename.c_str());
if (!oc) {
printf("Could not deduce output format from file extension: using MPEG.\n");
avformat_alloc_output_context2(&oc, NULL, "mpeg", filename.c_str());
}
if (!oc) {
return false;
}
fmt = oc->oformat;
// Add the audio and video streams using the default format codecs
// * and initialize the codecs. //
video_st = NULL;
audio_st = NULL;
if (fmt->video_codec != AV_CODEC_ID_NONE) {
video_st = add_stream(oc, &video_codec, fmt->video_codec);
}
if (fmt->audio_codec != AV_CODEC_ID_NONE) {
audio_st = add_stream(oc, &audio_codec, fmt->audio_codec);
}
//set initial video params
video_st->codec->width=w;
video_st->codec->height=h;
video_st->codec->time_base.num = 1;//codecCtx->ticks_per_frame;
video_st->codec->time_base.den = frameRate;
video_st->time_base = video_st->codec->time_base;
//audioStream->time_base = codecCtx->time_base; //???has the capability of crashing
video_st->codec->gop_size = 10; /* emit one intra frame every ten frames */
video_st->codec->pix_fmt = PIX_FMT_YUV420P;
// Now that all the parameters are set, we can open the audio and
// * video codecs and allocate the necessary encode buffers. //
if (video_st)
open_video(oc, video_codec, video_st);
if (audio_st)
size=open_audio(oc, audio_codec, audio_st);
std::cerr << "opened audio codec with "<<size<<" frame size"<<std::endl;
av_dump_format(oc, 0, filename.c_str(), 1);
// open the output file, if needed //
if (!(fmt->flags & AVFMT_NOFILE)) {
int ret = avio_open(&oc->pb, filename.c_str(), AVIO_FLAG_WRITE);
if (ret < 0) {
std::cerr <<"Could not open " << filename.c_str() << std::endl;
return false;
}
}
// Write the stream header, if any. //
int ret = avformat_write_header(oc, NULL);
if (ret < 0) {
//std::cerr <<"Error occurred when opening output file:" << av_err2str(ret) << std::endl;
return false;
}
if (frame)
frame->pts = 0;
outputframe=0;
return true;
}
bool libav::Exporter::encodeFrame(unsigned char *pixels,uint16_t *samples){
// Compute current audio and video time. //
if (audio_st)
audio_pts = (double)audio_st->pts.val * audio_st->time_base.num / audio_st->time_base.den;
else
audio_pts = 0.0;
if (video_st)
video_pts = (double)video_st->pts.val * video_st->time_base.num /
video_st->time_base.den;
else
video_pts = 0.0;
// write interleaved audio and video frames //
if (!video_st || (video_st && audio_st && audio_pts < video_pts)) {
write_audio_frame(oc, audio_st, samples);
} else {
write_video_frame(oc, video_st, pixels);
frame->pts += av_rescale_q(1, video_st->codec->time_base, video_st->time_base);
}
//std::cerr << "encoded frame " << outputframe << std::endl;
outputframe++;
return true;
}
void libav::Exporter::finishRecord(){
av_write_trailer(oc);
// Close each codec. //
if (video_st)
close_video(oc, video_st);
if (audio_st)
close_audio(oc, audio_st);
if (!(fmt->flags & AVFMT_NOFILE))
// Close the output file. //
avio_close(oc->pb);
// free the stream //
avformat_free_context(oc);
}
|