46 std::string filename = file.
getURL();
55 std::array<uint8_t, AVI_HEADER_SIZE> avi_header = {};
56 unsigned header_pos = 0;
58 auto AVIOUT4 = [&](std::string_view s) {
59 assert(s.size() == 4);
63 auto AVIOUTw = [&](uint16_t w) {
65 header_pos +=
sizeof(w);
67 auto AVIOUTd = [&](uint32_t d) {
69 header_pos +=
sizeof(d);
72 auto len1 = s.size() + 1;
74 header_pos += narrow<unsigned>((len1 + 1) & ~1);
77 bool hasAudio = audioRate != 0;
81 AVIOUTd(AVI_HEADER_SIZE + written - 8 +
unsigned(index.size() *
sizeof(
Endian::L32)));
84 auto main_list = header_pos;
90 AVIOUTd(uint32_t(1000000 / fps));
96 AVIOUTd(hasAudio? 2 : 1);
107 AVIOUTd(4 + 8 + 56 + 8 + 40);
118 AVIOUTd(uint32_t(1000000 * fps));
122 AVIOUTd(uint32_t(~0));
134 AVIOUTd(width * height * 4);
142 uint16_t bitsPerSample = 16;
143 unsigned bytesPerSample = bitsPerSample / 8;
144 unsigned bytesPerFragment = bytesPerSample * channels;
145 unsigned bytesPerSecond = audioRate * bytesPerFragment;
146 unsigned fragments = audioWritten / channels;
150 AVIOUTd(4 + 8 + 56 + 8 + 16);
161 AVIOUTd(bytesPerFragment);
162 AVIOUTd(bytesPerSecond);
166 AVIOUTd(
unsigned(~0));
167 AVIOUTd(bytesPerFragment);
174 AVIOUTw(narrow<uint16_t>(channels));
176 AVIOUTd(bytesPerSecond);
177 AVIOUTw(narrow<uint16_t>(bytesPerFragment));
178 AVIOUTw(bitsPerSample);
194 constexpr size_t size = (4 + 1 + 2 + 1 + 2 + 1) + 22;
195 std::array<char, size> dateStr;
196 time_t
t = time(
nullptr);
197 const struct tm* tm = localtime(&
t);
198 size_t dateLen = snprintf(dateStr.data(),
sizeof(dateStr),
"%04d-%02d-%02d", 1900 + tm->tm_year,
199 tm->tm_mon + 1, tm->tm_mday);
200 assert(dateLen < size);
203 AVIOUTd(narrow<uint32_t>(
205 + (4 + 4 + ((versionStr.size() + 1 + 1) & ~1))
206 + (4 + 4 + ((dateLen + 1 + 1) & ~1))
210 AVIOUTd(
unsigned(versionStr.size()) + 1);
213 AVIOUTd(
unsigned(dateLen) + 1);
220 auto nMain = header_pos - main_list - 4;
221 auto nJunk = AVI_HEADER_SIZE - 8 - 12 - header_pos;
226 header_pos = main_list;
228 header_pos = AVI_HEADER_SIZE - 12;
231 AVIOUTd(written + 4);
236 unsigned idxSize = unsigned(index.size()) *
sizeof(
Endian::L32);
237 index[0] = (
'i' << 0) | (
'd' << 8) | (
'x' << 16) | (
'1' << 24);
238 index[1] = idxSize - 8;
239 file.
write(std::span{index});
241 file.
write(avi_header);
247void AviWriter::addAviChunk(std::span<const char, 4> tag, std::span<const uint8_t> data,
unsigned flags)