Unified · Split
| @@ -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++) { |
| @@ -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; |
| @@ -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 very | 633 | /* 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 | }; |
| @@ -25,16 +25,31 @@ · 24 unmodified lines | |||
| 25 | 25 | ||
| 26 | extern const FFPsyModel ff_aac_psy_model; | 26 | extern const FFPsyModel ff_aac_psy_model; |
| 27 | 27 | ||
| 28 | av_cold int ff_psy_init(FFPsyContext *ctx, AVCodecContext *avctx, | 28 | av_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 | ||
| 63 | FFPsyChannelGroup *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 | |||
| 48 | av_cold void ff_psy_end(FFPsyContext *ctx) | 73 | av_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 | ||
| 57 | typedef struct FFPsyPreprocessContext{ | 83 | typedef struct FFPsyPreprocessContext{ |
| @@ -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 | */ | ||
| 46 | typedef 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 | */ | ||
| 54 | typedef 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 information | 61 | * windowing related information |
| 45 | */ | 62 | */ |
| @@ -58,14 +75,14 @@ typedef struct FFPsyContext { · 12 unmodified lines | |||
| 58 | AVCodecContext *avctx; ///< encoder context | 75 | AVCodecContext *avctx; ///< encoder context |
| 59 | const struct FFPsyModel *model; ///< encoder-specific model functions | 76 | const struct FFPsyModel *model; ///< encoder-specific model functions |
| 60 | 77 | ||
| 61 | FFPsyBand *psy_bands; ///< frame bands information | 78 | 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 sizes | 82 | uint8_t **bands; ///< scalefactor band sizes for possible frame sizes |
| 64 | int *num_bands; ///< number of scalefactor bands for possible frame sizes | 83 | int *num_bands; ///< number of scalefactor bands for possible frame sizes |
| 65 | int num_lens; ///< number of scalefactor band sets | 84 | 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 bits | 87 | int size; ///< size of the bitresevoir in bits |
| 71 | int bits; ///< number of bits used in the bitresevoir | 88 | 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 context | 117 | * @param ctx model context |
| 101 | * @param channel audio channel number | 118 | * @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 lengths | 142 | * @param num_lens number of possible frame lengths |
| 116 | * @param bands scalefactor band lengths for all frame lengths | 143 | * @param bands scalefactor band lengths for all frame lengths |
| 117 | * @param num_bands number of scalefactor bands for all frame lengths | 144 | * @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 not | 148 | * @return zero if successful, a negative value if not |
| 120 | */ | 149 | */ |
| 121 | av_cold int ff_psy_init(FFPsyContext *ctx, AVCodecContext *avctx, | 150 | av_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 | */ | ||
| 162 | FFPsyChannelGroup *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. |