[FFmpeg-soc] [soc]: r2402 - aacenc/aacenc.c
kostya
subversion at mplayerhq.hu
Sat Jun 7 12:44:39 CEST 2008
Author: kostya
Date: Sat Jun 7 12:44:39 2008
New Revision: 2402
Log:
Extremely simple bitstream writer
Modified:
aacenc/aacenc.c
Modified: aacenc/aacenc.c
==============================================================================
--- aacenc/aacenc.c (original)
+++ aacenc/aacenc.c Sat Jun 7 12:44:39 2008
@@ -142,9 +142,13 @@ typedef struct {
DECLARE_ALIGNED_16(int, icoefs[2][1024]);
int samplerate_index;
+ int common_window;
uint8_t *swb_sizes;
int swb_num;
int coded_swb_num;
+ int codebooks[MAX_SWB_SIZE];
+
+ int global_gain;
} AACEncContext;
/**
@@ -222,16 +226,200 @@ static void analyze(AVCodecContext *avct
apply_psychoacoustics(avctx, channel);
}
+/**
+ * Encode ics_info element.
+ * @see Table 4.6
+ */
+static void put_ics_info(AVCodecContext *avctx)
+{
+ AACEncContext *s = avctx->priv_data;
+
+ put_bits(&s->pb, 1, 0); // ics_reserved bit
+ put_bits(&s->pb, 2, 0); // only_long_window_sequence
+ put_bits(&s->pb, 1, 0); // windows shape
+ put_bits(&s->pb, 6, s->coded_swb_num); // max scalefactor bands
+ put_bits(&s->pb, 1, 0); // no prediction
+}
+
+/**
+ * Scan spectral band and determine optimal codebook for it.
+ */
+static int determine_section_info(AACEncContext *s, int channel, int start, int size)
+{
+ int i;
+ int maxval, sign;
+
+ maxval = 0;
+ sign = 0;
+ for(i = start; i < start + size; i++){
+ maxval = FFMAX(maxval, FFABS(s->icoefs[channel][i]));
+ if(s->icoefs[channel][i] < 0) sign = 1;
+ }
+
+ ///TODO: better decision
+ if(!maxval) return 0; //zero codebook
+ if(maxval == 1) return 2;
+ return 11; //escape codebook
+}
+
+static void encode_codebook(AACEncContext *s, int channel, int start, int size, int cb)
+{
+ const uint8_t *bits = aac_cb_info[cb].bits;
+ const uint16_t *codes = aac_cb_info[cb].codes;
+ const int dim = (aac_cb_info[cb].flags & CB_PAIRS) ? 2 : 4;
+ int i, j, idx;
+
+ if(!bits || !codes) return;
+
+ //TODO: factorize?
+ if(aac_cb_info[cb].flags & CB_ESCAPE){
+ for(i = start; i < start + size; i += dim){
+ idx = 0;
+ for(j = 0; j < dim; j++)
+ idx = idx*17 + FFMIN(FFABS(s->icoefs[channel][i+j]), 16);
+ put_bits(&s->pb, bits[idx], codes[idx]);
+ //output signs
+ for(j = 0; j < dim; j++)
+ if(s->icoefs[channel][i+j])
+ put_bits(&s->pb, 1, s->icoefs[channel][i+j] < 0);
+ //output escape values
+ for(j = 0; j < dim; j++)
+ if(FFABS(s->icoefs[channel][i+j]) > 15){
+ int l = av_log2(FFABS(s->icoefs[channel][i+j]));
+
+ put_bits(&s->pb, l - 4 + 1, (1 << (l - 4 + 1)) - 2);
+ put_bits(&s->pb, l, FFABS(s->icoefs[channel][i+j]) & ((1 << l) - 1));
+ }
+ }
+ }else if(aac_cb_info[cb].flags & CB_UNSIGNED){
+ for(i = start; i < start + size; i += dim){
+ idx = 0;
+ for(j = 0; j < dim; j++)
+ idx = idx * aac_cb_info[cb].maxval + FFABS(s->icoefs[channel][i+j]);
+ put_bits(&s->pb, bits[idx], codes[idx]);
+ //output signs
+ for(j = 0; j < dim; j++)
+ if(s->icoefs[channel][i+j])
+ put_bits(&s->pb, 1, s->icoefs[channel][i+j] < 0);
+ }
+ }else{
+ for(i = start; i < start + size; i += dim){
+ idx = 0;
+ for(j = 0; j < dim; j++)
+ idx = idx * (aac_cb_info[cb].maxval*2 + 1) + s->icoefs[channel][i+j] + aac_cb_info[cb].maxval;
+ put_bits(&s->pb, bits[idx], codes[idx]);
+ }
+ }
+}
+
+static void encode_section_data(AVCodecContext *avctx, AACEncContext *s, int channel)
+{
+ int i;
+ int bits = 5; //for long window
+ int count = 0;
+
+ for(i = 0; i < s->coded_swb_num; i++){
+ if(!i || s->codebooks[i] != s->codebooks[i-1]){
+ if(count){
+ while(count >= (1 << bits) - 1){
+ put_bits(&s->pb, bits, (1 << bits) - 1);
+ count -= (1 << bits) - 1;
+ }
+ put_bits(&s->pb, bits, count);
+ }
+ put_bits(&s->pb, 4, s->codebooks[i]);
+ count = 1;
+ }else
+ count++;
+ }
+ if(count){
+ while(count >= (1 << bits) - 1){
+ put_bits(&s->pb, bits, (1 << bits) - 1);
+ count -= (1 << bits) - 1;
+ }
+ put_bits(&s->pb, bits, count);
+ }
+}
+
+static void encode_scale_factor_data(AVCodecContext *avctx, AACEncContext *s, int channel)
+{
+// int off = s->global_gain;
+ int i;
+
+ for(i = 0; i < s->coded_swb_num; i++){
+ if(s->codebooks[i] != 0){
+ put_bits(&s->pb, bits[60], code[60]);
+ }
+ }
+}
+
+static void encode_spectral_data(AVCodecContext *avctx, AACEncContext *s, int channel)
+{
+ int start = 0, i;
+
+ for(i = 0; i < s->coded_swb_num; i++){
+ encode_codebook(s, channel, start, s->swb_sizes[i], s->codebooks[i]);
+ start += s->swb_sizes[i];
+ }
+}
+
+/**
+ * Encode one channel of audio data.
+ */
+static int encode_individual_channel(AVCodecContext *avctx, int channel, int common_window)
+{
+ AACEncContext *s = avctx->priv_data;
+ int i, j, g = 0;
+
+ s->coded_swb_num = s->swb_num;
+ s->global_gain = 128;
+ i = 0;
+ while(i < 1024){
+ s->codebooks[g] = determine_section_info(s, channel, i, s->swb_sizes[g]);
+ i += s->swb_sizes[g];
+ g++;
+ }
+
+ put_bits(&s->pb, 8, s->global_gain); //global gain
+ put_ics_info(avctx);
+ encode_section_data(avctx, s, channel);
+ encode_scale_factor_data(avctx, s, channel);
+ put_bits(&s->pb, 1, 0); //pulse
+ put_bits(&s->pb, 1, 0); //tns
+ put_bits(&s->pb, 1, 0); //ssr
+ encode_spectral_data(avctx, s, channel);
+ return 0;
+}
+
static int aac_encode_frame(AVCodecContext *avctx,
uint8_t *frame, int buf_size, void *data)
{
- int i,k,channel;
AACEncContext *s = avctx->priv_data;
int16_t *samples = data;
+ analyze(avctx, s, samples, 0);
+ if(avctx->channels > 1)
+ analyze(avctx, s, samples, 1);
+
init_put_bits(&s->pb, frame, buf_size*8);
- put_bits(&s->pb, 8, 0xAB);
+ //output encoded
+ switch(avctx->channels){
+ case 1:
+ put_bits(&s->pb, 3, ID_SCE);
+ put_bits(&s->pb, 4, 0); //tag
+ encode_individual_channel(avctx, 0, 0);
+ break;
+ case 2:
+ put_bits(&s->pb, 3, ID_CPE);
+ put_bits(&s->pb, 4, 0); //tag
+ encode_individual_channel(avctx, 0, 1);
+ encode_individual_channel(avctx, 1, 1);
+ break;
+ default:
+ av_log(NULL,0,"?");
+ }
+ put_bits(&s->pb, 3, ID_END);
flush_put_bits(&s->pb);
return put_bits_count(&s->pb)>>3;
}
More information about the FFmpeg-soc
mailing list