Clean up some header files
[lsnes.git] / videodumper2.cpp
blobd7942eb80fb4744577f7f82cf1f6504cacf9157d
1 #include "videodumper.hpp"
2 #include "settings.hpp"
3 #include "videodumper2.hpp"
4 #include <iomanip>
5 #include <cassert>
6 #include <cstring>
7 #include <sstream>
8 #include <zlib.h>
9 #include "misc.hpp"
10 #include "fieldsplit.hpp"
11 #include "command.hpp"
13 avidumper* vid_dumper = NULL;
15 void update_movie_state();
17 namespace
19 screen dscr;
20 boolean_setting dump_large("large-video", false);
22 class dump_video_command : public command
24 public:
25 dump_video_command() throw(std::bad_alloc) : command("dump-video") {}
26 void invoke(const std::string& args, window* win) throw(std::bad_alloc, std::runtime_error)
28 tokensplitter t(args);
29 std::string level = t;
30 std::string prefix = t.tail();
31 if(prefix == "")
32 throw std::runtime_error("Expected prefix");
33 if(vid_dumper)
34 throw std::runtime_error("Video dumping already in progress");
35 unsigned long level2;
36 try {
37 level2 = parse_value<unsigned long>(level);
38 if(level2 > 18)
39 throw std::runtime_error("Level must be 0-18");
40 } catch(std::bad_alloc& e) {
41 OOM_panic(win);
42 } catch(std::runtime_error& e) {
43 throw std::runtime_error("Bad video compression level '" + level + "': " + e.what());
45 struct avi_info parameters;
46 parameters.compression_level = (level2 > 9) ? (level2 - 9) : level2;
47 parameters.audio_drop_counter_inc = 81;
48 parameters.audio_drop_counter_max = 64081;
49 parameters.audio_sampling_rate = 32000;
50 parameters.audio_native_sampling_rate = 32040.5;
51 parameters.keyframe_interval = (level2 > 9) ? 300 : 1;
52 try {
53 vid_dumper = new avidumper(prefix, parameters);
54 } catch(std::bad_alloc& e) {
55 OOM_panic(win);
56 } catch(std::exception& e) {
57 std::ostringstream x;
58 x << "Error starting dump: " << e.what();
59 throw std::runtime_error(x.str());
61 out(win) << "Dumping to " << prefix << " at level " << level2 << std::endl;
62 update_movie_state();
64 std::string get_short_help() throw(std::bad_alloc) { return "Start video capture"; }
65 std::string get_long_help() throw(std::bad_alloc)
67 return "Syntax: dump-video <level> <prefix>\n"
68 "Start video capture to <prefix> using compression\n"
69 "level <level> (0-18).\n";
71 } dump_video;
73 class end_video_command : public command
75 public:
76 end_video_command() throw(std::bad_alloc) : command("end-video") {}
77 void invoke(const std::string& args, window* win) throw(std::bad_alloc, std::runtime_error)
79 if(args != "")
80 throw std::runtime_error("This command does not take parameters");
81 if(!vid_dumper)
82 throw std::runtime_error("No video dump in progress");
83 try {
84 vid_dumper->on_end();
85 out(win) << "Dump finished" << std::endl;
86 } catch(std::bad_alloc& e) {
87 OOM_panic(win);
88 } catch(std::exception& e) {
89 out(win) << "Error ending dump: " << e.what() << std::endl;
91 delete vid_dumper;
92 vid_dumper = NULL;
93 update_movie_state();
95 std::string get_short_help() throw(std::bad_alloc) { return "End video capture"; }
96 std::string get_long_help() throw(std::bad_alloc)
98 return "Syntax: end-video\n"
99 "End a video capture.\n";
101 } end_vieo;
105 void end_vid_dump() throw(std::bad_alloc, std::runtime_error)
107 if(vid_dumper)
108 try {
109 vid_dumper->on_end();
110 } catch(std::bad_alloc& e) {
111 throw;
112 } catch(std::exception& e) {
113 std::cerr << "Error ending dump: " << e.what() << std::endl;
117 void dump_frame(lcscreen& ls, render_queue* rq, uint32_t left, uint32_t right, uint32_t top, uint32_t bottom,
118 bool region, window* win) throw(std::bad_alloc, std::runtime_error)
120 if(vid_dumper)
121 try {
122 vid_dumper->wait_idle();
123 uint32_t hscl = 1;
124 uint32_t vscl = 1;
125 if(dump_large && ls.width < 400)
126 hscl = 2;
127 if(dump_large && ls.height < 400)
128 vscl = 2;
129 uint32_t _magic = 403703808;
130 uint8_t* magic = reinterpret_cast<uint8_t*>(&_magic);
131 dscr.reallocate(left + hscl * ls.width + right, top + vscl * ls.height + bottom, left, top,
132 true);
133 dscr.set_palette(magic[2], magic[1], magic[0]);
134 dscr.copy_from(ls, hscl, vscl);
135 if(rq)
136 rq->run(dscr);
137 assert(dscr.memory);
138 assert(dscr.width);
139 assert(dscr.height);
140 uint32_t fps_n = 10738636;
141 uint32_t fps_d = 178683;
142 if(region) {
143 fps_n = 322445;
144 fps_d = 6448;
146 vid_dumper->on_frame(dscr.memory, dscr.width, dscr.height, fps_n, fps_d);
147 } catch(std::bad_alloc& e) {
148 OOM_panic(win);
149 } catch(std::exception& e) {
150 out(win) << "Error sending video frame: " << e.what() << std::endl;
152 if(rq)
153 rq->clear();
156 void dump_audio_sample(int16_t l_sample, int16_t r_sample, window* win) throw(std::bad_alloc, std::runtime_error)
158 if(vid_dumper)
159 try {
160 vid_dumper->on_sample(l_sample, r_sample);
161 } catch(std::bad_alloc& e) {
162 OOM_panic(win);
163 } catch(std::exception& e) {
164 out(win) << "Error sending audio sample: " << e.what() << std::endl;
168 bool dump_in_progress() throw()
170 return (vid_dumper != NULL);
173 void video_fill_shifts(uint32_t& r, uint32_t& g, uint32_t& b)
175 r = dscr.active_rshift;
176 g = dscr.active_gshift;
177 b = dscr.active_bshift;