18 unsigned height_,
unsigned bpp,
unsigned channels_,
21 , codec(width_, height_, bpp)
29 file.
write(dummy,
sizeof(dummy));
52 unsigned header_pos = 0;
54 auto AVIOUT4 = [&](
const char (&s)[5]) {
56 memcpy(&avi_header[header_pos], s, 4);
59 auto AVIOUTw = [&](uint16_t w) {
61 header_pos +=
sizeof(w);
63 auto AVIOUTd = [&](uint32_t d) {
65 header_pos +=
sizeof(d);
67 auto AVIOUTs = [&](
const char* s) {
68 auto len1 = strlen(s) + 1;
69 memcpy(&avi_header[header_pos], s, len1);
70 header_pos += (len1 + 1) & ~1;
73 bool hasAudio = audiorate != 0;
80 unsigned main_list = header_pos;
86 AVIOUTd(
unsigned(1000000 / fps));
92 AVIOUTd(hasAudio? 2 : 1);
103 AVIOUTd(4 + 8 + 56 + 8 + 40);
114 AVIOUTd(
unsigned(1000000 * fps));
118 AVIOUTd(
unsigned(~0));
130 AVIOUTd(width * height * 4);
138 unsigned bitsPerSample = 16;
139 unsigned bytesPerSample = bitsPerSample / 8;
140 unsigned bytesPerFragment = bytesPerSample * channels;
141 unsigned bytesPerSecond = audiorate * bytesPerFragment;
142 unsigned fragments = audiowritten / channels;
146 AVIOUTd(4 + 8 + 56 + 8 + 16);
157 AVIOUTd(bytesPerFragment);
158 AVIOUTd(bytesPerSecond);
162 AVIOUTd(
unsigned(~0));
163 AVIOUTd(bytesPerFragment);
172 AVIOUTd(bytesPerSecond);
173 AVIOUTw(bytesPerFragment);
174 AVIOUTw(bitsPerSample);
190 constexpr
size_t size = (4 + 1 + 2 + 1 + 2 + 1) + 22;
192 time_t
t = time(
nullptr);
193 struct tm *tm = localtime(&
t);
194 snprintf(dateStr,
sizeof(dateStr),
"%04d-%02d-%02d", 1900 + tm->tm_year,
195 tm->tm_mon + 1, tm->tm_mday);
199 + (4 + 4 + ((versionStr.size() + 1 + 1) & ~1))
200 + (4 + 4 + ((strlen(dateStr ) + 1 + 1) & ~1))
204 AVIOUTd(
unsigned(versionStr.size()) + 1);
205 AVIOUTs(versionStr.c_str());
207 AVIOUTd(
unsigned(strlen(dateStr)) + 1);
214 int nMain = header_pos - main_list - 4;
220 header_pos = main_list;
225 AVIOUTd(written + 4);
230 unsigned idxSize = unsigned(index.size()) *
sizeof(
Endian::L32);
231 index[0] = (
'i' << 0) | (
'd' << 8) | (
'x' << 16) | (
'1' << 24);
232 index[1] = idxSize - 8;
233 file.
write(&index[0], idxSize);
241 void AviWriter::addAviChunk(
const char* tag,
unsigned size,
const void* data,
unsigned flags)
247 memcpy(chunk.t, tag,
sizeof(chunk.t));
249 file.
write(&chunk,
sizeof(chunk));
251 unsigned writesize = (
size + 1) & ~1;
252 file.
write(data, writesize);
253 unsigned pos = written + 4;
254 written += writesize + 8;
256 size_t idxSize = index.size();
257 index.resize(idxSize + 4);
259 index[idxSize + 1] = flags;
260 index[idxSize + 2] = pos;
261 index[idxSize + 3] =
size;
266 bool keyFrame = (frames++ % 300 == 0);
268 addAviChunk(
"00dc", buffer.size(), buffer.data(), keyFrame ? 0x10 : 0x0);
271 assert((samples % channels) == 0);
272 assert(audiorate != 0);
273 if (OPENMSX_BIGENDIAN) {
276 std::vector<Endian::L16> buf(sampleData, sampleData + samples);
277 addAviChunk(
"01wb", samples *
sizeof(int16_t), buf.data(), 0);
279 addAviChunk(
"01wb", samples *
sizeof(int16_t), sampleData, 0);
281 audiowritten += samples;