/* * $Id$ * Copyright (C) 2010 gingko - http://gingko.homeip.net/ * * This file is part of Pouchin TV Mod, a free DVB-T viewer. * See http://www.pouchintv.fr/ for updates. * * Pouchin TV Mod is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Pouchin TV Mod is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * * Most files of this project have been changed from the Pouchin TV * project (Copyright (C) 2006 Pouchin ), * to use with a modified version of this software. * See http://pouchinteve.free.fr/ for the original project. */ /** \file * \brief Gestion d'intervalles mémoire et de flux d'octets et de bits * * Ce fichier implémente les méthodes utilisées par les structures de * référencement d'intervalles d'adresses mémoire, ainsi que pour la lecture de * flux d'octets et de bits. **/ #include "stdafx.h" #include "sbuffer.h" // ==================================================================================== void BitStream::load_byte_in_cache() { if (bit_cnt > sizeof(bit_cache)*8 -8) throw serr_TooManyBitsRequestedAtOnce; bit_cache = bit_cache<<8 | next_byte(); bit_cnt += 8; } UINT8 BitStream::getbit() { if (!bit_cnt) load_byte_in_cache(); return UINT8((bit_cache >> --bit_cnt) & 1); } /** * \brief Lecture des \p cnt bits suivants dans le flot * \param[in] cnt Nombre de bits à lire * \return Bits lus, sous forme d'entier non signé * \note La valeur de \p cnt est valide pour le nombre de bits contenus dans un entier moins 7, * soit 25 en compilation 32 bits, et 57 en compilation 64 bits * Cette limite est portée à 32 ou 64 juste après l'appel de la fonction membre \p align. **/ UINT32 BitStream::getbits(UINT8 cnt) { // Chargement d'octets dans le cache jusqu'à ce que celui-ci contienne au moins autant de bits // qu'il en est demandé while (bit_cnt< cnt) load_byte_in_cache(); bit_cnt = UINT8(bit_cnt - cnt); return (bit_cache >> bit_cnt) & ((1<> 1)); return res >> 1; } /** * Lecture d'après une table VLC (Variable Length Code). * Le premier élément de cette table est un mot de 16 bits de la forme 'bbbbdddddddddddd', avec * 'bbbb' = nombre de bits à lire + 7 (donc le bit de poids fort est toujours à 1, constituant * ainsi un déterminant), et 'dddddddddddd' est un offset positif vers une sous-table de * longueur 2^(bbbb-7), dans laquelle on lit une valeur indexée par la valeur retournée par * les (bbbb-7) bits lus. * Chaque élément de cette sous-table est, soit un autre mot de 16 bits analogue * (et on continue à parcourir la table, en extrayant à chaque fois du flux le nombre de bits * indiqués dans cette table), soit du type '0vvvvvvvvvvvvvvv', auquel cas on retourne la * valeur 'vvvvvvvvvvvvvvv'. **/ UINT16 BitStream::get_vlc_bits(PCUINT16 pvlc) { UINT16 val; while ((val = *pvlc) & 0x8000) pvlc += (val & 0x0fff)+getbits(UINT8((val>>12)-7)); return val; } /** * Alignement à l'octet, avec déchargement des bits préchargés si nécessaire ; après appel à cette * fonction, il est garanti que le pointeur 'pcur' pointe le prochain octet à lire **/ void BitStream::align() { if (bit_cnt!=0) { UINT8 decr = bit_cnt>>3; if (decr) { // Déchargement des octets entiers préchargés unread_bytes(decr); bit_cache >>= 8; bit_cnt &= 0x07; } if (bit_cnt!=0) // Alignement à l'octet suivant getbits(bit_cnt); } } UINT32 BitStream::peekbits(UINT8 count) { UINT32 res = getbits(count); bit_cnt = UINT8(bit_cnt + count); return res; } void BitStream::rewind_bits(UINT8 count) { UINT8 new_cnt = bit_cnt+count; if (new_cnt > sizeof(bit_cache)*8) throw serr_RewindTooLarge; bit_cnt = UINT8(new_cnt); } // ==================================================================================== UINT8 BitRng_ep3::next_byte() { UINT8 res = __super::next_byte(); switch (res) { case 0x00: if (zerocount < 2) ++zerocount; break; case 0x03: if (zerocount >= 2) __super::next_byte(); // ... default: zerocount = 0; } return res; } // ====================================================================================