4 #include "settings.hpp"
12 #include "avsnoop.hpp"
13 #include "command.hpp"
17 boolean_setting
dump_large("large-video", false);
18 numeric_setting
dtb("default-top-border", 0, 8191, 0);
19 numeric_setting
dbb("default-bottom-border", 0, 8191, 0);
20 numeric_setting
dlb("default-left-border", 0, 8191, 0);
21 numeric_setting
drb("default-right-border", 0, 8191, 0);
22 numeric_setting
max_frames_per_segment("max-frames-per-segment", 0, 999999999, 0);
24 class avi_avsnoop
: public av_snooper
27 avi_avsnoop(const std::string
& prefix
, struct avi_info parameters
) throw(std::bad_alloc
)
29 vid_dumper
= new avidumper(prefix
, parameters
);
30 soxdumper
= new sox_dumper(prefix
+ ".sox", 32040.5, 2);
34 ~avi_avsnoop() throw()
40 void frame(struct lcscreen
& _frame
, uint32_t fps_n
, uint32_t fps_d
)
41 throw(std::bad_alloc
, std::runtime_error
)
43 vid_dumper
->wait_idle();
46 if(dump_large
&& _frame
.width
< 400)
48 if(dump_large
&& _frame
.height
< 400)
50 uint32_t _magic
= 403703808;
51 uint8_t* magic
= reinterpret_cast<uint8_t*>(&_magic
);
52 dscr
.set_palette(magic
[2], magic
[1], magic
[0]);
54 struct lua_render_context lrc
;
61 lrc
.width
= _frame
.width
* hscl
;
62 lrc
.height
= _frame
.height
* vscl
;
63 lrc
.rshift
= magic
[2];
64 lrc
.gshift
= magic
[1];
65 lrc
.bshift
= magic
[0];
66 lua_callback_do_video(&lrc
);
68 dscr
.reallocate(lrc
.left_gap
+ hscl
* _frame
.width
+ lrc
.right_gap
, lrc
.top_gap
+ vscl
*
69 _frame
.height
+ lrc
.bottom_gap
, lrc
.left_gap
, lrc
.top_gap
, true);
70 dscr
.copy_from(_frame
, hscl
, vscl
);
72 vid_dumper
->on_frame(dscr
.memory
, dscr
.width
, dscr
.height
, fps_n
, fps_d
);
75 void sample(short l
, short r
) throw(std::bad_alloc
, std::runtime_error
)
79 vid_dumper
->on_sample(l
, r
);
82 soxdumper
->sample(l
, r
);
85 void end() throw(std::bad_alloc
, std::runtime_error
)
91 void gameinfo(const std::string
& gamename
, const std::list
<std::pair
<std::string
, std::string
>>&
92 authors
, double gametime
, const std::string
& rerecords
) throw(std::bad_alloc
,
95 //We don't have place for this info and thus ignore it.
98 avidumper
* vid_dumper
;
99 sox_dumper
* soxdumper
;
104 avi_avsnoop
* vid_dumper
;
106 class dump_video_command
: public command
109 dump_video_command() throw(std::bad_alloc
) : command("dump-avi") {}
110 void invoke(const std::string
& args
) throw(std::bad_alloc
, std::runtime_error
)
112 tokensplitter
t(args
);
113 std::string level
= t
;
114 std::string prefix
= t
.tail();
116 throw std::runtime_error("Expected prefix");
118 throw std::runtime_error("AVI dumping already in progress");
119 unsigned long level2
;
121 level2
= parse_value
<unsigned long>(level
);
123 throw std::runtime_error("Level must be 0-18");
124 } catch(std::bad_alloc
& e
) {
126 } catch(std::runtime_error
& e
) {
127 throw std::runtime_error("Bad AVI compression level '" + level
+ "': " + e
.what());
129 struct avi_info parameters
;
130 parameters
.compression_level
= (level2
> 9) ? (level2
- 9) : level2
;
131 parameters
.audio_sampling_rate
= 32000;
132 parameters
.keyframe_interval
= (level2
> 9) ? 300 : 1;
133 parameters
.max_frames_per_segment
= max_frames_per_segment
;
135 vid_dumper
= new avi_avsnoop(prefix
, parameters
);
136 } catch(std::bad_alloc
& e
) {
138 } catch(std::exception
& e
) {
139 std::ostringstream x
;
140 x
<< "Error starting dump: " << e
.what();
141 throw std::runtime_error(x
.str());
143 window::out() << "Dumping to " << prefix
<< " at level " << level2
<< std::endl
;
145 std::string
get_short_help() throw(std::bad_alloc
) { return "Start AVI capture"; }
146 std::string
get_long_help() throw(std::bad_alloc
)
148 return "Syntax: dump-avi <level> <prefix>\n"
149 "Start AVI capture to <prefix> using compression\n"
150 "level <level> (0-18).\n";
154 class end_video_command
: public command
157 end_video_command() throw(std::bad_alloc
) : command("end-avi") {}
158 void invoke(const std::string
& args
) throw(std::bad_alloc
, std::runtime_error
)
161 throw std::runtime_error("This command does not take parameters");
163 throw std::runtime_error("No video dump in progress");
166 window::out() << "Dump finished" << std::endl
;
167 } catch(std::bad_alloc
& e
) {
169 } catch(std::exception
& e
) {
170 window::out() << "Error ending dump: " << e
.what() << std::endl
;
175 std::string
get_short_help() throw(std::bad_alloc
) { return "End AVI capture"; }
176 std::string
get_long_help() throw(std::bad_alloc
)
178 return "Syntax: end-avi\n"
179 "End a AVI capture.\n";