2 FreeSat Huffman decoder for VDR
3 Copyright (C) 2008 DOM http://www.rst38.org.uk/vdr/
5 Copyright (C) 2008 Martin Croome
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 #include "freesatv2.h"
18 #ifdef FREESATV2_DEBUG
21 #include <asm/types.h>
28 # define DATADIR "/usr/share"
31 #ifndef FREESAT_DATA_DIRECTORY
32 #define FREESAT_DATA_DIRECTORY DATADIR
34 #define TABLE1_FILENAME FREESAT_DATA_DIRECTORY "/enigma2/freesat.t1"
35 #define TABLE2_FILENAME FREESAT_DATA_DIRECTORY "/enigma2/freesat.t2"
37 static void loadFile(huffTableEntry **table, const char *filename);
45 huffTableEntry * nextEntry;
47 huffTableEntry(unsigned int value, short bits, char next) : value(value), bits(bits), next(next), nextEntry(NULL)
51 freesatHuffmanDecoder::freesatHuffmanDecoder()
53 memset(m_tables, 0, sizeof(m_tables));
54 loadFile(&m_tables[0][0], TABLE1_FILENAME);
55 loadFile(&m_tables[1][0], TABLE2_FILENAME);
58 freesatHuffmanDecoder::~freesatHuffmanDecoder()
61 huffTableEntry *currentEntry, *nextEntry;
62 for ( j = 0 ; j < 2; j++ )
64 for ( i = 0 ; i < 256; i++ )
66 currentEntry = m_tables[j][i];
67 while ( currentEntry != NULL )
69 nextEntry = currentEntry->nextEntry;
71 currentEntry = nextEntry;
73 m_tables[j][i] = NULL;
79 /** \brief Convert a textual character description into a value
81 * \param str - Encoded (in someway) string
83 * \return Raw character
85 static unsigned char resolveChar(const char *str)
88 unsigned c0 = *p++, c1 = *p++;
93 if ( sscanf(p,"%02x", &c1) == 1 )
97 if ( !strcmp(p,"CAPE") )
101 if ( !strcmp(p,"OP") )
103 else if ( !strcmp(p,"ART") )
111 /** \brief Decode a binary string into a value
113 * \param binary - Binary string to decode
115 * \return Decoded value
117 static unsigned long decodeBinary(const char *binary)
119 unsigned long mask = 0x80000000;
120 unsigned long val = 0;
124 if ( *binary == '1' )
134 static void loadFile(huffTableEntry **table, const char *filename)
142 FILE *fp = fopen(filename, "r");
145 while ( fgets(buf,sizeof(buf),fp) != NULL )
147 // Tokenize string "in place"
149 colon = strchr(buf, ':');
154 colon = strchr(binary, ':');
159 colon = strchr(to, ':');
163 int bin_len = strlen(binary);
164 int from_char = resolveChar(from);
165 char to_char = resolveChar(to);
166 unsigned long bin = decodeBinary(binary);
168 // Add entry to end of bucket
169 huffTableEntry **pCurrent = &table[from_char];
170 while ( *pCurrent != NULL )
172 pCurrent = &((*pCurrent)->nextEntry);
174 *pCurrent = new huffTableEntry(bin, bin_len, to_char);
179 #ifdef FREESATV2_DEBUG
182 eDebug("[FREESAT] Cannot load '%s'",filename);
188 /** \brief Decode an EPG string as necessary
190 * \param src - Possibly encoded string
191 * \param size - Size of the buffer
193 * \retval NULL - Can't decode
194 * \return A decoded string
196 std::string freesatHuffmanDecoder::decode(const unsigned char *src, size_t size)
198 std::string uncompressed;
203 const unsigned int table_index = src[1] - 1;
205 if (table_index <= 1)
207 huffTableEntry **table = &m_tables[table_index][0];
208 unsigned int value = 0;
209 unsigned int byte = 2;
210 unsigned int bit = 0;
213 while (byte < 6 && byte < size)
215 value |= src[byte] << ((5-byte) * 8);
222 unsigned bitShift = 0;
223 if (lastch == ESCAPE)
225 char nextCh = (value >> 24) & 0xff;
227 // Encoded in the next 8 bits.
228 // Terminated by the first ASCII character.
230 if ((nextCh & 0x80) == 0)
232 uncompressed.append(&nextCh, 1);
236 huffTableEntry * currentEntry = table[lastch];
237 while ( currentEntry != NULL )
239 unsigned mask = 0, maskbit = 0x80000000;
241 for ( kk = 0; kk < currentEntry->bits; kk++)
246 if ((value & mask) == currentEntry->value)
248 char nextCh = currentEntry->next;
249 bitShift = currentEntry->bits;
250 if (nextCh != STOP && nextCh != ESCAPE)
252 uncompressed.append(&nextCh, 1);
258 currentEntry = currentEntry->nextEntry;
263 // Shift up by the number of bits.
265 for ( b = 0; b < bitShift; b++)
267 value = (value << 1) & 0xfffffffe;
269 value |= (src[byte] >> (7-bit)) & 1;
280 #ifdef FREESATV2_DEBUG
281 eDebug("[FREESAT] Missing table %d entry: <%s>", table_index + 1, uncompressed.c_str());
285 } while (lastch != STOP && value != 0);