10 #include "newpacket.hpp"
11 #include "timecounter.hpp"
14 timecounter
curtime(60);
15 std::vector
<std::string
> inputfiles
;
16 std::string outputfile
;
17 bool always_file
= false;
19 void add_file(const std::string
& file
)
22 inputfiles
.push_back(outputfile
);
28 std::cerr
<< "Syntax: picturestodump.exe <options> <input>... <output>" << std::endl
;
29 std::cerr
<< "--fps=<fps>\tSet framerate to <fps>. Default 60." << std::endl
;
30 std::cerr
<< "<input>...\tInput files, in order." << std::endl
;
31 std::cerr
<< "<output>\t\tOutput file." << std::endl
;
35 void resize_block(unsigned char*& block
, size_t& alloc
, size_t min
= 0)
37 size_t new_size
= 3 * alloc
/ 2 + 5;
40 block
= (unsigned char*)realloc(block
, new_size
);
42 std::cerr
<< "Out of memory while trying to allocate " << new_size
<< " bytes." << std::endl
;
48 void reset_zlib_output(z_stream
* s
, unsigned char* buffer
, size_t buffersize
)
51 s
->avail_out
= buffersize
;
54 void flush_zlib_output(z_stream
* s
, std::vector
<unsigned char>& block
, unsigned char* buffer
, size_t buffersize
)
56 //Resize the block so the new data fits.
57 size_t delta
= buffersize
- s
->avail_out
;
59 size_t osize
= block
.size();
60 block
.resize(osize
+ delta
);
62 memcpy(&block
[osize
], buffer
, delta
);
66 s
->avail_out
= buffersize
;
69 #define INBUFFER_SIZE 65536
70 #define OUTBUFFER_SIZE 16384
72 void write_image(const std::string
& name
, write_channel
& wchan
)
78 p
.rp_channel
= 0; //On video channel.
79 p
.rp_minor
= 1; //Compressed frame.
80 p
.rp_timestamp
= curtime
; //time.
84 SDL_Surface
* img
= IMG_Load(name
.c_str());
86 std::cerr
<< "Can't load image '" << name
<< "':" << IMG_GetError() << std::endl
;
90 //Convert the SDL surface into raw image.
93 pixels
= new uint8_t[4 * width
* height
];
95 for(uint32_t y
= 0; y
< height
; y
++)
96 for(uint32_t x
= 0; x
< width
; x
++) {
98 size_t addr
= y
* img
->pitch
+ x
* img
->format
->BytesPerPixel
;
99 SDL_GetRGB(*(Uint32
*)((unsigned char*)img
->pixels
+ addr
), img
->format
, &r
, &g
, &b
);
100 pixels
[4 * width
* y
+ 4 * x
+ 0] = r
;
101 pixels
[4 * width
* y
+ 4 * x
+ 1] = g
;
102 pixels
[4 * width
* y
+ 4 * x
+ 2] = b
;
103 pixels
[4 * width
* y
+ 4 * x
+ 3] = 0;
105 SDL_UnlockSurface(img
);
106 SDL_FreeSurface(img
);
108 //Reserve space for dimensions and write them.
109 p
.rp_payload
.push_back((width
>> 8) & 0xFF);
110 p
.rp_payload
.push_back(width
& 0xFF);
111 p
.rp_payload
.push_back((height
>> 8) & 0xFF);
112 p
.rp_payload
.push_back(height
& 0xFF);
114 //Compress the image data.
115 size_t bytes_processed
= 0;
116 size_t bytes_total
= 4 * width
* height
;
117 unsigned char in
[INBUFFER_SIZE
];
118 unsigned char out
[OUTBUFFER_SIZE
];
119 bool finished
= false;
122 memset(&s
, 0, sizeof(z_stream
));
123 int r
= deflateInit(&s
, 9);
125 std::cerr
<< "Zlib error: " << s
.msg
<< " while initializing deflate." << std::endl
;
129 reset_zlib_output(&s
, out
, OUTBUFFER_SIZE
);
131 int flushflag
= Z_NO_FLUSH
;
133 if(s
.avail_in
== 0) {
134 //Fill the input buffer.
136 if(INBUFFER_SIZE
> bytes_total
- bytes_processed
) {
137 memcpy(in
, pixels
+ bytes_processed
, bytes_total
- bytes_processed
);
138 s
.avail_in
= bytes_total
- bytes_processed
;
139 bytes_processed
= bytes_total
;
141 memcpy(in
, pixels
+ bytes_processed
, INBUFFER_SIZE
);
142 s
.avail_in
= INBUFFER_SIZE
;
143 bytes_processed
+= INBUFFER_SIZE
;
147 //Set the finish flag if needed.
148 if(bytes_processed
== bytes_total
)
149 flushflag
= Z_FINISH
;
151 r
= deflate(&s
, flushflag
);
154 std::cerr
<< "Zlib error: " << s
.msg
<< " while deflating data." << std::endl
;
157 if(r
== Z_STREAM_END
)
159 flush_zlib_output(&s
, p
.rp_payload
, out
, OUTBUFFER_SIZE
);
163 //Give the payload, write and free the payload.
168 int real_main(int argc
, char** argv
)
170 if(SDL_Init(0) < 0) {
171 std::cerr
<< "Can't initialize SDL." << std::endl
;
174 IMG_Init(IMG_INIT_JPG
| IMG_INIT_PNG
| IMG_INIT_TIF
);
176 for(int i
= 1; i
< argc
; i
++) {
177 if(!always_file
&& !strcmp(argv
[i
], "--"))
179 else if(!always_file
&& !strncmp(argv
[i
], "--fps=", 6))
181 curtime
= timecounter(argv
[i
] + 6);
182 } catch(std::exception
& e
) {
183 std::cerr
<< "Invalid --fps value: " << e
.what() << std::endl
;
186 else if(!always_file
&& !strncmp(argv
[i
], "--", 2))
189 add_file(std::string(argv
[i
]));
191 if(inputfiles
.size() == 0)
194 std::vector
<channel
> channels
;
196 channels
[0].c_channel
= 0; //Channel #0.
197 channels
[0].c_type
= 0; //Video channel.
198 channels
[0].c_channel_name
= "<VIDEO>"; //Channel name.
199 channels
[1].c_channel
= 1; //Channel #1.
200 channels
[1].c_type
= 3; //Comment channel.
201 channels
[1].c_channel_name
= "<DUMMY>"; //Channel name.
203 //Open the dump and start new segment.
204 write_channel
wchan(outputfile
.c_str());
205 wchan
.start_segment(channels
);
208 for(std::vector
<std::string
>::iterator i
= inputfiles
.begin(); i
!= inputfiles
.end(); ++i
) {
209 write_image(*i
, wchan
);
213 //Closing comment packet and end stream.
215 p
.rp_channel
= 1; //On comment channel.
216 p
.rp_minor
= 0; //Ignored.
217 p
.rp_timestamp
= curtime
; //Ending time.
218 //Payload defaults to empty.