Hi, Patch attached.
Umair
From 56281948ec484c19dd9009c861ded38905e1b786 Mon Sep 17 00:00:00 2001 From: Umair Khan <omerj...@gmail.com> Date: Sat, 25 Jun 2016 22:48:02 +0530 Subject: [PATCH] avcodec/als: floating point support in ALS decoder Signed-off-by: Umair Khan <omerj...@gmail.com> --- libavcodec/Makefile | 2 +- libavcodec/alsdec.c | 286 +++++++++++++++++++++++++++++++++++++++++- libavcodec/mlz.c | 162 ++++++++++++++++++++++++ libavcodec/mlz.h | 67 ++++++++++ libavutil/softfloat_ieee754.h | 115 +++++++++++++++++ 5 files changed, 629 insertions(+), 3 deletions(-) create mode 100644 libavcodec/mlz.c create mode 100644 libavcodec/mlz.h create mode 100644 libavutil/softfloat_ieee754.h diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 8f63261..3b6c7a8 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -161,7 +161,7 @@ OBJS-$(CONFIG_ALAC_DECODER) += alac.o alac_data.o alacdsp.o OBJS-$(CONFIG_ALAC_ENCODER) += alacenc.o alac_data.o OBJS-$(CONFIG_ALIAS_PIX_DECODER) += aliaspixdec.o OBJS-$(CONFIG_ALIAS_PIX_ENCODER) += aliaspixenc.o -OBJS-$(CONFIG_ALS_DECODER) += alsdec.o bgmc.o mpeg4audio.o +OBJS-$(CONFIG_ALS_DECODER) += alsdec.o bgmc.o mlz.o mpeg4audio.o OBJS-$(CONFIG_AMRNB_DECODER) += amrnbdec.o celp_filters.o \ celp_math.o acelp_filters.o \ acelp_vectors.o \ diff --git a/libavcodec/alsdec.c b/libavcodec/alsdec.c index 842fc7d..00c7eab 100644 --- a/libavcodec/alsdec.c +++ b/libavcodec/alsdec.c @@ -35,8 +35,11 @@ #include "bgmc.h" #include "bswapdsp.h" #include "internal.h" +#include "mlz.h" #include "libavutil/samplefmt.h" #include "libavutil/crc.h" +#include "libavutil/softfloat_ieee754.h" +#include "libavutil/intfloat.h" #include <stdint.h> @@ -225,6 +228,14 @@ typedef struct ALSDecContext { int32_t **raw_samples; ///< decoded raw samples for each channel int32_t *raw_buffer; ///< contains all decoded raw samples including carryover samples uint8_t *crc_buffer; ///< buffer of byte order corrected samples used for CRC check + MLZ* mlz; ///< masked lz decompression structure + SoftFloat_IEEE754 *acf; ///< contains common multiplier for all channels + int *last_acf_mantissa; ///< contains the last acf mantissa data of common multiplier for all channels + int *shift_value; ///< value by which the binary point is to be shifted for all channels + int *last_shift_value; ///< contains last shift value for all channels + int **raw_mantissa; ///< decoded mantissa bits of the difference signal + unsigned char *larray; ///< buffer to store the output of masked lz decompression + int *nbits; ///< contains the number of bits to read for masked lz decompression for all samples } ALSDecContext; @@ -441,7 +452,6 @@ static int check_specific_config(ALSDecContext *ctx) } \ } - MISSING_ERR(sconf->floating, "Floating point decoding", AVERROR_PATCHWELCOME); MISSING_ERR(sconf->rlslms, "Adaptive RLS-LMS prediction", AVERROR_PATCHWELCOME); return error; @@ -1351,6 +1361,241 @@ static int revert_channel_correlation(ALSDecContext *ctx, ALSBlockData *bd, } +/** multiply two softfloats and handle the rounding off + */ +static SoftFloat_IEEE754 multiply(SoftFloat_IEEE754 a, SoftFloat_IEEE754 b) { + uint64_t mantissa_temp; + uint64_t mask_64; + int bit_count; + int cutoff_bit_count; + unsigned char last_2_bits; + unsigned int mantissa; + uint32_t return_val = 0; + int32_t sign; + + sign = a.sign ^ b.sign; + + //Multiply mantissa bits in a 64-bit register + mantissa_temp = (uint64_t)a.mant * (uint64_t)b.mant; + + // Count the valid bit count + for(bit_count=48, mask_64=(uint64_t)0x1 << 47; !(mantissa_temp & mask_64) && mask_64; bit_count--, mask_64>>=1); + + // Round off + cutoff_bit_count = bit_count - 24; + if (cutoff_bit_count > 0) { + last_2_bits = (unsigned char)(((unsigned int)mantissa_temp >> (cutoff_bit_count - 1)) & 0x3 ); + if ((last_2_bits == 0x3) || ((last_2_bits == 0x1) && ((unsigned int)mantissa_temp & ((0x1UL << (cutoff_bit_count - 1)) - 1)))) { + // Need to round up + mantissa_temp += (uint64_t)0x1 << cutoff_bit_count; + } + } + + mantissa = (unsigned int)(mantissa_temp >> cutoff_bit_count); + // Need one more shift? + if (mantissa & 0x01000000ul) { + bit_count++; + mantissa >>= 1; + } + + if (!sign) { + return_val = 0x80000000U; + } + return_val |= (a.exp + b.exp + bit_count - 47) << 23; + return_val |= mantissa; + return av_bits2sf_ieee754(return_val); +} + + +/** Read and decode the floating point sample data + */ +static int read_diff_float_data(ALSDecContext *ctx, unsigned int ra_frame) { + AVCodecContext *avctx = ctx->avctx; + GetBitContext *gb = &ctx->gb; + SoftFloat_IEEE754 *acf = ctx->acf; + int *shift_value = ctx->shift_value; + int *last_shift_value = ctx->last_shift_value; + int *last_acf_mantissa = ctx->last_acf_mantissa; + int **raw_mantissa = ctx->raw_mantissa; + int *nbits = ctx->nbits; + unsigned char *larray = ctx->larray; + int frame_length = ctx->cur_frame_length; + SoftFloat_IEEE754 scale = av_int2sf_ieee754(0x1u, 23); + unsigned int partA_flag; + unsigned int highest_byte; + unsigned int shift_amp; + uint32_t tmp_32; + int use_acf; + int nchars; + int i; + int c; + long k; + long nbits_aligned; + unsigned long acc; + unsigned long j; + uint32_t sign; + uint32_t e; + uint32_t mantissa; + + skip_bits_long(gb, 32); //num_bytes_diff_float + use_acf = get_bits1(gb); + + if (ra_frame) { + for (c = 0; c < avctx->channels; ++c) { + last_acf_mantissa[c] = 0; + last_shift_value[c] = 0; + } + ff_mlz_flush_dict(ctx->mlz); + } + + for (c = 0; c < avctx->channels; ++c) { + if (use_acf) { + //acf_flag + if (get_bits1(gb)) { + tmp_32 = get_bits(gb, 23); + last_acf_mantissa[c] = tmp_32; + } else { + tmp_32 = last_acf_mantissa[c]; + } + acf[c] = av_bits2sf_ieee754(tmp_32); + } else { + acf[c] = FLOAT_1; + } + + highest_byte = get_bits(gb, 2); + shift_amp = get_bits1(gb); + partA_flag = get_bits1(gb); + + if (shift_amp) { + shift_value[c] = get_bits(gb, 8); + last_shift_value[c] = shift_value[c]; + } else { + shift_value[c] = last_shift_value[c]; + } + + if (partA_flag) { + if (!get_bits1(gb)) { //uncompressed + + for (i = 0; i < frame_length; ++i) { + if (ctx->raw_samples[c][i] == 0) { + ctx->raw_mantissa[c][i] = get_bits_long(gb, 32); + } + } + + } else { //compressed + nchars = 0; + for (i = 0; i < frame_length; ++i) { + if (ctx->raw_samples[c][i] == 0) { + nchars += 4; + } + } + + tmp_32 = ff_mlz_decompression(ctx->mlz, gb, nchars, larray); + if(tmp_32 != nchars) { + av_log(ctx->avctx, AV_LOG_ERROR, "Error in MLZ decompression (%d, %d).\n", tmp_32, nchars); + return AVERROR_INVALIDDATA; + } + + for (i = 0; i < frame_length; ++i) { + tmp_32 = (larray[i] << 24) | larray[i+1] << 16 | larray[i+2] << 8 | larray[i+3]; + ctx->raw_mantissa[c][i] = tmp_32; + } + } + } + + //decode part B + if (highest_byte) { + + for (i = 0; i < frame_length; ++i) { + if (ctx->raw_samples[c][i] != 0) { + //The following logic is taken from Tabel 14.45 and 14.46 from the ISO spec + if (av_cmp_sf_ieee754(acf[c], FLOAT_1)) { + nbits[i] = 23 - av_log2(abs(ctx->raw_samples[c][i])); + } else { + nbits[i] = 23; + } + nbits[i] = FFMIN(nbits[i], highest_byte*8); + } + } + + if (!get_bits1(gb)) { //uncompressed + + for (i = 0; i < frame_length; ++i) { + if (ctx->raw_samples[c][i] != 0) { + raw_mantissa[c][i] = get_bits(gb, nbits[i]); + } + } + + } else { //compressed + + nchars = 0; + for (i = 0; i < frame_length; ++i) { + if (ctx->raw_samples[c][i]) { + nchars += (int) nbits[i] / 8; + if (nbits[i] % 8 > 0) { + ++nchars; + } + } + } + + tmp_32 = ff_mlz_decompression(ctx->mlz, gb, nchars, larray); + if(tmp_32 != nchars) { + av_log(ctx->avctx, AV_LOG_ERROR, "Error in MLZ decompression (%d, %d).\n", tmp_32, nchars); + return AVERROR_INVALIDDATA; + } + + j = 0; + for (i = 0; i < frame_length; ++i) { + if (ctx->raw_samples[c][i]) { + if ((nbits[i] % 8) > 0) { + nbits_aligned = 8 * ((unsigned int)(nbits[i] / 8) + 1); + } else { + nbits_aligned = nbits[i]; + } + acc = 0; + for (k = 0; k < nbits_aligned/8; ++k) { + acc = (acc << 8) + larray[j++]; + } + acc >>= (nbits_aligned - nbits[i]); + raw_mantissa[c][i] = acc; + } + } + + } + } + + for (i = 0; i < frame_length; ++i) { + SoftFloat_IEEE754 pcm_sf = av_int2sf_ieee754(ctx->raw_samples[c][i], 0); + pcm_sf = av_div_sf_ieee754(pcm_sf, scale); + + if (ctx->raw_samples[c][i] != 0) { + if (!av_cmp_sf_ieee754(acf[c], FLOAT_1)) { + pcm_sf = multiply(acf[c], pcm_sf); + } + + sign = pcm_sf.sign; + e = pcm_sf.exp; + mantissa = (pcm_sf.mant | 0x800000) + raw_mantissa[c][i]; + + while(mantissa >= 0x1000000) { + e++; + mantissa >>= 1; + } + if (mantissa) e += (shift_value[c] - 127); + mantissa &= 0x007fffffUL; + + tmp_32 = (sign << 31) | ((e + EXP_BIAS) << 23) | (mantissa); + ctx->raw_samples[c][i] = tmp_32; + } else { + ctx->raw_samples[c][i] = raw_mantissa[c][i] & 0x007fffffUL; + } + } + align_get_bits(gb); + } + return 0; +} + + /** Read the frame data. */ static int read_frame_data(ALSDecContext *ctx, unsigned int ra_frame) @@ -1492,7 +1737,9 @@ static int read_frame_data(ALSDecContext *ctx, unsigned int ra_frame) sizeof(*ctx->raw_samples[c]) * sconf->max_order); } - // TODO: read_diff_float_data + if (sconf->floating) { + read_diff_float_data(ctx, ra_frame); + } if (get_bits_left(gb) < 0) { av_log(ctx->avctx, AV_LOG_ERROR, "Overread %d\n", -get_bits_left(gb)); @@ -1662,6 +1909,14 @@ static av_cold int decode_end(AVCodecContext *avctx) av_freep(&ctx->chan_data_buffer); av_freep(&ctx->reverted_channels); av_freep(&ctx->crc_buffer); + av_freep(&ctx->mlz); + av_freep(&ctx->acf); + av_freep(&ctx->last_acf_mantissa); + av_freep(&ctx->shift_value); + av_freep(&ctx->last_shift_value); + av_freep(&ctx->raw_mantissa); + av_freep(&ctx->larray); + av_freep(&ctx->nbits); return 0; } @@ -1798,6 +2053,33 @@ static av_cold int decode_init(AVCodecContext *avctx) ctx->raw_buffer = av_mallocz_array(avctx->channels * channel_size, sizeof(*ctx->raw_buffer)); ctx->raw_samples = av_malloc_array(avctx->channels, sizeof(*ctx->raw_samples)); + if (sconf->floating) { + ctx->acf = av_malloc_array(avctx->channels, sizeof(*ctx->acf)); + ctx->shift_value = av_malloc_array(avctx->channels, sizeof(*ctx->shift_value)); + ctx->last_shift_value = av_malloc_array(avctx->channels, sizeof(*ctx->last_shift_value)); + ctx->last_acf_mantissa = av_malloc_array(avctx->channels, sizeof(*ctx->last_acf_mantissa)); + ctx->raw_mantissa = av_malloc_array(avctx->channels, sizeof(*ctx->raw_mantissa)); + for (int c = 0; c < avctx->channels; ++c) { + ctx->raw_mantissa[c] = av_malloc_array(ctx->cur_frame_length, sizeof(**ctx->raw_mantissa)); + for (int i = 0; i < ctx->cur_frame_length; ++i) { + ctx->raw_mantissa[c][i] = 0x0u; + } + } + ctx->larray = av_malloc_array(ctx->cur_frame_length * 4, sizeof(*ctx->larray)); + ctx->nbits = av_malloc_array(ctx->cur_frame_length, sizeof(*ctx->nbits)); + + ctx->mlz = av_malloc(sizeof(*ctx->mlz)); + ff_mlz_init_dict(ctx->mlz); + ff_mlz_flush_dict(ctx->mlz); + + if (!ctx->mlz || !ctx->acf || !ctx->shift_value || !ctx->last_shift_value + || !ctx->last_acf_mantissa || !ctx->raw_mantissa) { + av_log(avctx, AV_LOG_ERROR, "Allocating buffer memory failed.\n"); + ret = AVERROR(ENOMEM); + goto fail; + } + } + // allocate previous raw sample buffer if (!ctx->prev_raw_samples || !ctx->raw_buffer|| !ctx->raw_samples) { av_log(avctx, AV_LOG_ERROR, "Allocating buffer memory failed.\n"); diff --git a/libavcodec/mlz.c b/libavcodec/mlz.c new file mode 100644 index 0000000..24d48e4 --- /dev/null +++ b/libavcodec/mlz.c @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2016 Umair Khan <omerj...@gmail.com> + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mlz.h" + +av_cold void ff_mlz_init_dict(MLZ *mlz) { + mlz->dict = av_malloc_array(TABLE_SIZE, sizeof(*mlz->dict)); + + mlz->flush_code = FLUSH_CODE; + mlz->current_dic_index_max = DIC_INDEX_INIT; + mlz->dic_code_bit = CODE_BIT_INIT; + mlz->bump_code = (DIC_INDEX_INIT - 1); + mlz->next_code = FIRST_CODE; + mlz->freeze_flag = 0; +} + +av_cold void ff_mlz_flush_dict(MLZ *mlz) { + MLZDict *dict = mlz->dict; + int i; + for ( i = 0; i < TABLE_SIZE; i++ ) { + dict[i].string_code = CODE_UNSET; + dict[i].parent_code = CODE_UNSET; + dict[i].match_len = 0; + } + mlz->current_dic_index_max = DIC_INDEX_INIT; + mlz->dic_code_bit = CODE_BIT_INIT; // DicCodeBitInit; + mlz->bump_code = mlz->current_dic_index_max - 1; + mlz->next_code = FIRST_CODE; + mlz->freeze_flag = 0; +} + +static void set_new_entry_dict(MLZDict* dict, int string_code, int parent_code, int char_code) { + dict[string_code].parent_code = parent_code; + dict[string_code].string_code = string_code; + dict[string_code].char_code = char_code; + if (parent_code < FIRST_CODE) { + dict[string_code].match_len = 2; + } else { + dict[string_code].match_len = (dict[parent_code].match_len) + 1; + } +} + +static int decode_string(MLZDict *dict, unsigned char *buff, int string_code, int *first_char_code, unsigned long bufsize) { + unsigned long count, offset; + int current_code, parent_code, tmp_code; + + count = 0; + current_code = string_code; + *first_char_code = CODE_UNSET; + + while (count < bufsize) { + switch (current_code) { + case CODE_UNSET: + return count; + break; + default: + if (current_code < FIRST_CODE) { + *first_char_code = current_code; + buff[0] = current_code; + count++; + return count; + } else { + offset = dict[current_code].match_len - 1; + tmp_code = dict[current_code].char_code; + buff[offset] = tmp_code; + count++; + } + current_code = dict[current_code].parent_code; + if ((current_code < 0) || (current_code > (DIC_INDEX_MAX - 1))) { + av_log(NULL, AV_LOG_ERROR, "Dic index error.\n"); + return count; + } + if (current_code > FIRST_CODE) { + parent_code = dict[current_code].parent_code; + offset = (dict[current_code].match_len) - 1; + if (parent_code < 0 || parent_code > DIC_INDEX_MAX-1) { + av_log(NULL, AV_LOG_ERROR, "Dic index error.\n"); + return count; + } + if (( offset > (DIC_INDEX_MAX - 1))) { + av_log(NULL, AV_LOG_ERROR, "Dic offset error.\n"); + return count; + } + } + break; + } + } + return count; +} + +int ff_mlz_decompression(MLZ* mlz, GetBitContext* gb, int size, unsigned char *buff) { + MLZDict *dict = mlz->dict; + unsigned long output_chars; + int string_code, last_string_code, char_code; + + string_code = 0; + char_code = -1; + last_string_code = -1; + output_chars = 0; + + while (output_chars < size) { + string_code = get_bits(gb, mlz->dic_code_bit); + switch (string_code) { + case FLUSH_CODE: + case MAX_CODE: + ff_mlz_flush_dict(mlz); + char_code = -1; + last_string_code = -1; + break; + case FREEZE_CODE: + mlz->freeze_flag = 1; + break; + default: + if (string_code > mlz->current_dic_index_max) { + av_log(NULL, AV_LOG_ERROR, "String code %d exceeds maximum value of %d.\n", string_code, mlz->current_dic_index_max); + return output_chars; + } + if (string_code == (int) mlz->bump_code) { + ++mlz->dic_code_bit; + mlz->current_dic_index_max *= 2; + mlz->bump_code = mlz->current_dic_index_max - 1; + } else { + if (string_code >= mlz->next_code) { + output_chars += decode_string(dict, &buff[output_chars], last_string_code, &char_code, size - output_chars); + output_chars += decode_string(dict, &buff[output_chars], char_code, &char_code, size - output_chars); + set_new_entry_dict(dict, mlz->next_code, last_string_code, char_code); + mlz->next_code++; + } else { + output_chars += decode_string(dict, &buff[output_chars], string_code, &char_code, size - output_chars); + if (output_chars <= size && !mlz->freeze_flag) { + if (last_string_code != -1) { + set_new_entry_dict(dict, mlz->next_code, last_string_code, char_code); + mlz->next_code++; + } + } else { + break; + } + } + last_string_code = string_code; + } + break; + } + } + return output_chars; +} diff --git a/libavcodec/mlz.h b/libavcodec/mlz.h new file mode 100644 index 0000000..00f34c1 --- /dev/null +++ b/libavcodec/mlz.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2016 Umair Khan <omerj...@gmail.com> + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_MLZ_H +#define AVCODEC_MLZ_H + +#include "get_bits.h" + +#define CODE_UNSET -1 +#define CODE_BIT_INIT 9 +#define DIC_INDEX_INIT 512 // 2^9 +#define DIC_INDEX_MAX 32768L // 2^15 +#define FLUSH_CODE 256 +#define FREEZE_CODE 257 +#define FIRST_CODE 258 +#define MAX_CODE 32767L +#define TABLE_SIZE 35023L // TABLE_SIZE must be a prime number + +/** Dictionary structure for mlz decompression + */ +typedef struct MLZDict { + int string_code; + int parent_code; + int char_code; + int match_len; +} MLZDict; + +/** MLZ data strucure + */ +typedef struct MLZ { + int dic_code_bit; + int current_dic_index_max; + unsigned int bump_code; + unsigned int flush_code; + int next_code; + int freeze_flag; + MLZDict* dict; +} MLZ; + +/** Initialize the dictionary + */ +void ff_mlz_init_dict(MLZ *mlz); +/** Flush the dictionary + */ +void ff_mlz_flush_dict(MLZ *dict); +/** Run mlz decompression on the next size bits and the output will be stored in buff + */ +int ff_mlz_decompression(MLZ* mlz, GetBitContext* gb, int size, unsigned char *buff); + +#endif /*AVCODEC_MLZ_H*/ diff --git a/libavutil/softfloat_ieee754.h b/libavutil/softfloat_ieee754.h new file mode 100644 index 0000000..7c4745b --- /dev/null +++ b/libavutil/softfloat_ieee754.h @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2016 Umair Khan <omerj...@gmail.com> + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_SOFTFLOAT_IEEE754_H +#define AVUTIL_SOFTFLOAT_IEEE754_H + +#include <stdint.h> + +#define EXP_BIAS 127 +#define MANT_BITS 23 + +typedef struct SoftFloat_IEEE754 { + int32_t sign; + uint64_t mant; + int32_t exp; +} SoftFloat_IEEE754; + +static const SoftFloat_IEEE754 FLOAT_0 = {0, 0, -126}; +static const SoftFloat_IEEE754 FLOAT_1 = {0, 0, 0}; + +/** Normalize the softfloat as defined by IEEE 754 single-recision floating + * point specification + */ +static SoftFloat_IEEE754 av_normalize_sf_ieee754(SoftFloat_IEEE754 sf) { + while( sf.mant >= 0x1000000UL ) { + sf.exp++; + sf.mant >>= 1; + } + sf.mant &= 0x007fffffUL; + return sf; +} + +/** Convert integer to softfloat. + * @return softfloat with value n * 2^e + */ +static SoftFloat_IEEE754 av_int2sf_ieee754(int64_t n, int e) { + int sign = 0; + + if (n < 0) { + sign = 1; + n *= -1; + } + return av_normalize_sf_ieee754((SoftFloat_IEEE754) {sign, n << MANT_BITS, 0 + e}); +} + +/** Make a softfloat out of the bitstream. Assumes the bits are in the form as defined + * by the IEEE 754 spec. + */ +static SoftFloat_IEEE754 av_bits2sf_ieee754(uint32_t n) { + return ((SoftFloat_IEEE754) { (n & 0x80000000UL), (n & 0x7F800000UL), (n & 0x7FFFFFUL) }); +} + +/** Convert the softfloat to integer + */ +static int av_sf2int_ieee754(SoftFloat_IEEE754 a) { + if(a.exp >= 0) return a.mant << a.exp ; + else return a.mant >>(-a.exp); +} + +/** Divide a by b. b should not be zero. + * @return normalized result + */ +static SoftFloat_IEEE754 av_div_sf_ieee754(SoftFloat_IEEE754 a, SoftFloat_IEEE754 b) { + int32_t mant, exp, sign; + a = av_normalize_sf_ieee754(a); + b = av_normalize_sf_ieee754(b); + sign = a.sign ^ b.sign; + mant = ((((uint64_t) (a.mant | 0x00800000UL)) << MANT_BITS) / (b.mant| 0x00800000UL)); + exp = a.exp - b.exp; + return av_normalize_sf_ieee754((SoftFloat_IEEE754) {sign, mant, exp}); +} + +/** Multiply a with b + * #return normalized result + */ +static SoftFloat_IEEE754 av_mul_sf_ieee754(SoftFloat_IEEE754 a, SoftFloat_IEEE754 b) { + int32_t sign, mant, exp; + a = av_normalize_sf_ieee754(a); + b = av_normalize_sf_ieee754(b); + sign = a.sign ^ b.sign; + mant = (((uint64_t)(a.mant|0x00800000UL) * (uint64_t)(b.mant|0x00800000UL))>>MANT_BITS); + exp = a.exp + b.exp; + return av_normalize_sf_ieee754((SoftFloat_IEEE754) {sign, mant, exp}); +} + +/** Compare a with b strictly + * @returns 1 if the a and b are equal, 0 otherwise. + */ +static int av_cmp_sf_ieee754(SoftFloat_IEEE754 a, SoftFloat_IEEE754 b) { + a = av_normalize_sf_ieee754(a); + b = av_normalize_sf_ieee754(b); + if (a.sign != b.sign) return 0; + if (a.mant != b.mant) return 0; + if (a.exp != b.exp ) return 0; + return 1; +} + +#endif /*AVUTIL_SOFTFLOAT_IEEE754_H*/ -- 2.7.4
_______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel