/*
 * FLAC (Free Lossless Audio Codec) decoder
 * Copyright (c) 2003 Alex Beregszaszi
 *
 * 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
 */

/**
 * @file
 * FLAC (Free Lossless Audio Codec) decoder
 * @author Alex Beregszaszi
 *
 * For more information on the FLAC format, visit:
 *  http://flac.sourceforge.net/
 *
 * This decoder can be used in 1 of 2 ways: Either raw FLAC data can be fed
 * through, starting from the initial 'fLaC' signature; or by passing the
 * 34-byte streaminfo structure through avctx->extradata[_size] followed
 * by data starting with the 0xFFF8 marker.
 */

//#define MPXPLAY_USE_DEBUGF 1
#define MPXPLAY_DEBUG_OUTPUT stdout

#ifdef MPXPLAY_USE_DEBUGF
#include "..\..\newfunc\newfunc.h"
#else
#define mpxplay_debugf(...)
#endif

#include <limits.h>
#include <errno.h>

#include "common.h"
#include "crc.h"
#include "avcodecm.h"
#include "bitstrea.h"
//#include "internal.h"
//#include "get_bits.h"
#include "bytestre.h"
#include "golomb.h"
#undef NDEBUG

// flac.h -------------------------------------------------
#define FLAC_STREAMINFO_SIZE   34
#define FLAC_MAX_CHANNELS       8
#define FLAC_MIN_BLOCKSIZE     16
#define FLAC_MAX_BLOCKSIZE  65535
#define FLAC_MIN_FRAME_SIZE    11

enum {
    FLAC_CHMODE_INDEPENDENT =  0,
    FLAC_CHMODE_LEFT_SIDE   =  8,
    FLAC_CHMODE_RIGHT_SIDE  =  9,
    FLAC_CHMODE_MID_SIDE    = 10,
};

enum {
    FLAC_METADATA_TYPE_STREAMINFO = 0,
    FLAC_METADATA_TYPE_PADDING,
    FLAC_METADATA_TYPE_APPLICATION,
    FLAC_METADATA_TYPE_SEEKTABLE,
    FLAC_METADATA_TYPE_VORBIS_COMMENT,
    FLAC_METADATA_TYPE_CUESHEET,
    FLAC_METADATA_TYPE_PICTURE,
    FLAC_METADATA_TYPE_INVALID = 127
};

enum FLACExtradataFormat {
    FLAC_EXTRADATA_FORMAT_STREAMINFO  = 0,
    FLAC_EXTRADATA_FORMAT_FULL_HEADER = 1
};

#define FLACCOMMONINFO \
    int samplerate;         /**< sample rate                             */\
    int channels;           /**< number of channels                      */\
    int bps;                /**< bits-per-sample                         */\

/**
 * Data needed from the Streaminfo header for use by the raw FLAC demuxer
 * and/or the FLAC decoder.
 */
#define FLACSTREAMINFO \
    FLACCOMMONINFO \
    int max_blocksize;      /**< maximum block size, in samples          */\
    int max_framesize;      /**< maximum frame size, in bytes            */\
    int64_t samples;        /**< total number of samples                 */\

typedef struct FLACStreaminfo {
    FLACSTREAMINFO
} FLACStreaminfo;

typedef struct FLACFrameInfo {
    FLACCOMMONINFO
    int blocksize;          /**< block size of the frame                 */
    int ch_mode;            /**< channel decorrelation mode              */
} FLACFrameInfo;

//flac.c -----------------------------------------------------------------
static int ff_flac_get_max_frame_size(int blocksize, int ch, int bps)
{
    /* Technically, there is no limit to FLAC frame size, but an encoder
       should not write a frame that is larger than if verbatim encoding mode
       were to be used. */

    int count;

    count = 16;                  /* frame header */
    count += ch * ((7+bps+7)/8); /* subframe headers */
    if (ch == 2) {
        /* for stereo, need to account for using decorrelation */
        count += (( 2*bps+1) * blocksize + 7) / 8;
    } else {
        count += ( ch*bps    * blocksize + 7) / 8;
    }
    count += 2; /* frame footer */

    return count;
}

//flacdata.c --------------------------------------------------------------
const int mpxplay_ff_flac_sample_rate_table[16] =
{ 0,
  88200, 176400, 192000,
  8000, 16000, 22050, 24000, 32000, 44100, 48000, 96000,
  0, 0, 0, 0 };

const int mpxplay_ff_flac_blocksize_table[16] = {
     0,    192, 576<<0, 576<<1, 576<<2, 576<<3,      0,      0,
256<<0, 256<<1, 256<<2, 256<<3, 256<<4, 256<<5, 256<<6, 256<<7
};

