diff options
author | Ramiro Polla <ramiro.polla@gmail.com> | 2008-08-18 02:47:40 +0400 |
---|---|---|
committer | Ramiro Polla <ramiro.polla@gmail.com> | 2008-08-18 02:47:40 +0400 |
commit | ca048266273a8964d7c7c168bd0255236f460961 (patch) | |
tree | 3455516020de4e4d34ee7dc48ae12d8261e70ee3 /libavcodec/alacenc.c | |
parent | 46dd2738ae321adcc36cc9137b6a978e2e007733 (diff) |
Import more ok'd parts of ALAC encoder from GSoC repo.
Originally committed as revision 14820 to svn://svn.ffmpeg.org/ffmpeg/trunk
Diffstat (limited to 'libavcodec/alacenc.c')
-rw-r--r-- | libavcodec/alacenc.c | 140 |
1 files changed, 125 insertions, 15 deletions
diff --git a/libavcodec/alacenc.c b/libavcodec/alacenc.c index 98a3451597..0a802f1525 100644 --- a/libavcodec/alacenc.c +++ b/libavcodec/alacenc.c @@ -33,15 +33,52 @@ #define ALAC_ESCAPE_CODE 0x1FF #define ALAC_MAX_LPC_ORDER 30 - +#define DEFAULT_MAX_PRED_ORDER 6 +#define DEFAULT_MIN_PRED_ORDER 4 +#define ALAC_MAX_LPC_PRECISION 9 +#define ALAC_MAX_LPC_SHIFT 9 + +typedef struct RiceContext { + int history_mult; + int initial_history; + int k_modifier; + int rice_modifier; +} RiceContext; + +typedef struct LPCContext { + int lpc_order; + int lpc_coeff[ALAC_MAX_LPC_ORDER+1]; + int lpc_quant; +} LPCContext; + +typedef struct AlacEncodeContext { + int compression_level; + int max_coded_frame_size; + int write_sample_size; + int32_t sample_buf[MAX_CHANNELS][DEFAULT_FRAME_SIZE]; int interlacing_shift; int interlacing_leftweight; PutBitContext pbctx; + RiceContext rc; + LPCContext lpc[MAX_CHANNELS]; DSPContext dspctx; AVCodecContext *avctx; } AlacEncodeContext; +static void init_sample_buffers(AlacEncodeContext *s, int16_t *input_samples) +{ + int ch, i; + + for(ch=0;ch<s->avctx->channels;ch++) { + int16_t *sptr = input_samples + ch; + for(i=0;i<s->avctx->frame_size;i++) { + s->sample_buf[ch][i] = *sptr; + sptr += s->avctx->channels; + } + } +} + static void encode_scalar(AlacEncodeContext *s, int x, int k, int write_sample_size) { int divisor, q, r; @@ -71,7 +108,7 @@ static void encode_scalar(AlacEncodeContext *s, int x, int k, int write_sample_s static void write_frame_header(AlacEncodeContext *s, int is_verbatim) { - put_bits(&s->pbctx, 3, s->channels-1); // No. of channels -1 + put_bits(&s->pbctx, 3, s->avctx->channels-1); // No. of channels -1 put_bits(&s->pbctx, 16, 0); // Seems to be zero put_bits(&s->pbctx, 1, 1); // Sample count is in the header put_bits(&s->pbctx, 2, 0); // FIXME: Wasted bytes field @@ -79,6 +116,38 @@ static void write_frame_header(AlacEncodeContext *s, int is_verbatim) put_bits(&s->pbctx, 32, s->avctx->frame_size); // No. of samples in the frame } +static int estimate_stereo_mode(int32_t *left_ch, int32_t *right_ch, int n) +{ + int i, best; + int32_t lt, rt; + uint64_t sum[4]; + uint64_t score[4]; + + /* calculate sum of 2nd order residual for each channel */ + sum[0] = sum[1] = sum[2] = sum[3] = 0; + for(i=2; i<n; i++) { + lt = left_ch[i] - 2*left_ch[i-1] + left_ch[i-2]; + rt = right_ch[i] - 2*right_ch[i-1] + right_ch[i-2]; + sum[2] += FFABS((lt + rt) >> 1); + sum[3] += FFABS(lt - rt); + sum[0] += FFABS(lt); + sum[1] += FFABS(rt); + } + + /* calculate score for each mode */ + score[0] = sum[0] + sum[1]; + score[1] = sum[0] + sum[3]; + score[2] = sum[1] + sum[3]; + score[3] = sum[2] + sum[3]; + + /* return mode with lowest score */ + best = 0; + for(i=1; i<4; i++) { + if(score[i] < score[best]) { + best = i; + } + } + static void write_compressed_frame(AlacEncodeContext *s) { int i, j; @@ -88,7 +157,7 @@ static void write_compressed_frame(AlacEncodeContext *s) put_bits(&s->pbctx, 8, s->interlacing_shift); put_bits(&s->pbctx, 8, s->interlacing_leftweight); - for(i=0;i<s->channels;i++) { + for(i=0;i<s->avctx->channels;i++) { calc_predictor_params(s, i); @@ -105,7 +174,7 @@ static void write_compressed_frame(AlacEncodeContext *s) // apply lpc and entropy coding to audio samples - for(i=0;i<s->channels;i++) { + for(i=0;i<s->avctx->channels;i++) { alac_linear_predictor(s, i); alac_entropy_coder(s); } @@ -118,8 +187,6 @@ static av_cold int alac_encode_init(AVCodecContext *avctx) avctx->frame_size = DEFAULT_FRAME_SIZE; avctx->bits_per_sample = DEFAULT_SAMPLE_SIZE; - s->channels = avctx->channels; - s->samplerate = avctx->sample_rate; if(avctx->sample_fmt != SAMPLE_FMT_S16) { av_log(avctx, AV_LOG_ERROR, "only pcm_s16 input samples are supported\n"); @@ -139,18 +206,18 @@ static av_cold int alac_encode_init(AVCodecContext *avctx) s->rc.rice_modifier = 4; s->max_coded_frame_size = (ALAC_FRAME_HEADER_SIZE + ALAC_FRAME_FOOTER_SIZE + - avctx->frame_size*s->channels*avctx->bits_per_sample)>>3; + avctx->frame_size*avctx->channels*avctx->bits_per_sample)>>3; - s->write_sample_size = avctx->bits_per_sample + s->channels - 1; // FIXME: consider wasted_bytes + s->write_sample_size = avctx->bits_per_sample + avctx->channels - 1; // FIXME: consider wasted_bytes AV_WB32(alac_extradata, ALAC_EXTRADATA_SIZE); AV_WB32(alac_extradata+4, MKBETAG('a','l','a','c')); AV_WB32(alac_extradata+12, avctx->frame_size); AV_WB8 (alac_extradata+17, avctx->bits_per_sample); - AV_WB8 (alac_extradata+21, s->channels); + AV_WB8 (alac_extradata+21, avctx->channels); AV_WB32(alac_extradata+24, s->max_coded_frame_size); - AV_WB32(alac_extradata+28, s->samplerate*s->channels*avctx->bits_per_sample); // average bitrate - AV_WB32(alac_extradata+32, s->samplerate); + AV_WB32(alac_extradata+28, avctx->sample_rate*avctx->channels*avctx->bits_per_sample); // average bitrate + AV_WB32(alac_extradata+32, avctx->sample_rate); // Set relevant extradata fields if(s->compression_level > 0) { @@ -168,19 +235,62 @@ static av_cold int alac_encode_init(AVCodecContext *avctx) s->avctx = avctx; dsputil_init(&s->dspctx, avctx); - allocate_sample_buffers(s); - return 0; } -static av_cold int alac_encode_close(AVCodecContext *avctx) +static int alac_encode_frame(AVCodecContext *avctx, uint8_t *frame, + int buf_size, void *data) { AlacEncodeContext *s = avctx->priv_data; + PutBitContext *pb = &s->pbctx; + int i, out_bytes, verbatim_flag = 0; + if(avctx->frame_size > DEFAULT_FRAME_SIZE) { + av_log(avctx, AV_LOG_ERROR, "input frame size exceeded\n"); + return -1; + } + + if(buf_size < 2*s->max_coded_frame_size) { + av_log(avctx, AV_LOG_ERROR, "buffer size is too small\n"); + return -1; + } + + if((s->compression_level == 0) || verbatim_flag) { + // Verbatim mode + int16_t *samples = data; + write_frame_header(s, 1); + for(i=0; i<avctx->frame_size*avctx->channels; i++) { + put_sbits(pb, 16, *samples++); + } + } else { + init_sample_buffers(s, data); + write_frame_header(s, 0); + write_compressed_frame(s); + } + + put_bits(pb, 3, 7); + flush_put_bits(pb); + out_bytes = put_bits_count(pb) >> 3; + + if(out_bytes > s->max_coded_frame_size) { + /* frame too large. use verbatim mode */ + if(verbatim_flag || (s->compression_level == 0)) { + /* still too large. must be an error. */ + av_log(avctx, AV_LOG_ERROR, "error encoding frame\n"); + return -1; + } + verbatim_flag = 1; + goto verbatim; + } + + return out_bytes; +} + +static av_cold int alac_encode_close(AVCodecContext *avctx) +{ av_freep(&avctx->extradata); avctx->extradata_size = 0; av_freep(&avctx->coded_frame); - free_sample_buffers(s); return 0; } |