зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1270016: P1. Add FLAC support to our ffmpeg extract. r=kentuckyfriedtakahe
Code was extracted from FFmpeg 3.1. MozReview-Commit-ID: FgySRWoGMB5 --HG-- extra : rebase_source : cf15573de36faa3e286b1886062d9a7222c534e7
This commit is contained in:
Родитель
682eddd902
Коммит
58c41caa45
|
@ -576,11 +576,11 @@
|
|||
#define CONFIG_FAANDCT 0
|
||||
#define CONFIG_FAANIDCT 0
|
||||
#define CONFIG_FDCTDSP 0
|
||||
#define CONFIG_FLACDSP 0
|
||||
#define CONFIG_FLACDSP 1
|
||||
#define CONFIG_FMTCONVERT 0
|
||||
#define CONFIG_FRAME_THREAD_ENCODER 0
|
||||
#define CONFIG_G722DSP 0
|
||||
#define CONFIG_GOLOMB 0
|
||||
#define CONFIG_GOLOMB 1
|
||||
#define CONFIG_GPLV3 0
|
||||
#define CONFIG_H263DSP 0
|
||||
#define CONFIG_H264CHROMA 0
|
||||
|
@ -922,7 +922,7 @@
|
|||
#define CONFIG_EAC3_DECODER 0
|
||||
#define CONFIG_EVRC_DECODER 0
|
||||
#define CONFIG_FFWAVESYNTH_DECODER 0
|
||||
#define CONFIG_FLAC_DECODER 0
|
||||
#define CONFIG_FLAC_DECODER 1
|
||||
#define CONFIG_G723_1_DECODER 0
|
||||
#define CONFIG_G729_DECODER 0
|
||||
#define CONFIG_GSM_DECODER 0
|
||||
|
@ -2104,7 +2104,7 @@
|
|||
#define CONFIG_DVBSUB_PARSER 0
|
||||
#define CONFIG_DVDSUB_PARSER 0
|
||||
#define CONFIG_DVD_NAV_PARSER 0
|
||||
#define CONFIG_FLAC_PARSER 0
|
||||
#define CONFIG_FLAC_PARSER 1
|
||||
#define CONFIG_G729_PARSER 0
|
||||
#define CONFIG_GSM_PARSER 0
|
||||
#define CONFIG_H261_PARSER 0
|
||||
|
|
|
@ -561,11 +561,11 @@
|
|||
%define CONFIG_FAANDCT 0
|
||||
%define CONFIG_FAANIDCT 0
|
||||
%define CONFIG_FDCTDSP 0
|
||||
%define CONFIG_FLACDSP 0
|
||||
%define CONFIG_FLACDSP 1
|
||||
%define CONFIG_FMTCONVERT 0
|
||||
%define CONFIG_FRAME_THREAD_ENCODER 0
|
||||
%define CONFIG_G722DSP 0
|
||||
%define CONFIG_GOLOMB 0
|
||||
%define CONFIG_GOLOMB 1
|
||||
%define CONFIG_GPLV3 0
|
||||
%define CONFIG_H263DSP 0
|
||||
%define CONFIG_H264CHROMA 0
|
||||
|
@ -907,7 +907,7 @@
|
|||
%define CONFIG_EAC3_DECODER 0
|
||||
%define CONFIG_EVRC_DECODER 0
|
||||
%define CONFIG_FFWAVESYNTH_DECODER 0
|
||||
%define CONFIG_FLAC_DECODER 0
|
||||
%define CONFIG_FLAC_DECODER 1
|
||||
%define CONFIG_G723_1_DECODER 0
|
||||
%define CONFIG_G729_DECODER 0
|
||||
%define CONFIG_GSM_DECODER 0
|
||||
|
@ -2089,7 +2089,7 @@
|
|||
%define CONFIG_DVBSUB_PARSER 0
|
||||
%define CONFIG_DVDSUB_PARSER 0
|
||||
%define CONFIG_DVD_NAV_PARSER 0
|
||||
%define CONFIG_FLAC_PARSER 0
|
||||
%define CONFIG_FLAC_PARSER 1
|
||||
%define CONFIG_G729_PARSER 0
|
||||
%define CONFIG_GSM_PARSER 0
|
||||
%define CONFIG_H261_PARSER 0
|
||||
|
|
|
@ -576,11 +576,11 @@
|
|||
#define CONFIG_FAANDCT 0
|
||||
#define CONFIG_FAANIDCT 0
|
||||
#define CONFIG_FDCTDSP 0
|
||||
#define CONFIG_FLACDSP 0
|
||||
#define CONFIG_FLACDSP 1
|
||||
#define CONFIG_FMTCONVERT 0
|
||||
#define CONFIG_FRAME_THREAD_ENCODER 0
|
||||
#define CONFIG_G722DSP 0
|
||||
#define CONFIG_GOLOMB 0
|
||||
#define CONFIG_GOLOMB 1
|
||||
#define CONFIG_GPLV3 0
|
||||
#define CONFIG_H263DSP 0
|
||||
#define CONFIG_H264CHROMA 0
|
||||
|
@ -922,7 +922,7 @@
|
|||
#define CONFIG_EAC3_DECODER 0
|
||||
#define CONFIG_EVRC_DECODER 0
|
||||
#define CONFIG_FFWAVESYNTH_DECODER 0
|
||||
#define CONFIG_FLAC_DECODER 0
|
||||
#define CONFIG_FLAC_DECODER 1
|
||||
#define CONFIG_G723_1_DECODER 0
|
||||
#define CONFIG_G729_DECODER 0
|
||||
#define CONFIG_GSM_DECODER 0
|
||||
|
@ -2104,7 +2104,7 @@
|
|||
#define CONFIG_DVBSUB_PARSER 0
|
||||
#define CONFIG_DVDSUB_PARSER 0
|
||||
#define CONFIG_DVD_NAV_PARSER 0
|
||||
#define CONFIG_FLAC_PARSER 0
|
||||
#define CONFIG_FLAC_PARSER 1
|
||||
#define CONFIG_G729_PARSER 0
|
||||
#define CONFIG_GSM_PARSER 0
|
||||
#define CONFIG_H261_PARSER 0
|
||||
|
|
|
@ -575,11 +575,11 @@
|
|||
#define CONFIG_FAANDCT 0
|
||||
#define CONFIG_FAANIDCT 0
|
||||
#define CONFIG_FDCTDSP 0
|
||||
#define CONFIG_FLACDSP 0
|
||||
#define CONFIG_FLACDSP 1
|
||||
#define CONFIG_FMTCONVERT 0
|
||||
#define CONFIG_FRAME_THREAD_ENCODER 0
|
||||
#define CONFIG_G722DSP 0
|
||||
#define CONFIG_GOLOMB 0
|
||||
#define CONFIG_GOLOMB 1
|
||||
#define CONFIG_GPLV3 0
|
||||
#define CONFIG_H263DSP 0
|
||||
#define CONFIG_H264CHROMA 0
|
||||
|
@ -921,7 +921,7 @@
|
|||
#define CONFIG_EAC3_DECODER 0
|
||||
#define CONFIG_EVRC_DECODER 0
|
||||
#define CONFIG_FFWAVESYNTH_DECODER 0
|
||||
#define CONFIG_FLAC_DECODER 0
|
||||
#define CONFIG_FLAC_DECODER 1
|
||||
#define CONFIG_G723_1_DECODER 0
|
||||
#define CONFIG_G729_DECODER 0
|
||||
#define CONFIG_GSM_DECODER 0
|
||||
|
@ -2103,7 +2103,7 @@
|
|||
#define CONFIG_DVBSUB_PARSER 0
|
||||
#define CONFIG_DVDSUB_PARSER 0
|
||||
#define CONFIG_DVD_NAV_PARSER 0
|
||||
#define CONFIG_FLAC_PARSER 0
|
||||
#define CONFIG_FLAC_PARSER 1
|
||||
#define CONFIG_G729_PARSER 0
|
||||
#define CONFIG_GSM_PARSER 0
|
||||
#define CONFIG_H261_PARSER 0
|
||||
|
|
|
@ -561,11 +561,11 @@
|
|||
%define CONFIG_FAANDCT 0
|
||||
%define CONFIG_FAANIDCT 0
|
||||
%define CONFIG_FDCTDSP 0
|
||||
%define CONFIG_FLACDSP 0
|
||||
%define CONFIG_FLACDSP 1
|
||||
%define CONFIG_FMTCONVERT 0
|
||||
%define CONFIG_FRAME_THREAD_ENCODER 0
|
||||
%define CONFIG_G722DSP 0
|
||||
%define CONFIG_GOLOMB 0
|
||||
%define CONFIG_GOLOMB 1
|
||||
%define CONFIG_GPLV3 0
|
||||
%define CONFIG_H263DSP 0
|
||||
%define CONFIG_H264CHROMA 0
|
||||
|
@ -907,7 +907,7 @@
|
|||
%define CONFIG_EAC3_DECODER 0
|
||||
%define CONFIG_EVRC_DECODER 0
|
||||
%define CONFIG_FFWAVESYNTH_DECODER 0
|
||||
%define CONFIG_FLAC_DECODER 0
|
||||
%define CONFIG_FLAC_DECODER 1
|
||||
%define CONFIG_G723_1_DECODER 0
|
||||
%define CONFIG_G729_DECODER 0
|
||||
%define CONFIG_GSM_DECODER 0
|
||||
|
@ -2089,7 +2089,7 @@
|
|||
%define CONFIG_DVBSUB_PARSER 0
|
||||
%define CONFIG_DVDSUB_PARSER 0
|
||||
%define CONFIG_DVD_NAV_PARSER 0
|
||||
%define CONFIG_FLAC_PARSER 0
|
||||
%define CONFIG_FLAC_PARSER 1
|
||||
%define CONFIG_G729_PARSER 0
|
||||
%define CONFIG_GSM_PARSER 0
|
||||
%define CONFIG_H261_PARSER 0
|
||||
|
|
|
@ -576,11 +576,11 @@
|
|||
#define CONFIG_FAANDCT 0
|
||||
#define CONFIG_FAANIDCT 0
|
||||
#define CONFIG_FDCTDSP 0
|
||||
#define CONFIG_FLACDSP 0
|
||||
#define CONFIG_FLACDSP 1
|
||||
#define CONFIG_FMTCONVERT 0
|
||||
#define CONFIG_FRAME_THREAD_ENCODER 0
|
||||
#define CONFIG_G722DSP 0
|
||||
#define CONFIG_GOLOMB 0
|
||||
#define CONFIG_GOLOMB 1
|
||||
#define CONFIG_GPLV3 0
|
||||
#define CONFIG_H263DSP 0
|
||||
#define CONFIG_H264CHROMA 0
|
||||
|
@ -922,7 +922,7 @@
|
|||
#define CONFIG_EAC3_DECODER 0
|
||||
#define CONFIG_EVRC_DECODER 0
|
||||
#define CONFIG_FFWAVESYNTH_DECODER 0
|
||||
#define CONFIG_FLAC_DECODER 0
|
||||
#define CONFIG_FLAC_DECODER 1
|
||||
#define CONFIG_G723_1_DECODER 0
|
||||
#define CONFIG_G729_DECODER 0
|
||||
#define CONFIG_GSM_DECODER 0
|
||||
|
@ -2104,7 +2104,7 @@
|
|||
#define CONFIG_DVBSUB_PARSER 0
|
||||
#define CONFIG_DVDSUB_PARSER 0
|
||||
#define CONFIG_DVD_NAV_PARSER 0
|
||||
#define CONFIG_FLAC_PARSER 0
|
||||
#define CONFIG_FLAC_PARSER 1
|
||||
#define CONFIG_G729_PARSER 0
|
||||
#define CONFIG_GSM_PARSER 0
|
||||
#define CONFIG_H261_PARSER 0
|
||||
|
|
|
@ -561,11 +561,11 @@
|
|||
%define CONFIG_FAANDCT 0
|
||||
%define CONFIG_FAANIDCT 0
|
||||
%define CONFIG_FDCTDSP 0
|
||||
%define CONFIG_FLACDSP 0
|
||||
%define CONFIG_FLACDSP 1
|
||||
%define CONFIG_FMTCONVERT 0
|
||||
%define CONFIG_FRAME_THREAD_ENCODER 0
|
||||
%define CONFIG_G722DSP 0
|
||||
%define CONFIG_GOLOMB 0
|
||||
%define CONFIG_GOLOMB 1
|
||||
%define CONFIG_GPLV3 0
|
||||
%define CONFIG_H263DSP 0
|
||||
%define CONFIG_H264CHROMA 0
|
||||
|
@ -907,7 +907,7 @@
|
|||
%define CONFIG_EAC3_DECODER 0
|
||||
%define CONFIG_EVRC_DECODER 0
|
||||
%define CONFIG_FFWAVESYNTH_DECODER 0
|
||||
%define CONFIG_FLAC_DECODER 0
|
||||
%define CONFIG_FLAC_DECODER 1
|
||||
%define CONFIG_G723_1_DECODER 0
|
||||
%define CONFIG_G729_DECODER 0
|
||||
%define CONFIG_GSM_DECODER 0
|
||||
|
@ -2089,7 +2089,7 @@
|
|||
%define CONFIG_DVBSUB_PARSER 0
|
||||
%define CONFIG_DVDSUB_PARSER 0
|
||||
%define CONFIG_DVD_NAV_PARSER 0
|
||||
%define CONFIG_FLAC_PARSER 0
|
||||
%define CONFIG_FLAC_PARSER 1
|
||||
%define CONFIG_G729_PARSER 0
|
||||
%define CONFIG_GSM_PARSER 0
|
||||
%define CONFIG_H261_PARSER 0
|
||||
|
|
|
@ -576,11 +576,11 @@
|
|||
#define CONFIG_FAANDCT 0
|
||||
#define CONFIG_FAANIDCT 0
|
||||
#define CONFIG_FDCTDSP 0
|
||||
#define CONFIG_FLACDSP 0
|
||||
#define CONFIG_FLACDSP 1
|
||||
#define CONFIG_FMTCONVERT 0
|
||||
#define CONFIG_FRAME_THREAD_ENCODER 0
|
||||
#define CONFIG_G722DSP 0
|
||||
#define CONFIG_GOLOMB 0
|
||||
#define CONFIG_GOLOMB 1
|
||||
#define CONFIG_GPLV3 0
|
||||
#define CONFIG_H263DSP 0
|
||||
#define CONFIG_H264CHROMA 0
|
||||
|
@ -922,7 +922,7 @@
|
|||
#define CONFIG_EAC3_DECODER 0
|
||||
#define CONFIG_EVRC_DECODER 0
|
||||
#define CONFIG_FFWAVESYNTH_DECODER 0
|
||||
#define CONFIG_FLAC_DECODER 0
|
||||
#define CONFIG_FLAC_DECODER 1
|
||||
#define CONFIG_G723_1_DECODER 0
|
||||
#define CONFIG_G729_DECODER 0
|
||||
#define CONFIG_GSM_DECODER 0
|
||||
|
@ -2104,7 +2104,7 @@
|
|||
#define CONFIG_DVBSUB_PARSER 0
|
||||
#define CONFIG_DVDSUB_PARSER 0
|
||||
#define CONFIG_DVD_NAV_PARSER 0
|
||||
#define CONFIG_FLAC_PARSER 0
|
||||
#define CONFIG_FLAC_PARSER 1
|
||||
#define CONFIG_G729_PARSER 0
|
||||
#define CONFIG_GSM_PARSER 0
|
||||
#define CONFIG_H261_PARSER 0
|
||||
|
|
|
@ -561,11 +561,11 @@
|
|||
%define CONFIG_FAANDCT 0
|
||||
%define CONFIG_FAANIDCT 0
|
||||
%define CONFIG_FDCTDSP 0
|
||||
%define CONFIG_FLACDSP 0
|
||||
%define CONFIG_FLACDSP 1
|
||||
%define CONFIG_FMTCONVERT 0
|
||||
%define CONFIG_FRAME_THREAD_ENCODER 0
|
||||
%define CONFIG_G722DSP 0
|
||||
%define CONFIG_GOLOMB 0
|
||||
%define CONFIG_GOLOMB 1
|
||||
%define CONFIG_GPLV3 0
|
||||
%define CONFIG_H263DSP 0
|
||||
%define CONFIG_H264CHROMA 0
|
||||
|
@ -907,7 +907,7 @@
|
|||
%define CONFIG_EAC3_DECODER 0
|
||||
%define CONFIG_EVRC_DECODER 0
|
||||
%define CONFIG_FFWAVESYNTH_DECODER 0
|
||||
%define CONFIG_FLAC_DECODER 0
|
||||
%define CONFIG_FLAC_DECODER 1
|
||||
%define CONFIG_G723_1_DECODER 0
|
||||
%define CONFIG_G729_DECODER 0
|
||||
%define CONFIG_GSM_DECODER 0
|
||||
|
@ -2089,7 +2089,7 @@
|
|||
%define CONFIG_DVBSUB_PARSER 0
|
||||
%define CONFIG_DVDSUB_PARSER 0
|
||||
%define CONFIG_DVD_NAV_PARSER 0
|
||||
%define CONFIG_FLAC_PARSER 0
|
||||
%define CONFIG_FLAC_PARSER 1
|
||||
%define CONFIG_G729_PARSER 0
|
||||
%define CONFIG_GSM_PARSER 0
|
||||
%define CONFIG_H261_PARSER 0
|
||||
|
|
|
@ -576,11 +576,11 @@
|
|||
#define CONFIG_FAANDCT 0
|
||||
#define CONFIG_FAANIDCT 0
|
||||
#define CONFIG_FDCTDSP 0
|
||||
#define CONFIG_FLACDSP 0
|
||||
#define CONFIG_FLACDSP 1
|
||||
#define CONFIG_FMTCONVERT 0
|
||||
#define CONFIG_FRAME_THREAD_ENCODER 0
|
||||
#define CONFIG_G722DSP 0
|
||||
#define CONFIG_GOLOMB 0
|
||||
#define CONFIG_GOLOMB 1
|
||||
#define CONFIG_GPLV3 0
|
||||
#define CONFIG_H263DSP 0
|
||||
#define CONFIG_H264CHROMA 0
|
||||
|
@ -922,7 +922,7 @@
|
|||
#define CONFIG_EAC3_DECODER 0
|
||||
#define CONFIG_EVRC_DECODER 0
|
||||
#define CONFIG_FFWAVESYNTH_DECODER 0
|
||||
#define CONFIG_FLAC_DECODER 0
|
||||
#define CONFIG_FLAC_DECODER 1
|
||||
#define CONFIG_G723_1_DECODER 0
|
||||
#define CONFIG_G729_DECODER 0
|
||||
#define CONFIG_GSM_DECODER 0
|
||||
|
@ -2104,7 +2104,7 @@
|
|||
#define CONFIG_DVBSUB_PARSER 0
|
||||
#define CONFIG_DVDSUB_PARSER 0
|
||||
#define CONFIG_DVD_NAV_PARSER 0
|
||||
#define CONFIG_FLAC_PARSER 0
|
||||
#define CONFIG_FLAC_PARSER 1
|
||||
#define CONFIG_G729_PARSER 0
|
||||
#define CONFIG_GSM_PARSER 0
|
||||
#define CONFIG_H261_PARSER 0
|
||||
|
|
|
@ -10,6 +10,7 @@ typedef struct H264PredContext H264PredContext;
|
|||
typedef struct VideoDSPContext VideoDSPContext;
|
||||
typedef struct VP8DSPContext VP8DSPContext;
|
||||
typedef struct VP9DSPContext VP9DSPContext;
|
||||
typedef struct FLACDSPContext FLACDSPContext;
|
||||
|
||||
AVHWAccel ff_h263_vaapi_hwaccel;
|
||||
AVHWAccel ff_h263_vdpau_hwaccel;
|
||||
|
@ -400,7 +401,6 @@ AVCodec ff_eac3_decoder;
|
|||
AVCodec ff_evrc_decoder;
|
||||
AVCodec ff_ffwavesynth_decoder;
|
||||
AVCodec ff_flac_encoder;
|
||||
AVCodec ff_flac_decoder;
|
||||
AVCodec ff_g723_1_encoder;
|
||||
AVCodec ff_g723_1_decoder;
|
||||
AVCodec ff_g729_decoder;
|
||||
|
@ -729,7 +729,6 @@ AVCodecParser ff_dvaudio_parser;
|
|||
AVCodecParser ff_dvbsub_parser;
|
||||
AVCodecParser ff_dvdsub_parser;
|
||||
AVCodecParser ff_dvd_nav_parser;
|
||||
AVCodecParser ff_flac_parser;
|
||||
AVCodecParser ff_g729_parser;
|
||||
AVCodecParser ff_gsm_parser;
|
||||
AVCodecParser ff_h261_parser;
|
||||
|
@ -785,7 +784,13 @@ void ff_vp78dsp_init_ppc(VP8DSPContext *c) {}
|
|||
void ff_vp8dsp_init_arm(VP8DSPContext *c) {}
|
||||
void ff_vp8dsp_init_mips(VP8DSPContext *c) {}
|
||||
void ff_vp9dsp_init_mips(VP9DSPContext *dsp, int bpp) {}
|
||||
|
||||
void ff_flacdsp_init_arm(FLACDSPContext *c, enum AVSampleFormat fmt, int channels, int bps) {}
|
||||
#if !defined(HAVE_64BIT_BUILD)
|
||||
void ff_flac_decorrelate_indep8_16_sse2(uint8_t **out, int32_t **in, int channels, int len, int shift) {}
|
||||
void ff_flac_decorrelate_indep8_32_avx(uint8_t **out, int32_t **in, int channels, int len, int shift) {}
|
||||
void ff_flac_decorrelate_indep8_16_avx(uint8_t **out, int32_t **in, int channels, int len, int shift) {}
|
||||
void ff_flac_decorrelate_indep8_32_sse2(uint8_t **out, int32_t **in, int channels, int len, int shift) {}
|
||||
#endif
|
||||
void av_bitstream_filter_close(AVBitStreamFilterContext *bsf) {}
|
||||
int av_bitstream_filter_filter(AVBitStreamFilterContext *bsfc,
|
||||
AVCodecContext *avctx, const char *args,
|
||||
|
|
|
@ -0,0 +1,237 @@
|
|||
/*
|
||||
* FLAC common code
|
||||
* Copyright (c) 2009 Justin Ruggles
|
||||
*
|
||||
* 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 "libavutil/channel_layout.h"
|
||||
#include "libavutil/crc.h"
|
||||
#include "libavutil/log.h"
|
||||
#include "bytestream.h"
|
||||
#include "get_bits.h"
|
||||
#include "flac.h"
|
||||
#include "flacdata.h"
|
||||
|
||||
static const int8_t sample_size_table[] = { 0, 8, 12, 0, 16, 20, 24, 0 };
|
||||
|
||||
static const uint64_t flac_channel_layouts[8] = {
|
||||
AV_CH_LAYOUT_MONO,
|
||||
AV_CH_LAYOUT_STEREO,
|
||||
AV_CH_LAYOUT_SURROUND,
|
||||
AV_CH_LAYOUT_QUAD,
|
||||
AV_CH_LAYOUT_5POINT0,
|
||||
AV_CH_LAYOUT_5POINT1,
|
||||
AV_CH_LAYOUT_6POINT1,
|
||||
AV_CH_LAYOUT_7POINT1
|
||||
};
|
||||
|
||||
static int64_t get_utf8(GetBitContext *gb)
|
||||
{
|
||||
int64_t val;
|
||||
GET_UTF8(val, get_bits(gb, 8), return -1;)
|
||||
return val;
|
||||
}
|
||||
|
||||
int ff_flac_decode_frame_header(AVCodecContext *avctx, GetBitContext *gb,
|
||||
FLACFrameInfo *fi, int log_level_offset)
|
||||
{
|
||||
int bs_code, sr_code, bps_code;
|
||||
|
||||
/* frame sync code */
|
||||
if ((get_bits(gb, 15) & 0x7FFF) != 0x7FFC) {
|
||||
av_log(avctx, AV_LOG_ERROR + log_level_offset, "invalid sync code\n");
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
|
||||
/* variable block size stream code */
|
||||
fi->is_var_size = get_bits1(gb);
|
||||
|
||||
/* 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_MAX_CHANNELS + FLAC_CHMODE_MID_SIDE) {
|
||||
fi->channels = 2;
|
||||
fi->ch_mode -= FLAC_MAX_CHANNELS - 1;
|
||||
} else {
|
||||
av_log(avctx, AV_LOG_ERROR + log_level_offset,
|
||||
"invalid channel mode: %d\n", fi->ch_mode);
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
|
||||
/* bits per sample */
|
||||
bps_code = get_bits(gb, 3);
|
||||
if (bps_code == 3 || bps_code == 7) {
|
||||
av_log(avctx, AV_LOG_ERROR + log_level_offset,
|
||||
"invalid sample size code (%d)\n",
|
||||
bps_code);
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
fi->bps = sample_size_table[bps_code];
|
||||
|
||||
/* reserved bit */
|
||||
if (get_bits1(gb)) {
|
||||
av_log(avctx, AV_LOG_ERROR + log_level_offset,
|
||||
"broken stream, invalid padding\n");
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
|
||||
/* sample or frame count */
|
||||
fi->frame_or_sample_num = get_utf8(gb);
|
||||
if (fi->frame_or_sample_num < 0) {
|
||||
av_log(avctx, AV_LOG_ERROR + log_level_offset,
|
||||
"sample/frame number invalid; utf8 fscked\n");
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
|
||||
/* blocksize */
|
||||
if (bs_code == 0) {
|
||||
av_log(avctx, AV_LOG_ERROR + log_level_offset,
|
||||
"reserved blocksize code: 0\n");
|
||||
return AVERROR_INVALIDDATA;
|
||||
} 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 = ff_flac_blocksize_table[bs_code];
|
||||
}
|
||||
|
||||
/* sample rate */
|
||||
if (sr_code < 12) {
|
||||
fi->samplerate = 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 {
|
||||
av_log(avctx, AV_LOG_ERROR + log_level_offset,
|
||||
"illegal sample rate code %d\n",
|
||||
sr_code);
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
|
||||
/* header CRC-8 check */
|
||||
skip_bits(gb, 8);
|
||||
if (av_crc(av_crc_get_table(AV_CRC_8_ATM), 0, gb->buffer,
|
||||
get_bits_count(gb)/8)) {
|
||||
av_log(avctx, AV_LOG_ERROR + log_level_offset,
|
||||
"header crc mismatch\n");
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
int ff_flac_is_extradata_valid(AVCodecContext *avctx,
|
||||
enum FLACExtradataFormat *format,
|
||||
uint8_t **streaminfo_start)
|
||||
{
|
||||
if (!avctx->extradata || avctx->extradata_size < FLAC_STREAMINFO_SIZE) {
|
||||
av_log(avctx, AV_LOG_ERROR, "extradata NULL or too small.\n");
|
||||
return 0;
|
||||
}
|
||||
if (AV_RL32(avctx->extradata) != MKTAG('f','L','a','C')) {
|
||||
/* extradata contains STREAMINFO only */
|
||||
if (avctx->extradata_size != FLAC_STREAMINFO_SIZE) {
|
||||
av_log(avctx, AV_LOG_WARNING, "extradata contains %d bytes too many.\n",
|
||||
FLAC_STREAMINFO_SIZE-avctx->extradata_size);
|
||||
}
|
||||
*format = FLAC_EXTRADATA_FORMAT_STREAMINFO;
|
||||
*streaminfo_start = avctx->extradata;
|
||||
} else {
|
||||
if (avctx->extradata_size < 8+FLAC_STREAMINFO_SIZE) {
|
||||
av_log(avctx, AV_LOG_ERROR, "extradata too small.\n");
|
||||
return 0;
|
||||
}
|
||||
*format = FLAC_EXTRADATA_FORMAT_FULL_HEADER;
|
||||
*streaminfo_start = &avctx->extradata[8];
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void ff_flac_set_channel_layout(AVCodecContext *avctx)
|
||||
{
|
||||
if (avctx->channels <= FF_ARRAY_ELEMS(flac_channel_layouts))
|
||||
avctx->channel_layout = flac_channel_layouts[avctx->channels - 1];
|
||||
else
|
||||
avctx->channel_layout = 0;
|
||||
}
|
||||
|
||||
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) {
|
||||
av_log(avctx, AV_LOG_WARNING, "invalid max blocksize: %d\n",
|
||||
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;
|
||||
|
||||
if (!avctx->channel_layout ||
|
||||
av_get_channel_layout_nb_channels(avctx->channel_layout) != avctx->channels)
|
||||
ff_flac_set_channel_layout(avctx);
|
||||
|
||||
s->samples = get_bits64(&gb, 36);
|
||||
|
||||
skip_bits_long(&gb, 64); /* md5 sum */
|
||||
skip_bits_long(&gb, 64); /* md5 sum */
|
||||
}
|
|
@ -0,0 +1,153 @@
|
|||
/*
|
||||
* FLAC (Free Lossless Audio Codec) decoder/demuxer common functions
|
||||
* Copyright (c) 2008 Justin Ruggles
|
||||
*
|
||||
* 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/demuxer common functions
|
||||
*/
|
||||
|
||||
#ifndef AVCODEC_FLAC_H
|
||||
#define AVCODEC_FLAC_H
|
||||
|
||||
#include "avcodec.h"
|
||||
#include "bytestream.h"
|
||||
#include "get_bits.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 = 1,
|
||||
FLAC_CHMODE_RIGHT_SIDE = 2,
|
||||
FLAC_CHMODE_MID_SIDE = 3,
|
||||
};
|
||||
|
||||
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 */
|
||||
int64_t frame_or_sample_num; /**< frame number or sample number */
|
||||
int is_var_size; /**< specifies if the stream uses variable
|
||||
block sizes or a fixed block size;
|
||||
also determines the meaning of
|
||||
frame_or_sample_num */
|
||||
} FLACFrameInfo;
|
||||
|
||||
/**
|
||||
* Parse the Streaminfo metadata block
|
||||
* @param[out] avctx codec context to set basic stream parameters
|
||||
* @param[out] s where parsed information is stored
|
||||
* @param[in] buffer pointer to start of 34-byte streaminfo data
|
||||
*/
|
||||
void ff_flac_parse_streaminfo(AVCodecContext *avctx, struct FLACStreaminfo *s,
|
||||
const uint8_t *buffer);
|
||||
|
||||
/**
|
||||
* Validate the FLAC extradata.
|
||||
* @param[in] avctx codec context containing the extradata.
|
||||
* @param[out] format extradata format.
|
||||
* @param[out] streaminfo_start pointer to start of 34-byte STREAMINFO data.
|
||||
* @return 1 if valid, 0 if not valid.
|
||||
*/
|
||||
int ff_flac_is_extradata_valid(AVCodecContext *avctx,
|
||||
enum FLACExtradataFormat *format,
|
||||
uint8_t **streaminfo_start);
|
||||
|
||||
/**
|
||||
* Calculate an estimate for the maximum frame size based on verbatim mode.
|
||||
* @param blocksize block size, in samples
|
||||
* @param ch number of channels
|
||||
* @param bps bits-per-sample
|
||||
*/
|
||||
int ff_flac_get_max_frame_size(int blocksize, int ch, int bps);
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @param log_level_offset log level offset. can be used to silence error messages.
|
||||
* @return non-zero on error, 0 if ok
|
||||
*/
|
||||
int ff_flac_decode_frame_header(AVCodecContext *avctx, GetBitContext *gb,
|
||||
FLACFrameInfo *fi, int log_level_offset);
|
||||
|
||||
void ff_flac_set_channel_layout(AVCodecContext *avctx);
|
||||
|
||||
/**
|
||||
* Parse the metadata block parameters from the header.
|
||||
* @param[in] block_header header data, at least 4 bytes
|
||||
* @param[out] last indicator for last metadata block
|
||||
* @param[out] type metadata block type
|
||||
* @param[out] size metadata block size
|
||||
*/
|
||||
static av_always_inline void 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);
|
||||
}
|
||||
|
||||
#endif /* AVCODEC_FLAC_H */
|
|
@ -0,0 +1,755 @@
|
|||
/*
|
||||
* FLAC parser
|
||||
* Copyright (c) 2010 Michael Chinen
|
||||
*
|
||||
* 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 parser
|
||||
*
|
||||
* The FLAC parser buffers input until FLAC_MIN_HEADERS has been found.
|
||||
* Each time it finds and verifies a CRC-8 header it sees which of the
|
||||
* FLAC_MAX_SEQUENTIAL_HEADERS that came before it have a valid CRC-16 footer
|
||||
* that ends at the newly found header.
|
||||
* Headers are scored by FLAC_HEADER_BASE_SCORE plus the max of its crc-verified
|
||||
* children, penalized by changes in sample rate, frame number, etc.
|
||||
* The parser returns the frame with the highest score.
|
||||
**/
|
||||
|
||||
#include "libavutil/attributes.h"
|
||||
#include "libavutil/crc.h"
|
||||
#include "libavutil/fifo.h"
|
||||
#include "bytestream.h"
|
||||
#include "parser.h"
|
||||
#include "flac.h"
|
||||
|
||||
/** maximum number of adjacent headers that compare CRCs against each other */
|
||||
#define FLAC_MAX_SEQUENTIAL_HEADERS 4
|
||||
/** minimum number of headers buffered and checked before returning frames */
|
||||
#define FLAC_MIN_HEADERS 10
|
||||
/** estimate for average size of a FLAC frame */
|
||||
#define FLAC_AVG_FRAME_SIZE 8192
|
||||
|
||||
/** scoring settings for score_header */
|
||||
#define FLAC_HEADER_BASE_SCORE 10
|
||||
#define FLAC_HEADER_CHANGED_PENALTY 7
|
||||
#define FLAC_HEADER_CRC_FAIL_PENALTY 50
|
||||
#define FLAC_HEADER_NOT_PENALIZED_YET 100000
|
||||
#define FLAC_HEADER_NOT_SCORED_YET -100000
|
||||
|
||||
/** largest possible size of flac header */
|
||||
#define MAX_FRAME_HEADER_SIZE 16
|
||||
|
||||
typedef struct FLACHeaderMarker {
|
||||
int offset; /**< byte offset from start of FLACParseContext->buffer */
|
||||
int *link_penalty; /**< pointer to array of local scores between this header
|
||||
and the one at a distance equal array position */
|
||||
int max_score; /**< maximum score found after checking each child that
|
||||
has a valid CRC */
|
||||
FLACFrameInfo fi; /**< decoded frame header info */
|
||||
struct FLACHeaderMarker *next; /**< next CRC-8 verified header that
|
||||
immediately follows this one in
|
||||
the bytestream */
|
||||
struct FLACHeaderMarker *best_child; /**< following frame header with
|
||||
which this frame has the best
|
||||
score with */
|
||||
} FLACHeaderMarker;
|
||||
|
||||
typedef struct FLACParseContext {
|
||||
AVCodecParserContext *pc; /**< parent context */
|
||||
AVCodecContext *avctx; /**< codec context pointer for logging */
|
||||
FLACHeaderMarker *headers; /**< linked-list that starts at the first
|
||||
CRC-8 verified header within buffer */
|
||||
FLACHeaderMarker *best_header; /**< highest scoring header within buffer */
|
||||
int nb_headers_found; /**< number of headers found in the last
|
||||
flac_parse() call */
|
||||
int nb_headers_buffered; /**< number of headers that are buffered */
|
||||
int best_header_valid; /**< flag set when the parser returns junk;
|
||||
if set return best_header next time */
|
||||
AVFifoBuffer *fifo_buf; /**< buffer to store all data until headers
|
||||
can be verified */
|
||||
int end_padded; /**< specifies if fifo_buf's end is padded */
|
||||
uint8_t *wrap_buf; /**< general fifo read buffer when wrapped */
|
||||
int wrap_buf_allocated_size; /**< actual allocated size of the buffer */
|
||||
FLACFrameInfo last_fi; /**< last decoded frame header info */
|
||||
int last_fi_valid; /**< set if last_fi is valid */
|
||||
} FLACParseContext;
|
||||
|
||||
static int frame_header_is_valid(AVCodecContext *avctx, const uint8_t *buf,
|
||||
FLACFrameInfo *fi)
|
||||
{
|
||||
GetBitContext gb;
|
||||
init_get_bits(&gb, buf, MAX_FRAME_HEADER_SIZE * 8);
|
||||
return !ff_flac_decode_frame_header(avctx, &gb, fi, 127);
|
||||
}
|
||||
|
||||
/**
|
||||
* Non-destructive fast fifo pointer fetching
|
||||
* Returns a pointer from the specified offset.
|
||||
* If possible the pointer points within the fifo buffer.
|
||||
* Otherwise (if it would cause a wrap around,) a pointer to a user-specified
|
||||
* buffer is used.
|
||||
* The pointer can be NULL. In any case it will be reallocated to hold the size.
|
||||
* If the returned pointer will be used after subsequent calls to flac_fifo_read_wrap
|
||||
* then the subsequent calls should pass in a different wrap_buf so as to not
|
||||
* overwrite the contents of the previous wrap_buf.
|
||||
* This function is based on av_fifo_generic_read, which is why there is a comment
|
||||
* about a memory barrier for SMP.
|
||||
*/
|
||||
static uint8_t* flac_fifo_read_wrap(FLACParseContext *fpc, int offset, int len,
|
||||
uint8_t** wrap_buf, int* allocated_size)
|
||||
{
|
||||
AVFifoBuffer *f = fpc->fifo_buf;
|
||||
uint8_t *start = f->rptr + offset;
|
||||
uint8_t *tmp_buf;
|
||||
|
||||
if (start >= f->end)
|
||||
start -= f->end - f->buffer;
|
||||
if (f->end - start >= len)
|
||||
return start;
|
||||
|
||||
tmp_buf = av_fast_realloc(*wrap_buf, allocated_size, len);
|
||||
|
||||
if (!tmp_buf) {
|
||||
av_log(fpc->avctx, AV_LOG_ERROR,
|
||||
"couldn't reallocate wrap buffer of size %d", len);
|
||||
return NULL;
|
||||
}
|
||||
*wrap_buf = tmp_buf;
|
||||
do {
|
||||
int seg_len = FFMIN(f->end - start, len);
|
||||
memcpy(tmp_buf, start, seg_len);
|
||||
tmp_buf = (uint8_t*)tmp_buf + seg_len;
|
||||
// memory barrier needed for SMP here in theory
|
||||
|
||||
start += seg_len - (f->end - f->buffer);
|
||||
len -= seg_len;
|
||||
} while (len > 0);
|
||||
|
||||
return *wrap_buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a pointer in the fifo buffer where the offset starts at until
|
||||
* the wrap point or end of request.
|
||||
* len will contain the valid length of the returned buffer.
|
||||
* A second call to flac_fifo_read (with new offset and len) should be called
|
||||
* to get the post-wrap buf if the returned len is less than the requested.
|
||||
**/
|
||||
static uint8_t* flac_fifo_read(FLACParseContext *fpc, int offset, int *len)
|
||||
{
|
||||
AVFifoBuffer *f = fpc->fifo_buf;
|
||||
uint8_t *start = f->rptr + offset;
|
||||
|
||||
if (start >= f->end)
|
||||
start -= f->end - f->buffer;
|
||||
*len = FFMIN(*len, f->end - start);
|
||||
return start;
|
||||
}
|
||||
|
||||
static int find_headers_search_validate(FLACParseContext *fpc, int offset)
|
||||
{
|
||||
FLACFrameInfo fi;
|
||||
uint8_t *header_buf;
|
||||
int size = 0;
|
||||
header_buf = flac_fifo_read_wrap(fpc, offset,
|
||||
MAX_FRAME_HEADER_SIZE,
|
||||
&fpc->wrap_buf,
|
||||
&fpc->wrap_buf_allocated_size);
|
||||
if (frame_header_is_valid(fpc->avctx, header_buf, &fi)) {
|
||||
FLACHeaderMarker **end_handle = &fpc->headers;
|
||||
int i;
|
||||
|
||||
size = 0;
|
||||
while (*end_handle) {
|
||||
end_handle = &(*end_handle)->next;
|
||||
size++;
|
||||
}
|
||||
|
||||
*end_handle = av_mallocz(sizeof(**end_handle));
|
||||
if (!*end_handle) {
|
||||
av_log(fpc->avctx, AV_LOG_ERROR,
|
||||
"couldn't allocate FLACHeaderMarker\n");
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
(*end_handle)->fi = fi;
|
||||
(*end_handle)->offset = offset;
|
||||
(*end_handle)->link_penalty = av_malloc(sizeof(int) *
|
||||
FLAC_MAX_SEQUENTIAL_HEADERS);
|
||||
if (!(*end_handle)->link_penalty) {
|
||||
av_freep(end_handle);
|
||||
av_log(fpc->avctx, AV_LOG_ERROR,
|
||||
"couldn't allocate link_penalty\n");
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
|
||||
for (i = 0; i < FLAC_MAX_SEQUENTIAL_HEADERS; i++)
|
||||
(*end_handle)->link_penalty[i] = FLAC_HEADER_NOT_PENALIZED_YET;
|
||||
|
||||
fpc->nb_headers_found++;
|
||||
size++;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
static int find_headers_search(FLACParseContext *fpc, uint8_t *buf, int buf_size,
|
||||
int search_start)
|
||||
|
||||
{
|
||||
int size = 0, mod_offset = (buf_size - 1) % 4, i, j;
|
||||
uint32_t x;
|
||||
|
||||
for (i = 0; i < mod_offset; i++) {
|
||||
if ((AV_RB16(buf + i) & 0xFFFE) == 0xFFF8)
|
||||
size = find_headers_search_validate(fpc, search_start + i);
|
||||
}
|
||||
|
||||
for (; i < buf_size - 1; i += 4) {
|
||||
x = AV_RB32(buf + i);
|
||||
if (((x & ~(x + 0x01010101)) & 0x80808080)) {
|
||||
for (j = 0; j < 4; j++) {
|
||||
if ((AV_RB16(buf + i + j) & 0xFFFE) == 0xFFF8)
|
||||
size = find_headers_search_validate(fpc, search_start + i + j);
|
||||
}
|
||||
}
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
static int find_new_headers(FLACParseContext *fpc, int search_start)
|
||||
{
|
||||
FLACHeaderMarker *end;
|
||||
int search_end, size = 0, read_len, temp;
|
||||
uint8_t *buf;
|
||||
fpc->nb_headers_found = 0;
|
||||
|
||||
/* Search for a new header of at most 16 bytes. */
|
||||
search_end = av_fifo_size(fpc->fifo_buf) - (MAX_FRAME_HEADER_SIZE - 1);
|
||||
read_len = search_end - search_start + 1;
|
||||
buf = flac_fifo_read(fpc, search_start, &read_len);
|
||||
size = find_headers_search(fpc, buf, read_len, search_start);
|
||||
search_start += read_len - 1;
|
||||
|
||||
/* If fifo end was hit do the wrap around. */
|
||||
if (search_start != search_end) {
|
||||
uint8_t wrap[2];
|
||||
|
||||
wrap[0] = buf[read_len - 1];
|
||||
read_len = search_end - search_start + 1;
|
||||
|
||||
/* search_start + 1 is the post-wrap offset in the fifo. */
|
||||
buf = flac_fifo_read(fpc, search_start + 1, &read_len);
|
||||
wrap[1] = buf[0];
|
||||
|
||||
if ((AV_RB16(wrap) & 0xFFFE) == 0xFFF8) {
|
||||
temp = find_headers_search_validate(fpc, search_start);
|
||||
size = FFMAX(size, temp);
|
||||
}
|
||||
search_start++;
|
||||
|
||||
/* Continue to do the last half of the wrap. */
|
||||
temp = find_headers_search(fpc, buf, read_len, search_start);
|
||||
size = FFMAX(size, temp);
|
||||
search_start += read_len - 1;
|
||||
}
|
||||
|
||||
/* Return the size even if no new headers were found. */
|
||||
if (!size && fpc->headers)
|
||||
for (end = fpc->headers; end; end = end->next)
|
||||
size++;
|
||||
return size;
|
||||
}
|
||||
|
||||
static int check_header_fi_mismatch(FLACParseContext *fpc,
|
||||
FLACFrameInfo *header_fi,
|
||||
FLACFrameInfo *child_fi,
|
||||
int log_level_offset)
|
||||
{
|
||||
int deduction = 0;
|
||||
if (child_fi->samplerate != header_fi->samplerate) {
|
||||
deduction += FLAC_HEADER_CHANGED_PENALTY;
|
||||
av_log(fpc->avctx, AV_LOG_WARNING + log_level_offset,
|
||||
"sample rate change detected in adjacent frames\n");
|
||||
}
|
||||
if (child_fi->bps != header_fi->bps) {
|
||||
deduction += FLAC_HEADER_CHANGED_PENALTY;
|
||||
av_log(fpc->avctx, AV_LOG_WARNING + log_level_offset,
|
||||
"bits per sample change detected in adjacent frames\n");
|
||||
}
|
||||
if (child_fi->is_var_size != header_fi->is_var_size) {
|
||||
/* Changing blocking strategy not allowed per the spec */
|
||||
deduction += FLAC_HEADER_BASE_SCORE;
|
||||
av_log(fpc->avctx, AV_LOG_WARNING + log_level_offset,
|
||||
"blocking strategy change detected in adjacent frames\n");
|
||||
}
|
||||
if (child_fi->channels != header_fi->channels) {
|
||||
deduction += FLAC_HEADER_CHANGED_PENALTY;
|
||||
av_log(fpc->avctx, AV_LOG_WARNING + log_level_offset,
|
||||
"number of channels change detected in adjacent frames\n");
|
||||
}
|
||||
return deduction;
|
||||
}
|
||||
|
||||
static int check_header_mismatch(FLACParseContext *fpc,
|
||||
FLACHeaderMarker *header,
|
||||
FLACHeaderMarker *child,
|
||||
int log_level_offset)
|
||||
{
|
||||
FLACFrameInfo *header_fi = &header->fi, *child_fi = &child->fi;
|
||||
int deduction, deduction_expected = 0, i;
|
||||
deduction = check_header_fi_mismatch(fpc, header_fi, child_fi,
|
||||
log_level_offset);
|
||||
/* Check sample and frame numbers. */
|
||||
if ((child_fi->frame_or_sample_num - header_fi->frame_or_sample_num
|
||||
!= header_fi->blocksize) &&
|
||||
(child_fi->frame_or_sample_num
|
||||
!= header_fi->frame_or_sample_num + 1)) {
|
||||
FLACHeaderMarker *curr;
|
||||
int expected_frame_num, expected_sample_num;
|
||||
/* If there are frames in the middle we expect this deduction,
|
||||
as they are probably valid and this one follows it */
|
||||
|
||||
expected_frame_num = expected_sample_num = header_fi->frame_or_sample_num;
|
||||
curr = header;
|
||||
while (curr != child) {
|
||||
/* Ignore frames that failed all crc checks */
|
||||
for (i = 0; i < FLAC_MAX_SEQUENTIAL_HEADERS; i++) {
|
||||
if (curr->link_penalty[i] < FLAC_HEADER_CRC_FAIL_PENALTY) {
|
||||
expected_frame_num++;
|
||||
expected_sample_num += curr->fi.blocksize;
|
||||
break;
|
||||
}
|
||||
}
|
||||
curr = curr->next;
|
||||
}
|
||||
|
||||
if (expected_frame_num == child_fi->frame_or_sample_num ||
|
||||
expected_sample_num == child_fi->frame_or_sample_num)
|
||||
deduction_expected = deduction ? 0 : 1;
|
||||
|
||||
deduction += FLAC_HEADER_CHANGED_PENALTY;
|
||||
av_log(fpc->avctx, AV_LOG_WARNING + log_level_offset,
|
||||
"sample/frame number mismatch in adjacent frames\n");
|
||||
}
|
||||
|
||||
/* If we have suspicious headers, check the CRC between them */
|
||||
if (deduction && !deduction_expected) {
|
||||
FLACHeaderMarker *curr;
|
||||
int read_len;
|
||||
uint8_t *buf;
|
||||
uint32_t crc = 1;
|
||||
int inverted_test = 0;
|
||||
|
||||
/* Since CRC is expensive only do it if we haven't yet.
|
||||
This assumes a CRC penalty is greater than all other check penalties */
|
||||
curr = header->next;
|
||||
for (i = 0; i < FLAC_MAX_SEQUENTIAL_HEADERS && curr != child; i++)
|
||||
curr = curr->next;
|
||||
|
||||
if (header->link_penalty[i] < FLAC_HEADER_CRC_FAIL_PENALTY ||
|
||||
header->link_penalty[i] == FLAC_HEADER_NOT_PENALIZED_YET) {
|
||||
FLACHeaderMarker *start, *end;
|
||||
|
||||
/* Although overlapping chains are scored, the crc should never
|
||||
have to be computed twice for a single byte. */
|
||||
start = header;
|
||||
end = child;
|
||||
if (i > 0 &&
|
||||
header->link_penalty[i - 1] >= FLAC_HEADER_CRC_FAIL_PENALTY) {
|
||||
while (start->next != child)
|
||||
start = start->next;
|
||||
inverted_test = 1;
|
||||
} else if (i > 0 &&
|
||||
header->next->link_penalty[i-1] >=
|
||||
FLAC_HEADER_CRC_FAIL_PENALTY ) {
|
||||
end = header->next;
|
||||
inverted_test = 1;
|
||||
}
|
||||
|
||||
read_len = end->offset - start->offset;
|
||||
buf = flac_fifo_read(fpc, start->offset, &read_len);
|
||||
crc = av_crc(av_crc_get_table(AV_CRC_16_ANSI), 0, buf, read_len);
|
||||
read_len = (end->offset - start->offset) - read_len;
|
||||
|
||||
if (read_len) {
|
||||
buf = flac_fifo_read(fpc, end->offset - read_len, &read_len);
|
||||
crc = av_crc(av_crc_get_table(AV_CRC_16_ANSI), crc, buf, read_len);
|
||||
}
|
||||
}
|
||||
|
||||
if (!crc ^ !inverted_test) {
|
||||
deduction += FLAC_HEADER_CRC_FAIL_PENALTY;
|
||||
av_log(fpc->avctx, AV_LOG_WARNING + log_level_offset,
|
||||
"crc check failed from offset %i (frame %"PRId64") to %i (frame %"PRId64")\n",
|
||||
header->offset, header_fi->frame_or_sample_num,
|
||||
child->offset, child_fi->frame_or_sample_num);
|
||||
}
|
||||
}
|
||||
return deduction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Score a header.
|
||||
*
|
||||
* Give FLAC_HEADER_BASE_SCORE points to a frame for existing.
|
||||
* If it has children, (subsequent frames of which the preceding CRC footer
|
||||
* validates against this one,) then take the maximum score of the children,
|
||||
* with a penalty of FLAC_HEADER_CHANGED_PENALTY applied for each change to
|
||||
* bps, sample rate, channels, but not decorrelation mode, or blocksize,
|
||||
* because it can change often.
|
||||
**/
|
||||
static int score_header(FLACParseContext *fpc, FLACHeaderMarker *header)
|
||||
{
|
||||
FLACHeaderMarker *child;
|
||||
int dist = 0;
|
||||
int child_score;
|
||||
int base_score = FLAC_HEADER_BASE_SCORE;
|
||||
if (header->max_score != FLAC_HEADER_NOT_SCORED_YET)
|
||||
return header->max_score;
|
||||
|
||||
/* Modify the base score with changes from the last output header */
|
||||
if (fpc->last_fi_valid) {
|
||||
/* Silence the log since this will be repeated if selected */
|
||||
base_score -= check_header_fi_mismatch(fpc, &fpc->last_fi, &header->fi,
|
||||
AV_LOG_DEBUG);
|
||||
}
|
||||
|
||||
header->max_score = base_score;
|
||||
|
||||
/* Check and compute the children's scores. */
|
||||
child = header->next;
|
||||
for (dist = 0; dist < FLAC_MAX_SEQUENTIAL_HEADERS && child; dist++) {
|
||||
/* Look at the child's frame header info and penalize suspicious
|
||||
changes between the headers. */
|
||||
if (header->link_penalty[dist] == FLAC_HEADER_NOT_PENALIZED_YET) {
|
||||
header->link_penalty[dist] = check_header_mismatch(fpc, header,
|
||||
child, AV_LOG_DEBUG);
|
||||
}
|
||||
child_score = score_header(fpc, child) - header->link_penalty[dist];
|
||||
|
||||
if (FLAC_HEADER_BASE_SCORE + child_score > header->max_score) {
|
||||
/* Keep the child because the frame scoring is dynamic. */
|
||||
header->best_child = child;
|
||||
header->max_score = base_score + child_score;
|
||||
}
|
||||
child = child->next;
|
||||
}
|
||||
|
||||
return header->max_score;
|
||||
}
|
||||
|
||||
static void score_sequences(FLACParseContext *fpc)
|
||||
{
|
||||
FLACHeaderMarker *curr;
|
||||
int best_score = 0;//FLAC_HEADER_NOT_SCORED_YET;
|
||||
/* First pass to clear all old scores. */
|
||||
for (curr = fpc->headers; curr; curr = curr->next)
|
||||
curr->max_score = FLAC_HEADER_NOT_SCORED_YET;
|
||||
|
||||
/* Do a second pass to score them all. */
|
||||
for (curr = fpc->headers; curr; curr = curr->next) {
|
||||
if (score_header(fpc, curr) > best_score) {
|
||||
fpc->best_header = curr;
|
||||
best_score = curr->max_score;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int get_best_header(FLACParseContext* fpc, const uint8_t **poutbuf,
|
||||
int *poutbuf_size)
|
||||
{
|
||||
FLACHeaderMarker *header = fpc->best_header;
|
||||
FLACHeaderMarker *child = header->best_child;
|
||||
if (!child) {
|
||||
*poutbuf_size = av_fifo_size(fpc->fifo_buf) - header->offset;
|
||||
} else {
|
||||
*poutbuf_size = child->offset - header->offset;
|
||||
|
||||
/* If the child has suspicious changes, log them */
|
||||
check_header_mismatch(fpc, header, child, 0);
|
||||
}
|
||||
|
||||
if (header->fi.channels != fpc->avctx->channels ||
|
||||
!fpc->avctx->channel_layout) {
|
||||
fpc->avctx->channels = header->fi.channels;
|
||||
ff_flac_set_channel_layout(fpc->avctx);
|
||||
}
|
||||
fpc->avctx->sample_rate = header->fi.samplerate;
|
||||
fpc->pc->duration = header->fi.blocksize;
|
||||
*poutbuf = flac_fifo_read_wrap(fpc, header->offset, *poutbuf_size,
|
||||
&fpc->wrap_buf,
|
||||
&fpc->wrap_buf_allocated_size);
|
||||
|
||||
|
||||
if (fpc->pc->flags & PARSER_FLAG_USE_CODEC_TS){
|
||||
if (header->fi.is_var_size)
|
||||
fpc->pc->pts = header->fi.frame_or_sample_num;
|
||||
else if (header->best_child)
|
||||
fpc->pc->pts = header->fi.frame_or_sample_num * header->fi.blocksize;
|
||||
}
|
||||
|
||||
fpc->best_header_valid = 0;
|
||||
fpc->last_fi_valid = 1;
|
||||
fpc->last_fi = header->fi;
|
||||
|
||||
/* Return the negative overread index so the client can compute pos.
|
||||
This should be the amount overread to the beginning of the child */
|
||||
if (child)
|
||||
return child->offset - av_fifo_size(fpc->fifo_buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int flac_parse(AVCodecParserContext *s, AVCodecContext *avctx,
|
||||
const uint8_t **poutbuf, int *poutbuf_size,
|
||||
const uint8_t *buf, int buf_size)
|
||||
{
|
||||
FLACParseContext *fpc = s->priv_data;
|
||||
FLACHeaderMarker *curr;
|
||||
int nb_headers;
|
||||
const uint8_t *read_end = buf;
|
||||
const uint8_t *read_start = buf;
|
||||
|
||||
if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) {
|
||||
FLACFrameInfo fi;
|
||||
if (frame_header_is_valid(avctx, buf, &fi)) {
|
||||
s->duration = fi.blocksize;
|
||||
if (!avctx->sample_rate)
|
||||
avctx->sample_rate = fi.samplerate;
|
||||
if (fpc->pc->flags & PARSER_FLAG_USE_CODEC_TS){
|
||||
fpc->pc->pts = fi.frame_or_sample_num;
|
||||
if (!fi.is_var_size)
|
||||
fpc->pc->pts *= fi.blocksize;
|
||||
}
|
||||
}
|
||||
*poutbuf = buf;
|
||||
*poutbuf_size = buf_size;
|
||||
return buf_size;
|
||||
}
|
||||
|
||||
fpc->avctx = avctx;
|
||||
if (fpc->best_header_valid)
|
||||
return get_best_header(fpc, poutbuf, poutbuf_size);
|
||||
|
||||
/* If a best_header was found last call remove it with the buffer data. */
|
||||
if (fpc->best_header && fpc->best_header->best_child) {
|
||||
FLACHeaderMarker *temp;
|
||||
FLACHeaderMarker *best_child = fpc->best_header->best_child;
|
||||
|
||||
/* Remove headers in list until the end of the best_header. */
|
||||
for (curr = fpc->headers; curr != best_child; curr = temp) {
|
||||
if (curr != fpc->best_header) {
|
||||
av_log(avctx, AV_LOG_DEBUG,
|
||||
"dropping low score %i frame header from offset %i to %i\n",
|
||||
curr->max_score, curr->offset, curr->next->offset);
|
||||
}
|
||||
temp = curr->next;
|
||||
av_freep(&curr->link_penalty);
|
||||
av_free(curr);
|
||||
fpc->nb_headers_buffered--;
|
||||
}
|
||||
/* Release returned data from ring buffer. */
|
||||
av_fifo_drain(fpc->fifo_buf, best_child->offset);
|
||||
|
||||
/* Fix the offset for the headers remaining to match the new buffer. */
|
||||
for (curr = best_child->next; curr; curr = curr->next)
|
||||
curr->offset -= best_child->offset;
|
||||
|
||||
fpc->nb_headers_buffered--;
|
||||
best_child->offset = 0;
|
||||
fpc->headers = best_child;
|
||||
if (fpc->nb_headers_buffered >= FLAC_MIN_HEADERS) {
|
||||
fpc->best_header = best_child;
|
||||
return get_best_header(fpc, poutbuf, poutbuf_size);
|
||||
}
|
||||
fpc->best_header = NULL;
|
||||
} else if (fpc->best_header) {
|
||||
/* No end frame no need to delete the buffer; probably eof */
|
||||
FLACHeaderMarker *temp;
|
||||
|
||||
for (curr = fpc->headers; curr != fpc->best_header; curr = temp) {
|
||||
temp = curr->next;
|
||||
av_freep(&curr->link_penalty);
|
||||
av_free(curr);
|
||||
}
|
||||
fpc->headers = fpc->best_header->next;
|
||||
av_freep(&fpc->best_header->link_penalty);
|
||||
av_freep(&fpc->best_header);
|
||||
}
|
||||
|
||||
/* Find and score new headers. */
|
||||
/* buf_size is to zero when padding, so check for this since we do */
|
||||
/* not want to try to read more input once we have found the end. */
|
||||
/* Note that as (non-modified) parameters, buf can be non-NULL, */
|
||||
/* while buf_size is 0. */
|
||||
while ((buf && buf_size && read_end < buf + buf_size &&
|
||||
fpc->nb_headers_buffered < FLAC_MIN_HEADERS)
|
||||
|| ((!buf || !buf_size) && !fpc->end_padded)) {
|
||||
int start_offset;
|
||||
|
||||
/* Pad the end once if EOF, to check the final region for headers. */
|
||||
if (!buf || !buf_size) {
|
||||
fpc->end_padded = 1;
|
||||
buf_size = MAX_FRAME_HEADER_SIZE;
|
||||
read_end = read_start + MAX_FRAME_HEADER_SIZE;
|
||||
} else {
|
||||
/* The maximum read size is the upper-bound of what the parser
|
||||
needs to have the required number of frames buffered */
|
||||
int nb_desired = FLAC_MIN_HEADERS - fpc->nb_headers_buffered + 1;
|
||||
read_end = read_end + FFMIN(buf + buf_size - read_end,
|
||||
nb_desired * FLAC_AVG_FRAME_SIZE);
|
||||
}
|
||||
|
||||
if (!av_fifo_space(fpc->fifo_buf) &&
|
||||
av_fifo_size(fpc->fifo_buf) / FLAC_AVG_FRAME_SIZE >
|
||||
fpc->nb_headers_buffered * 20) {
|
||||
/* There is less than one valid flac header buffered for 20 headers
|
||||
* buffered. Therefore the fifo is most likely filled with invalid
|
||||
* data and the input is not a flac file. */
|
||||
goto handle_error;
|
||||
}
|
||||
|
||||
/* Fill the buffer. */
|
||||
if ( av_fifo_space(fpc->fifo_buf) < read_end - read_start
|
||||
&& av_fifo_realloc2(fpc->fifo_buf, (read_end - read_start) + 2*av_fifo_size(fpc->fifo_buf)) < 0) {
|
||||
av_log(avctx, AV_LOG_ERROR,
|
||||
"couldn't reallocate buffer of size %"PTRDIFF_SPECIFIER"\n",
|
||||
(read_end - read_start) + av_fifo_size(fpc->fifo_buf));
|
||||
goto handle_error;
|
||||
}
|
||||
|
||||
if (buf && buf_size) {
|
||||
av_fifo_generic_write(fpc->fifo_buf, (void*) read_start,
|
||||
read_end - read_start, NULL);
|
||||
} else {
|
||||
int8_t pad[MAX_FRAME_HEADER_SIZE] = { 0 };
|
||||
av_fifo_generic_write(fpc->fifo_buf, (void*) pad, sizeof(pad), NULL);
|
||||
}
|
||||
|
||||
/* Tag headers and update sequences. */
|
||||
start_offset = av_fifo_size(fpc->fifo_buf) -
|
||||
((read_end - read_start) + (MAX_FRAME_HEADER_SIZE - 1));
|
||||
start_offset = FFMAX(0, start_offset);
|
||||
nb_headers = find_new_headers(fpc, start_offset);
|
||||
|
||||
if (nb_headers < 0) {
|
||||
av_log(avctx, AV_LOG_ERROR,
|
||||
"find_new_headers couldn't allocate FLAC header\n");
|
||||
goto handle_error;
|
||||
}
|
||||
|
||||
fpc->nb_headers_buffered = nb_headers;
|
||||
/* Wait till FLAC_MIN_HEADERS to output a valid frame. */
|
||||
if (!fpc->end_padded && fpc->nb_headers_buffered < FLAC_MIN_HEADERS) {
|
||||
if (buf && read_end < buf + buf_size) {
|
||||
read_start = read_end;
|
||||
continue;
|
||||
} else {
|
||||
goto handle_error;
|
||||
}
|
||||
}
|
||||
|
||||
/* If headers found, update the scores since we have longer chains. */
|
||||
if (fpc->end_padded || fpc->nb_headers_found)
|
||||
score_sequences(fpc);
|
||||
|
||||
/* restore the state pre-padding */
|
||||
if (fpc->end_padded) {
|
||||
int warp = fpc->fifo_buf->wptr - fpc->fifo_buf->buffer < MAX_FRAME_HEADER_SIZE;
|
||||
/* HACK: drain the tail of the fifo */
|
||||
fpc->fifo_buf->wptr -= MAX_FRAME_HEADER_SIZE;
|
||||
fpc->fifo_buf->wndx -= MAX_FRAME_HEADER_SIZE;
|
||||
if (warp) {
|
||||
fpc->fifo_buf->wptr += fpc->fifo_buf->end -
|
||||
fpc->fifo_buf->buffer;
|
||||
}
|
||||
buf_size = 0;
|
||||
read_start = read_end = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
for (curr = fpc->headers; curr; curr = curr->next) {
|
||||
if (curr->max_score > 0 &&
|
||||
(!fpc->best_header || curr->max_score > fpc->best_header->max_score)) {
|
||||
fpc->best_header = curr;
|
||||
}
|
||||
}
|
||||
|
||||
if (fpc->best_header) {
|
||||
fpc->best_header_valid = 1;
|
||||
if (fpc->best_header->offset > 0) {
|
||||
/* Output a junk frame. */
|
||||
av_log(avctx, AV_LOG_DEBUG, "Junk frame till offset %i\n",
|
||||
fpc->best_header->offset);
|
||||
|
||||
/* Set duration to 0. It is unknown or invalid in a junk frame. */
|
||||
s->duration = 0;
|
||||
*poutbuf_size = fpc->best_header->offset;
|
||||
*poutbuf = flac_fifo_read_wrap(fpc, 0, *poutbuf_size,
|
||||
&fpc->wrap_buf,
|
||||
&fpc->wrap_buf_allocated_size);
|
||||
return buf_size ? (read_end - buf) : (fpc->best_header->offset -
|
||||
av_fifo_size(fpc->fifo_buf));
|
||||
}
|
||||
if (!buf_size)
|
||||
return get_best_header(fpc, poutbuf, poutbuf_size);
|
||||
}
|
||||
|
||||
handle_error:
|
||||
*poutbuf = NULL;
|
||||
*poutbuf_size = 0;
|
||||
return buf_size ? read_end - buf : 0;
|
||||
}
|
||||
|
||||
static av_cold int flac_parse_init(AVCodecParserContext *c)
|
||||
{
|
||||
FLACParseContext *fpc = c->priv_data;
|
||||
fpc->pc = c;
|
||||
/* There will generally be FLAC_MIN_HEADERS buffered in the fifo before
|
||||
it drains. This is allocated early to avoid slow reallocation. */
|
||||
fpc->fifo_buf = av_fifo_alloc_array(FLAC_MIN_HEADERS + 3, FLAC_AVG_FRAME_SIZE);
|
||||
if (!fpc->fifo_buf) {
|
||||
av_log(fpc->avctx, AV_LOG_ERROR,
|
||||
"couldn't allocate fifo_buf\n");
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void flac_parse_close(AVCodecParserContext *c)
|
||||
{
|
||||
FLACParseContext *fpc = c->priv_data;
|
||||
FLACHeaderMarker *curr = fpc->headers, *temp;
|
||||
|
||||
while (curr) {
|
||||
temp = curr->next;
|
||||
av_freep(&curr->link_penalty);
|
||||
av_free(curr);
|
||||
curr = temp;
|
||||
}
|
||||
av_fifo_freep(&fpc->fifo_buf);
|
||||
av_freep(&fpc->wrap_buf);
|
||||
}
|
||||
|
||||
AVCodecParser ff_flac_parser = {
|
||||
.codec_ids = { AV_CODEC_ID_FLAC },
|
||||
.priv_data_size = sizeof(FLACParseContext),
|
||||
.parser_init = flac_parse_init,
|
||||
.parser_parse = flac_parse,
|
||||
.parser_close = flac_parse_close,
|
||||
};
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* FLAC data
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
const int ff_flac_sample_rate_table[16] =
|
||||
{ 0,
|
||||
88200, 176400, 192000,
|
||||
8000, 16000, 22050, 24000, 32000, 44100, 48000, 96000,
|
||||
0, 0, 0, 0 };
|
||||
|
||||
const int32_t 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
|
||||
};
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* FLAC data header
|
||||
* 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
|
||||
*/
|
||||
|
||||
#ifndef AVCODEC_FLACDATA_H
|
||||
#define AVCODEC_FLACDATA_H
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
extern const int ff_flac_sample_rate_table[16];
|
||||
|
||||
extern const int32_t ff_flac_blocksize_table[16];
|
||||
|
||||
#endif /* AVCODEC_FLACDATA_H */
|
|
@ -0,0 +1,677 @@
|
|||
/*
|
||||
* 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
|
||||
* @see 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.
|
||||
*/
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#include "libavutil/avassert.h"
|
||||
#include "libavutil/crc.h"
|
||||
#include "libavutil/opt.h"
|
||||
#include "avcodec.h"
|
||||
#include "internal.h"
|
||||
#include "get_bits.h"
|
||||
#include "bytestream.h"
|
||||
#include "golomb.h"
|
||||
#include "flac.h"
|
||||
#include "flacdata.h"
|
||||
#include "flacdsp.h"
|
||||
#include "thread.h"
|
||||
#include "unary.h"
|
||||
|
||||
|
||||
typedef struct FLACContext {
|
||||
AVClass *class;
|
||||
struct FLACStreaminfo flac_stream_info;
|
||||
|
||||
AVCodecContext *avctx; ///< parent AVCodecContext
|
||||
GetBitContext gb; ///< GetBitContext initialized to start at the current frame
|
||||
|
||||
int blocksize; ///< number of samples in the current frame
|
||||
int sample_shift; ///< shift required to make output samples 16-bit or 32-bit
|
||||
int ch_mode; ///< channel decorrelation type in the current frame
|
||||
int got_streaminfo; ///< indicates if the STREAMINFO has been read
|
||||
|
||||
int32_t *decoded[FLAC_MAX_CHANNELS]; ///< decoded samples
|
||||
uint8_t *decoded_buffer;
|
||||
unsigned int decoded_buffer_size;
|
||||
int buggy_lpc; ///< use workaround for old lavc encoded files
|
||||
|
||||
FLACDSPContext dsp;
|
||||
} FLACContext;
|
||||
|
||||
static int allocate_buffers(FLACContext *s);
|
||||
|
||||
static void flac_set_bps(FLACContext *s)
|
||||
{
|
||||
enum AVSampleFormat req = s->avctx->request_sample_fmt;
|
||||
int need32 = s->flac_stream_info.bps > 16;
|
||||
int want32 = av_get_bytes_per_sample(req) > 2;
|
||||
int planar = av_sample_fmt_is_planar(req);
|
||||
|
||||
if (need32 || want32) {
|
||||
if (planar)
|
||||
s->avctx->sample_fmt = AV_SAMPLE_FMT_S32P;
|
||||
else
|
||||
s->avctx->sample_fmt = AV_SAMPLE_FMT_S32;
|
||||
s->sample_shift = 32 - s->flac_stream_info.bps;
|
||||
} else {
|
||||
if (planar)
|
||||
s->avctx->sample_fmt = AV_SAMPLE_FMT_S16P;
|
||||
else
|
||||
s->avctx->sample_fmt = AV_SAMPLE_FMT_S16;
|
||||
s->sample_shift = 16 - s->flac_stream_info.bps;
|
||||
}
|
||||
}
|
||||
|
||||
static av_cold int flac_decode_init(AVCodecContext *avctx)
|
||||
{
|
||||
enum FLACExtradataFormat format;
|
||||
uint8_t *streaminfo;
|
||||
int ret;
|
||||
FLACContext *s = avctx->priv_data;
|
||||
s->avctx = avctx;
|
||||
|
||||
/* 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 AVERROR_INVALIDDATA;
|
||||
|
||||
/* initialize based on the demuxer-supplied streamdata header */
|
||||
ff_flac_parse_streaminfo(avctx, &s->flac_stream_info, streaminfo);
|
||||
ret = allocate_buffers(s);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
flac_set_bps(s);
|
||||
ff_flacdsp_init(&s->dsp, avctx->sample_fmt,
|
||||
s->flac_stream_info.channels, s->flac_stream_info.bps);
|
||||
s->got_streaminfo = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dump_headers(AVCodecContext *avctx, FLACStreaminfo *s)
|
||||
{
|
||||
av_log(avctx, AV_LOG_DEBUG, " Max Blocksize: %d\n", s->max_blocksize);
|
||||
av_log(avctx, AV_LOG_DEBUG, " Max Framesize: %d\n", s->max_framesize);
|
||||
av_log(avctx, AV_LOG_DEBUG, " Samplerate: %d\n", s->samplerate);
|
||||
av_log(avctx, AV_LOG_DEBUG, " Channels: %d\n", s->channels);
|
||||
av_log(avctx, AV_LOG_DEBUG, " Bits: %d\n", s->bps);
|
||||
}
|
||||
|
||||
static int allocate_buffers(FLACContext *s)
|
||||
{
|
||||
int buf_size;
|
||||
int ret;
|
||||
|
||||
av_assert0(s->flac_stream_info.max_blocksize);
|
||||
|
||||
buf_size = av_samples_get_buffer_size(NULL, s->flac_stream_info.channels,
|
||||
s->flac_stream_info.max_blocksize,
|
||||
AV_SAMPLE_FMT_S32P, 0);
|
||||
if (buf_size < 0)
|
||||
return buf_size;
|
||||
|
||||
av_fast_malloc(&s->decoded_buffer, &s->decoded_buffer_size, buf_size);
|
||||
if (!s->decoded_buffer)
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
ret = av_samples_fill_arrays((uint8_t **)s->decoded, NULL,
|
||||
s->decoded_buffer,
|
||||
s->flac_stream_info.channels,
|
||||
s->flac_stream_info.max_blocksize,
|
||||
AV_SAMPLE_FMT_S32P, 0);
|
||||
return ret < 0 ? ret : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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, ret;
|
||||
|
||||
if (buf_size < FLAC_STREAMINFO_SIZE+8) {
|
||||
/* need more data */
|
||||
return 0;
|
||||
}
|
||||
flac_parse_block_header(&buf[4], NULL, &metadata_type, &metadata_size);
|
||||
if (metadata_type != FLAC_METADATA_TYPE_STREAMINFO ||
|
||||
metadata_size != FLAC_STREAMINFO_SIZE) {
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
ff_flac_parse_streaminfo(s->avctx, &s->flac_stream_info, &buf[8]);
|
||||
ret = allocate_buffers(s);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
flac_set_bps(s);
|
||||
ff_flacdsp_init(&s->dsp, s->avctx->sample_fmt,
|
||||
s->flac_stream_info.channels, s->flac_stream_info.bps);
|
||||
s->got_streaminfo = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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_end - buf < 4)
|
||||
return 0;
|
||||
flac_parse_block_header(buf, &metadata_last, NULL, &metadata_size);
|
||||
buf += 4;
|
||||
if (buf_end - buf < metadata_size) {
|
||||
/* 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) {
|
||||
av_log(s->avctx, AV_LOG_ERROR, "illegal residual coding method %d\n",
|
||||
method_type);
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
|
||||
rice_order = get_bits(&s->gb, 4);
|
||||
|
||||
samples= s->blocksize >> rice_order;
|
||||
if (samples << rice_order != s->blocksize) {
|
||||
av_log(s->avctx, AV_LOG_ERROR, "invalid rice order: %i blocksize %i\n",
|
||||
rice_order, s->blocksize);
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
|
||||
if (pred_order > samples) {
|
||||
av_log(s->avctx, AV_LOG_ERROR, "invalid predictor order: %i > %i\n",
|
||||
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++) {
|
||||
tmp = get_bits(&s->gb, rice_bits);
|
||||
if (tmp == rice_esc) {
|
||||
tmp = get_bits(&s->gb, 5);
|
||||
for (; i < samples; i++)
|
||||
*decoded++ = get_sbits_long(&s->gb, tmp);
|
||||
} else {
|
||||
for (; i < samples; i++) {
|
||||
*decoded++ = get_sr_golomb_flac(&s->gb, tmp, INT_MAX, 0);
|
||||
}
|
||||
}
|
||||
i= 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int decode_subframe_fixed(FLACContext *s, int32_t *decoded,
|
||||
int pred_order, int bps)
|
||||
{
|
||||
const int blocksize = s->blocksize;
|
||||
int av_uninit(a), av_uninit(b), av_uninit(c), av_uninit(d), i;
|
||||
int ret;
|
||||
|
||||
/* warm up samples */
|
||||
for (i = 0; i < pred_order; i++) {
|
||||
decoded[i] = get_sbits_long(&s->gb, bps);
|
||||
}
|
||||
|
||||
if ((ret = decode_residuals(s, decoded, pred_order)) < 0)
|
||||
return ret;
|
||||
|
||||
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:
|
||||
av_log(s->avctx, AV_LOG_ERROR, "illegal pred order %d\n", pred_order);
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void lpc_analyze_remodulate(int32_t *decoded, const int coeffs[32],
|
||||
int order, int qlevel, int len, int bps)
|
||||
{
|
||||
int i, j;
|
||||
int ebps = 1 << (bps-1);
|
||||
unsigned sigma = 0;
|
||||
|
||||
for (i = order; i < len; i++)
|
||||
sigma |= decoded[i] + ebps;
|
||||
|
||||
if (sigma < 2*ebps)
|
||||
return;
|
||||
|
||||
for (i = len - 1; i >= order; i--) {
|
||||
int64_t p = 0;
|
||||
for (j = 0; j < order; j++)
|
||||
p += coeffs[j] * (int64_t)decoded[i-order+j];
|
||||
decoded[i] -= p >> qlevel;
|
||||
}
|
||||
for (i = order; i < len; i++, decoded++) {
|
||||
int32_t p = 0;
|
||||
for (j = 0; j < order; j++)
|
||||
p += coeffs[j] * (uint32_t)decoded[j];
|
||||
decoded[j] += p >> qlevel;
|
||||
}
|
||||
}
|
||||
|
||||
static int decode_subframe_lpc(FLACContext *s, int32_t *decoded, int pred_order,
|
||||
int bps)
|
||||
{
|
||||
int i, ret;
|
||||
int coeff_prec, qlevel;
|
||||
int coeffs[32];
|
||||
|
||||
/* warm up samples */
|
||||
for (i = 0; i < pred_order; i++) {
|
||||
decoded[i] = get_sbits_long(&s->gb, bps);
|
||||
}
|
||||
|
||||
coeff_prec = get_bits(&s->gb, 4) + 1;
|
||||
if (coeff_prec == 16) {
|
||||
av_log(s->avctx, AV_LOG_ERROR, "invalid coeff precision\n");
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
qlevel = get_sbits(&s->gb, 5);
|
||||
if (qlevel < 0) {
|
||||
av_log(s->avctx, AV_LOG_ERROR, "qlevel %d not supported, maybe buggy stream\n",
|
||||
qlevel);
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
|
||||
for (i = 0; i < pred_order; i++) {
|
||||
coeffs[pred_order - i - 1] = get_sbits(&s->gb, coeff_prec);
|
||||
}
|
||||
|
||||
if ((ret = decode_residuals(s, decoded, pred_order)) < 0)
|
||||
return ret;
|
||||
|
||||
if ( ( s->buggy_lpc && s->flac_stream_info.bps <= 16)
|
||||
|| ( !s->buggy_lpc && bps <= 16
|
||||
&& bps + coeff_prec + av_log2(pred_order) <= 32)) {
|
||||
s->dsp.lpc16(decoded, coeffs, pred_order, qlevel, s->blocksize);
|
||||
} else {
|
||||
s->dsp.lpc32(decoded, coeffs, pred_order, qlevel, s->blocksize);
|
||||
if (s->flac_stream_info.bps <= 16)
|
||||
lpc_analyze_remodulate(decoded, coeffs, pred_order, qlevel, s->blocksize, bps);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int decode_subframe(FLACContext *s, int channel)
|
||||
{
|
||||
int32_t *decoded = s->decoded[channel];
|
||||
int type, wasted = 0;
|
||||
int bps = s->flac_stream_info.bps;
|
||||
int i, tmp, ret;
|
||||
|
||||
if (channel == 0) {
|
||||
if (s->ch_mode == FLAC_CHMODE_RIGHT_SIDE)
|
||||
bps++;
|
||||
} else {
|
||||
if (s->ch_mode == FLAC_CHMODE_LEFT_SIDE || s->ch_mode == FLAC_CHMODE_MID_SIDE)
|
||||
bps++;
|
||||
}
|
||||
|
||||
if (get_bits1(&s->gb)) {
|
||||
av_log(s->avctx, AV_LOG_ERROR, "invalid subframe padding\n");
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
type = get_bits(&s->gb, 6);
|
||||
|
||||
if (get_bits1(&s->gb)) {
|
||||
int left = get_bits_left(&s->gb);
|
||||
if ( left <= 0 ||
|
||||
(left < bps && !show_bits_long(&s->gb, left)) ||
|
||||
!show_bits_long(&s->gb, bps)) {
|
||||
av_log(s->avctx, AV_LOG_ERROR,
|
||||
"Invalid number of wasted bits > available bits (%d) - left=%d\n",
|
||||
bps, left);
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
wasted = 1 + get_unary(&s->gb, 1, get_bits_left(&s->gb));
|
||||
bps -= wasted;
|
||||
}
|
||||
if (bps > 32) {
|
||||
avpriv_report_missing_feature(s->avctx, "Decorrelated bit depth > 32");
|
||||
return AVERROR_PATCHWELCOME;
|
||||
}
|
||||
|
||||
//FIXME use av_log2 for types
|
||||
if (type == 0) {
|
||||
tmp = get_sbits_long(&s->gb, bps);
|
||||
for (i = 0; i < s->blocksize; i++)
|
||||
decoded[i] = tmp;
|
||||
} else if (type == 1) {
|
||||
for (i = 0; i < s->blocksize; i++)
|
||||
decoded[i] = get_sbits_long(&s->gb, bps);
|
||||
} else if ((type >= 8) && (type <= 12)) {
|
||||
if ((ret = decode_subframe_fixed(s, decoded, type & ~0x8, bps)) < 0)
|
||||
return ret;
|
||||
} else if (type >= 32) {
|
||||
if ((ret = decode_subframe_lpc(s, decoded, (type & ~0x20)+1, bps)) < 0)
|
||||
return ret;
|
||||
} else {
|
||||
av_log(s->avctx, AV_LOG_ERROR, "invalid coding type\n");
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
|
||||
if (wasted) {
|
||||
int i;
|
||||
for (i = 0; i < s->blocksize; i++)
|
||||
decoded[i] <<= wasted;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int decode_frame(FLACContext *s)
|
||||
{
|
||||
int i, ret;
|
||||
GetBitContext *gb = &s->gb;
|
||||
FLACFrameInfo fi;
|
||||
|
||||
if ((ret = ff_flac_decode_frame_header(s->avctx, gb, &fi, 0)) < 0) {
|
||||
av_log(s->avctx, AV_LOG_ERROR, "invalid frame header\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ( s->flac_stream_info.channels
|
||||
&& fi.channels != s->flac_stream_info.channels
|
||||
&& s->got_streaminfo) {
|
||||
s->flac_stream_info.channels = s->avctx->channels = fi.channels;
|
||||
ff_flac_set_channel_layout(s->avctx);
|
||||
ret = allocate_buffers(s);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
s->flac_stream_info.channels = s->avctx->channels = fi.channels;
|
||||
if (!s->avctx->channel_layout)
|
||||
ff_flac_set_channel_layout(s->avctx);
|
||||
s->ch_mode = fi.ch_mode;
|
||||
|
||||
if (!s->flac_stream_info.bps && !fi.bps) {
|
||||
av_log(s->avctx, AV_LOG_ERROR, "bps not found in STREAMINFO or frame header\n");
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
if (!fi.bps) {
|
||||
fi.bps = s->flac_stream_info.bps;
|
||||
} else if (s->flac_stream_info.bps && fi.bps != s->flac_stream_info.bps) {
|
||||
av_log(s->avctx, AV_LOG_ERROR, "switching bps mid-stream is not "
|
||||
"supported\n");
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
|
||||
if (!s->flac_stream_info.bps) {
|
||||
s->flac_stream_info.bps = s->avctx->bits_per_raw_sample = fi.bps;
|
||||
flac_set_bps(s);
|
||||
}
|
||||
|
||||
if (!s->flac_stream_info.max_blocksize)
|
||||
s->flac_stream_info.max_blocksize = FLAC_MAX_BLOCKSIZE;
|
||||
if (fi.blocksize > s->flac_stream_info.max_blocksize) {
|
||||
av_log(s->avctx, AV_LOG_ERROR, "blocksize %d > %d\n", fi.blocksize,
|
||||
s->flac_stream_info.max_blocksize);
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
s->blocksize = fi.blocksize;
|
||||
|
||||
if (!s->flac_stream_info.samplerate && !fi.samplerate) {
|
||||
av_log(s->avctx, AV_LOG_ERROR, "sample rate not found in STREAMINFO"
|
||||
" or frame header\n");
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
if (fi.samplerate == 0)
|
||||
fi.samplerate = s->flac_stream_info.samplerate;
|
||||
s->flac_stream_info.samplerate = s->avctx->sample_rate = fi.samplerate;
|
||||
|
||||
if (!s->got_streaminfo) {
|
||||
ret = allocate_buffers(s);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
s->got_streaminfo = 1;
|
||||
dump_headers(s->avctx, &s->flac_stream_info);
|
||||
}
|
||||
ff_flacdsp_init(&s->dsp, s->avctx->sample_fmt,
|
||||
s->flac_stream_info.channels, s->flac_stream_info.bps);
|
||||
|
||||
// dump_headers(s->avctx, &s->flac_stream_info);
|
||||
|
||||
/* subframes */
|
||||
for (i = 0; i < s->flac_stream_info.channels; i++) {
|
||||
if ((ret = decode_subframe(s, i)) < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
align_get_bits(gb);
|
||||
|
||||
/* frame footer */
|
||||
skip_bits(gb, 16); /* data crc */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int flac_decode_frame(AVCodecContext *avctx, void *data,
|
||||
int *got_frame_ptr, AVPacket *avpkt)
|
||||
{
|
||||
AVFrame *frame = data;
|
||||
ThreadFrame tframe = { .f = data };
|
||||
const uint8_t *buf = avpkt->data;
|
||||
int buf_size = avpkt->size;
|
||||
FLACContext *s = avctx->priv_data;
|
||||
int bytes_read = 0;
|
||||
int ret;
|
||||
|
||||
*got_frame_ptr = 0;
|
||||
|
||||
if (s->flac_stream_info.max_framesize == 0) {
|
||||
s->flac_stream_info.max_framesize =
|
||||
ff_flac_get_max_frame_size(s->flac_stream_info.max_blocksize ? s->flac_stream_info.max_blocksize : FLAC_MAX_BLOCKSIZE,
|
||||
FLAC_MAX_CHANNELS, 32);
|
||||
}
|
||||
|
||||
if (buf_size > 5 && !memcmp(buf, "\177FLAC", 5)) {
|
||||
av_log(s->avctx, AV_LOG_DEBUG, "skipping flac header packet 1\n");
|
||||
return buf_size;
|
||||
}
|
||||
|
||||
if (buf_size > 0 && (*buf & 0x7F) == FLAC_METADATA_TYPE_VORBIS_COMMENT) {
|
||||
av_log(s->avctx, AV_LOG_DEBUG, "skipping vorbis comment\n");
|
||||
return buf_size;
|
||||
}
|
||||
|
||||
/* 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)
|
||||
return buf_size;
|
||||
|
||||
/* check for inline header */
|
||||
if (AV_RB32(buf) == MKBETAG('f','L','a','C')) {
|
||||
if (!s->got_streaminfo && (ret = parse_streaminfo(s, buf, buf_size))) {
|
||||
av_log(s->avctx, AV_LOG_ERROR, "invalid header\n");
|
||||
return ret;
|
||||
}
|
||||
return get_metadata_size(buf, buf_size);
|
||||
}
|
||||
|
||||
/* decode frame */
|
||||
if ((ret = init_get_bits8(&s->gb, buf, buf_size)) < 0)
|
||||
return ret;
|
||||
if ((ret = decode_frame(s)) < 0) {
|
||||
av_log(s->avctx, AV_LOG_ERROR, "decode_frame() failed\n");
|
||||
return ret;
|
||||
}
|
||||
bytes_read = get_bits_count(&s->gb)/8;
|
||||
|
||||
if ((s->avctx->err_recognition & (AV_EF_CRCCHECK|AV_EF_COMPLIANT)) &&
|
||||
av_crc(av_crc_get_table(AV_CRC_16_ANSI),
|
||||
0, buf, bytes_read)) {
|
||||
av_log(s->avctx, AV_LOG_ERROR, "CRC error at PTS %"PRId64"\n", avpkt->pts);
|
||||
if (s->avctx->err_recognition & AV_EF_EXPLODE)
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
|
||||
/* get output buffer */
|
||||
frame->nb_samples = s->blocksize;
|
||||
if ((ret = ff_thread_get_buffer(avctx, &tframe, 0)) < 0)
|
||||
return ret;
|
||||
|
||||
s->dsp.decorrelate[s->ch_mode](frame->data, s->decoded,
|
||||
s->flac_stream_info.channels,
|
||||
s->blocksize, s->sample_shift);
|
||||
|
||||
if (bytes_read > buf_size) {
|
||||
av_log(s->avctx, AV_LOG_ERROR, "overread: %d\n", bytes_read - buf_size);
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
if (bytes_read < buf_size) {
|
||||
av_log(s->avctx, AV_LOG_DEBUG, "underread: %d orig size: %d\n",
|
||||
buf_size - bytes_read, buf_size);
|
||||
}
|
||||
|
||||
*got_frame_ptr = 1;
|
||||
|
||||
return bytes_read;
|
||||
}
|
||||
|
||||
#if HAVE_THREADS
|
||||
static int init_thread_copy(AVCodecContext *avctx)
|
||||
{
|
||||
FLACContext *s = avctx->priv_data;
|
||||
s->decoded_buffer = NULL;
|
||||
s->decoded_buffer_size = 0;
|
||||
s->avctx = avctx;
|
||||
if (s->flac_stream_info.max_blocksize)
|
||||
return allocate_buffers(s);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static av_cold int flac_decode_close(AVCodecContext *avctx)
|
||||
{
|
||||
FLACContext *s = avctx->priv_data;
|
||||
|
||||
av_freep(&s->decoded_buffer);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const AVOption options[] = {
|
||||
{ "use_buggy_lpc", "emulate old buggy lavc behavior", offsetof(FLACContext, buggy_lpc), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_AUDIO_PARAM },
|
||||
{ NULL },
|
||||
};
|
||||
|
||||
static const AVClass flac_decoder_class = {
|
||||
"FLAC decoder",
|
||||
av_default_item_name,
|
||||
options,
|
||||
LIBAVUTIL_VERSION_INT,
|
||||
};
|
||||
|
||||
AVCodec ff_flac_decoder = {
|
||||
.name = "flac",
|
||||
.long_name = NULL_IF_CONFIG_SMALL("FLAC (Free Lossless Audio Codec)"),
|
||||
.type = AVMEDIA_TYPE_AUDIO,
|
||||
.id = AV_CODEC_ID_FLAC,
|
||||
.priv_data_size = sizeof(FLACContext),
|
||||
.init = flac_decode_init,
|
||||
.close = flac_decode_close,
|
||||
.decode = flac_decode_frame,
|
||||
.init_thread_copy = ONLY_IF_THREADS_ENABLED(init_thread_copy),
|
||||
.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS,
|
||||
.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16,
|
||||
AV_SAMPLE_FMT_S16P,
|
||||
AV_SAMPLE_FMT_S32,
|
||||
AV_SAMPLE_FMT_S32P,
|
||||
AV_SAMPLE_FMT_NONE },
|
||||
.priv_class = &flac_decoder_class,
|
||||
};
|
|
@ -0,0 +1,130 @@
|
|||
/*
|
||||
* Copyright (c) 2012 Mans Rullgard <mans@mansr.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 "libavutil/attributes.h"
|
||||
#include "libavutil/samplefmt.h"
|
||||
#include "flacdsp.h"
|
||||
#include "config.h"
|
||||
|
||||
#define SAMPLE_SIZE 16
|
||||
#define PLANAR 0
|
||||
#include "flacdsp_template.c"
|
||||
#include "flacdsp_lpc_template.c"
|
||||
|
||||
#undef PLANAR
|
||||
#define PLANAR 1
|
||||
#include "flacdsp_template.c"
|
||||
|
||||
#undef SAMPLE_SIZE
|
||||
#undef PLANAR
|
||||
#define SAMPLE_SIZE 32
|
||||
#define PLANAR 0
|
||||
#include "flacdsp_template.c"
|
||||
#include "flacdsp_lpc_template.c"
|
||||
|
||||
#undef PLANAR
|
||||
#define PLANAR 1
|
||||
#include "flacdsp_template.c"
|
||||
|
||||
static void flac_lpc_16_c(int32_t *decoded, const int coeffs[32],
|
||||
int pred_order, int qlevel, int len)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i = pred_order; i < len - 1; i += 2, decoded += 2) {
|
||||
int c = coeffs[0];
|
||||
int d = decoded[0];
|
||||
int s0 = 0, s1 = 0;
|
||||
for (j = 1; j < pred_order; j++) {
|
||||
s0 += c*d;
|
||||
d = decoded[j];
|
||||
s1 += c*d;
|
||||
c = coeffs[j];
|
||||
}
|
||||
s0 += c*d;
|
||||
d = decoded[j] += s0 >> qlevel;
|
||||
s1 += c*d;
|
||||
decoded[j + 1] += s1 >> qlevel;
|
||||
}
|
||||
if (i < len) {
|
||||
int sum = 0;
|
||||
for (j = 0; j < pred_order; j++)
|
||||
sum += coeffs[j] * decoded[j];
|
||||
decoded[j] += sum >> qlevel;
|
||||
}
|
||||
}
|
||||
|
||||
static void flac_lpc_32_c(int32_t *decoded, const int coeffs[32],
|
||||
int pred_order, int qlevel, int len)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i = pred_order; i < len; i++, decoded++) {
|
||||
int64_t sum = 0;
|
||||
for (j = 0; j < pred_order; j++)
|
||||
sum += (int64_t)coeffs[j] * decoded[j];
|
||||
decoded[j] += sum >> qlevel;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
av_cold void ff_flacdsp_init(FLACDSPContext *c, enum AVSampleFormat fmt, int channels,
|
||||
int bps)
|
||||
{
|
||||
c->lpc16 = flac_lpc_16_c;
|
||||
c->lpc32 = flac_lpc_32_c;
|
||||
c->lpc16_encode = flac_lpc_encode_c_16;
|
||||
c->lpc32_encode = flac_lpc_encode_c_32;
|
||||
|
||||
switch (fmt) {
|
||||
case AV_SAMPLE_FMT_S32:
|
||||
c->decorrelate[0] = flac_decorrelate_indep_c_32;
|
||||
c->decorrelate[1] = flac_decorrelate_ls_c_32;
|
||||
c->decorrelate[2] = flac_decorrelate_rs_c_32;
|
||||
c->decorrelate[3] = flac_decorrelate_ms_c_32;
|
||||
break;
|
||||
|
||||
case AV_SAMPLE_FMT_S32P:
|
||||
c->decorrelate[0] = flac_decorrelate_indep_c_32p;
|
||||
c->decorrelate[1] = flac_decorrelate_ls_c_32p;
|
||||
c->decorrelate[2] = flac_decorrelate_rs_c_32p;
|
||||
c->decorrelate[3] = flac_decorrelate_ms_c_32p;
|
||||
break;
|
||||
|
||||
case AV_SAMPLE_FMT_S16:
|
||||
c->decorrelate[0] = flac_decorrelate_indep_c_16;
|
||||
c->decorrelate[1] = flac_decorrelate_ls_c_16;
|
||||
c->decorrelate[2] = flac_decorrelate_rs_c_16;
|
||||
c->decorrelate[3] = flac_decorrelate_ms_c_16;
|
||||
break;
|
||||
|
||||
case AV_SAMPLE_FMT_S16P:
|
||||
c->decorrelate[0] = flac_decorrelate_indep_c_16p;
|
||||
c->decorrelate[1] = flac_decorrelate_ls_c_16p;
|
||||
c->decorrelate[2] = flac_decorrelate_rs_c_16p;
|
||||
c->decorrelate[3] = flac_decorrelate_ms_c_16p;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ARCH_ARM)
|
||||
ff_flacdsp_init_arm(c, fmt, channels, bps);
|
||||
if (ARCH_X86)
|
||||
ff_flacdsp_init_x86(c, fmt, channels, bps);
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* 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_FLACDSP_H
|
||||
#define AVCODEC_FLACDSP_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "libavutil/samplefmt.h"
|
||||
|
||||
typedef struct FLACDSPContext {
|
||||
void (*decorrelate[4])(uint8_t **out, int32_t **in, int channels,
|
||||
int len, int shift);
|
||||
void (*lpc16)(int32_t *samples, const int coeffs[32], int order,
|
||||
int qlevel, int len);
|
||||
void (*lpc32)(int32_t *samples, const int coeffs[32], int order,
|
||||
int qlevel, int len);
|
||||
void (*lpc16_encode)(int32_t *res, const int32_t *smp, int len, int order,
|
||||
const int32_t coefs[32], int shift);
|
||||
void (*lpc32_encode)(int32_t *res, const int32_t *smp, int len, int order,
|
||||
const int32_t coefs[32], int shift);
|
||||
} FLACDSPContext;
|
||||
|
||||
void ff_flacdsp_init(FLACDSPContext *c, enum AVSampleFormat fmt, int channels, int bps);
|
||||
void ff_flacdsp_init_arm(FLACDSPContext *c, enum AVSampleFormat fmt, int channels, int bps);
|
||||
void ff_flacdsp_init_x86(FLACDSPContext *c, enum AVSampleFormat fmt, int channels, int bps);
|
||||
|
||||
#endif /* AVCODEC_FLACDSP_H */
|
|
@ -0,0 +1,159 @@
|
|||
/*
|
||||
* 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 <stdint.h>
|
||||
#include "libavutil/avutil.h"
|
||||
#include "mathops.h"
|
||||
|
||||
#undef FUNC
|
||||
#undef sum_type
|
||||
#undef MUL
|
||||
#undef CLIP
|
||||
#undef FSUF
|
||||
|
||||
#define FUNC(n) AV_JOIN(n ## _, SAMPLE_SIZE)
|
||||
|
||||
#if SAMPLE_SIZE == 32
|
||||
# define sum_type int64_t
|
||||
# define MUL(a, b) MUL64(a, b)
|
||||
# define CLIP(x) av_clipl_int32(x)
|
||||
#else
|
||||
# define sum_type int32_t
|
||||
# define MUL(a, b) ((a) * (b))
|
||||
# define CLIP(x) (x)
|
||||
#endif
|
||||
|
||||
#define LPC1(x) { \
|
||||
int c = coefs[(x)-1]; \
|
||||
p0 += MUL(c, s); \
|
||||
s = smp[i-(x)+1]; \
|
||||
p1 += MUL(c, s); \
|
||||
}
|
||||
|
||||
static av_always_inline void FUNC(lpc_encode_unrolled)(int32_t *res,
|
||||
const int32_t *smp, int len, int order,
|
||||
const int32_t *coefs, int shift, int big)
|
||||
{
|
||||
int i;
|
||||
for (i = order; i < len; i += 2) {
|
||||
int s = smp[i-order];
|
||||
sum_type p0 = 0, p1 = 0;
|
||||
if (big) {
|
||||
switch (order) {
|
||||
case 32: LPC1(32)
|
||||
case 31: LPC1(31)
|
||||
case 30: LPC1(30)
|
||||
case 29: LPC1(29)
|
||||
case 28: LPC1(28)
|
||||
case 27: LPC1(27)
|
||||
case 26: LPC1(26)
|
||||
case 25: LPC1(25)
|
||||
case 24: LPC1(24)
|
||||
case 23: LPC1(23)
|
||||
case 22: LPC1(22)
|
||||
case 21: LPC1(21)
|
||||
case 20: LPC1(20)
|
||||
case 19: LPC1(19)
|
||||
case 18: LPC1(18)
|
||||
case 17: LPC1(17)
|
||||
case 16: LPC1(16)
|
||||
case 15: LPC1(15)
|
||||
case 14: LPC1(14)
|
||||
case 13: LPC1(13)
|
||||
case 12: LPC1(12)
|
||||
case 11: LPC1(11)
|
||||
case 10: LPC1(10)
|
||||
case 9: LPC1( 9)
|
||||
LPC1( 8)
|
||||
LPC1( 7)
|
||||
LPC1( 6)
|
||||
LPC1( 5)
|
||||
LPC1( 4)
|
||||
LPC1( 3)
|
||||
LPC1( 2)
|
||||
LPC1( 1)
|
||||
}
|
||||
} else {
|
||||
switch (order) {
|
||||
case 8: LPC1( 8)
|
||||
case 7: LPC1( 7)
|
||||
case 6: LPC1( 6)
|
||||
case 5: LPC1( 5)
|
||||
case 4: LPC1( 4)
|
||||
case 3: LPC1( 3)
|
||||
case 2: LPC1( 2)
|
||||
case 1: LPC1( 1)
|
||||
}
|
||||
}
|
||||
res[i ] = smp[i ] - CLIP(p0 >> shift);
|
||||
res[i+1] = smp[i+1] - CLIP(p1 >> shift);
|
||||
}
|
||||
}
|
||||
|
||||
static void FUNC(flac_lpc_encode_c)(int32_t *res, const int32_t *smp, int len,
|
||||
int order, const int32_t *coefs, int shift)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < order; i++)
|
||||
res[i] = smp[i];
|
||||
#if CONFIG_SMALL
|
||||
for (i = order; i < len; i += 2) {
|
||||
int j;
|
||||
int s = smp[i];
|
||||
sum_type p0 = 0, p1 = 0;
|
||||
for (j = 0; j < order; j++) {
|
||||
int c = coefs[j];
|
||||
p1 += MUL(c, s);
|
||||
s = smp[i-j-1];
|
||||
p0 += MUL(c, s);
|
||||
}
|
||||
res[i ] = smp[i ] - CLIP(p0 >> shift);
|
||||
res[i+1] = smp[i+1] - CLIP(p1 >> shift);
|
||||
}
|
||||
#else
|
||||
switch (order) {
|
||||
case 1: FUNC(lpc_encode_unrolled)(res, smp, len, 1, coefs, shift, 0); break;
|
||||
case 2: FUNC(lpc_encode_unrolled)(res, smp, len, 2, coefs, shift, 0); break;
|
||||
case 3: FUNC(lpc_encode_unrolled)(res, smp, len, 3, coefs, shift, 0); break;
|
||||
case 4: FUNC(lpc_encode_unrolled)(res, smp, len, 4, coefs, shift, 0); break;
|
||||
case 5: FUNC(lpc_encode_unrolled)(res, smp, len, 5, coefs, shift, 0); break;
|
||||
case 6: FUNC(lpc_encode_unrolled)(res, smp, len, 6, coefs, shift, 0); break;
|
||||
case 7: FUNC(lpc_encode_unrolled)(res, smp, len, 7, coefs, shift, 0); break;
|
||||
case 8: FUNC(lpc_encode_unrolled)(res, smp, len, 8, coefs, shift, 0); break;
|
||||
default: FUNC(lpc_encode_unrolled)(res, smp, len, order, coefs, shift, 1); break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Comment for clarity/de-obfuscation.
|
||||
*
|
||||
* for (int i = order; i < len; i++) {
|
||||
* int32_t p = 0;
|
||||
* for (int j = 0; j < order; j++) {
|
||||
* int c = coefs[j];
|
||||
* int s = smp[(i-1)-j];
|
||||
* p += c*s;
|
||||
* }
|
||||
* res[i] = smp[i] - (p >> shift);
|
||||
* }
|
||||
*
|
||||
* The CONFIG_SMALL code above simplifies to this, in the case of SAMPLE_SIZE
|
||||
* not being equal to 32 (at the present time that means for 16-bit audio). The
|
||||
* code above does 2 samples per iteration. Commit bfdd5bc (made all the way
|
||||
* back in 2007) says that way is faster.
|
||||
*/
|
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
* Copyright (c) 2012 Mans Rullgard <mans@mansr.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 <stdint.h>
|
||||
#include "libavutil/avutil.h"
|
||||
|
||||
#undef FUNC
|
||||
#undef FSUF
|
||||
#undef sample
|
||||
#undef sample_type
|
||||
#undef OUT
|
||||
#undef S
|
||||
|
||||
#if SAMPLE_SIZE == 32
|
||||
# define sample_type int32_t
|
||||
#else
|
||||
# define sample_type int16_t
|
||||
#endif
|
||||
|
||||
#if PLANAR
|
||||
# define FSUF AV_JOIN(SAMPLE_SIZE, p)
|
||||
# define sample sample_type *
|
||||
# define OUT(n) n
|
||||
# define S(s, c, i) (s[c][i])
|
||||
#else
|
||||
# define FSUF SAMPLE_SIZE
|
||||
# define sample sample_type
|
||||
# define OUT(n) n[0]
|
||||
# define S(s, c, i) (*s++)
|
||||
#endif
|
||||
|
||||
#define FUNC(n) AV_JOIN(n ## _, FSUF)
|
||||
|
||||
static void FUNC(flac_decorrelate_indep_c)(uint8_t **out, int32_t **in,
|
||||
int channels, int len, int shift)
|
||||
{
|
||||
sample *samples = (sample *) OUT(out);
|
||||
int i, j;
|
||||
|
||||
for (j = 0; j < len; j++)
|
||||
for (i = 0; i < channels; i++)
|
||||
S(samples, i, j) = in[i][j] << shift;
|
||||
}
|
||||
|
||||
static void FUNC(flac_decorrelate_ls_c)(uint8_t **out, int32_t **in,
|
||||
int channels, int len, int shift)
|
||||
{
|
||||
sample *samples = (sample *) OUT(out);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
int a = in[0][i];
|
||||
int b = in[1][i];
|
||||
S(samples, 0, i) = a << shift;
|
||||
S(samples, 1, i) = (a - b) << shift;
|
||||
}
|
||||
}
|
||||
|
||||
static void FUNC(flac_decorrelate_rs_c)(uint8_t **out, int32_t **in,
|
||||
int channels, int len, int shift)
|
||||
{
|
||||
sample *samples = (sample *) OUT(out);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
int a = in[0][i];
|
||||
int b = in[1][i];
|
||||
S(samples, 0, i) = (a + b) << shift;
|
||||
S(samples, 1, i) = b << shift;
|
||||
}
|
||||
}
|
||||
|
||||
static void FUNC(flac_decorrelate_ms_c)(uint8_t **out, int32_t **in,
|
||||
int channels, int len, int shift)
|
||||
{
|
||||
sample *samples = (sample *) OUT(out);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
int a = in[0][i];
|
||||
int b = in[1][i];
|
||||
a -= b >> 1;
|
||||
S(samples, 0, i) = (a + b) << shift;
|
||||
S(samples, 1, i) = a << shift;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,173 @@
|
|||
/*
|
||||
* exp golomb vlc stuff
|
||||
* Copyright (c) 2003 Michael Niedermayer <michaelni@gmx.at>
|
||||
*
|
||||
* 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
|
||||
* @brief
|
||||
* exp golomb vlc stuff
|
||||
* @author Michael Niedermayer <michaelni@gmx.at>
|
||||
*/
|
||||
|
||||
#include "libavutil/common.h"
|
||||
|
||||
const uint8_t ff_golomb_vlc_len[512]={
|
||||
19,17,15,15,13,13,13,13,11,11,11,11,11,11,11,11,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
|
||||
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
|
||||
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
|
||||
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
|
||||
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
|
||||
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
|
||||
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
|
||||
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
|
||||
};
|
||||
|
||||
const uint8_t ff_ue_golomb_vlc_code[512]={
|
||||
32,32,32,32,32,32,32,32,31,32,32,32,32,32,32,32,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,
|
||||
7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9,10,10,10,10,11,11,11,11,12,12,12,12,13,13,13,13,14,14,14,14,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
|
||||
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
const int8_t ff_se_golomb_vlc_code[512]={
|
||||
17, 17, 17, 17, 17, 17, 17, 17, 16, 17, 17, 17, 17, 17, 17, 17, 8, -8, 9, -9, 10,-10, 11,-11, 12,-12, 13,-13, 14,-14, 15,-15,
|
||||
4, 4, 4, 4, -4, -4, -4, -4, 5, 5, 5, 5, -5, -5, -5, -5, 6, 6, 6, 6, -6, -6, -6, -6, 7, 7, 7, 7, -7, -7, -7, -7,
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
};
|
||||
|
||||
|
||||
const uint8_t ff_ue_golomb_len[256]={
|
||||
1, 3, 3, 5, 5, 5, 5, 7, 7, 7, 7, 7, 7, 7, 7, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,11,
|
||||
11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,13,
|
||||
13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,
|
||||
13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,15,
|
||||
15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
|
||||
15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
|
||||
15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
|
||||
15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,17,
|
||||
};
|
||||
|
||||
const uint8_t ff_interleaved_golomb_vlc_len[256]={
|
||||
9,9,7,7,9,9,7,7,5,5,5,5,5,5,5,5,
|
||||
9,9,7,7,9,9,7,7,5,5,5,5,5,5,5,5,
|
||||
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
|
||||
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
|
||||
9,9,7,7,9,9,7,7,5,5,5,5,5,5,5,5,
|
||||
9,9,7,7,9,9,7,7,5,5,5,5,5,5,5,5,
|
||||
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
|
||||
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
};
|
||||
|
||||
const uint8_t ff_interleaved_ue_golomb_vlc_code[256]={
|
||||
15,16,7, 7, 17,18,8, 8, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
19,20,9, 9, 21,22,10,10,4, 4, 4, 4, 4, 4, 4, 4,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
23,24,11,11,25,26,12,12,5, 5, 5, 5, 5, 5, 5, 5,
|
||||
27,28,13,13,29,30,14,14,6, 6, 6, 6, 6, 6, 6, 6,
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
};
|
||||
|
||||
const int8_t ff_interleaved_se_golomb_vlc_code[256]={
|
||||
8, -8, 4, 4, 9, -9, -4, -4, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
10,-10, 5, 5, 11,-11, -5, -5, -2, -2, -2, -2, -2, -2, -2, -2,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
12,-12, 6, 6, 13,-13, -6, -6, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
14,-14, 7, 7, 15,-15, -7, -7, -3, -3, -3, -3, -3, -3, -3, -3,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
};
|
||||
|
||||
const uint8_t ff_interleaved_dirac_golomb_vlc_code[256]={
|
||||
0, 1, 0, 0, 2, 3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
4, 5, 2, 2, 6, 7, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
8, 9, 4, 4, 10,11,5, 5, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
12,13,6, 6, 14,15,7, 7, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,};
|
|
@ -0,0 +1,579 @@
|
|||
/*
|
||||
* exp golomb vlc stuff
|
||||
* Copyright (c) 2003 Michael Niedermayer <michaelni@gmx.at>
|
||||
* Copyright (c) 2004 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
|
||||
* @brief
|
||||
* exp golomb vlc stuff
|
||||
* @author Michael Niedermayer <michaelni@gmx.at> and Alex Beregszaszi
|
||||
*/
|
||||
|
||||
#ifndef AVCODEC_GOLOMB_H
|
||||
#define AVCODEC_GOLOMB_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "get_bits.h"
|
||||
#include "put_bits.h"
|
||||
|
||||
#define INVALID_VLC 0x80000000
|
||||
|
||||
extern const uint8_t ff_golomb_vlc_len[512];
|
||||
extern const uint8_t ff_ue_golomb_vlc_code[512];
|
||||
extern const int8_t ff_se_golomb_vlc_code[512];
|
||||
extern const uint8_t ff_ue_golomb_len[256];
|
||||
|
||||
extern const uint8_t ff_interleaved_golomb_vlc_len[256];
|
||||
extern const uint8_t ff_interleaved_ue_golomb_vlc_code[256];
|
||||
extern const int8_t ff_interleaved_se_golomb_vlc_code[256];
|
||||
extern const uint8_t ff_interleaved_dirac_golomb_vlc_code[256];
|
||||
|
||||
/**
|
||||
* Read an unsigned Exp-Golomb code in the range 0 to 8190.
|
||||
*/
|
||||
static inline int get_ue_golomb(GetBitContext *gb)
|
||||
{
|
||||
unsigned int buf;
|
||||
|
||||
OPEN_READER(re, gb);
|
||||
UPDATE_CACHE(re, gb);
|
||||
buf = GET_CACHE(re, gb);
|
||||
|
||||
if (buf >= (1 << 27)) {
|
||||
buf >>= 32 - 9;
|
||||
LAST_SKIP_BITS(re, gb, ff_golomb_vlc_len[buf]);
|
||||
CLOSE_READER(re, gb);
|
||||
|
||||
return ff_ue_golomb_vlc_code[buf];
|
||||
} else {
|
||||
int log = 2 * av_log2(buf) - 31;
|
||||
LAST_SKIP_BITS(re, gb, 32 - log);
|
||||
CLOSE_READER(re, gb);
|
||||
if (log < 7) {
|
||||
av_log(NULL, AV_LOG_ERROR, "Invalid UE golomb code\n");
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
buf >>= log;
|
||||
buf--;
|
||||
|
||||
return buf;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read an unsigned Exp-Golomb code in the range 0 to UINT32_MAX-1.
|
||||
*/
|
||||
static inline unsigned get_ue_golomb_long(GetBitContext *gb)
|
||||
{
|
||||
unsigned buf, log;
|
||||
|
||||
buf = show_bits_long(gb, 32);
|
||||
log = 31 - av_log2(buf);
|
||||
skip_bits_long(gb, log);
|
||||
|
||||
return get_bits_long(gb, log + 1) - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* read unsigned exp golomb code, constraint to a max of 31.
|
||||
* the return value is undefined if the stored value exceeds 31.
|
||||
*/
|
||||
static inline int get_ue_golomb_31(GetBitContext *gb)
|
||||
{
|
||||
unsigned int buf;
|
||||
|
||||
OPEN_READER(re, gb);
|
||||
UPDATE_CACHE(re, gb);
|
||||
buf = GET_CACHE(re, gb);
|
||||
|
||||
buf >>= 32 - 9;
|
||||
LAST_SKIP_BITS(re, gb, ff_golomb_vlc_len[buf]);
|
||||
CLOSE_READER(re, gb);
|
||||
|
||||
return ff_ue_golomb_vlc_code[buf];
|
||||
}
|
||||
|
||||
static inline unsigned get_interleaved_ue_golomb(GetBitContext *gb)
|
||||
{
|
||||
uint32_t buf;
|
||||
|
||||
OPEN_READER(re, gb);
|
||||
UPDATE_CACHE(re, gb);
|
||||
buf = GET_CACHE(re, gb);
|
||||
|
||||
if (buf & 0xAA800000) {
|
||||
buf >>= 32 - 8;
|
||||
LAST_SKIP_BITS(re, gb, ff_interleaved_golomb_vlc_len[buf]);
|
||||
CLOSE_READER(re, gb);
|
||||
|
||||
return ff_interleaved_ue_golomb_vlc_code[buf];
|
||||
} else {
|
||||
unsigned ret = 1;
|
||||
|
||||
do {
|
||||
buf >>= 32 - 8;
|
||||
LAST_SKIP_BITS(re, gb,
|
||||
FFMIN(ff_interleaved_golomb_vlc_len[buf], 8));
|
||||
|
||||
if (ff_interleaved_golomb_vlc_len[buf] != 9) {
|
||||
ret <<= (ff_interleaved_golomb_vlc_len[buf] - 1) >> 1;
|
||||
ret |= ff_interleaved_dirac_golomb_vlc_code[buf];
|
||||
break;
|
||||
}
|
||||
ret = (ret << 4) | ff_interleaved_dirac_golomb_vlc_code[buf];
|
||||
UPDATE_CACHE(re, gb);
|
||||
buf = GET_CACHE(re, gb);
|
||||
} while (ret<0x8000000U && BITS_AVAILABLE(re, gb));
|
||||
|
||||
CLOSE_READER(re, gb);
|
||||
return ret - 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* read unsigned truncated exp golomb code.
|
||||
*/
|
||||
static inline int get_te0_golomb(GetBitContext *gb, int range)
|
||||
{
|
||||
av_assert2(range >= 1);
|
||||
|
||||
if (range == 1)
|
||||
return 0;
|
||||
else if (range == 2)
|
||||
return get_bits1(gb) ^ 1;
|
||||
else
|
||||
return get_ue_golomb(gb);
|
||||
}
|
||||
|
||||
/**
|
||||
* read unsigned truncated exp golomb code.
|
||||
*/
|
||||
static inline int get_te_golomb(GetBitContext *gb, int range)
|
||||
{
|
||||
av_assert2(range >= 1);
|
||||
|
||||
if (range == 2)
|
||||
return get_bits1(gb) ^ 1;
|
||||
else
|
||||
return get_ue_golomb(gb);
|
||||
}
|
||||
|
||||
/**
|
||||
* read signed exp golomb code.
|
||||
*/
|
||||
static inline int get_se_golomb(GetBitContext *gb)
|
||||
{
|
||||
unsigned int buf;
|
||||
|
||||
OPEN_READER(re, gb);
|
||||
UPDATE_CACHE(re, gb);
|
||||
buf = GET_CACHE(re, gb);
|
||||
|
||||
if (buf >= (1 << 27)) {
|
||||
buf >>= 32 - 9;
|
||||
LAST_SKIP_BITS(re, gb, ff_golomb_vlc_len[buf]);
|
||||
CLOSE_READER(re, gb);
|
||||
|
||||
return ff_se_golomb_vlc_code[buf];
|
||||
} else {
|
||||
int log = av_log2(buf), sign;
|
||||
LAST_SKIP_BITS(re, gb, 31 - log);
|
||||
UPDATE_CACHE(re, gb);
|
||||
buf = GET_CACHE(re, gb);
|
||||
|
||||
buf >>= log;
|
||||
|
||||
LAST_SKIP_BITS(re, gb, 32 - log);
|
||||
CLOSE_READER(re, gb);
|
||||
|
||||
sign = -(buf & 1);
|
||||
buf = ((buf >> 1) ^ sign) - sign;
|
||||
|
||||
return buf;
|
||||
}
|
||||
}
|
||||
|
||||
static inline int get_se_golomb_long(GetBitContext *gb)
|
||||
{
|
||||
unsigned int buf = get_ue_golomb_long(gb);
|
||||
int sign = (buf & 1) - 1;
|
||||
return ((buf >> 1) ^ sign) + 1;
|
||||
}
|
||||
|
||||
static inline int get_interleaved_se_golomb(GetBitContext *gb)
|
||||
{
|
||||
unsigned int buf;
|
||||
|
||||
OPEN_READER(re, gb);
|
||||
UPDATE_CACHE(re, gb);
|
||||
buf = GET_CACHE(re, gb);
|
||||
|
||||
if (buf & 0xAA800000) {
|
||||
buf >>= 32 - 8;
|
||||
LAST_SKIP_BITS(re, gb, ff_interleaved_golomb_vlc_len[buf]);
|
||||
CLOSE_READER(re, gb);
|
||||
|
||||
return ff_interleaved_se_golomb_vlc_code[buf];
|
||||
} else {
|
||||
int log;
|
||||
LAST_SKIP_BITS(re, gb, 8);
|
||||
UPDATE_CACHE(re, gb);
|
||||
buf |= 1 | (GET_CACHE(re, gb) >> 8);
|
||||
|
||||
if ((buf & 0xAAAAAAAA) == 0)
|
||||
return INVALID_VLC;
|
||||
|
||||
for (log = 31; (buf & 0x80000000) == 0; log--)
|
||||
buf = (buf << 2) - ((buf << log) >> (log - 1)) + (buf >> 30);
|
||||
|
||||
LAST_SKIP_BITS(re, gb, 63 - 2 * log - 8);
|
||||
CLOSE_READER(re, gb);
|
||||
|
||||
return (signed) (((((buf << log) >> log) - 1) ^ -(buf & 0x1)) + 1) >> 1;
|
||||
}
|
||||
}
|
||||
|
||||
static inline int dirac_get_se_golomb(GetBitContext *gb)
|
||||
{
|
||||
uint32_t ret = get_interleaved_ue_golomb(gb);
|
||||
|
||||
if (ret) {
|
||||
int sign = -get_bits1(gb);
|
||||
ret = (ret ^ sign) - sign;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* read unsigned golomb rice code (ffv1).
|
||||
*/
|
||||
static inline int get_ur_golomb(GetBitContext *gb, int k, int limit,
|
||||
int esc_len)
|
||||
{
|
||||
unsigned int buf;
|
||||
int log;
|
||||
|
||||
OPEN_READER(re, gb);
|
||||
UPDATE_CACHE(re, gb);
|
||||
buf = GET_CACHE(re, gb);
|
||||
|
||||
log = av_log2(buf);
|
||||
|
||||
if (log > 31 - limit) {
|
||||
buf >>= log - k;
|
||||
buf += (30U - log) << k;
|
||||
LAST_SKIP_BITS(re, gb, 32 + k - log);
|
||||
CLOSE_READER(re, gb);
|
||||
|
||||
return buf;
|
||||
} else {
|
||||
LAST_SKIP_BITS(re, gb, limit);
|
||||
UPDATE_CACHE(re, gb);
|
||||
|
||||
buf = SHOW_UBITS(re, gb, esc_len);
|
||||
|
||||
LAST_SKIP_BITS(re, gb, esc_len);
|
||||
CLOSE_READER(re, gb);
|
||||
|
||||
return buf + limit - 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* read unsigned golomb rice code (jpegls).
|
||||
*/
|
||||
static inline int get_ur_golomb_jpegls(GetBitContext *gb, int k, int limit,
|
||||
int esc_len)
|
||||
{
|
||||
unsigned int buf;
|
||||
int log;
|
||||
|
||||
OPEN_READER(re, gb);
|
||||
UPDATE_CACHE(re, gb);
|
||||
buf = GET_CACHE(re, gb);
|
||||
|
||||
log = av_log2(buf);
|
||||
|
||||
if (log - k >= 32 - MIN_CACHE_BITS + (MIN_CACHE_BITS == 32) &&
|
||||
32 - log < limit) {
|
||||
buf >>= log - k;
|
||||
buf += (30U - log) << k;
|
||||
LAST_SKIP_BITS(re, gb, 32 + k - log);
|
||||
CLOSE_READER(re, gb);
|
||||
|
||||
return buf;
|
||||
} else {
|
||||
int i;
|
||||
for (i = 0; i < limit && SHOW_UBITS(re, gb, 1) == 0; i++) {
|
||||
if (gb->size_in_bits <= re_index)
|
||||
return -1;
|
||||
LAST_SKIP_BITS(re, gb, 1);
|
||||
UPDATE_CACHE(re, gb);
|
||||
}
|
||||
SKIP_BITS(re, gb, 1);
|
||||
|
||||
if (i < limit - 1) {
|
||||
if (k) {
|
||||
if (k > MIN_CACHE_BITS - 1) {
|
||||
buf = SHOW_UBITS(re, gb, 16) << (k-16);
|
||||
LAST_SKIP_BITS(re, gb, 16);
|
||||
UPDATE_CACHE(re, gb);
|
||||
buf |= SHOW_UBITS(re, gb, k-16);
|
||||
LAST_SKIP_BITS(re, gb, k-16);
|
||||
} else {
|
||||
buf = SHOW_UBITS(re, gb, k);
|
||||
LAST_SKIP_BITS(re, gb, k);
|
||||
}
|
||||
} else {
|
||||
buf = 0;
|
||||
}
|
||||
|
||||
CLOSE_READER(re, gb);
|
||||
return buf + (i << k);
|
||||
} else if (i == limit - 1) {
|
||||
buf = SHOW_UBITS(re, gb, esc_len);
|
||||
LAST_SKIP_BITS(re, gb, esc_len);
|
||||
CLOSE_READER(re, gb);
|
||||
|
||||
return buf + 1;
|
||||
} else
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* read signed golomb rice code (ffv1).
|
||||
*/
|
||||
static inline int get_sr_golomb(GetBitContext *gb, int k, int limit,
|
||||
int esc_len)
|
||||
{
|
||||
unsigned v = get_ur_golomb(gb, k, limit, esc_len);
|
||||
return (v >> 1) ^ -(v & 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* read signed golomb rice code (flac).
|
||||
*/
|
||||
static inline int get_sr_golomb_flac(GetBitContext *gb, int k, int limit,
|
||||
int esc_len)
|
||||
{
|
||||
unsigned v = get_ur_golomb_jpegls(gb, k, limit, esc_len);
|
||||
return (v >> 1) ^ -(v & 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* read unsigned golomb rice code (shorten).
|
||||
*/
|
||||
static inline unsigned int get_ur_golomb_shorten(GetBitContext *gb, int k)
|
||||
{
|
||||
return get_ur_golomb_jpegls(gb, k, INT_MAX, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* read signed golomb rice code (shorten).
|
||||
*/
|
||||
static inline int get_sr_golomb_shorten(GetBitContext *gb, int k)
|
||||
{
|
||||
int uvar = get_ur_golomb_jpegls(gb, k + 1, INT_MAX, 0);
|
||||
return (uvar >> 1) ^ -(uvar & 1);
|
||||
}
|
||||
|
||||
#ifdef TRACE
|
||||
|
||||
static inline int get_ue(GetBitContext *s, const char *file, const char *func,
|
||||
int line)
|
||||
{
|
||||
int show = show_bits(s, 24);
|
||||
int pos = get_bits_count(s);
|
||||
int i = get_ue_golomb(s);
|
||||
int len = get_bits_count(s) - pos;
|
||||
int bits = show >> (24 - len);
|
||||
|
||||
av_log(NULL, AV_LOG_DEBUG, "%5d %2d %3d ue @%5d in %s %s:%d\n",
|
||||
bits, len, i, pos, file, func, line);
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
static inline int get_se(GetBitContext *s, const char *file, const char *func,
|
||||
int line)
|
||||
{
|
||||
int show = show_bits(s, 24);
|
||||
int pos = get_bits_count(s);
|
||||
int i = get_se_golomb(s);
|
||||
int len = get_bits_count(s) - pos;
|
||||
int bits = show >> (24 - len);
|
||||
|
||||
av_log(NULL, AV_LOG_DEBUG, "%5d %2d %3d se @%5d in %s %s:%d\n",
|
||||
bits, len, i, pos, file, func, line);
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
static inline int get_te(GetBitContext *s, int r, char *file, const char *func,
|
||||
int line)
|
||||
{
|
||||
int show = show_bits(s, 24);
|
||||
int pos = get_bits_count(s);
|
||||
int i = get_te0_golomb(s, r);
|
||||
int len = get_bits_count(s) - pos;
|
||||
int bits = show >> (24 - len);
|
||||
|
||||
av_log(NULL, AV_LOG_DEBUG, "%5d %2d %3d te @%5d in %s %s:%d\n",
|
||||
bits, len, i, pos, file, func, line);
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
#define get_ue_golomb(a) get_ue(a, __FILE__, __PRETTY_FUNCTION__, __LINE__)
|
||||
#define get_se_golomb(a) get_se(a, __FILE__, __PRETTY_FUNCTION__, __LINE__)
|
||||
#define get_te_golomb(a, r) get_te(a, r, __FILE__, __PRETTY_FUNCTION__, __LINE__)
|
||||
#define get_te0_golomb(a, r) get_te(a, r, __FILE__, __PRETTY_FUNCTION__, __LINE__)
|
||||
|
||||
#endif /* TRACE */
|
||||
|
||||
/**
|
||||
* write unsigned exp golomb code.
|
||||
*/
|
||||
static inline void set_ue_golomb(PutBitContext *pb, int i)
|
||||
{
|
||||
av_assert2(i >= 0);
|
||||
|
||||
if (i < 256)
|
||||
put_bits(pb, ff_ue_golomb_len[i], i + 1);
|
||||
else {
|
||||
int e = av_log2(i + 1);
|
||||
put_bits(pb, 2 * e + 1, i + 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* write truncated unsigned exp golomb code.
|
||||
*/
|
||||
static inline void set_te_golomb(PutBitContext *pb, int i, int range)
|
||||
{
|
||||
av_assert2(range >= 1);
|
||||
av_assert2(i <= range);
|
||||
|
||||
if (range == 2)
|
||||
put_bits(pb, 1, i ^ 1);
|
||||
else
|
||||
set_ue_golomb(pb, i);
|
||||
}
|
||||
|
||||
/**
|
||||
* write signed exp golomb code. 16 bits at most.
|
||||
*/
|
||||
static inline void set_se_golomb(PutBitContext *pb, int i)
|
||||
{
|
||||
#if 0
|
||||
if (i <= 0)
|
||||
i = -2 * i;
|
||||
else
|
||||
i = 2 * i - 1;
|
||||
#elif 1
|
||||
i = 2 * i - 1;
|
||||
if (i < 0)
|
||||
i ^= -1; //FIXME check if gcc does the right thing
|
||||
#else
|
||||
i = 2 * i - 1;
|
||||
i ^= (i >> 31);
|
||||
#endif
|
||||
set_ue_golomb(pb, i);
|
||||
}
|
||||
|
||||
/**
|
||||
* write unsigned golomb rice code (ffv1).
|
||||
*/
|
||||
static inline void set_ur_golomb(PutBitContext *pb, int i, int k, int limit,
|
||||
int esc_len)
|
||||
{
|
||||
int e;
|
||||
|
||||
av_assert2(i >= 0);
|
||||
|
||||
e = i >> k;
|
||||
if (e < limit)
|
||||
put_bits(pb, e + k + 1, (1 << k) + av_mod_uintp2(i, k));
|
||||
else
|
||||
put_bits(pb, limit + esc_len, i - limit + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* write unsigned golomb rice code (jpegls).
|
||||
*/
|
||||
static inline void set_ur_golomb_jpegls(PutBitContext *pb, int i, int k,
|
||||
int limit, int esc_len)
|
||||
{
|
||||
int e;
|
||||
|
||||
av_assert2(i >= 0);
|
||||
|
||||
e = (i >> k) + 1;
|
||||
if (e < limit) {
|
||||
while (e > 31) {
|
||||
put_bits(pb, 31, 0);
|
||||
e -= 31;
|
||||
}
|
||||
put_bits(pb, e, 1);
|
||||
if (k)
|
||||
put_sbits(pb, k, i);
|
||||
} else {
|
||||
while (limit > 31) {
|
||||
put_bits(pb, 31, 0);
|
||||
limit -= 31;
|
||||
}
|
||||
put_bits(pb, limit, 1);
|
||||
put_bits(pb, esc_len, i - 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* write signed golomb rice code (ffv1).
|
||||
*/
|
||||
static inline void set_sr_golomb(PutBitContext *pb, int i, int k, int limit,
|
||||
int esc_len)
|
||||
{
|
||||
int v;
|
||||
|
||||
v = -2 * i - 1;
|
||||
v ^= (v >> 31);
|
||||
|
||||
set_ur_golomb(pb, v, k, limit, esc_len);
|
||||
}
|
||||
|
||||
/**
|
||||
* write signed golomb rice code (flac).
|
||||
*/
|
||||
static inline void set_sr_golomb_flac(PutBitContext *pb, int i, int k,
|
||||
int limit, int esc_len)
|
||||
{
|
||||
int v;
|
||||
|
||||
v = -2 * i - 1;
|
||||
v ^= (v >> 31);
|
||||
|
||||
set_ur_golomb_jpegls(pb, v, k, limit, esc_len);
|
||||
}
|
||||
|
||||
#endif /* AVCODEC_GOLOMB_H */
|
|
@ -18,6 +18,12 @@ SOURCES += [
|
|||
'bitstream.c',
|
||||
'codec_desc.c',
|
||||
'dummy_funcs.c',
|
||||
'flac.c',
|
||||
'flac_parser.c',
|
||||
'flacdata.c',
|
||||
'flacdec.c',
|
||||
'flacdsp.c',
|
||||
'golomb.c',
|
||||
'h264pred.c',
|
||||
'imgconvert.c',
|
||||
'log2_tab.c',
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* copyright (c) 2004 Michael Niedermayer <michaelni@gmx.at>
|
||||
*
|
||||
* 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_UNARY_H
|
||||
#define AVCODEC_UNARY_H
|
||||
|
||||
#include "get_bits.h"
|
||||
|
||||
/**
|
||||
* Get unary code of limited length
|
||||
* @param gb GetBitContext
|
||||
* @param[in] stop The bitstop value (unary code of 1's or 0's)
|
||||
* @param[in] len Maximum length
|
||||
* @return Unary length/index
|
||||
*/
|
||||
static inline int get_unary(GetBitContext *gb, int stop, int len)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; i < len && get_bits1(gb) != stop; i++);
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get unary code terminated by a 0 with a maximum length of 33
|
||||
* @param gb GetBitContext
|
||||
* @return Unary length/index
|
||||
*/
|
||||
static inline int get_unary_0_33(GetBitContext *gb)
|
||||
{
|
||||
return get_unary(gb, 0, 33);
|
||||
}
|
||||
|
||||
static inline int get_unary_0_9(GetBitContext *gb)
|
||||
{
|
||||
return get_unary(gb, 0, 9);
|
||||
}
|
||||
|
||||
#endif /* AVCODEC_UNARY_H */
|
|
@ -0,0 +1,313 @@
|
|||
;******************************************************************************
|
||||
;* FLAC DSP SIMD optimizations
|
||||
;*
|
||||
;* Copyright (C) 2014 Loren Merritt
|
||||
;* Copyright (C) 2014 James Almer
|
||||
;*
|
||||
;* 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 "libavutil/x86/x86util.asm"
|
||||
|
||||
SECTION .text
|
||||
|
||||
%macro PMACSDQL 5
|
||||
%if cpuflag(xop)
|
||||
pmacsdql %1, %2, %3, %1
|
||||
%else
|
||||
pmuldq %2, %3
|
||||
paddq %1, %2
|
||||
%endif
|
||||
%endmacro
|
||||
|
||||
%macro LPC_32 1
|
||||
INIT_XMM %1
|
||||
cglobal flac_lpc_32, 5,6,5, decoded, coeffs, pred_order, qlevel, len, j
|
||||
sub lend, pred_orderd
|
||||
jle .ret
|
||||
lea decodedq, [decodedq+pred_orderq*4-8]
|
||||
lea coeffsq, [coeffsq+pred_orderq*4]
|
||||
neg pred_orderq
|
||||
movd m4, qlevelm
|
||||
ALIGN 16
|
||||
.loop_sample:
|
||||
movd m0, [decodedq+pred_orderq*4+8]
|
||||
add decodedq, 8
|
||||
movd m1, [coeffsq+pred_orderq*4]
|
||||
pxor m2, m2
|
||||
pxor m3, m3
|
||||
lea jq, [pred_orderq+1]
|
||||
test jq, jq
|
||||
jz .end_order
|
||||
.loop_order:
|
||||
PMACSDQL m2, m0, m1, m2, m0
|
||||
movd m0, [decodedq+jq*4]
|
||||
PMACSDQL m3, m1, m0, m3, m1
|
||||
movd m1, [coeffsq+jq*4]
|
||||
inc jq
|
||||
jl .loop_order
|
||||
.end_order:
|
||||
PMACSDQL m2, m0, m1, m2, m0
|
||||
psrlq m2, m4
|
||||
movd m0, [decodedq]
|
||||
paddd m0, m2
|
||||
movd [decodedq], m0
|
||||
sub lend, 2
|
||||
jl .ret
|
||||
PMACSDQL m3, m1, m0, m3, m1
|
||||
psrlq m3, m4
|
||||
movd m1, [decodedq+4]
|
||||
paddd m1, m3
|
||||
movd [decodedq+4], m1
|
||||
jg .loop_sample
|
||||
.ret:
|
||||
REP_RET
|
||||
%endmacro
|
||||
|
||||
%if HAVE_XOP_EXTERNAL
|
||||
LPC_32 xop
|
||||
%endif
|
||||
LPC_32 sse4
|
||||
|
||||
;----------------------------------------------------------------------------------
|
||||
;void ff_flac_decorrelate_[lrm]s_16_sse2(uint8_t **out, int32_t **in, int channels,
|
||||
; int len, int shift);
|
||||
;----------------------------------------------------------------------------------
|
||||
%macro FLAC_DECORRELATE_16 3-4
|
||||
cglobal flac_decorrelate_%1_16, 2, 4, 4, out, in0, in1, len
|
||||
%if ARCH_X86_32
|
||||
mov lend, lenm
|
||||
%endif
|
||||
movd m3, r4m
|
||||
shl lend, 2
|
||||
mov in1q, [in0q + gprsize]
|
||||
mov in0q, [in0q]
|
||||
mov outq, [outq]
|
||||
add in1q, lenq
|
||||
add in0q, lenq
|
||||
add outq, lenq
|
||||
neg lenq
|
||||
|
||||
align 16
|
||||
.loop:
|
||||
mova m0, [in0q + lenq]
|
||||
mova m1, [in1q + lenq]
|
||||
%ifidn %1, ms
|
||||
psrad m2, m1, 1
|
||||
psubd m0, m2
|
||||
%endif
|
||||
%ifnidn %1, indep2
|
||||
p%4d m2, m0, m1
|
||||
%endif
|
||||
packssdw m%2, m%2
|
||||
packssdw m%3, m%3
|
||||
punpcklwd m%2, m%3
|
||||
psllw m%2, m3
|
||||
mova [outq + lenq], m%2
|
||||
add lenq, 16
|
||||
jl .loop
|
||||
REP_RET
|
||||
%endmacro
|
||||
|
||||
INIT_XMM sse2
|
||||
FLAC_DECORRELATE_16 ls, 0, 2, sub
|
||||
FLAC_DECORRELATE_16 rs, 2, 1, add
|
||||
FLAC_DECORRELATE_16 ms, 2, 0, add
|
||||
|
||||
;----------------------------------------------------------------------------------
|
||||
;void ff_flac_decorrelate_[lrm]s_32_sse2(uint8_t **out, int32_t **in, int channels,
|
||||
; int len, int shift);
|
||||
;----------------------------------------------------------------------------------
|
||||
%macro FLAC_DECORRELATE_32 5
|
||||
cglobal flac_decorrelate_%1_32, 2, 4, 4, out, in0, in1, len
|
||||
%if ARCH_X86_32
|
||||
mov lend, lenm
|
||||
%endif
|
||||
movd m3, r4m
|
||||
mov in1q, [in0q + gprsize]
|
||||
mov in0q, [in0q]
|
||||
mov outq, [outq]
|
||||
sub in1q, in0q
|
||||
|
||||
align 16
|
||||
.loop:
|
||||
mova m0, [in0q]
|
||||
mova m1, [in0q + in1q]
|
||||
%ifidn %1, ms
|
||||
psrad m2, m1, 1
|
||||
psubd m0, m2
|
||||
%endif
|
||||
p%5d m2, m0, m1
|
||||
pslld m%2, m3
|
||||
pslld m%3, m3
|
||||
|
||||
SBUTTERFLY dq, %2, %3, %4
|
||||
|
||||
mova [outq ], m%2
|
||||
mova [outq + mmsize], m%3
|
||||
|
||||
add in0q, mmsize
|
||||
add outq, mmsize*2
|
||||
sub lend, mmsize/4
|
||||
jg .loop
|
||||
REP_RET
|
||||
%endmacro
|
||||
|
||||
INIT_XMM sse2
|
||||
FLAC_DECORRELATE_32 ls, 0, 2, 1, sub
|
||||
FLAC_DECORRELATE_32 rs, 2, 1, 0, add
|
||||
FLAC_DECORRELATE_32 ms, 2, 0, 1, add
|
||||
|
||||
;-----------------------------------------------------------------------------------------
|
||||
;void ff_flac_decorrelate_indep<ch>_<bps>_<opt>(uint8_t **out, int32_t **in, int channels,
|
||||
; int len, int shift);
|
||||
;-----------------------------------------------------------------------------------------
|
||||
;%1 = bps
|
||||
;%2 = channels
|
||||
;%3 = last xmm reg used
|
||||
;%4 = word/dword (shift instruction)
|
||||
%macro FLAC_DECORRELATE_INDEP 4
|
||||
%define REPCOUNT %2/(32/%1) ; 16bits = channels / 2; 32bits = channels
|
||||
cglobal flac_decorrelate_indep%2_%1, 2, %2+2, %3+1, out, in0, in1, len, in2, in3, in4, in5, in6, in7
|
||||
%if ARCH_X86_32
|
||||
%if %2 == 6
|
||||
DEFINE_ARGS out, in0, in1, in2, in3, in4, in5
|
||||
%define lend dword r3m
|
||||
%else
|
||||
mov lend, lenm
|
||||
%endif
|
||||
%endif
|
||||
movd m%3, r4m
|
||||
|
||||
%assign %%i 1
|
||||
%rep %2-1
|
||||
mov in %+ %%i %+ q, [in0q+%%i*gprsize]
|
||||
%assign %%i %%i+1
|
||||
%endrep
|
||||
|
||||
mov in0q, [in0q]
|
||||
mov outq, [outq]
|
||||
|
||||
%assign %%i 1
|
||||
%rep %2-1
|
||||
sub in %+ %%i %+ q, in0q
|
||||
%assign %%i %%i+1
|
||||
%endrep
|
||||
|
||||
align 16
|
||||
.loop:
|
||||
mova m0, [in0q]
|
||||
|
||||
%assign %%i 1
|
||||
%rep REPCOUNT-1
|
||||
mova m %+ %%i, [in0q + in %+ %%i %+ q]
|
||||
%assign %%i %%i+1
|
||||
%endrep
|
||||
|
||||
%if %1 == 32
|
||||
|
||||
%if %2 == 8
|
||||
TRANSPOSE8x4D 0, 1, 2, 3, 4, 5, 6, 7, 8
|
||||
%elif %2 == 6
|
||||
SBUTTERFLY dq, 0, 1, 6
|
||||
SBUTTERFLY dq, 2, 3, 6
|
||||
SBUTTERFLY dq, 4, 5, 6
|
||||
|
||||
punpcklqdq m6, m0, m2
|
||||
punpckhqdq m2, m4
|
||||
shufps m4, m0, 0xe4
|
||||
punpcklqdq m0, m1, m3
|
||||
punpckhqdq m3, m5
|
||||
shufps m5, m1, 0xe4
|
||||
SWAP 0,6,1,4,5,3
|
||||
%elif %2 == 4
|
||||
TRANSPOSE4x4D 0, 1, 2, 3, 4
|
||||
%else ; %2 == 2
|
||||
SBUTTERFLY dq, 0, 1, 2
|
||||
%endif
|
||||
|
||||
%else ; %1 == 16
|
||||
|
||||
%if %2 == 8
|
||||
packssdw m0, [in0q + in4q]
|
||||
packssdw m1, [in0q + in5q]
|
||||
packssdw m2, [in0q + in6q]
|
||||
packssdw m3, [in0q + in7q]
|
||||
TRANSPOSE2x4x4W 0, 1, 2, 3, 4
|
||||
%elif %2 == 6
|
||||
packssdw m0, [in0q + in3q]
|
||||
packssdw m1, [in0q + in4q]
|
||||
packssdw m2, [in0q + in5q]
|
||||
pshufd m3, m0, q1032
|
||||
punpcklwd m0, m1
|
||||
punpckhwd m1, m2
|
||||
punpcklwd m2, m3
|
||||
|
||||
shufps m3, m0, m2, q2020
|
||||
shufps m0, m1, q2031
|
||||
shufps m2, m1, q3131
|
||||
shufps m1, m2, m3, q3120
|
||||
shufps m3, m0, q0220
|
||||
shufps m0, m2, q3113
|
||||
SWAP 2, 0, 3
|
||||
%else ; %2 == 4
|
||||
packssdw m0, [in0q + in2q]
|
||||
packssdw m1, [in0q + in3q]
|
||||
SBUTTERFLY wd, 0, 1, 2
|
||||
SBUTTERFLY dq, 0, 1, 2
|
||||
%endif
|
||||
|
||||
%endif
|
||||
|
||||
%assign %%i 0
|
||||
%rep REPCOUNT
|
||||
psll%4 m %+ %%i, m%3
|
||||
%assign %%i %%i+1
|
||||
%endrep
|
||||
|
||||
%assign %%i 0
|
||||
%rep REPCOUNT
|
||||
mova [outq + %%i*mmsize], m %+ %%i
|
||||
%assign %%i %%i+1
|
||||
%endrep
|
||||
|
||||
add in0q, mmsize
|
||||
add outq, mmsize*REPCOUNT
|
||||
sub lend, mmsize/4
|
||||
jg .loop
|
||||
REP_RET
|
||||
%endmacro
|
||||
|
||||
INIT_XMM sse2
|
||||
FLAC_DECORRELATE_16 indep2, 0, 1 ; Reuse stereo 16bits macro
|
||||
FLAC_DECORRELATE_INDEP 32, 2, 3, d
|
||||
FLAC_DECORRELATE_INDEP 16, 4, 3, w
|
||||
FLAC_DECORRELATE_INDEP 32, 4, 5, d
|
||||
FLAC_DECORRELATE_INDEP 16, 6, 4, w
|
||||
FLAC_DECORRELATE_INDEP 32, 6, 7, d
|
||||
%if ARCH_X86_64
|
||||
FLAC_DECORRELATE_INDEP 16, 8, 5, w
|
||||
FLAC_DECORRELATE_INDEP 32, 8, 9, d
|
||||
%endif
|
||||
|
||||
INIT_XMM avx
|
||||
FLAC_DECORRELATE_INDEP 32, 4, 5, d
|
||||
FLAC_DECORRELATE_INDEP 32, 6, 7, d
|
||||
%if ARCH_X86_64
|
||||
FLAC_DECORRELATE_INDEP 16, 8, 5, w
|
||||
FLAC_DECORRELATE_INDEP 32, 8, 9, d
|
||||
%endif
|
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
* Copyright (c) 2014 James Almer
|
||||
*
|
||||
* 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 "libavcodec/flacdsp.h"
|
||||
#include "libavutil/x86/cpu.h"
|
||||
#include "config.h"
|
||||
|
||||
void ff_flac_lpc_32_sse4(int32_t *samples, const int coeffs[32], int order,
|
||||
int qlevel, int len);
|
||||
void ff_flac_lpc_32_xop(int32_t *samples, const int coeffs[32], int order,
|
||||
int qlevel, int len);
|
||||
|
||||
void ff_flac_enc_lpc_16_sse4(int32_t *, const int32_t *, int, int, const int32_t *,int);
|
||||
|
||||
#define DECORRELATE_FUNCS(fmt, opt) \
|
||||
void ff_flac_decorrelate_ls_##fmt##_##opt(uint8_t **out, int32_t **in, int channels, \
|
||||
int len, int shift); \
|
||||
void ff_flac_decorrelate_rs_##fmt##_##opt(uint8_t **out, int32_t **in, int channels, \
|
||||
int len, int shift); \
|
||||
void ff_flac_decorrelate_ms_##fmt##_##opt(uint8_t **out, int32_t **in, int channels, \
|
||||
int len, int shift); \
|
||||
void ff_flac_decorrelate_indep2_##fmt##_##opt(uint8_t **out, int32_t **in, int channels, \
|
||||
int len, int shift); \
|
||||
void ff_flac_decorrelate_indep4_##fmt##_##opt(uint8_t **out, int32_t **in, int channels, \
|
||||
int len, int shift); \
|
||||
void ff_flac_decorrelate_indep6_##fmt##_##opt(uint8_t **out, int32_t **in, int channels, \
|
||||
int len, int shift); \
|
||||
void ff_flac_decorrelate_indep8_##fmt##_##opt(uint8_t **out, int32_t **in, int channels, \
|
||||
int len, int shift)
|
||||
|
||||
DECORRELATE_FUNCS(16, sse2);
|
||||
DECORRELATE_FUNCS(16, avx);
|
||||
DECORRELATE_FUNCS(32, sse2);
|
||||
DECORRELATE_FUNCS(32, avx);
|
||||
|
||||
av_cold void ff_flacdsp_init_x86(FLACDSPContext *c, enum AVSampleFormat fmt, int channels,
|
||||
int bps)
|
||||
{
|
||||
#if HAVE_YASM
|
||||
int cpu_flags = av_get_cpu_flags();
|
||||
|
||||
#if CONFIG_FLAC_DECODER
|
||||
if (EXTERNAL_SSE2(cpu_flags)) {
|
||||
if (fmt == AV_SAMPLE_FMT_S16) {
|
||||
if (channels == 2)
|
||||
c->decorrelate[0] = ff_flac_decorrelate_indep2_16_sse2;
|
||||
else if (channels == 4)
|
||||
c->decorrelate[0] = ff_flac_decorrelate_indep4_16_sse2;
|
||||
else if (channels == 6)
|
||||
c->decorrelate[0] = ff_flac_decorrelate_indep6_16_sse2;
|
||||
else if (ARCH_X86_64 && channels == 8)
|
||||
c->decorrelate[0] = ff_flac_decorrelate_indep8_16_sse2;
|
||||
c->decorrelate[1] = ff_flac_decorrelate_ls_16_sse2;
|
||||
c->decorrelate[2] = ff_flac_decorrelate_rs_16_sse2;
|
||||
c->decorrelate[3] = ff_flac_decorrelate_ms_16_sse2;
|
||||
} else if (fmt == AV_SAMPLE_FMT_S32) {
|
||||
if (channels == 2)
|
||||
c->decorrelate[0] = ff_flac_decorrelate_indep2_32_sse2;
|
||||
else if (channels == 4)
|
||||
c->decorrelate[0] = ff_flac_decorrelate_indep4_32_sse2;
|
||||
else if (channels == 6)
|
||||
c->decorrelate[0] = ff_flac_decorrelate_indep6_32_sse2;
|
||||
else if (ARCH_X86_64 && channels == 8)
|
||||
c->decorrelate[0] = ff_flac_decorrelate_indep8_32_sse2;
|
||||
c->decorrelate[1] = ff_flac_decorrelate_ls_32_sse2;
|
||||
c->decorrelate[2] = ff_flac_decorrelate_rs_32_sse2;
|
||||
c->decorrelate[3] = ff_flac_decorrelate_ms_32_sse2;
|
||||
}
|
||||
}
|
||||
if (EXTERNAL_SSE4(cpu_flags)) {
|
||||
c->lpc32 = ff_flac_lpc_32_sse4;
|
||||
}
|
||||
if (EXTERNAL_AVX(cpu_flags)) {
|
||||
if (fmt == AV_SAMPLE_FMT_S16) {
|
||||
if (ARCH_X86_64 && channels == 8)
|
||||
c->decorrelate[0] = ff_flac_decorrelate_indep8_16_avx;
|
||||
} else if (fmt == AV_SAMPLE_FMT_S32) {
|
||||
if (channels == 4)
|
||||
c->decorrelate[0] = ff_flac_decorrelate_indep4_32_avx;
|
||||
else if (channels == 6)
|
||||
c->decorrelate[0] = ff_flac_decorrelate_indep6_32_avx;
|
||||
else if (ARCH_X86_64 && channels == 8)
|
||||
c->decorrelate[0] = ff_flac_decorrelate_indep8_32_avx;
|
||||
}
|
||||
}
|
||||
if (EXTERNAL_XOP(cpu_flags)) {
|
||||
c->lpc32 = ff_flac_lpc_32_xop;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CONFIG_FLAC_ENCODER
|
||||
if (EXTERNAL_SSE4(cpu_flags)) {
|
||||
if (CONFIG_GPL)
|
||||
c->lpc16_encode = ff_flac_enc_lpc_16_sse4;
|
||||
}
|
||||
#endif
|
||||
#endif /* HAVE_YASM */
|
||||
}
|
|
@ -6,6 +6,8 @@
|
|||
|
||||
SOURCES += [
|
||||
'constants.c',
|
||||
'flacdsp.asm',
|
||||
'flacdsp_init.c',
|
||||
'h264_intrapred.asm',
|
||||
'h264_intrapred_10bit.asm',
|
||||
'h264_intrapred_init.c',
|
||||
|
|
Загрузка…
Ссылка в новой задаче