//flacdec.c ---------------------------------------------------------------
typedef struct FLACContext {
    FLACSTREAMINFO

    AVCodecContext *avctx;                  ///< parent AVCodecContext
    GetBitContext gb;                       ///< GetBitContext initialized to start at the current frame

    int blocksize;                          ///< number of samples in the current frame
    int curr_bps;                           ///< bps for current subframe, adjusted for channel correlation and wasted bits
    int sample_shift;                       ///< shift required to make output samples 16-bit or 32-bit
    int is32;                               ///< flag to indicate if output should be 32-bit instead of 16-bit
    int ch_mode;                            ///< channel decorrelation type in the current frame
    int got_streaminfo;                     ///< indicates if the STREAMINFO has been read

    int allocated_decoded_size;
    int32_t *decoded[FLAC_MAX_CHANNELS];    ///< decoded samples
} FLACContext;

static void ff_flac_parse_streaminfo(AVCodecContext *avctx, struct FLACStreaminfo *s,const uint8_t *buffer);

static const int sample_size_table[] =
{ 0, 8, 12, 0, 16, 20, 24, 0 };

/*static int64_t get_utf8(GetBitContext *gb)
{
    int64_t val;
    GET_UTF8(val, get_bits(gb, 8), return -1;)
    return val;
}*/

static int64_t get_utf8(GetBitContext *gb)
{
    uint64_t val;
    int ones=0, bytes;
    int left = get_bits_left(gb);

    while(((left--)>0) && get_bits1(gb))
        ones++;

    if     (ones==0) bytes=0;
    else if(ones==1) return -1;
    else             bytes= ones - 1;

    val= get_bits(gb, 7-ones);
    left = get_bits_left(gb);
    while(bytes-- && (left--)>0){
        const int tmp = get_bits(gb, 8);

        if((tmp>>6) != 2)
            return -1;
        val<<=6;
        val|= tmp&0x3F;
    }
    return val;
}

static int allocate_buffers(FLACContext *s);

static int ff_flac_is_extradata_valid(AVCodecContext *avctx,
                               enum FLACExtradataFormat *format,
                               uint8_t **streaminfo_start)
{
    if (!avctx->extradata || avctx->extradata_size < FLAC_STREAMINFO_SIZE) {
        mpxplay_debugf(MPXPLAY_DEBUG_OUTPUT,"extradata NULL or too small");
        return 0;
    }
    if (AV_RL32(avctx->extradata) != MKTAG('f','L','a','C')) {
        /* extradata contains STREAMINFO only */
        if (avctx->extradata_size != FLAC_STREAMINFO_SIZE) {
            mpxplay_debugf(MPXPLAY_DEBUG_OUTPUT, "extradata contains %d bytes too many",
                   FLAC_STREAMINFO_SIZE-avctx->extradata_size);
        }
        *format = FLAC_EXTRADATA_FORMAT_STREAMINFO;
        *streaminfo_start = avctx->extradata;
    } else {
        if (avctx->extradata_size < 8+FLAC_STREAMINFO_SIZE) {
            mpxplay_debugf(MPXPLAY_DEBUG_OUTPUT, "extradata too small.\n");
            return 0;
        }
        *format = FLAC_EXTRADATA_FORMAT_FULL_HEADER;
        *streaminfo_start = &avctx->extradata[8];
    }
    return 1;
}

static av_cold int flac_decode_init(AVCodecContext *avctx)
{
    enum FLACExtradataFormat format;
    uint8_t *streaminfo;
    FLACContext *s = avctx->priv_data;
    s->avctx = avctx;

    avctx->sample_fmt = SAMPLE_FMT_S16;

    /* for now, the raw FLAC header is allowed to be passed to the decoder as
       frame data instead of extradata. */
    if (!avctx->extradata)
        return 0;

    if (!ff_flac_is_extradata_valid(avctx, &format, &streaminfo))
        return -1;

    /* initialize based on the demuxer-supplied streamdata header */
    ff_flac_parse_streaminfo(avctx, (FLACStreaminfo *)s, streaminfo);
    if (s->bps > 16)
        avctx->sample_fmt = SAMPLE_FMT_S32;
    else
        avctx->sample_fmt = SAMPLE_FMT_S16;

    if(allocate_buffers(s)<0)
     return -1;

    s->got_streaminfo = 1;

    return 0;
}

