5
5
#include " common/swaglog.h"
6
6
#include " common/util.h"
7
7
8
- VideoWriter::VideoWriter (const char *path, const char *filename, bool remuxing, int width, int height, int fps, cereal::EncodeIndex::Type codec, bool include_audio )
8
+ VideoWriter::VideoWriter (const char *path, const char *filename, bool remuxing, int width, int height, int fps, cereal::EncodeIndex::Type codec)
9
9
: remuxing(remuxing) {
10
10
vid_path = util::string_format (" %s/%s" , path, filename);
11
11
lock_path = util::string_format (" %s/%s.lock" , path, filename);
@@ -41,45 +41,6 @@ VideoWriter::VideoWriter(const char *path, const char *filename, bool remuxing,
41
41
this ->out_stream = avformat_new_stream (this ->ofmt_ctx , raw ? avcodec : NULL );
42
42
assert (this ->out_stream );
43
43
44
- if (include_audio) {
45
- assert (this ->ofmt_ctx ->oformat ->audio_codec != AV_CODEC_ID_NONE); // check output format supports audio streams
46
- const AVCodec *audio_avcodec = avcodec_find_encoder (AV_CODEC_ID_AAC);
47
- assert (audio_avcodec);
48
- this ->audio_codec_ctx = avcodec_alloc_context3 (audio_avcodec);
49
- assert (this ->audio_codec_ctx );
50
- this ->audio_codec_ctx ->sample_fmt = AV_SAMPLE_FMT_FLTP;
51
- this ->audio_codec_ctx ->sample_rate = 16000 ; // from system/micd.py
52
- #if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 28, 100) // FFmpeg 5.1+
53
- av_channel_layout_default (&this ->audio_codec_ctx ->ch_layout , 1 );
54
- #else
55
- this ->audio_codec_ctx ->channel_layout = AV_CH_LAYOUT_MONO;
56
- #endif
57
- this ->audio_codec_ctx ->bit_rate = 32000 ;
58
- this ->audio_codec_ctx ->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
59
- this ->audio_codec_ctx ->time_base = (AVRational){1 , audio_codec_ctx->sample_rate };
60
- int err = avcodec_open2 (this ->audio_codec_ctx , audio_avcodec, NULL );
61
- assert (err >= 0 );
62
- av_log_set_level (AV_LOG_WARNING); // hide "QAvg" info msgs at the end of every segment
63
-
64
- this ->audio_stream = avformat_new_stream (this ->ofmt_ctx , NULL );
65
- assert (this ->audio_stream );
66
- err = avcodec_parameters_from_context (this ->audio_stream ->codecpar , this ->audio_codec_ctx );
67
- assert (err >= 0 );
68
-
69
- this ->audio_frame = av_frame_alloc ();
70
- assert (this ->audio_frame );
71
- this ->audio_frame ->format = this ->audio_codec_ctx ->sample_fmt ;
72
- #if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 28, 100) // FFmpeg 5.1+
73
- av_channel_layout_copy (&this ->audio_frame ->ch_layout , &this ->audio_codec_ctx ->ch_layout );
74
- #else
75
- this ->audio_frame ->channel_layout = this ->audio_codec_ctx ->channel_layout ;
76
- #endif
77
- this ->audio_frame ->sample_rate = this ->audio_codec_ctx ->sample_rate ;
78
- this ->audio_frame ->nb_samples = this ->audio_codec_ctx ->frame_size ;
79
- err = av_frame_get_buffer (this ->audio_frame , 0 );
80
- assert (err >= 0 );
81
- }
82
-
83
44
int err = avio_open (&this ->ofmt_ctx ->pb , this ->vid_path .c_str (), AVIO_FLAG_WRITE);
84
45
assert (err >= 0 );
85
46
@@ -89,6 +50,45 @@ VideoWriter::VideoWriter(const char *path, const char *filename, bool remuxing,
89
50
}
90
51
}
91
52
53
+ void VideoWriter::initialize_audio (int sample_rate) {
54
+ assert (this ->ofmt_ctx ->oformat ->audio_codec != AV_CODEC_ID_NONE); // check output format supports audio streams
55
+ const AVCodec *audio_avcodec = avcodec_find_encoder (AV_CODEC_ID_AAC);
56
+ assert (audio_avcodec);
57
+ this ->audio_codec_ctx = avcodec_alloc_context3 (audio_avcodec);
58
+ assert (this ->audio_codec_ctx );
59
+ this ->audio_codec_ctx ->sample_fmt = AV_SAMPLE_FMT_FLTP;
60
+ this ->audio_codec_ctx ->sample_rate = sample_rate;
61
+ #if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 28, 100) // FFmpeg 5.1+
62
+ av_channel_layout_default (&this ->audio_codec_ctx ->ch_layout , 1 );
63
+ #else
64
+ this ->audio_codec_ctx ->channel_layout = AV_CH_LAYOUT_MONO;
65
+ #endif
66
+ this ->audio_codec_ctx ->bit_rate = 32000 ;
67
+ this ->audio_codec_ctx ->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
68
+ this ->audio_codec_ctx ->time_base = (AVRational){1 , audio_codec_ctx->sample_rate };
69
+ int err = avcodec_open2 (this ->audio_codec_ctx , audio_avcodec, NULL );
70
+ assert (err >= 0 );
71
+ av_log_set_level (AV_LOG_WARNING); // hide "QAvg" info msgs at the end of every segment
72
+
73
+ this ->audio_stream = avformat_new_stream (this ->ofmt_ctx , NULL );
74
+ assert (this ->audio_stream );
75
+ err = avcodec_parameters_from_context (this ->audio_stream ->codecpar , this ->audio_codec_ctx );
76
+ assert (err >= 0 );
77
+
78
+ this ->audio_frame = av_frame_alloc ();
79
+ assert (this ->audio_frame );
80
+ this ->audio_frame ->format = this ->audio_codec_ctx ->sample_fmt ;
81
+ #if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 28, 100) // FFmpeg 5.1+
82
+ av_channel_layout_copy (&this ->audio_frame ->ch_layout , &this ->audio_codec_ctx ->ch_layout );
83
+ #else
84
+ this ->audio_frame ->channel_layout = this ->audio_codec_ctx ->channel_layout ;
85
+ #endif
86
+ this ->audio_frame ->sample_rate = this ->audio_codec_ctx ->sample_rate ;
87
+ this ->audio_frame ->nb_samples = this ->audio_codec_ctx ->frame_size ;
88
+ err = av_frame_get_buffer (this ->audio_frame , 0 );
89
+ assert (err >= 0 );
90
+ }
91
+
92
92
void VideoWriter::write (uint8_t *data, int len, long long timestamp, bool codecconfig, bool keyframe) {
93
93
if (of && data) {
94
94
size_t written = util::safe_fwrite (data, 1 , len, of);
@@ -106,9 +106,9 @@ void VideoWriter::write(uint8_t *data, int len, long long timestamp, bool codecc
106
106
}
107
107
int err = avcodec_parameters_from_context (out_stream->codecpar , codec_ctx);
108
108
assert (err >= 0 );
109
- err = avformat_write_header (ofmt_ctx, NULL );
110
- assert (err >= 0 );
111
- } else {
109
+ err = avformat_write_header (ofmt_ctx, NULL );
110
+ assert (err >= 0 );
111
+ } else {
112
112
// input timestamps are in microseconds
113
113
AVRational in_timebase = {1 , 1000000 };
114
114
@@ -135,8 +135,13 @@ void VideoWriter::write(uint8_t *data, int len, long long timestamp, bool codecc
135
135
}
136
136
}
137
137
138
- void VideoWriter::write_audio (uint8_t *data, int len, long long timestamp) {
139
- if (!remuxing || !audio_codec_ctx) return ;
138
+ void VideoWriter::write_audio (uint8_t *data, int len, long long timestamp, int sample_rate) {
139
+ if (!remuxing) return ;
140
+ if (!audio_initialized) {
141
+ initialize_audio (sample_rate);
142
+ audio_initialized = true ;
143
+ }
144
+ if (!audio_codec_ctx) return ;
140
145
141
146
// sync logMonoTime of first audio packet with the timestampEof of first video packet
142
147
if (audio_pts == 0 ) {
@@ -174,6 +179,7 @@ void VideoWriter::encode_and_write_audio_frame(AVFrame* frame) {
174
179
if (err < 0 ) {
175
180
LOGW (" AUDIO: Write frame failed - error: %d" , err);
176
181
}
182
+ av_packet_unref (pkt);
177
183
}
178
184
av_packet_free (&pkt);
179
185
} else {
0 commit comments