1 #include "video/avi/codec.hpp"
2 #include "core/instance.hpp"
3 #include "core/settings.hpp"
4 #include "library/zlibstream.hpp"
14 settingvar::supervariable
<settingvar::model_int
<0,9>> clvl(lsnes_setgrp
, "avi-cscd-compression",
15 "AVI‣CSCD‣Compression", 7);
16 settingvar::supervariable
<settingvar::model_int
<0,999999999>> kint(lsnes_setgrp
, "avi-cscd-keyint",
17 "AVI‣CSCD‣Keyframe interval", 0);
19 struct avi_codec_cscd
: public avi_video_codec
21 avi_codec_cscd(uint32_t _level
, uint32_t maxpframes
);
23 avi_video_codec::format
reset(uint32_t width
, uint32_t height
, uint32_t fps_n
, uint32_t fps_d
);
24 void frame(uint32_t* data
, uint32_t stride
);
26 avi_packet
getpacket();
28 void readrow(uint32_t* rptr
);
39 std::vector
<uint8_t> row
;
40 std::vector
<uint8_t> prevframe
;
43 avi_codec_cscd::~avi_codec_cscd()
47 unsigned getzlevel(uint32_t _level
)
49 if(_level
< 0 || _level
> 9)
50 throw std::runtime_error("Invalid compression level");
54 avi_codec_cscd::avi_codec_cscd(uint32_t _level
, uint32_t maxpframes
)
55 : z(getzlevel(_level
))
58 max_pframes
= maxpframes
;
61 avi_video_codec::format
avi_codec_cscd::reset(uint32_t width
, uint32_t height
, uint32_t fps_n
, uint32_t fps_d
)
63 pframes
= std::numeric_limits
<unsigned>::max(); //Next frame has to be keyframe.
66 ewidth
= (iwidth
+ 3) >> 2 << 2;
67 eheight
= (iheight
+ 3) >> 2 << 2;
69 row
.resize(3 * ewidth
);
70 prevframe
.resize(3 * ewidth
* eheight
);
71 memset(&row
[0], 0, 3 * ewidth
);
72 memset(&prevframe
[0], 0, 3 * ewidth
* eheight
);
73 avi_video_codec::format
fmt(ewidth
, eheight
, 0x44435343, 24);
77 void avi_codec_cscd::frame(uint32_t* data
, uint32_t stride
)
79 bool keyframe
= false;
80 if(pframes
>= max_pframes
) {
87 h
[0] = (keyframe
? 0x3 : 0x2) | (level
<< 4);
91 for(uint32_t y
= 0; y
< eheight
; y
++) {
92 if(y
< eheight
- iheight
)
95 readrow(data
+ (eheight
- y
- 1) * stride
);
97 memcpy(&prevframe
[3 * y
* ewidth
], &row
[0], 3 * ewidth
);
99 //Ew, we need to have prevframe = row, row = row - prevframe at the same time.
100 for(unsigned i
= 0; i
< 3 * ewidth
; i
++) {
101 uint8_t tmp
= row
[i
];
102 row
[i
] -= prevframe
[3 * y
* ewidth
+ i
];
103 prevframe
[3 * y
* ewidth
+ i
] = tmp
;
106 z
.write(&row
[0], row
.size());
109 out
.typecode
= 0x6264; //Not exactly correct according to specs...
111 out
.indexflags
= keyframe
? 0x10 : 0;
115 bool avi_codec_cscd::ready()
120 avi_packet
avi_codec_cscd::getpacket()
126 void avi_codec_cscd::readrow(uint32_t* rptr
)
129 memset(&row
[0], 0, 3 * iwidth
);
131 for(uint32_t i
= 0; i
< iwidth
; i
++) {
132 row
[3 * i
+ 0] = rptr
[i
] >> 16;
133 row
[3 * i
+ 1] = rptr
[i
] >> 8;
134 row
[3 * i
+ 2] = rptr
[i
] >> 0;
138 avi_video_codec_type
rgb("cscd", "Camstudio video codec",
139 []() -> avi_video_codec
* {
140 return new avi_codec_cscd(clvl(*CORE().settings
), kint(*CORE().settings
));