static int allocate_buffers(FLACContext *s)
{
 int i;

 if(!s->max_blocksize)
  return -1;

 if(s->max_framesize == 0 && s->max_blocksize)
  s->max_framesize = ff_flac_get_max_frame_size(s->max_blocksize,s->channels, s->bps);

 if(s->allocated_decoded_size < s->max_blocksize){
  for(i = 0; i < s->channels; i++){
   s->decoded[i] = mpxplay_av_realloc(s->decoded[i],sizeof(int32_t)*s->max_blocksize);
   if(!s->decoded[i])
    return -1;
  }
  s->allocated_decoded_size=s->max_blocksize;
 }

 return 0;
}

static void ff_flac_parse_streaminfo(AVCodecContext *avctx, struct FLACStreaminfo *s,
                              const uint8_t *buffer)
{
    GetBitContext gb;
    init_get_bits(&gb, buffer, FLAC_STREAMINFO_SIZE*8);

    skip_bits(&gb, 16); /* skip min blocksize */
    s->max_blocksize = get_bits(&gb, 16);
    if (s->max_blocksize < FLAC_MIN_BLOCKSIZE) {
        mpxplay_debugf(MPXPLAY_DEBUG_OUTPUT, "invalid max blocksize: %d",s->max_blocksize);
        s->max_blocksize = 16;
    }

    skip_bits(&gb, 24); /* skip min frame size */
    s->max_framesize = get_bits_long(&gb, 24);

    s->samplerate = get_bits_long(&gb, 20);
    s->channels = get_bits(&gb, 3) + 1;
    s->bps = get_bits(&gb, 5) + 1;

    avctx->channels = s->channels;
    avctx->sample_rate = s->samplerate;
    //avctx->bits_per_raw_sample = s->bps;

    s->samples  = get_bits_long(&gb, 32) << 4;
    s->samples |= get_bits(&gb, 4);

    skip_bits_long(&gb, 64); /* md5 sum */
    skip_bits_long(&gb, 64); /* md5 sum */

    //dump_headers(avctx, s);
}

void ff_flac_parse_block_header(const uint8_t *block_header,
                                int *last, int *type, int *size)
{
    int tmp = bytestream_get_byte(&block_header);
    if (last)
        *last = tmp & 0x80;
    if (type)
        *type = tmp & 0x7F;
    if (size)
        *size = bytestream_get_be24(&block_header);
}

/**
 * Parse the STREAMINFO from an inline header.
 * @param s the flac decoding context
 * @param buf input buffer, starting with the "fLaC" marker
 * @param buf_size buffer size
 * @return non-zero if metadata is invalid
 */
static int parse_streaminfo(FLACContext *s, const uint8_t *buf, int buf_size)
{
    int metadata_type, metadata_size;

    if (buf_size < FLAC_STREAMINFO_SIZE+8) {
        /* need more data */
        return 0;
    }
    ff_flac_parse_block_header(&buf[4], NULL, &metadata_type, &metadata_size);
    if (metadata_type != FLAC_METADATA_TYPE_STREAMINFO ||
        metadata_size != FLAC_STREAMINFO_SIZE) {
        return EINVAL;
    }
    ff_flac_parse_streaminfo(s->avctx, (FLACStreaminfo *)s, &buf[8]);
    if(allocate_buffers(s)<0)
     return -1;
    s->got_streaminfo = 1;

    return 1;
}

/**
 * Determine the size of an inline header.
 * @param buf input buffer, starting with the "fLaC" marker
 * @param buf_size buffer size
 * @return number of bytes in the header, or 0 if more data is needed
 */
static int get_metadata_size(const uint8_t *buf, int buf_size)
{
    int metadata_last, metadata_size;
    const uint8_t *buf_end = buf + buf_size;

    buf += 4;
    do {
        if((buf + 4) > buf_end)
            return 0;
        ff_flac_parse_block_header(buf, &metadata_last, NULL, &metadata_size);
        buf += 4;
        if ((buf + metadata_size) > buf_end) {
            /* need more data in order to read the complete header */
            return 0;
        }
        buf += metadata_size;
    } while (!metadata_last);

    return buf_size - (buf_end - buf);
}

