Merge branch 'rr1-maint'
This commit is contained in:
commit
3df182b498
3 changed files with 71 additions and 53 deletions
|
@ -42,6 +42,23 @@ struct zlibstream
|
||||||
* Parameter out: The buffer to write to.
|
* Parameter out: The buffer to write to.
|
||||||
*/
|
*/
|
||||||
void read(std::vector<char>& out);
|
void read(std::vector<char>& out);
|
||||||
|
/**
|
||||||
|
* Read the data so far as buffer and empty compressed data.
|
||||||
|
*
|
||||||
|
* This performs a sync flush.
|
||||||
|
*
|
||||||
|
* Parameter out: The buffer to write to.
|
||||||
|
*/
|
||||||
|
void readsync(std::vector<char>& out);
|
||||||
|
/**
|
||||||
|
* Clear the output stream and add some uncompressed data.
|
||||||
|
*
|
||||||
|
* This is useful after doing readsync().
|
||||||
|
*
|
||||||
|
* Parameter data: The data to write (may be NULL if datalen=0).
|
||||||
|
* Parameter datalen: The length of data.
|
||||||
|
*/
|
||||||
|
void adddata(uint8_t* data, size_t datalen);
|
||||||
/**
|
/**
|
||||||
* Set flag.
|
* Set flag.
|
||||||
*
|
*
|
||||||
|
@ -61,7 +78,9 @@ private:
|
||||||
size_t used;
|
size_t used;
|
||||||
};
|
};
|
||||||
|
|
||||||
void flushpage(uint8_t* data, size_t datalen, bool final);
|
void _read(std::vector<char>& out, int mode);
|
||||||
|
void _reset(uint8_t* data, size_t datalen, bool doactually);
|
||||||
|
void flushpage(uint8_t* data, size_t datalen, int mode);
|
||||||
zlibstream(zlibstream&);
|
zlibstream(zlibstream&);
|
||||||
zlibstream& operator=(zlibstream&);
|
zlibstream& operator=(zlibstream&);
|
||||||
z_stream z;
|
z_stream z;
|
||||||
|
|
|
@ -37,6 +37,11 @@ zlibstream::~zlibstream()
|
||||||
}
|
}
|
||||||
|
|
||||||
void zlibstream::reset(uint8_t* data, size_t datalen)
|
void zlibstream::reset(uint8_t* data, size_t datalen)
|
||||||
|
{
|
||||||
|
_reset(data, datalen, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void zlibstream::_reset(uint8_t* data, size_t datalen, bool doactually)
|
||||||
{
|
{
|
||||||
std::list<struct page> tmp;
|
std::list<struct page> tmp;
|
||||||
size_t odatalen = datalen;
|
size_t odatalen = datalen;
|
||||||
|
@ -48,6 +53,7 @@ void zlibstream::reset(uint8_t* data, size_t datalen)
|
||||||
data += copylen;
|
data += copylen;
|
||||||
datalen -= copylen;
|
datalen -= copylen;
|
||||||
}
|
}
|
||||||
|
if(doactually)
|
||||||
deflateReset(&z);
|
deflateReset(&z);
|
||||||
streamsize = odatalen;
|
streamsize = odatalen;
|
||||||
flag = false;
|
flag = false;
|
||||||
|
@ -56,12 +62,17 @@ void zlibstream::reset(uint8_t* data, size_t datalen)
|
||||||
|
|
||||||
void zlibstream::write(uint8_t* data, size_t datalen)
|
void zlibstream::write(uint8_t* data, size_t datalen)
|
||||||
{
|
{
|
||||||
flushpage(data, datalen, false);
|
flushpage(data, datalen, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void zlibstream::read(std::vector<char>& out)
|
void zlibstream::read(std::vector<char>& out)
|
||||||
{
|
{
|
||||||
flushpage(NULL, 0, true);
|
_read(out, Z_FINISH);
|
||||||
|
}
|
||||||
|
|
||||||
|
void zlibstream::_read(std::vector<char>& out, int mode)
|
||||||
|
{
|
||||||
|
flushpage(NULL, 0, mode);
|
||||||
out.resize(streamsize);
|
out.resize(streamsize);
|
||||||
size_t itr = 0;
|
size_t itr = 0;
|
||||||
for(auto& i : storage) {
|
for(auto& i : storage) {
|
||||||
|
@ -70,14 +81,11 @@ void zlibstream::read(std::vector<char>& out)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern void* orig_return_address;
|
void zlibstream::flushpage(uint8_t* data, size_t datalen, int mode)
|
||||||
extern void* orig_return_address2;
|
|
||||||
|
|
||||||
void zlibstream::flushpage(uint8_t* data, size_t datalen, bool final)
|
|
||||||
{
|
{
|
||||||
z.next_in = data;
|
z.next_in = data;
|
||||||
z.avail_in = datalen;
|
z.avail_in = datalen;
|
||||||
while(z.avail_in || final) {
|
while(z.avail_in || mode) {
|
||||||
if(storage.empty() || storage.back().used == ZLIB_PAGE_STORAGE) {
|
if(storage.empty() || storage.back().used == ZLIB_PAGE_STORAGE) {
|
||||||
storage.push_back(page());
|
storage.push_back(page());
|
||||||
storage.back().used = 0;
|
storage.back().used = 0;
|
||||||
|
@ -85,15 +93,25 @@ void zlibstream::flushpage(uint8_t* data, size_t datalen, bool final)
|
||||||
z.next_out = storage.back().data + storage.back().used;
|
z.next_out = storage.back().data + storage.back().used;
|
||||||
z.avail_out = ZLIB_PAGE_STORAGE - storage.back().used;
|
z.avail_out = ZLIB_PAGE_STORAGE - storage.back().used;
|
||||||
size_t itmp = z.avail_out;
|
size_t itmp = z.avail_out;
|
||||||
int x = deflate(&z, final ? Z_FINISH : 0);
|
int x = deflate(&z, mode);
|
||||||
storage.back().used += (itmp - z.avail_out);
|
storage.back().used += (itmp - z.avail_out);
|
||||||
streamsize += (itmp - z.avail_out);
|
streamsize += (itmp - z.avail_out);
|
||||||
throw_zlib_error(x);
|
throw_zlib_error(x);
|
||||||
if(final && x == Z_STREAM_END)
|
if(mode && !z.avail_in && z.avail_out)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void zlibstream::readsync(std::vector<char>& out)
|
||||||
|
{
|
||||||
|
_read(out, Z_SYNC_FLUSH);
|
||||||
|
}
|
||||||
|
|
||||||
|
void zlibstream::adddata(uint8_t* data, size_t datalen)
|
||||||
|
{
|
||||||
|
_reset(data, datalen, false);
|
||||||
|
}
|
||||||
|
|
||||||
void zlibstream::set_flag(bool f)
|
void zlibstream::set_flag(bool f)
|
||||||
{
|
{
|
||||||
flag = f;
|
flag = f;
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "video/avi/codec.hpp"
|
#include "video/avi/codec.hpp"
|
||||||
#include "core/settings.hpp"
|
#include "core/settings.hpp"
|
||||||
|
#include "library/zlibstream.hpp"
|
||||||
#include <zlib.h>
|
#include <zlib.h>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
@ -51,8 +52,6 @@ namespace
|
||||||
unsigned pframes;
|
unsigned pframes;
|
||||||
//Maximum number of P-frames to write in sequence.
|
//Maximum number of P-frames to write in sequence.
|
||||||
unsigned max_pframes;
|
unsigned max_pframes;
|
||||||
//Compression level to use.
|
|
||||||
unsigned level;
|
|
||||||
//Size of one block.
|
//Size of one block.
|
||||||
uint32_t bw;
|
uint32_t bw;
|
||||||
uint32_t bh;
|
uint32_t bh;
|
||||||
|
@ -66,16 +65,12 @@ namespace
|
||||||
uint32_t* prev_frame;
|
uint32_t* prev_frame;
|
||||||
//Scratch block pointer.
|
//Scratch block pointer.
|
||||||
uint32_t* scratch;
|
uint32_t* scratch;
|
||||||
//Output buffer. Sufficient space to hold both compressed and uncompressed data.
|
//Output buffer. Sufficient space to hold uncompressed data.
|
||||||
std::vector<char> outbuffer;
|
std::vector<char> outbuffer;
|
||||||
//Output scratch memory.
|
//Output scratch memory.
|
||||||
char* oscratch;
|
char* oscratch;
|
||||||
//The actual output buffer. Pointer, size and ued.
|
//Zlib streaam.
|
||||||
char* outbuf;
|
zlibstream z;
|
||||||
size_t outbuf_size;
|
|
||||||
size_t outbuf_used;
|
|
||||||
//Zlib state.
|
|
||||||
z_stream zstream;
|
|
||||||
//Compute penalty for motion vector (dx, dy) on block with upper-left corner at (bx, by).
|
//Compute penalty for motion vector (dx, dy) on block with upper-left corner at (bx, by).
|
||||||
uint32_t mv_penalty(uint32_t bx, uint32_t by, int dx, int dy);
|
uint32_t mv_penalty(uint32_t bx, uint32_t by, int dx, int dy);
|
||||||
//Do motion detection for block with upper-left corner at (bx, by). M is filled with the resulting
|
//Do motion detection for block with upper-left corner at (bx, by). M is filled with the resulting
|
||||||
|
@ -125,6 +120,7 @@ namespace
|
||||||
|
|
||||||
void avi_codec_zmbv::serialize_frame(bool keyframe)
|
void avi_codec_zmbv::serialize_frame(bool keyframe)
|
||||||
{
|
{
|
||||||
|
unsigned char tmp[7];
|
||||||
uint32_t nhb, nvb, nb;
|
uint32_t nhb, nvb, nb;
|
||||||
//In_stride/in_offset is in units of words, out_stride is in units of bytes.
|
//In_stride/in_offset is in units of words, out_stride is in units of bytes.
|
||||||
size_t in_stride = (ewidth + 2 * MAXIMUM_VECTOR);
|
size_t in_stride = (ewidth + 2 * MAXIMUM_VECTOR);
|
||||||
|
@ -164,28 +160,21 @@ namespace
|
||||||
}
|
}
|
||||||
compress:
|
compress:
|
||||||
//Compress the output data.
|
//Compress the output data.
|
||||||
zstream.next_in = reinterpret_cast<uint8_t*>(oscratch);
|
if(keyframe)
|
||||||
zstream.avail_in = osize;
|
{
|
||||||
|
tmp[0] = 1; //Keyframe
|
||||||
osize = 0;
|
tmp[1] = 0; //Major version.
|
||||||
outbuf[osize++] = keyframe ? 1 : 0; //Indicate keyframe/not.
|
tmp[2] = 1; //Minor version.
|
||||||
if(keyframe) {
|
tmp[3] = 1; //Zlib compresison.
|
||||||
//Write the keyframe header.
|
tmp[4] = 8; //32-bit
|
||||||
outbuf[osize++] = 0; //Version 0.1
|
tmp[5] = bw; //Block size.
|
||||||
outbuf[osize++] = 1;
|
tmp[6] = bh; //Block size.
|
||||||
outbuf[osize++] = 1; //Zlib compression.
|
z.reset(tmp, 7);
|
||||||
outbuf[osize++] = 8; //32 bit.
|
} else {
|
||||||
outbuf[osize++] = bw; //Block size.
|
tmp[0] = 0; //Not keyframe.
|
||||||
outbuf[osize++] = bh;
|
z.adddata(tmp, 1);
|
||||||
deflateReset(&zstream); //Reset the zlib context.
|
|
||||||
}
|
}
|
||||||
zstream.next_out = reinterpret_cast<uint8_t*>(&outbuf[osize]);
|
z.write(reinterpret_cast<uint8_t*>(oscratch), osize);
|
||||||
zstream.avail_out = outbuf_size - osize;
|
|
||||||
if(deflate(&zstream, Z_SYNC_FLUSH) != Z_OK)
|
|
||||||
throw std::runtime_error("Zlib error while compressing data");
|
|
||||||
if(zstream.avail_in || !zstream.avail_out)
|
|
||||||
throw std::runtime_error("Buffer overrun while compressing data");
|
|
||||||
outbuf_used = outbuf_size - zstream.avail_out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//If candidate is better than best, update best. Returns true if ideal has been reached, else false.
|
//If candidate is better than best, update best. Returns true if ideal has been reached, else false.
|
||||||
|
@ -228,7 +217,6 @@ compress:
|
||||||
|
|
||||||
avi_codec_zmbv::~avi_codec_zmbv()
|
avi_codec_zmbv::~avi_codec_zmbv()
|
||||||
{
|
{
|
||||||
deflateEnd(&zstream);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned getzlevel(uint32_t _level)
|
unsigned getzlevel(uint32_t _level)
|
||||||
|
@ -239,14 +227,11 @@ compress:
|
||||||
}
|
}
|
||||||
|
|
||||||
avi_codec_zmbv::avi_codec_zmbv(uint32_t _level, uint32_t maxpframes, uint32_t _bw, uint32_t _bh)
|
avi_codec_zmbv::avi_codec_zmbv(uint32_t _level, uint32_t maxpframes, uint32_t _bw, uint32_t _bh)
|
||||||
|
: z(getzlevel(_level))
|
||||||
{
|
{
|
||||||
bh = _bh;
|
bh = _bh;
|
||||||
bw = _bw;
|
bw = _bw;
|
||||||
level = _level;
|
|
||||||
max_pframes = maxpframes;
|
max_pframes = maxpframes;
|
||||||
memset(&zstream, 0, sizeof(zstream));
|
|
||||||
if(deflateInit(&zstream, getzlevel(_level)))
|
|
||||||
throw std::runtime_error("Error initializing deflate");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
avi_video_codec::format avi_codec_zmbv::reset(uint32_t width, uint32_t height, uint32_t fps_n, uint32_t fps_d)
|
avi_video_codec::format avi_codec_zmbv::reset(uint32_t width, uint32_t height, uint32_t fps_n, uint32_t fps_d)
|
||||||
|
@ -264,11 +249,8 @@ compress:
|
||||||
prev_frame = &pixbuf[(ewidth + 2 * MAXIMUM_VECTOR) * (eheight + 2 * MAXIMUM_VECTOR)];
|
prev_frame = &pixbuf[(ewidth + 2 * MAXIMUM_VECTOR) * (eheight + 2 * MAXIMUM_VECTOR)];
|
||||||
scratch = &pixbuf[2 * (ewidth + 2 * MAXIMUM_VECTOR) * (eheight + 2 * MAXIMUM_VECTOR)];
|
scratch = &pixbuf[2 * (ewidth + 2 * MAXIMUM_VECTOR) * (eheight + 2 * MAXIMUM_VECTOR)];
|
||||||
mv.resize(((ewidth + bw - 1) / bw) * ((eheight + bh - 1) / bh));
|
mv.resize(((ewidth + bw - 1) / bw) * ((eheight + bh - 1) / bh));
|
||||||
size_t maxdiff = 4 * ((mv.size() + 1) / 2) + 4 * ewidth * eheight;
|
outbuffer.resize(4 * ((mv.size() + 1) / 2) + 4 * ewidth * eheight);
|
||||||
outbuf_size = deflateBound(&zstream, maxdiff) + 128;
|
oscratch = &outbuffer[0];
|
||||||
outbuffer.resize(maxdiff + outbuf_size);
|
|
||||||
oscratch = &outbuffer[outbuf_size];
|
|
||||||
outbuf = &outbuffer[0];
|
|
||||||
memset(&pixbuf[0], 0, 4 * pixbuf.size());
|
memset(&pixbuf[0], 0, 4 * pixbuf.size());
|
||||||
return fmt;
|
return fmt;
|
||||||
}
|
}
|
||||||
|
@ -328,8 +310,7 @@ compress:
|
||||||
//Serialize and output.
|
//Serialize and output.
|
||||||
serialize_frame(keyframe);
|
serialize_frame(keyframe);
|
||||||
std::swap(current_frame, prev_frame);
|
std::swap(current_frame, prev_frame);
|
||||||
out.payload.resize(outbuf_used);
|
z.readsync(out.payload);
|
||||||
memcpy(&out.payload[0], outbuf, outbuf_used);
|
|
||||||
out.typecode = 0x6264; //Not exactly correct according to specs...
|
out.typecode = 0x6264; //Not exactly correct according to specs...
|
||||||
out.hidden = false;
|
out.hidden = false;
|
||||||
out.indexflags = keyframe ? 0x10 : 0;
|
out.indexflags = keyframe ? 0x10 : 0;
|
||||||
|
|
Loading…
Add table
Reference in a new issue