diff options
-rw-r--r-- | spuencoder.c | 98 | ||||
-rw-r--r-- | spuencoder.h | 9 |
2 files changed, 106 insertions, 1 deletions
diff --git a/spuencoder.c b/spuencoder.c index bb88f4c..13b4832 100644 --- a/spuencoder.c +++ b/spuencoder.c @@ -79,6 +79,9 @@ void cSpuEncoder::encode(cBitmap *bmap, int top, int left) memset(rleData.bottom, 0, sizeof(rleData.bottom)); memset(spu, 0, sizeof(spu)); + // free previouse used regions + clearRegions(); + // get needed informations about used colors colors = bitmap->Colors(numColors); @@ -87,6 +90,20 @@ void cSpuEncoder::encode(cBitmap *bmap, int top, int left) // generate and upload color palette generateColorPalette(); + // add one region + cSpuRegion *reg = new cSpuRegion(); + + for (int i = 0; i < numColors; i++) { + reg->addColIndex(bitmap->Index(colors[i])); + } + + regions.push(reg); + + dsyslog("[dxr3-spuencoder] rle data"); + + // encode whole bitmap with rle and store top and bottom lines + rle4colors(); + // as we have only small space for all our spu data, we do here // a little trick. If we run out of space, when using // top and odd bottom, we try to use two times the top lines. @@ -104,6 +121,10 @@ void cSpuEncoder::encode(cBitmap *bmap, int top, int left) // make a try with only even lines generateSpuData(false); } + + // we are ready to send generated spu data + dsyslog("[dxr3-spuencoder] spu packet size %d (bytes). %d left", written, (MAX_SPU_DATA - written)); + cDxr3Interface::instance()->WriteSpu((uchar *)&spu, written); } void cSpuEncoder::writeNibble(uint8_t val) @@ -219,3 +240,80 @@ void cSpuEncoder::generateSpuData(bool topAndBottom) throw (char const* ) spu[0] = written >> 8; spu[1] = written & 0xff; } + +void cSpuEncoder::clearRegions() +{ + while (!regions.empty()) { + cSpuRegion *reg = regions.front(); + delete reg; + regions.pop(); + } +} + +void cSpuEncoder::rle4colors() +{ + int len; + p = rleData.top; + + // first encode all top lines (0, 2, 4, ...) followed by + // all bottom lines (1, 3, 5, ...) + + for (int i = 0; i < 2; i++) { + + nholder = 0; + ncnt = 0; + written = 0; + + if (i == 1) { + p = rleData.bottom; + } + + for (int y = (0 + i); y < bitmap->Height(); y += 2) { + + for (int x = 0; x < bitmap->Width(); x += len) { + tIndex color = *(bitmap->Data(x, y)); + + for (len = 1; x+len < bitmap->Width(); ++len) { + if (*(bitmap->Data(x+len, y)) != color) { + break; + } + } + + if (len < 0x04) { + writeNibble((len << 2) | color); + } else if (len < 0x10) { + writeNibble(len >> 2); + writeNibble((len << 2) | color); + } else if (len < 0x40) { + writeNibble(0); + writeNibble(len >> 2); + writeNibble((len << 2) | color); + } else if (x + len == bitmap->Width()) { + writeNibble(0); + writeNibble(0); + writeNibble(0); + writeNibble(color); + } else { + if (len > 0xff) { + len = 0xff; + } + writeNibble(0); + writeNibble(len >> 6); + writeNibble(len >> 2); + writeNibble((len << 2) | color); + } + } + + // end of line + if (ncnt & 1) { + writeNibble(0); + } + } + + if (i == 0) { + rleData.topLen = written; + } else { + rleData.bottomLen = written; + } + } +} diff --git a/spuencoder.h b/spuencoder.h index 42a4d34..dbeb833 100644 --- a/spuencoder.h +++ b/spuencoder.h @@ -29,9 +29,11 @@ #include <stdint.h> #include <vdr/osd.h> +#include <queue> #include "dxr3singleton.h" +#include "spuregion.h" -static const int MAX_SPU_DATA = 65220; // TODO vaidate this value +static const int MAX_SPU_DATA = 65220; // TODO validate this value struct sRle { uint8_t top[MAX_SPU_DATA]; @@ -56,6 +58,7 @@ private: int32_t written; // how much data are written sRle rleData; // storage for encoded data + std::queue<cSpuRegion *> regions; int numColors; // len of tColor array of current bitmap const tColor* colors; // pointer to tColor array from current bitmap @@ -65,6 +68,10 @@ private: void writeNibble(uint8_t val); void generateColorPalette(); void generateSpuData(bool topAndBottom) throw (char const* ); + + void clearRegions(); + + void rle4colors(); }; #endif // SPUENCODER_H |