static int decode_residuals(FLACContext *s, int32_t *decoded, int pred_order)
{
    int i, tmp, partition, method_type, rice_order;
    int rice_bits, rice_esc;
    int samples;

    method_type = get_bits(&s->gb, 2);
    if (method_type > 1) {
        mpxplay_debugf(MPXPLAY_DEBUG_OUTPUT, "illegal residual coding method %d",method_type);
        return AVERROR_INVALIDDATA;
    }

    rice_order = get_bits(&s->gb, 4);

    samples= s->blocksize >> rice_order;
    if ((samples << rice_order) != s->blocksize) {
         mpxplay_debugf(MPXPLAY_DEBUG_OUTPUT, "invalid rice order: %d blocksize %d", rice_order, s->blocksize);
        return AVERROR_INVALIDDATA;
    }
    if (pred_order > samples) {
        mpxplay_debugf(MPXPLAY_DEBUG_OUTPUT, "invalid predictor order: %i > %i",pred_order, samples);
        return AVERROR_INVALIDDATA;
    }

    rice_bits = 4 + method_type;
    rice_esc  = (1 << rice_bits) - 1;

    decoded += pred_order;
    i= pred_order;
    for (partition = 0; partition < (1 << rice_order); partition++) {
        if(get_bits_left(&s->gb) < rice_bits)
        	return AVERROR_DATA_UNDERRUN;
        tmp = get_bits(&s->gb, rice_bits);
        if (tmp == rice_esc) {
            tmp = get_bits(&s->gb, 5);
            if(get_bits_left(&s->gb) < (tmp * (samples - i)))
            	return AVERROR_DATA_UNDERRUN;
            for (; i < samples; i++)
                *decoded++ = get_sbits_long(&s->gb, tmp);
        } else {
            for (; i < samples; i++) {
            	int retcode = get_sr_golomb_flac(&s->gb, tmp, INT_MAX, 0);
            	if(((retcode == AVERROR_INVALIDDATA) || (retcode == AVERROR_DATA_UNDERRUN))){
            		mpxplay_debugf(MPXPLAY_DEBUG_OUTPUT, "err: %d pt:%d i:%d k:%d po:%d sn:%d bs:%d ro:%d", -retcode, partition, i, tmp, pred_order, samples, s->blocksize, rice_order);
            		if((partition + 1) < (1 << rice_order)) // FIXME: ???
            			return retcode;
            		retcode = (i > 0)? *(decoded - 1) : 0;

            	}
                *decoded++ = retcode;
            }
        }
        i= 0;
    }

    return 0;
}

static int decode_subframe_fixed(FLACContext *s, int32_t *decoded, int pred_order)
{
    const int blocksize = s->blocksize;
    int av_uninit(a), av_uninit(b), av_uninit(c), av_uninit(d), i, retcode;

    if(get_bits_left(&s->gb) < (pred_order*s->curr_bps))
      return AVERROR_DATA_UNDERRUN;

    /* warm up samples */
    for (i = 0; i < pred_order; i++) {
        decoded[i] = get_sbits_long(&s->gb, s->curr_bps);
    }

    if ((retcode = decode_residuals(s, decoded, pred_order)) < 0)
        return retcode;

    if (pred_order > 0)
        a = decoded[pred_order-1];
    if (pred_order > 1)
        b = a - decoded[pred_order-2];
    if (pred_order > 2)
        c = b - decoded[pred_order-2] + decoded[pred_order-3];
    if (pred_order > 3)
        d = c - decoded[pred_order-2] + 2*decoded[pred_order-3] - decoded[pred_order-4];

    switch (pred_order) {
    case 0:
        break;
    case 1:
        for (i = pred_order; i < blocksize; i++)
            decoded[i] = a += decoded[i];
        break;
    case 2:
        for (i = pred_order; i < blocksize; i++)
            decoded[i] = a += b += decoded[i];
        break;
    case 3:
        for (i = pred_order; i < blocksize; i++)
            decoded[i] = a += b += c += decoded[i];
        break;
    case 4:
        for (i = pred_order; i < blocksize; i++)
            decoded[i] = a += b += c += d += decoded[i];
        break;
    default:
        mpxplay_debugf(MPXPLAY_DEBUG_OUTPUT, "illegal pred order %d\n", pred_order);
        return AVERROR_INVALIDDATA;
    }

    return 0;
}

