/* $Id: mcl_fec.h,v 1.5 2003/10/16 16:13:39 roca Exp $ */ /* * Copyright (c) 2003 INRIA - All rights reserved * (main author: Vincent Roca - vincent.roca@inrialpes.fr) * * 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. */ #ifndef MCL_FEC_H /* { */ #define MCL_FEC_H /** * The following defines are specifying the identifiers used by * the ALC/LCT protocol. See RFC 3452 for further details. */ /** * FEC Encoding ID (RFC 3452). * It determines the FTI format and is carried in the LCT codepoint * header field. */ #define FEC_ENCODING_ID_NO_FEC 0 #define FEC_ENCODING_ID_SMALL_LARGE_EXP_FEC 128 #define FEC_ENCODING_ID_LDPC_FEC 140 // private! /** * FEC Instance ID (RFC 3452). * Along with the FEC Encoding ID, it determines the FEC codec in use. * WARNING: these values must be the same as the MCL_FEC_CODE_XXX values! */ enum fec_instance_id { FEC_INSTANCE_ID_NULL = 0, /* when using MCL_FEC_CODE_NULL */ FEC_INSTANCE_ID_RSE, /* when using MCL_FEC_CODE_RSE */ FEC_INSTANCE_ID_LDGM, /* when using MCL_FEC_CODE_LDGM */ FEC_INSTANCE_ID_LDPC /* when using MCL_FEC_CODE_LDPC */ }; #ifdef LDPC_FEC /** * context used as an opaque parameter to decoded_pkt_callback. */ typedef struct ldpc_callback_context { struct mclcb_s *mclcb; block_t *block; } ldpc_callback_context_t; #endif /** * Main FEC class. * Shared by the various FEC codecs. */ class mcl_fec { public: /****** Public Members ************************************************/ /** * Default constructor. * Initializes all the supported FEC code parameters. * Initializes the default FEC code. */ mcl_fec (); ~mcl_fec (); /** * Initializes the FEC class for all supported FEC codes: * MCL_FEC_CODE_NULL, ...RSE, ...LDGM, ...LDPC. * (see mcl_lib_api_alc.h). * Initializes the default constructor. */ void initialize (void); /** * Return the maximum source block size (k) in number of DUs. * This parameter is set at mcl_fec service initialization * depending on the FEC code used. * We have: max_k <= max_n (no FEC DU if equal). * @return maximum k */ INT32 get_max_k () const; /** * Return the maximum FEC block size (in number of DUs). * This parameter is set at mcl_fec service initialization * depending on the FEC code used. * @return maximum n */ INT32 get_max_n () const; /** * Set the effective block size to use (in number of DUs). * 0 < k <= max_k made possible by the code. * If k == n, then no FEC DU will be produced. */ void set_k (const INT32 k); /** * Return the effective block size used currently (in number of DUs). */ INT32 get_k (void) const; /** * Set the effective n to use (in number of DUs). * 0 < n <= max_n made possible by the code. * If k == n, then no FEC DU will be produced. */ void set_n (const INT32 n); /** * Return the effective n parameter used currently (in number of DUs). */ INT32 get_n (void) const; /** * Set the FEC code to be used. * This function is sender specific (a receiver gets the FEC * codec information info from the various incoming packet fields). * This function only changes the FEC code to use from now on, * without modifying anything else. It assumes that the FEC * codec specific parameters have already been initialized. * @param new_code FEC code to use from now on, in: * {MCL_FEC_CODE_NULL; MCL_FEC_CODE_RSE; * MCL_FEC_CODE_LDGM; MCL_FEC_CODE_LDPC} * @return Completion status (MCL_OK or MCL_ERROR). */ mcl_error_status set_fec_code (struct mclcb_s *const mclcb, const INT32 new_code); /** * Return the FEC code corresponding to the current FEC codec used. * @return FEC code value in: * {MCL_FEC_CODE_NULL; MCL_FEC_CODE_RSE; * MCL_FEC_CODE_LDGM; MCL_FEC_CODE_LDPC} */ fec_instance_id get_fec_code () const; /** * Set the maximum FEC ratio, defined as n/k. * Calling this function modifies the cur_k/max_k accordingly. * @return Completion status (MCL_OK or MCL_ERROR). */ mcl_error_status set_max_fec_ratio (struct mclcb_s *const mclcb, float max_fec_ratio); /** * Return the maximum FEC ratio, defined as n/k. */ float get_max_fec_ratio () const; #if 0 /** * Return the number of available FEC packets (ie that have been * created) that have not yet been sent. */ INT32 get_nb_fresh_fec_pkts (mclcb_t *const mclcb, mcl_block *blk); #endif /** * Return the number of FEC packets that can still be created for this * block. */ INT32 get_rem_nb_fec_pkts_to_create (struct mclcb_s *const mclcb, block_t *blk); /** * Encode the block and create the appropriate number of new FEC * packets. * The FEC packets are inserted in the block FEC list. (XXX: not yet) * The number of FEC packets created is automatically determined * by the block size and scheduling session. * @param mclcb * @param blk block for which FEC packets must be created * @return < 0 if error, the number of FEC symbols * created if ok */ INT32 encode (struct mclcb_s *const mclcb, block_t *blk); #ifdef RSE_FEC /** * Decode the block immediately. * This function is for Reed-Solomon and similar FEC codes who, * thanks to their MDS feature, decode blocks as a whole, as soon * as enough (i.e. blk->k) packets have been received. * @param mclcb * @param blk block for which decoding must be done * @return < 0 if error, the number of FEC symbols * created if ok */ INT32 decode (struct mclcb_s *const mclcb, block_t *blk); #endif /* RSE_FEC */ #ifdef LDPC_FEC /** * Progress in the block decoding with the given packet. * This function is for LDPC and similar FEC codes who use an * iterative decoding approach. * @param mclcb * @param rx_du DU for the packet just received * @return < 0 if error, the number of FEC symbols * created if ok */ INT32 decode (struct mclcb_s *const mclcb, du_t *rx_du); /** * Test if decoding is completed for this block. * @return true if completed, false if there are * missing source packets. */ bool is_decoding_complete (block_t *blk); #endif /* LDPC_FEC */ /****** Public Attributes *********************************************/ private: /****** Private Members ***********************************************/ /** * Determine the number of FEC packets required for this block. * Depends on the block size (k) and the kind of scheduling used * for this session. * @param mclcb * @param k k parameter for this block * @return n parameter for this block */ INT32 compute_n_for_this_block (struct mclcb_s *const mclcb, INT32 k); #ifdef LDPC_FEC #if 0 /** * This callback function will be called each time the * DecodeFecStep() function needs to allocate a buffer. * Allocate the buffer, using the VRM service if applicable, * and return the buffer. This function replaces malloc(). * This function is STATIC to enable pointer-to-member-function. * @param size buffer size to allocate. * @param context pointer to an ldpc_callback_context_t * structure. * @return pointer to the buffer allocated, or NULL * in case of error. */ static void *dec_malloc_callback (INT32 size, void *context); #endif /** * This callback function will be called each time a packet * is decoded by the DecodeFecStep() function. * Create the associated DU, and insert the packet in the rx list. * Allocate the buffer, using the VRM service if applicable. * This function is STATIC to enable pointer-to-member-function. * @param pkt_buf pointer to the packet buffer * @param pkt_seq sequence number of packet in block * ({0..n-1} range). Can be used to * differentiate source and FEC packets. * @param context pointer to an ldpc_callback_context_t * structure. */ static void *decoded_pkt_callback (INT32 size, INT32 pkt_seq, void *context); #endif /* LDPC_FEC */ /****** Private Attributes ********************************************/ INT32 fec_codec; /** * Codec to use for this session. * Can be one of MCL_FEC_CODE_NULL, ...RSE, * ...LDGM, ...LDPC. */ INT32 max_k[MCL_FEC_CODE_MAX_NB]; /** Max k value. FEC dependant */ INT32 max_n[MCL_FEC_CODE_MAX_NB]; /** Max n value. FEC dependant */ INT32 cur_k[MCL_FEC_CODE_MAX_NB]; /** k value currently in use. */ INT32 cur_n[MCL_FEC_CODE_MAX_NB]; /** n value currently in use. */ float max_fratio; /** Maximum FEC ratio defined as n/k. */ }; //------------------------------------------------------------------------------ // Inlines for all classes follow //------------------------------------------------------------------------------ inline INT32 mcl_fec::get_max_k () const { return this->max_k[this->fec_codec]; } inline INT32 mcl_fec::get_max_n () const { return this->max_n[this->fec_codec]; } inline INT32 mcl_fec::get_k (void) const { return this->cur_k[this->fec_codec]; } inline void mcl_fec::set_k (const INT32 k) { ASSERT(k <= max_k[this->fec_codec]); ASSERT(k > 0); ASSERT(k <= cur_n[this->fec_codec]); this->cur_k[this->fec_codec] = k; } inline INT32 mcl_fec::get_n () const { return this->cur_n[this->fec_codec]; } inline void mcl_fec::set_n (const INT32 n) { ASSERT(n <= max_n[this->fec_codec]); ASSERT(n > 0); ASSERT(cur_k[this->fec_codec] <= n); this->cur_n[this->fec_codec] = n; } inline fec_instance_id mcl_fec::get_fec_code () const { /* * WARNING: assumes that lct_codepoint values are the same * as the MCL_FEC_CODE_XXX values! */ return (fec_instance_id) this->fec_codec; } inline float mcl_fec::get_max_fec_ratio () const { return this->max_fratio; } #ifdef LDPC_FEC inline bool mcl_fec::is_decoding_complete (block_t *blk) { ASSERT(blk->ldpc_ses); ASSERT(blk->pkt_canvas); return (blk->ldpc_ses->IsDecodingComplete(blk->pkt_canvas)); } #endif #endif /* } MCL_FEC_H */