/* dvdisaster: Additional error correction for optical media. * Copyright (C) 2004-2010 Carsten Gnoerlich. * Project home page: http://www.dvdisaster.com * Email: carsten@dvdisaster.com -or- cgnoerlich@fsfe.org * * This program 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. * * This program 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA, * or direct your browser at http://www.gnu.org. */ #include "dvdisaster.h" /*** *** Reed-Solomon encoding ***/ /* Portable (non-SSE2) version. * Using 32bit operands seems to be a good choice for the lowest * common denominator between the non-SSE2 systems. */ #ifdef HAVE_BIG_ENDIAN #define SHIFT_LEFT << #define SHIFT_RIGHT >> #else #define SHIFT_LEFT >> #define SHIFT_RIGHT << #endif /* HAVE_BIG_ENDIAN */ static void encode_next_layer_portable(ReedSolomonTables *rt, unsigned char *data, unsigned char *parity, guint64 layer_size, int shift) { gint32 *gf_index_of = rt->gfTables->indexOf; gint32 *enc_alpha_to = rt->gfTables->encAlphaTo; gint32 *rs_gpoly = rt->gpoly; int nroots = rt->nroots; int nroots_aligned = (nroots+15)&~15; int nroots_aligned32 = (nroots+3)&~3; int nroots_full = nroots_aligned32>>2; int i,j; for(i=0; ibLut[feedback]+(offset&~3))); /* Process lut in 32 bit steps */ switch(byte_offset) { case 0: for(j=nroots_full; j; j--) *par_idx++ ^= *e_lut++; break; case 1: { for(j=nroots_full; j; j--) { guint32 span = *e_lut SHIFT_LEFT 8; e_lut++; span |= *e_lut SHIFT_RIGHT 24; *par_idx++ ^= span; } } break; case 2: { for(j=nroots_full; j; j--) { guint32 span = *e_lut SHIFT_LEFT 16; e_lut++; span |= *e_lut SHIFT_RIGHT 16; *par_idx++ ^= span; } } break; case 3: { for(j=nroots_full; j; j--) { guint32 span = *e_lut SHIFT_LEFT 24; e_lut++; span |= *e_lut SHIFT_RIGHT 8; *par_idx++ ^= span; } } break; } parity[shift] = enc_alpha_to[feedback + rs_gpoly[0]]; } else /* zero feedback term */ parity[shift] = 0; parity += nroots_aligned; } } /* * Dispatch upon availability of SSE2 intrinsics */ void encode_next_layer_sse2(ReedSolomonTables*, unsigned char*, unsigned char*, guint64, int); void encode_next_layer_altivec(ReedSolomonTables*, unsigned char*, unsigned char*, guint64, int); void EncodeNextLayer(ReedSolomonTables *rt, unsigned char *data, unsigned char *parity, guint64 layer_size, int shift) { if(Closure->useSSE2) encode_next_layer_sse2(rt, data, parity, layer_size, shift); else if(Closure->useAltiVec) encode_next_layer_altivec(rt, data, parity, layer_size, shift); else encode_next_layer_portable(rt, data, parity, layer_size, shift); }