static int decode_subframe_lpc(FLACContext *s, int32_t *decoded, int pred_order)
{
    int i, j;
    int coeff_prec, qlevel, retcode;
    int coeffs[32];

    /* warm up samples */
    for (i = 0; i < pred_order; i++) {
        decoded[i] = get_sbits_long(&s->gb, s->curr_bps);
    }

    coeff_prec = get_bits(&s->gb, 4) + 1;
    if (coeff_prec == 16) {
        mpxplay_debugf(MPXPLAY_DEBUG_OUTPUT, "invalid coeff precision");
        return -1;
    }
    qlevel = get_sbits(&s->gb, 5);
    if (qlevel < 0) {
        mpxplay_debugf(MPXPLAY_DEBUG_OUTPUT, "qlevel %d not supported, maybe buggy stream",qlevel);
        return -1;
    }

    for (i = 0; i < pred_order; i++) {
        coeffs[i] = get_sbits(&s->gb, coeff_prec);
    }

    if ((retcode = decode_residuals(s, decoded, pred_order)) < 0)
        return retcode;

    if (s->bps > 16) {
        int64_t sum;
        for (i = pred_order; i < s->blocksize; i++) {
            sum = 0;
            for (j = 0; j < pred_order; j++)
                sum += (int64_t)coeffs[j] * decoded[i-j-1];
            decoded[i] += sum >> qlevel;
        }
    } else {
        for (i = pred_order; i < s->blocksize-1; i += 2) {
            int c;
            int d = decoded[i-pred_order];
            int s0 = 0, s1 = 0;
            for (j = pred_order-1; j > 0; j--) {
                c = coeffs[j];
                s0 += c*d;
                d = decoded[i-j];
                s1 += c*d;
            }
            c = coeffs[0];
            s0 += c*d;
            d = decoded[i] += s0 >> qlevel;
            s1 += c*d;
            decoded[i+1] += s1 >> qlevel;
        }
        if (i < s->blocksize) {
            int sum = 0;
            for (j = 0; j < pred_order; j++)
                sum += coeffs[j] * decoded[i-j-1];
            decoded[i] += sum >> qlevel;
        }
    }

    return 0;
}

static inline int decode_subframe(FLACContext *s, int channel)
{
    int32_t *decoded = s->decoded[channel];
    int type, wasted = 0;
    int left = get_bits_left(&s->gb);
    int i, tmp, retcode = 0;

    if(left<8){
     mpxplay_debugf(MPXPLAY_DEBUG_OUTPUT, "decode_subframe left<8 error ch:%d", channel);
     return AVERROR_DATA_UNDERRUN;
    }

    s->curr_bps = s->bps;
    if (channel == 0) {
        if (s->ch_mode == FLAC_CHMODE_RIGHT_SIDE)
            s->curr_bps++;
    } else {
        if (s->ch_mode == FLAC_CHMODE_LEFT_SIDE || s->ch_mode == FLAC_CHMODE_MID_SIDE)
            s->curr_bps++;
    }

    if (get_bits1(&s->gb)) {
        mpxplay_debugf(MPXPLAY_DEBUG_OUTPUT, "invalid subframe padding");
        return AVERROR_INVALIDDATA;
    }
    type = get_bits(&s->gb, 6);

    left-=8;
    if(get_bits1(&s->gb)) {
        wasted = 1;
        if( (left <= 0) ||
            (left < s->curr_bps && !show_bits_long(&s->gb, left)) ||
                                   !show_bits_long(&s->gb, s->curr_bps)) {
            mpxplay_debugf(MPXPLAY_DEBUG_OUTPUT,"Invalid number of wasted bits > available bits (%d) - left=%d\n",s->curr_bps, left);
            return AVERROR_INVALIDDATA;
        }
        while(((left--)>0) && !get_bits1(&s->gb))
            wasted++;

        if(wasted>=s->curr_bps){
         mpxplay_debugf(MPXPLAY_DEBUG_OUTPUT, "decode_subframe wasted>=s->curr_bps failure");
         return AVERROR_INVALIDDATA;
        }
        s->curr_bps -= wasted;
    }
    if(s->curr_bps > 32) {
        mpxplay_debugf(MPXPLAY_DEBUG_OUTPUT, "decorrelated bit depth > 32");
        //av_log_missing_feature(s->avctx, "decorrelated bit depth > 32", 0);
        return AVERROR_INVALIDDATA;
    }

//FIXME use av_log2 for types
    if (type == 0) {
        if(left<s->curr_bps){
        	mpxplay_debugf(MPXPLAY_DEBUG_OUTPUT, "type == 0 failed");
        	return AVERROR_DATA_UNDERRUN;
        }
        tmp = get_sbits_long(&s->gb, s->curr_bps);
        for (i = 0; i < s->blocksize; i++)
            decoded[i] = tmp;
    } else if (type == 1) {
        if(left<(s->blocksize*s->curr_bps)){
        	mpxplay_debugf(MPXPLAY_DEBUG_OUTPUT, "type == 1 failed");
        	return AVERROR_DATA_UNDERRUN;
        }
        for (i = 0; i < s->blocksize; i++)
            decoded[i] = get_sbits_long(&s->gb, s->curr_bps);
    } else if ((type >= 8) && (type <= 12)) {
        if ((retcode = decode_subframe_fixed(s, decoded, type & ~0x8)) < 0){
        	mpxplay_debugf(MPXPLAY_DEBUG_OUTPUT, "decode_subframe_fixed failed");
            return retcode;
        }
    } else if (type >= 32) {
        if ((retcode = decode_subframe_lpc(s, decoded, (type & ~0x20)+1)) < 0){
        	mpxplay_debugf(MPXPLAY_DEBUG_OUTPUT, "decode_subframe_lpc failed");
            return retcode;
        }
    } else {
        mpxplay_debugf(MPXPLAY_DEBUG_OUTPUT, "invalid coding type");
        return AVERROR_INVALIDDATA;
    }

    if (wasted) {
        int i;
        for (i = 0; i < s->blocksize; i++)
            decoded[i] <<= wasted;
    }

    return retcode;
}

