Unravel Engine C++ Reference
Loading...
Searching...
No Matches
aviwriter.h
Go to the documentation of this file.
1/*
2 * Copyright 2011-2023 Branimir Karadzic. All rights reserved.
3 * License: https://github.com/bkaradzic/bgfx/blob/master/LICENSE
4 */
5
6#ifndef AVIWRITER_H_HEADER_GUARD
7#define AVIWRITER_H_HEADER_GUARD
8
9#include <bx/readerwriter.h>
10
11// Simple AVI writer. VideoLAN and VirtualDub can decode it.
12// Needs some bits to get jiggled to work with other players. But it's good
13// enough for an example.
15{
16 AviWriter(bx::FileWriterI* _writer)
17 : m_writer(_writer)
18 , m_frame(NULL)
19 , m_frameSize(0)
20 , m_numFrames(0)
21 , m_width(0)
22 , m_height(0)
23 , m_yflip(false)
24 {
25 }
26
27 bool open(const char* _filePath, uint32_t _width, uint32_t _height, uint32_t _fps, bool _yflip)
28 {
29 if(!bx::open(m_writer, _filePath))
30 {
31 return false;
32 }
33
34 m_frameSize = _width * _height * 3;
35 m_frame = new uint8_t[m_frameSize + 8];
36 m_numFrames = 0;
37 m_width = _width;
38 m_height = _height;
39
40 // Bgfx returns _yflip true for OpenGL since bottom left corner is 0, 0. In D3D top left corner
41 // is 0, 0. DIB expect OpenGL style coordinates, so this is inverted logic for AVI writer.
42 m_yflip = !_yflip;
43
44 bx::Error err;
45
46 bx::StaticMemoryBlockWriter mem(m_frame, 8);
47 // Stream Data (LIST 'movi' Chunk) http://msdn.microsoft.com/en-us/library/ms899496.aspx
48 bx::write(&mem, BX_MAKEFOURCC('0', '0', 'd', 'b'), &err);
49 bx::write(&mem, m_frameSize, &err);
50
51 bx::write(m_writer, BX_MAKEFOURCC('R', 'I', 'F', 'F'), &err);
52 m_riffSizeOffset = m_writer->seek();
53 bx::write(m_writer, uint32_t(0), &err);
54
55 bx::write(m_writer, BX_MAKEFOURCC('A', 'V', 'I', ' '), &err);
56
57 // AVI RIFF Form http://msdn.microsoft.com/en-us/library/ms899422.aspx
58 bx::write(m_writer, BX_MAKEFOURCC('L', 'I', 'S', 'T'), &err);
59 bx::write(m_writer, uint32_t(192), &err);
60 bx::write(m_writer, BX_MAKEFOURCC('h', 'd', 'r', 'l'), &err);
61
62 // AVI Main Header http://msdn.microsoft.com/en-us/library/ms779632.aspx
63 bx::write(m_writer, BX_MAKEFOURCC('a', 'v', 'i', 'h'), &err);
64 bx::write(m_writer, uint32_t(56), &err);
65 bx::write(m_writer, uint32_t(0), &err); // dwMicroSecPerFrame
66 bx::write(m_writer, uint32_t(0), &err); // dwMaxBytesPerSec
67 bx::write(m_writer, uint32_t(0), &err); // dwPaddingGranularity
68 bx::write(m_writer, uint32_t(0x110), &err); // dwFlags
69
71 bx::write(m_writer, uint32_t(0), &err); // dwTotalFrames
72
73 bx::write(m_writer, uint32_t(0), &err); // dwInitialFrames
74 bx::write(m_writer, uint32_t(1), &err); // dwStreams
75 bx::write(m_writer, uint32_t(0), &err); // dwSuggestedBufferSize
76 bx::write(m_writer, _width, &err); // dwWidth
77 bx::write(m_writer, _height, &err); // dwHeight
78 bx::write(m_writer, uint32_t(0), &err); // dwReserved0
79 bx::write(m_writer, uint32_t(0), &err); // dwReserved1
80 bx::write(m_writer, uint32_t(0), &err); // dwReserved2
81 bx::write(m_writer, uint32_t(0), &err); // dwReserved3
82
83 bx::write(m_writer, BX_MAKEFOURCC('L', 'I', 'S', 'T'), &err);
84 bx::write(m_writer, uint32_t(116), &err);
85 bx::write(m_writer, BX_MAKEFOURCC('s', 't', 'r', 'l'), &err);
86
87 // AVISTREAMHEADER Structure http://msdn.microsoft.com/en-us/library/ms779638.aspx
88 bx::write(m_writer, BX_MAKEFOURCC('s', 't', 'r', 'h'), &err);
89 bx::write(m_writer, uint32_t(56), &err);
90 // AVI Stream Headers http://msdn.microsoft.com/en-us/library/ms899423.aspx
91 bx::write(m_writer, BX_MAKEFOURCC('v', 'i', 'd', 's'), &err); // fccType
92 bx::write(m_writer, BX_MAKEFOURCC('D', 'I', 'B', ' '), &err); // fccHandler
93 bx::write(m_writer, uint32_t(0), &err); // dwFlags
94 bx::write(m_writer, uint16_t(0), &err); // wPriority
95 bx::write(m_writer, uint16_t(0), &err); // wLanguage
96 bx::write(m_writer, uint32_t(0), &err); // dwInitialFrames
97 bx::write(m_writer, uint32_t(1), &err); // dwScale
98 bx::write(m_writer, _fps, &err); // dwRate
99 bx::write(m_writer, uint32_t(0), &err); // dwStart
100
101 m_lengthOffset = m_writer->seek();
102 bx::write(m_writer, uint32_t(0), &err); // dwLength
103
104 bx::write(m_writer, m_frameSize, &err); // dwSuggestedBufferSize
105 bx::write(m_writer, UINT32_MAX, &err); // dwQuality
106 bx::write(m_writer, uint32_t(0), &err); // dwSampleSize
107 bx::write(m_writer, int16_t(0), &err); // rcFrame.left
108 bx::write(m_writer, int16_t(0), &err); // rcFrame.top
109 bx::write(m_writer, uint16_t(_width), &err); // rcFrame.right
110 bx::write(m_writer, uint16_t(_height), &err); // rcFrame.bottom
111
112 bx::write(m_writer, BX_MAKEFOURCC('s', 't', 'r', 'f'), &err);
113 bx::write(m_writer, uint32_t(40), &err);
114
115 // BITMAPINFOHEADER structure http://msdn.microsoft.com/en-us/library/windows/desktop/dd318229%28v=vs.85%29.aspx
116 bx::write(m_writer, uint32_t(40), &err); // biSize
117 bx::write(m_writer, _width, &err); // biWidth
118 bx::write(m_writer, _height, &err); // biHeight
119 bx::write(m_writer, uint16_t(1), &err); // biPlanes
120 bx::write(m_writer, uint16_t(24), &err); // biBitCount
121 bx::write(m_writer, uint32_t(0), &err); // biCompression
122 bx::write(m_writer, m_frameSize, &err); // biSizeImage
123 bx::write(m_writer, uint32_t(0), &err); // biXPelsPerMeter
124 bx::write(m_writer, uint32_t(0), &err); // biYPelsPerMeter
125 bx::write(m_writer, uint32_t(0), &err); // biClrUsed
126 bx::write(m_writer, uint32_t(0), &err); // biClrImportant
127
128 bx::write(m_writer, BX_MAKEFOURCC('L', 'I', 'S', 'T'), &err);
129
130 m_moviListOffset = m_writer->seek();
131 bx::write(m_writer, uint32_t(0), &err);
132 bx::write(m_writer, BX_MAKEFOURCC('m', 'o', 'v', 'i'), &err);
133
134 return true;
135 }
136
137 void close()
138 {
139 if(NULL != m_frame)
140 {
141 bx::Error err;
142
143 int64_t pos = m_writer->seek();
144 m_writer->seek(m_moviListOffset, bx::Whence::Begin);
145 bx::write(m_writer, uint32_t(pos - m_moviListOffset - 4), &err);
146 m_writer->seek(pos, bx::Whence::Begin);
147
148 bx::write(m_writer, BX_MAKEFOURCC('i', 'd', 'x', '1'), &err);
149 bx::write(m_writer, m_numFrames * 16, &err);
150
151 for(uint32_t ii = 0, offset = 4; ii < m_numFrames; ++ii)
152 {
153 bx::write(m_writer, BX_MAKEFOURCC('0', '0', 'd', 'b'), &err);
154 bx::write(m_writer, uint32_t(16), &err);
155 bx::write(m_writer, offset, &err);
156 bx::write(m_writer, m_frameSize, &err);
157 offset += m_frameSize + 8;
158 }
159
160 pos = m_writer->seek();
161 m_writer->seek(m_riffSizeOffset, bx::Whence::Begin);
162 bx::write(m_writer, uint32_t(pos - m_riffSizeOffset - 4), &err);
163
164 m_writer->seek(m_totalFramesOffset, bx::Whence::Begin);
165 bx::write(m_writer, m_numFrames, &err);
166
167 m_writer->seek(m_lengthOffset, bx::Whence::Begin);
168 bx::write(m_writer, m_numFrames, &err);
169
170 bx::close(m_writer);
171
172 delete[] m_frame;
173 m_frame = NULL;
174 m_frameSize = 0;
175 }
176 }
177
178 void frame(const void* _data)
179 {
180 if(NULL != m_frame)
181 {
182 ++m_numFrames;
183 uint32_t width = m_width;
184 uint32_t height = m_height;
185
186 uint8_t* bgr = &m_frame[8];
187
188 if(m_yflip)
189 {
190 for(uint32_t yy = 0; yy < height; ++yy)
191 {
192 const uint8_t* bgra = (const uint8_t*)_data + (height - 1 - yy) * width * 4;
193
194 for(uint32_t ii = 0; ii < width; ++ii)
195 {
196 bgr[0] = bgra[0];
197 bgr[1] = bgra[1];
198 bgr[2] = bgra[2];
199 bgr += 3;
200 bgra += 4;
201 }
202 }
203 }
204 else
205 {
206 const uint8_t* bgra = (const uint8_t*)_data;
207 for(uint32_t ii = 0, num = m_frameSize / 3; ii < num; ++ii)
208 {
209 bgr[0] = bgra[0];
210 bgr[1] = bgra[1];
211 bgr[2] = bgra[2];
212 bgr += 3;
213 bgra += 4;
214 }
215 }
216
217 bx::Error err;
218 bx::write(m_writer, m_frame, m_frameSize + 8, &err);
219 }
220 }
221
222 bx::FileWriterI* m_writer;
227 uint8_t* m_frame;
228 uint32_t m_frameSize;
229 uint32_t m_numFrames;
230 uint32_t m_width;
231 uint32_t m_height;
233};
234
235#endif // AVIWRITER_H_HEADER_GUARD
int64_t m_riffSizeOffset
Definition aviwriter.h:223
uint8_t * m_frame
Definition aviwriter.h:227
uint32_t m_height
Definition aviwriter.h:231
int64_t m_moviListOffset
Definition aviwriter.h:226
bool m_yflip
Definition aviwriter.h:232
void close()
Definition aviwriter.h:137
uint32_t m_frameSize
Definition aviwriter.h:228
bx::FileWriterI * m_writer
Definition aviwriter.h:222
uint32_t m_numFrames
Definition aviwriter.h:229
AviWriter(bx::FileWriterI *_writer)
Definition aviwriter.h:16
int64_t m_totalFramesOffset
Definition aviwriter.h:224
int64_t m_lengthOffset
Definition aviwriter.h:225
bool open(const char *_filePath, uint32_t _width, uint32_t _height, uint32_t _fps, bool _yflip)
Definition aviwriter.h:27
uint32_t m_width
Definition aviwriter.h:230
void frame(const void *_data)
Definition aviwriter.h:178