History

psymodel: Add channels and channel groups to the psymodel.

Nathan Caldwell committed 15 years ago

Commit 0bc01cc1 parent a3e1f805 files · +91 −25Browse files

Unified · Split

5 files
  1. libavcodec/aaccoder.c +7 −7
  2. libavcodec/aacenc.c +4 −4
  3. libavcodec/aacpsy.c +3 −2
  4. libavcodec/psymodel.c +31 −5
  5. libavcodec/psymodel.h +46 −7
libavcodec/aaccoder.c+7−7
@@ -345,7 +345,7 @@ static void encode_window_bands_info(AACEncContext *s, SingleChannelElement *sce · 344 unmodified lines
345 float cost_stay_here, cost_get_here;345 float cost_stay_here, cost_get_here;
346 float rd = 0.0f;346 float rd = 0.0f;
347 for (w = 0; w < group_len; w++) {347 for (w = 0; w < group_len; w++) {
348 FFPsyBand *band = &s->psy.psy_bands[s->cur_channel*PSY_MAX_BANDS+(win+w)*16+swb];348 FFPsyBand *band = &s->psy.ch[s->cur_channel].psy_bands[(win+w)*16+swb];
349 rd += quantize_band_cost(s, sce->coeffs + start + w*128,349 rd += quantize_band_cost(s, sce->coeffs + start + w*128,
350 s->scoefs + start + w*128, size,350 s->scoefs + start + w*128, size,
351 sce->sf_idx[(win+w)*16+swb], cb,351 sce->sf_idx[(win+w)*16+swb], cb,
@@ -625,7 +625,7 @@ static void search_for_quantizers_anmr(AVCodecContext *avctx, AACEncContext *s, · 273 unmodified lines
625 qmin = INT_MAX;625 qmin = INT_MAX;
626 qmax = 0.0f;626 qmax = 0.0f;
627 for (w2 = 0; w2 < sce->ics.group_len[w]; w2++) {627 for (w2 = 0; w2 < sce->ics.group_len[w]; w2++) {
628 FFPsyBand *band = &s->psy.psy_bands[s->cur_channel*PSY_MAX_BANDS+(w+w2)*16+g];628 FFPsyBand *band = &s->psy.ch[s->cur_channel].psy_bands[(w+w2)*16+g];
629 if (band->energy <= band->threshold || band->threshold == 0.0f) {629 if (band->energy <= band->threshold || band->threshold == 0.0f) {
630 sce->zeroes[(w+w2)*16+g] = 1;630 sce->zeroes[(w+w2)*16+g] = 1;
631 continue;631 continue;
@@ -654,7 +654,7 @@ static void search_for_quantizers_anmr(AVCodecContext *avctx, AACEncContext *s, · 22 unmodified lines
654 float dist = 0;654 float dist = 0;
655 int cb = find_min_book(maxval, sce->sf_idx[w*16+g]);655 int cb = find_min_book(maxval, sce->sf_idx[w*16+g]);
656 for (w2 = 0; w2 < sce->ics.group_len[w]; w2++) {656 for (w2 = 0; w2 < sce->ics.group_len[w]; w2++) {
657 FFPsyBand *band = &s->psy.psy_bands[s->cur_channel*PSY_MAX_BANDS+(w+w2)*16+g];657 FFPsyBand *band = &s->psy.ch[s->cur_channel].psy_bands[(w+w2)*16+g];
658 dist += quantize_band_cost(s, coefs + w2*128, s->scoefs + start + w2*128, sce->ics.swb_sizes[g],658 dist += quantize_band_cost(s, coefs + w2*128, s->scoefs + start + w2*128, sce->ics.swb_sizes[g],
659 q + q0, cb, lambda / band->threshold, INFINITY, NULL);659 q + q0, cb, lambda / band->threshold, INFINITY, NULL);
660 }660 }
@@ -727,7 +727,7 @@ static void search_for_quantizers_twoloop(AVCodecContext *avctx, · 66 unmodified lines
727 int nz = 0;727 int nz = 0;
728 float uplim = 0.0f;728 float uplim = 0.0f;
729 for (w2 = 0; w2 < sce->ics.group_len[w]; w2++) {729 for (w2 = 0; w2 < sce->ics.group_len[w]; w2++) {
730 FFPsyBand *band = &s->psy.psy_bands[s->cur_channel*PSY_MAX_BANDS+(w+w2)*16+g];730 FFPsyBand *band = &s->psy.ch[s->cur_channel].psy_bands[(w+w2)*16+g];
731 uplim += band->threshold;731 uplim += band->threshold;
732 if (band->energy <= band->threshold || band->threshold == 0.0f) {732 if (band->energy <= band->threshold || band->threshold == 0.0f) {
733 sce->zeroes[(w+w2)*16+g] = 1;733 sce->zeroes[(w+w2)*16+g] = 1;
@@ -1027,7 +1027,7 @@ static void search_for_quantizers_fast(AVCodecContext *avctx, AACEncContext *s, · 293 unmodified lines
1027 for (w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]) {1027 for (w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]) {
1028 for (g = 0; g < sce->ics.num_swb; g++) {1028 for (g = 0; g < sce->ics.num_swb; g++) {
1029 for (w2 = 0; w2 < sce->ics.group_len[w]; w2++) {1029 for (w2 = 0; w2 < sce->ics.group_len[w]; w2++) {
1030 FFPsyBand *band = &s->psy.psy_bands[s->cur_channel*PSY_MAX_BANDS+(w+w2)*16+g];1030 FFPsyBand *band = &s->psy.ch[s->cur_channel].psy_bands[(w+w2)*16+g];
1031 if (band->energy <= band->threshold) {1031 if (band->energy <= band->threshold) {
1032 sce->sf_idx[(w+w2)*16+g] = 218;1032 sce->sf_idx[(w+w2)*16+g] = 218;
1033 sce->zeroes[(w+w2)*16+g] = 1;1033 sce->zeroes[(w+w2)*16+g] = 1;
@@ -1065,8 +1065,8 @@ static void search_for_ms(AACEncContext *s, ChannelElement *cpe, · 31 unmodified lines
1065 if (!cpe->ch[0].zeroes[w*16+g] && !cpe->ch[1].zeroes[w*16+g]) {1065 if (!cpe->ch[0].zeroes[w*16+g] && !cpe->ch[1].zeroes[w*16+g]) {
1066 float dist1 = 0.0f, dist2 = 0.0f;1066 float dist1 = 0.0f, dist2 = 0.0f;
1067 for (w2 = 0; w2 < sce0->ics.group_len[w]; w2++) {1067 for (w2 = 0; w2 < sce0->ics.group_len[w]; w2++) {
1068 FFPsyBand *band0 = &s->psy.psy_bands[(s->cur_channel+0)*PSY_MAX_BANDS+(w+w2)*16+g];1068 FFPsyBand *band0 = &s->psy.ch[s->cur_channel+0].psy_bands[(w+w2)*16+g];
1069 FFPsyBand *band1 = &s->psy.psy_bands[(s->cur_channel+1)*PSY_MAX_BANDS+(w+w2)*16+g];1069 FFPsyBand *band1 = &s->psy.ch[s->cur_channel+1].psy_bands[(w+w2)*16+g];
1070 float minthr = FFMIN(band0->threshold, band1->threshold);1070 float minthr = FFMIN(band0->threshold, band1->threshold);
1071 float maxthr = FFMAX(band0->threshold, band1->threshold);1071 float maxthr = FFMAX(band0->threshold, band1->threshold);
1072 for (i = 0; i < sce0->ics.swb_sizes[g]; i++) {1072 for (i = 0; i < sce0->ics.swb_sizes[g]; i++) {
libavcodec/aacenc.c+4−4
@@ -210,7 +210,7 @@ static av_cold int aac_encode_init(AVCodecContext *avctx) · 209 unmodified lines
210 sizes[1] = swb_size_128[i];210 sizes[1] = swb_size_128[i];
211 lengths[0] = ff_aac_num_swb_1024[i];211 lengths[0] = ff_aac_num_swb_1024[i];
212 lengths[1] = ff_aac_num_swb_128[i];212 lengths[1] = ff_aac_num_swb_128[i];
213 ff_psy_init(&s->psy, avctx, 2, sizes, lengths);213 ff_psy_init(&s->psy, avctx, 2, sizes, lengths, s->chan_map[0], &s->chan_map[1]);
214 s->psypp = ff_psy_preprocess_init(avctx);214 s->psypp = ff_psy_preprocess_init(avctx);
215 s->coder = &ff_aac_coders[2];215 s->coder = &ff_aac_coders[2];
216 216
@@ -570,8 +570,8 @@ static int aac_encode_frame(AVCodecContext *avctx, · 353 unmodified lines
570 put_bits(&s->pb, 3, tag);570 put_bits(&s->pb, 3, tag);
571 put_bits(&s->pb, 4, chan_el_counter[tag]++);571 put_bits(&s->pb, 4, chan_el_counter[tag]++);
572 for (ch = 0; ch < chans; ch++) {572 for (ch = 0; ch < chans; ch++) {
573 s->cur_channel = start_ch + ch;573 s->cur_channel = start_ch * 2 + ch;
574 s->psy.model->analyze(&s->psy, s->cur_channel, cpe->ch[ch].coeffs, &wi[ch]);574 s->psy.model->analyze(&s->psy, start_ch + ch, cpe->ch[ch].coeffs, &wi[ch]);
575 s->coder->search_for_quantizers(avctx, s, &cpe->ch[ch], s->lambda);575 s->coder->search_for_quantizers(avctx, s, &cpe->ch[ch], s->lambda);
576 }576 }
577 cpe->common_window = 0;577 cpe->common_window = 0;
@@ -587,7 +587,7 @@ static int aac_encode_frame(AVCodecContext *avctx, · 9 unmodified lines
587 }587 }
588 }588 }
589 }589 }
590 s->cur_channel = start_ch;590 s->cur_channel = start_ch * 2;
591 if (s->options.stereo_mode && cpe->common_window) {591 if (s->options.stereo_mode && cpe->common_window) {
592 if (s->options.stereo_mode > 0) {592 if (s->options.stereo_mode > 0) {
593 IndividualChannelStream *ics = &cpe->ch[0].ics;593 IndividualChannelStream *ics = &cpe->ch[0].ics;
libavcodec/aacpsy.c+3−2
@@ -627,7 +627,7 @@ static void psy_3gpp_analyze(FFPsyContext *ctx, int channel, · 626 unmodified lines
627 }627 }
628 628
629 /* 5.6.1.3.2 "Calculation of the desired perceptual entropy" */629 /* 5.6.1.3.2 "Calculation of the desired perceptual entropy" */
630 ctx->pe[channel] = pe;630 ctx->ch[channel].entropy = pe;
631 desired_bits = calc_bit_demand(pctx, pe, ctx->bitres.bits, ctx->bitres.size, wi->num_windows == 8);631 desired_bits = calc_bit_demand(pctx, pe, ctx->bitres.bits, ctx->bitres.size, wi->num_windows == 8);
632 desired_pe = PSY_3GPP_BITS_TO_PE(desired_bits);632 desired_pe = PSY_3GPP_BITS_TO_PE(desired_bits);
633 /* NOTE: PE correction is kept simple. During initial testing it had very633 /* NOTE: PE correction is kept simple. During initial testing it had very
@@ -731,7 +731,7 @@ static void psy_3gpp_analyze(FFPsyContext *ctx, int channel, · 97 unmodified lines
731 for (w = 0; w < wi->num_windows*16; w += 16) {731 for (w = 0; w < wi->num_windows*16; w += 16) {
732 for (g = 0; g < num_bands; g++) {732 for (g = 0; g < num_bands; g++) {
733 AacPsyBand *band = &pch->band[w+g];733 AacPsyBand *band = &pch->band[w+g];
734 FFPsyBand *psy_band = &ctx->psy_bands[channel*PSY_MAX_BANDS+w+g];734 FFPsyBand *psy_band = &ctx->ch[channel].psy_bands[w+g];
735 735
736 psy_band->threshold = band->thr;736 psy_band->threshold = band->thr;
737 psy_band->energy = band->energy;737 psy_band->energy = band->energy;
@@ -921,5 +921,6 @@ const FFPsyModel ff_aac_psy_model = · 183 unmodified lines
921 .init = psy_3gpp_init,921 .init = psy_3gpp_init,
922 .window = psy_lame_window,922 .window = psy_lame_window,
923 .analyze = psy_3gpp_analyze,923 .analyze = psy_3gpp_analyze,
924 .analyze_group = NULL,
924 .end = psy_3gpp_end,925 .end = psy_3gpp_end,
925};926};
libavcodec/psymodel.c+31−5
@@ -25,16 +25,31 @@ · 24 unmodified lines
25 25
26extern const FFPsyModel ff_aac_psy_model;26extern const FFPsyModel ff_aac_psy_model;
27 27
28av_cold int ff_psy_init(FFPsyContext *ctx, AVCodecContext *avctx,28av_cold int ff_psy_init(FFPsyContext *ctx, AVCodecContext *avctx, int num_lens,
29 int num_lens,29 const uint8_t **bands, const int* num_bands,
30 const uint8_t **bands, const int* num_bands)30 int num_groups, const uint8_t *group_map)
31{31{
32 int i, j, k = 0;
33
32 ctx->avctx = avctx;34 ctx->avctx = avctx;
33 ctx->psy_bands = av_mallocz(sizeof(FFPsyBand) * PSY_MAX_BANDS * avctx->channels);35 ctx->ch = av_mallocz(sizeof(ctx->ch[0]) * avctx->channels * 2);
36 ctx->group = av_mallocz(sizeof(ctx->group[0]) * num_groups);
34 ctx->bands = av_malloc (sizeof(ctx->bands[0]) * num_lens);37 ctx->bands = av_malloc (sizeof(ctx->bands[0]) * num_lens);
35 ctx->num_bands = av_malloc (sizeof(ctx->num_bands[0]) * num_lens);38 ctx->num_bands = av_malloc (sizeof(ctx->num_bands[0]) * num_lens);
36 memcpy(ctx->bands, bands, sizeof(ctx->bands[0]) * num_lens);39 memcpy(ctx->bands, bands, sizeof(ctx->bands[0]) * num_lens);
37 memcpy(ctx->num_bands, num_bands, sizeof(ctx->num_bands[0]) * num_lens);40 memcpy(ctx->num_bands, num_bands, sizeof(ctx->num_bands[0]) * num_lens);
41
42 /* assign channels to groups (with virtual channels for coupling) */
43 for (i = 0; i < num_groups; i++) {
44 /* NOTE: Add 1 to handle the AAC chan_config without modification.
45 * This has the side effect of allowing an array of 0s to map
46 * to one channel per group.
47 */
48 ctx->group[i].num_ch = group_map[i] + 1;
49 for (j = 0; j < ctx->group[i].num_ch * 2; j++)
50 ctx->group[i].ch[j] = &ctx->ch[k++];
51 }
52
38 switch (ctx->avctx->codec_id) {53 switch (ctx->avctx->codec_id) {
39 case CODEC_ID_AAC:54 case CODEC_ID_AAC:
40 ctx->model = &ff_aac_psy_model;55 ctx->model = &ff_aac_psy_model;
@@ -45,13 +60,24 @@ av_cold int ff_psy_init(FFPsyContext *ctx, AVCodecContext *avctx, · 4 unmodified lines
45 return 0;60 return 0;
46}61}
47 62
63FFPsyChannelGroup *ff_psy_find_group(FFPsyContext *ctx, int channel)
64{
65 int i = 0, ch = 0;
66
67 while (ch <= channel)
68 ch += ctx->group[i++].num_ch;
69
70 return &ctx->group[i-1];
71}
72
48av_cold void ff_psy_end(FFPsyContext *ctx)73av_cold void ff_psy_end(FFPsyContext *ctx)
49{74{
50 if (ctx->model->end)75 if (ctx->model->end)
51 ctx->model->end(ctx);76 ctx->model->end(ctx);
52 av_freep(&ctx->bands);77 av_freep(&ctx->bands);
53 av_freep(&ctx->num_bands);78 av_freep(&ctx->num_bands);
54 av_freep(&ctx->psy_bands);79 av_freep(&ctx->group);
80 av_freep(&ctx->ch);
55}81}
56 82
57typedef struct FFPsyPreprocessContext{83typedef struct FFPsyPreprocessContext{
libavcodec/psymodel.h+46−7
@@ -40,6 +40,23 @@ typedef struct FFPsyBand { · 39 unmodified lines
40 float perceptual_weight;40 float perceptual_weight;
41} FFPsyBand;41} FFPsyBand;
42 42
43/**
44 * single channel psychoacoustic information
45 */
46typedef struct FFPsyChannel {
47 FFPsyBand psy_bands[PSY_MAX_BANDS]; ///< channel bands information
48 float entropy; ///< total PE for this channel
49} FFPsyChannel;
50
51/**
52 * psychoacoustic information for an arbitrary group of channels
53 */
54typedef struct FFPsyChannelGroup {
55 FFPsyChannel *ch[PSY_MAX_CHANS]; ///< pointers to the individual channels in the group
56 uint8_t num_ch; ///< number of channels in this group
57 uint8_t coupling[PSY_MAX_BANDS]; ///< allow coupling for this band in the group
58} FFPsyChannelGroup;
59
43/**60/**
44 * windowing related information61 * windowing related information
45 */62 */
@@ -58,14 +75,14 @@ typedef struct FFPsyContext { · 12 unmodified lines
58 AVCodecContext *avctx; ///< encoder context75 AVCodecContext *avctx; ///< encoder context
59 const struct FFPsyModel *model; ///< encoder-specific model functions76 const struct FFPsyModel *model; ///< encoder-specific model functions
60 77
61 FFPsyBand *psy_bands; ///< frame bands information78 FFPsyChannel *ch; ///< single channel information
79 FFPsyChannelGroup *group; ///< channel group information
80 int num_groups; ///< number of channel groups
62 81
63 uint8_t **bands; ///< scalefactor band sizes for possible frame sizes82 uint8_t **bands; ///< scalefactor band sizes for possible frame sizes
64 int *num_bands; ///< number of scalefactor bands for possible frame sizes83 int *num_bands; ///< number of scalefactor bands for possible frame sizes
65 int num_lens; ///< number of scalefactor band sets84 int num_lens; ///< number of scalefactor band sets
66 85
67 float pe[PSY_MAX_CHANS]; ///< total PE for each channel in the frame
68
69 struct {86 struct {
70 int size; ///< size of the bitresevoir in bits87 int size; ///< size of the bitresevoir in bits
71 int bits; ///< number of bits used in the bitresevoir88 int bits; ///< number of bits used in the bitresevoir
@@ -95,7 +112,7 @@ typedef struct FFPsyModel { · 23 unmodified lines
95 FFPsyWindowInfo (*window)(FFPsyContext *ctx, const int16_t *audio, const int16_t *la, int channel, int prev_type);112 FFPsyWindowInfo (*window)(FFPsyContext *ctx, const int16_t *audio, const int16_t *la, int channel, int prev_type);
96 113
97 /**114 /**
98 * Perform psychoacoustic analysis and set band info (threshold, energy).115 * Perform psychoacoustic analysis and set band info (threshold, energy) for a single channel.
99 *116 *
100 * @param ctx model context117 * @param ctx model context
101 * @param channel audio channel number118 * @param channel audio channel number
@@ -104,6 +121,16 @@ typedef struct FFPsyModel { · 2 unmodified lines
104 */121 */
105 void (*analyze)(FFPsyContext *ctx, int channel, const float *coeffs, const FFPsyWindowInfo *wi);122 void (*analyze)(FFPsyContext *ctx, int channel, const float *coeffs, const FFPsyWindowInfo *wi);
106 123
124 /**
125 * Perform psychoacoustic analysis and set band info (threshold, energy) for a group of channels.
126 *
127 * @param ctx model context
128 * @param channel channel number of the first channel in the group to perform analysis on
129 * @param coeffs array of pointers to the transformed coefficients
130 * @param wi window information for the channels in the group
131 */
132 void (*analyze_group)(FFPsyContext *ctx, int channel, const float **coeffs, const FFPsyWindowInfo *wi);
133
107 void (*end) (FFPsyContext *apc);134 void (*end) (FFPsyContext *apc);
108} FFPsyModel;135} FFPsyModel;
109 136
@@ -115,12 +142,24 @@ typedef struct FFPsyModel { · 5 unmodified lines
115 * @param num_lens number of possible frame lengths142 * @param num_lens number of possible frame lengths
116 * @param bands scalefactor band lengths for all frame lengths143 * @param bands scalefactor band lengths for all frame lengths
117 * @param num_bands number of scalefactor bands for all frame lengths144 * @param num_bands number of scalefactor bands for all frame lengths
145 * @param num_groups number of channel groups
146 * @param group_map array with # of channels in group - 1, for each group
118 *147 *
119 * @return zero if successful, a negative value if not148 * @return zero if successful, a negative value if not
120 */149 */
121av_cold int ff_psy_init(FFPsyContext *ctx, AVCodecContext *avctx,150av_cold int ff_psy_init(FFPsyContext *ctx, AVCodecContext *avctx, int num_lens,
122 int num_lens,151 const uint8_t **bands, const int* num_bands,
123 const uint8_t **bands, const int* num_bands);152 int num_groups, const uint8_t *group_map);
153
154/**
155 * Determine what group a channel belongs to.
156 *
157 * @param ctx psymodel context
158 * @param channel channel to locate the group for
159 *
160 * @return pointer to the FFPsyChannelGroup this channel belongs to
161 */
162FFPsyChannelGroup *ff_psy_find_group(FFPsyContext *ctx, int channel);
124 163
125/**164/**
126 * Cleanup model context at the end.165 * Cleanup model context at the end.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t