/**
 * Validate and decode a frame header.
 * @param      avctx AVCodecContext to use as av_log() context
 * @param      gb    GetBitContext from which to read frame header
 * @param[out] fi    frame information
 * @return non-zero on error, 0 if ok
 */
static int decode_frame_header(AVCodecContext *avctx, GetBitContext *gb,
                               FLACFrameInfo *fi)
{
    int bs_code, sr_code, bps_code;

    /* frame sync code */
    skip_bits(gb, 16);

    /* block size and sample rate codes */
    bs_code = get_bits(gb, 4);
    sr_code = get_bits(gb, 4);

    /* channels and decorrelation */
    fi->ch_mode = get_bits(gb, 4);
    if (fi->ch_mode < FLAC_MAX_CHANNELS) {
        fi->channels = fi->ch_mode + 1;
        fi->ch_mode = FLAC_CHMODE_INDEPENDENT;
    } else if (fi->ch_mode <= FLAC_CHMODE_MID_SIDE) {
        fi->channels = 2;
    } else {
        mpxplay_debugf(MPXPLAY_DEBUG_OUTPUT, "invalid channel mode: %d", fi->ch_mode);
        return -1;
    }

    /* bits per sample */
    bps_code = get_bits(gb, 3);
    if (bps_code == 3 || bps_code == 7) {
        mpxplay_debugf(MPXPLAY_DEBUG_OUTPUT, "invalid sample size code (%d)",bps_code);
        return -1;
    }
    fi->bps = sample_size_table[bps_code];

    /* reserved bit */
    if (get_bits1(gb)) {
        mpxplay_debugf(MPXPLAY_DEBUG_OUTPUT, "broken stream, invalid padding");
        return -1;
    }

    /* sample or frame count */
    if (get_utf8(gb) < 0) {
        mpxplay_debugf(MPXPLAY_DEBUG_OUTPUT, "utf8 fscked");
        return -1;
    }

    /* blocksize */
    if (bs_code == 0) {
        mpxplay_debugf(MPXPLAY_DEBUG_OUTPUT, "reserved blocksize code: 0");
        return -1;
    } else if (bs_code == 6) {
        fi->blocksize = get_bits(gb, 8) + 1;
    } else if (bs_code == 7) {
        fi->blocksize = get_bits(gb, 16) + 1;
    } else {
        fi->blocksize = mpxplay_ff_flac_blocksize_table[bs_code];
    }

    /* sample rate */
    if (sr_code < 12) {
        fi->samplerate = mpxplay_ff_flac_sample_rate_table[sr_code];
    } else if (sr_code == 12) {
        fi->samplerate = get_bits(gb, 8) * 1000;
    } else if (sr_code == 13) {
        fi->samplerate = get_bits(gb, 16);
    } else if (sr_code == 14) {
        fi->samplerate = get_bits(gb, 16) * 10;
    } else {
        mpxplay_debugf(MPXPLAY_DEBUG_OUTPUT, "illegal sample rate code %d",sr_code);
        return -1;
    }

    /* header CRC-8 check */
    skip_bits(gb, 8);
    if (mpxplay_av_crc(mpxplay_av_crc_get_table(AV_CRC_8_ATM), 0, gb->buffer, get_bits_count(gb)/8)) {
        mpxplay_debugf(MPXPLAY_DEBUG_OUTPUT, "header crc mismatch");
        return -1;
    }

    return 0;
}

static int decode_frame(FLACContext *s)
{
    int i;
    GetBitContext *gb = &s->gb;
    FLACFrameInfo fi;

    if (decode_frame_header(s->avctx, gb, &fi)<0) {
        mpxplay_debugf(MPXPLAY_DEBUG_OUTPUT, "invalid frame header");
        return -1;
    }

    if (fi.channels != s->channels) {
        mpxplay_debugf(MPXPLAY_DEBUG_OUTPUT, "switching channel layout mid-stream is not supported");
        return -1;
    }
    s->ch_mode = fi.ch_mode;

    if (fi.bps && fi.bps != s->bps) {
        mpxplay_debugf(MPXPLAY_DEBUG_OUTPUT, "switching bps mid-stream is not supported");
        return -1;
    }
    if (s->bps > 16) {
        s->avctx->sample_fmt = SAMPLE_FMT_S32;
        s->sample_shift = 32 - s->bps;
        s->is32 = 1;
    } else {
        s->avctx->sample_fmt = SAMPLE_FMT_S16;
        s->sample_shift = 16 - s->bps;
        s->is32 = 0;
    }

    if (fi.blocksize > s->max_blocksize) {
        mpxplay_debugf(MPXPLAY_DEBUG_OUTPUT, "blocksize %d > %d", fi.blocksize, s->max_blocksize);
        return -1;
    }
    s->blocksize = fi.blocksize;

    if (fi.samplerate == 0) {
        fi.samplerate = s->samplerate;
    } else if (fi.samplerate != s->samplerate) {
        mpxplay_debugf(MPXPLAY_DEBUG_OUTPUT, "sample rate changed from %d to %d",s->samplerate, fi.samplerate);
    }
    s->samplerate = s->avctx->sample_rate = fi.samplerate;

//    dump_headers(s->avctx, (FLACStreaminfo *)s);

    // subframes
    for (i = 0; i < s->channels; i++) {
    	int retcode = decode_subframe(s, i);
    	if(retcode < 0)
            return retcode;
    }

    align_get_bits(gb);

    // frame footer
    skip_bits(gb, 16); /* data crc */

    return 0;
}

static int flac_decode_frame(AVCodecContext *avctx,
                            void *data, int *data_size,
                            uint8_t *buf,int buf_size)
{
    FLACContext *s = avctx->priv_data;
    int i, j = 0, bytes_read = 0;
    int16_t *samples_16 = data;
    int32_t *samples_32 = data;
    int alloc_data_size= *data_size;
    int output_size, retcode;

    *data_size=0;

    /* check that there is at least the smallest decodable amount of data.
     this amount corresponds to the smallest valid FLAC frame possible.
     FF F8 69 02 00 00 9A 00 00 34 46 */
    if (buf_size < FLAC_MIN_FRAME_SIZE){
        mpxplay_debugf(MPXPLAY_DEBUG_OUTPUT, "invalid buf_size: %d",buf_size);
        goto end;
    }

    if (s->max_framesize == 0)
        s->max_framesize = ff_flac_get_max_frame_size(s->max_blocksize ? s->max_blocksize : FLAC_MAX_BLOCKSIZE, FLAC_MAX_CHANNELS, 32);

    if (buf_size > 5 && !memcmp(buf, "\177FLAC", 5)) {
        mpxplay_debugf(MPXPLAY_DEBUG_OUTPUT, "skipping flac header packet 1\n");
        return buf_size;
    }

    if (buf_size > 0 && (*buf & 0x7F) == FLAC_METADATA_TYPE_VORBIS_COMMENT) {
        mpxplay_debugf(MPXPLAY_DEBUG_OUTPUT, "skipping vorbis comment\n");
        return buf_size;
    }
 
    // check for inline header
    if (AV_RB32(buf) == MKBETAG('f','L','a','C')) {
        if (!s->got_streaminfo){
            int retval = parse_streaminfo(s, buf, buf_size);
            if(retval == 0) // not enough data
             goto end;
            if(retval < 0){
             mpxplay_debugf(MPXPLAY_DEBUG_OUTPUT, "invalid header");
             return retval;
            }
        }
        bytes_read = get_metadata_size(buf, buf_size);
        if(!bytes_read){ // running out of bs buffer (too large metadata)
         bytes_read = buf_size;
         mpxplay_debugf(MPXPLAY_DEBUG_OUTPUT, "FLAC: %d %d",buf_size,bytes_read);
        }
        goto end;
    }

    // check for frame sync code and resync stream if necessary
    if ((AV_RB16(buf) & 0xFFFE) != 0xFFF8) {
        const uint8_t *buf_end = buf + buf_size;
        while(((buf+2)<buf_end) && ((AV_RB16(buf)&0xFFFE)!=0xFFF8))
            buf++;
        bytes_read = buf_size - (buf_end - buf);
        //mpxplay_debugf(MPXPLAY_DEBUG_OUTPUT, "FRAME HEADER not here br:%d bs:%d",bytes_read,buf_size);
        if(bytes_read+2<buf_size){
         mpxplay_debugf(MPXPLAY_DEBUG_OUTPUT,"fh %8.8X %8.8X %8.8X",
          *((uint32_t *)buf),*((uint32_t *)(buf+4)),*((uint32_t *)(buf+8)));
        }
        goto end; // we may not have enough bits left to decode a frame, so try next time
    }

    // decode frame
    init_get_bits(&s->gb, buf, buf_size*8);
    retcode = decode_frame(s);
    if(retcode < 0) {
        mpxplay_debugf(MPXPLAY_DEBUG_OUTPUT, "decode_frame() failed %8.8X bs:%d max:%d", retcode, buf_size, s->max_blocksize);
        if(retcode == AVERROR_DATA_UNDERRUN)
         goto end;
        return -1;
    }
    bytes_read = (get_bits_count(&s->gb)+7)/8;
    if(bytes_read>buf_size)
     goto end;

    /*mpxplay_debugf(MPXPLAY_DEBUG_OUTPUT,"de %8.8X %8.8X %8.8X  %8.8X br:%d bs:%d",
          *((uint32_t *)buf),*((uint32_t *)(buf+4)),*((uint32_t *)(buf+8)),
          *((uint32_t *)(buf+buf_size-bytes_read)),bytes_read,buf_size );*/

    // check if allocated data size is large enough for output
    output_size = s->blocksize * s->channels * (s->is32 ? 4 : 2);
    if (output_size > alloc_data_size) {
        mpxplay_debugf(MPXPLAY_DEBUG_OUTPUT, "output data size is larger than allocated data size");
        goto end;
    }
    *data_size = output_size;

#define DECORRELATE(left, right)\
            for (i = 0; i < s->blocksize; i++) {\
                int a= s->decoded[0][i];\
                int b= s->decoded[1][i];\
                if (s->is32) {\
                    *samples_32++ = (left)  << s->sample_shift;\
                    *samples_32++ = (right) << s->sample_shift;\
                } else {\
                    *samples_16++ = (left)  << s->sample_shift;\
                    *samples_16++ = (right) << s->sample_shift;\
                }\
            }\
            break;

    switch (s->ch_mode) {
     case FLAC_CHMODE_INDEPENDENT:
        for (j = 0; j < s->blocksize; j++) {
            for (i = 0; i < s->channels; i++) {
                if (s->is32)
                    *samples_32++ = s->decoded[i][j] << s->sample_shift;
                else
                    *samples_16++ = s->decoded[i][j] << s->sample_shift;
            }
        }
        break;
     case FLAC_CHMODE_LEFT_SIDE:
        DECORRELATE(a,(a-b))
     case FLAC_CHMODE_RIGHT_SIDE:
        DECORRELATE((a+b),b)
     case FLAC_CHMODE_MID_SIDE:
        DECORRELATE( ((a-=b>>1) + b), a)
    }

end:
    if (bytes_read > buf_size) {
        mpxplay_debugf(MPXPLAY_DEBUG_OUTPUT, "overread: %d (%d)", bytes_read - buf_size, buf_size);
        bytes_read = buf_size;
    }

    //mpxplay_debugf(MPXPLAY_DEBUG_OUTPUT, "bytes_read: %d",bytes_read);
    return bytes_read;
}

static av_cold int flac_decode_close(AVCodecContext *avctx)
{
    FLACContext *s = avctx->priv_data;
    int i;

    for (i = 0; i < s->channels; i++) {
        mpxplay_av_freep(&s->decoded[i]);
    }

    return 0;
}

static void flac_flush(AVCodecContext *avctx,unsigned int fullclear)
{
 FLACContext *s = avctx->priv_data;
 int i;

 if(s->allocated_decoded_size)
  for(i=0; i<s->channels; i++)
   if(s->decoded[i])
    memset(s->decoded[i],0,s->allocated_decoded_size*sizeof(int32_t));
}

AVCodec mpxplay_flac_decoder = {
    "flac",
    CODEC_TYPE_AUDIO,
    CODEC_ID_FLAC,
    sizeof(FLACContext),
    flac_decode_init,
    NULL,
    flac_decode_close,
    flac_decode_frame,
    CODEC_CAP_DELAY | CODEC_CAP_SUBFRAMES, // FIXME: add a FLAC parser so that we will not need to use either of these capabilities
    .flush=flac_flush,
    //.long_name= NULL_IF_CONFIG_SMALL("FLAC (Free Lossless Audio Codec)"),
};
