| @@ -151,9 +151,7 @@ typedef struct vorbis_context_s { | |||||
| uint8_t mode_number; // mode number for the current packet | uint8_t mode_number; // mode number for the current packet | ||||
| uint8_t previous_window; | uint8_t previous_window; | ||||
| float *channel_residues; | float *channel_residues; | ||||
| float *channel_floors; | |||||
| float *saved; | float *saved; | ||||
| float scale_bias; // for float->int conversion | |||||
| } vorbis_context; | } vorbis_context; | ||||
| /* Helper functions */ | /* Helper functions */ | ||||
| @@ -192,7 +190,6 @@ static void vorbis_free(vorbis_context *vc) | |||||
| int i; | int i; | ||||
| av_freep(&vc->channel_residues); | av_freep(&vc->channel_residues); | ||||
| av_freep(&vc->channel_floors); | |||||
| av_freep(&vc->saved); | av_freep(&vc->saved); | ||||
| for (i = 0; i < vc->residue_count; i++) | for (i = 0; i < vc->residue_count; i++) | ||||
| @@ -951,12 +948,11 @@ static int vorbis_parse_id_hdr(vorbis_context *vc) | |||||
| } | } | ||||
| vc->channel_residues = av_malloc((vc->blocksize[1] / 2) * vc->audio_channels * sizeof(*vc->channel_residues)); | vc->channel_residues = av_malloc((vc->blocksize[1] / 2) * vc->audio_channels * sizeof(*vc->channel_residues)); | ||||
| vc->channel_floors = av_malloc((vc->blocksize[1] / 2) * vc->audio_channels * sizeof(*vc->channel_floors)); | |||||
| vc->saved = av_mallocz((vc->blocksize[1] / 4) * vc->audio_channels * sizeof(*vc->saved)); | vc->saved = av_mallocz((vc->blocksize[1] / 4) * vc->audio_channels * sizeof(*vc->saved)); | ||||
| vc->previous_window = 0; | vc->previous_window = 0; | ||||
| ff_mdct_init(&vc->mdct[0], bl0, 1, -vc->scale_bias); | |||||
| ff_mdct_init(&vc->mdct[1], bl1, 1, -vc->scale_bias); | |||||
| ff_mdct_init(&vc->mdct[0], bl0, 1, -1.0); | |||||
| ff_mdct_init(&vc->mdct[1], bl1, 1, -1.0); | |||||
| av_dlog(NULL, " vorbis version %d \n audio_channels %d \n audio_samplerate %d \n bitrate_max %d \n bitrate_nom %d \n bitrate_min %d \n blk_0 %d blk_1 %d \n ", | av_dlog(NULL, " vorbis version %d \n audio_channels %d \n audio_samplerate %d \n bitrate_max %d \n bitrate_nom %d \n bitrate_min %d \n blk_0 %d blk_1 %d \n ", | ||||
| vc->version, vc->audio_channels, vc->audio_samplerate, vc->bitrate_maximum, vc->bitrate_nominal, vc->bitrate_minimum, vc->blocksize[0], vc->blocksize[1]); | vc->version, vc->audio_channels, vc->audio_samplerate, vc->bitrate_maximum, vc->bitrate_nominal, vc->bitrate_minimum, vc->blocksize[0], vc->blocksize[1]); | ||||
| @@ -988,13 +984,7 @@ static av_cold int vorbis_decode_init(AVCodecContext *avccontext) | |||||
| avpriv_float_dsp_init(&vc->fdsp, avccontext->flags & CODEC_FLAG_BITEXACT); | avpriv_float_dsp_init(&vc->fdsp, avccontext->flags & CODEC_FLAG_BITEXACT); | ||||
| ff_fmt_convert_init(&vc->fmt_conv, avccontext); | ff_fmt_convert_init(&vc->fmt_conv, avccontext); | ||||
| if (avccontext->request_sample_fmt == AV_SAMPLE_FMT_FLT) { | |||||
| avccontext->sample_fmt = AV_SAMPLE_FMT_FLT; | |||||
| vc->scale_bias = 1.0f; | |||||
| } else { | |||||
| avccontext->sample_fmt = AV_SAMPLE_FMT_S16; | |||||
| vc->scale_bias = 32768.0f; | |||||
| } | |||||
| avccontext->sample_fmt = AV_SAMPLE_FMT_FLTP; | |||||
| if (!headers_len) { | if (!headers_len) { | ||||
| av_log(avccontext, AV_LOG_ERROR, "Extradata missing.\n"); | av_log(avccontext, AV_LOG_ERROR, "Extradata missing.\n"); | ||||
| @@ -1485,7 +1475,7 @@ void ff_vorbis_inverse_coupling(float *mag, float *ang, int blocksize) | |||||
| // Decode the audio packet using the functions above | // Decode the audio packet using the functions above | ||||
| static int vorbis_parse_audio_packet(vorbis_context *vc) | |||||
| static int vorbis_parse_audio_packet(vorbis_context *vc, float **floor_ptr) | |||||
| { | { | ||||
| GetBitContext *gb = &vc->gb; | GetBitContext *gb = &vc->gb; | ||||
| FFTContext *mdct; | FFTContext *mdct; | ||||
| @@ -1496,7 +1486,6 @@ static int vorbis_parse_audio_packet(vorbis_context *vc) | |||||
| uint8_t do_not_decode[255]; | uint8_t do_not_decode[255]; | ||||
| vorbis_mapping *mapping; | vorbis_mapping *mapping; | ||||
| float *ch_res_ptr = vc->channel_residues; | float *ch_res_ptr = vc->channel_residues; | ||||
| float *ch_floor_ptr = vc->channel_floors; | |||||
| uint8_t res_chan[255]; | uint8_t res_chan[255]; | ||||
| unsigned res_num = 0; | unsigned res_num = 0; | ||||
| int retlen = 0; | int retlen = 0; | ||||
| @@ -1528,7 +1517,8 @@ static int vorbis_parse_audio_packet(vorbis_context *vc) | |||||
| } | } | ||||
| memset(ch_res_ptr, 0, sizeof(float) * vc->audio_channels * vlen); //FIXME can this be removed ? | memset(ch_res_ptr, 0, sizeof(float) * vc->audio_channels * vlen); //FIXME can this be removed ? | ||||
| memset(ch_floor_ptr, 0, sizeof(float) * vc->audio_channels * vlen); //FIXME can this be removed ? | |||||
| for (i = 0; i < vc->audio_channels; ++i) | |||||
| memset(floor_ptr[i], 0, vlen * sizeof(floor_ptr[0][0])); //FIXME can this be removed ? | |||||
| // Decode floor | // Decode floor | ||||
| @@ -1541,14 +1531,13 @@ static int vorbis_parse_audio_packet(vorbis_context *vc) | |||||
| floor = &vc->floors[mapping->submap_floor[0]]; | floor = &vc->floors[mapping->submap_floor[0]]; | ||||
| } | } | ||||
| ret = floor->decode(vc, &floor->data, ch_floor_ptr); | |||||
| ret = floor->decode(vc, &floor->data, floor_ptr[i]); | |||||
| if (ret < 0) { | if (ret < 0) { | ||||
| av_log(vc->avccontext, AV_LOG_ERROR, "Invalid codebook in vorbis_floor_decode.\n"); | av_log(vc->avccontext, AV_LOG_ERROR, "Invalid codebook in vorbis_floor_decode.\n"); | ||||
| return AVERROR_INVALIDDATA; | return AVERROR_INVALIDDATA; | ||||
| } | } | ||||
| no_residue[i] = ret; | no_residue[i] = ret; | ||||
| ch_floor_ptr += vlen; | |||||
| } | } | ||||
| // Nonzero vector propagate | // Nonzero vector propagate | ||||
| @@ -1612,10 +1601,9 @@ static int vorbis_parse_audio_packet(vorbis_context *vc) | |||||
| mdct = &vc->mdct[blockflag]; | mdct = &vc->mdct[blockflag]; | ||||
| for (j = vc->audio_channels-1;j >= 0; j--) { | for (j = vc->audio_channels-1;j >= 0; j--) { | ||||
| ch_floor_ptr = vc->channel_floors + j * blocksize / 2; | |||||
| ch_res_ptr = vc->channel_residues + res_chan[j] * blocksize / 2; | ch_res_ptr = vc->channel_residues + res_chan[j] * blocksize / 2; | ||||
| vc->fdsp.vector_fmul(ch_floor_ptr, ch_floor_ptr, ch_res_ptr, blocksize / 2); | |||||
| mdct->imdct_half(mdct, ch_res_ptr, ch_floor_ptr); | |||||
| vc->fdsp.vector_fmul(floor_ptr[j], floor_ptr[j], ch_res_ptr, blocksize / 2); | |||||
| mdct->imdct_half(mdct, ch_res_ptr, floor_ptr[j]); | |||||
| } | } | ||||
| // Overlap/add, save data for next overlapping | // Overlap/add, save data for next overlapping | ||||
| @@ -1626,7 +1614,7 @@ static int vorbis_parse_audio_packet(vorbis_context *vc) | |||||
| unsigned bs1 = vc->blocksize[1]; | unsigned bs1 = vc->blocksize[1]; | ||||
| float *residue = vc->channel_residues + res_chan[j] * blocksize / 2; | float *residue = vc->channel_residues + res_chan[j] * blocksize / 2; | ||||
| float *saved = vc->saved + j * bs1 / 4; | float *saved = vc->saved + j * bs1 / 4; | ||||
| float *ret = vc->channel_floors + j * retlen; | |||||
| float *ret = floor_ptr[j]; | |||||
| float *buf = residue; | float *buf = residue; | ||||
| const float *win = vc->win[blockflag & previous_window]; | const float *win = vc->win[blockflag & previous_window]; | ||||
| @@ -1655,14 +1643,31 @@ static int vorbis_decode_frame(AVCodecContext *avccontext, void *data, | |||||
| int buf_size = avpkt->size; | int buf_size = avpkt->size; | ||||
| vorbis_context *vc = avccontext->priv_data; | vorbis_context *vc = avccontext->priv_data; | ||||
| GetBitContext *gb = &vc->gb; | GetBitContext *gb = &vc->gb; | ||||
| const float *channel_ptrs[255]; | |||||
| float *channel_ptrs[255]; | |||||
| int i, len, ret; | int i, len, ret; | ||||
| av_dlog(NULL, "packet length %d \n", buf_size); | av_dlog(NULL, "packet length %d \n", buf_size); | ||||
| /* get output buffer */ | |||||
| vc->frame.nb_samples = vc->blocksize[1] / 2; | |||||
| if ((ret = avccontext->get_buffer(avccontext, &vc->frame)) < 0) { | |||||
| av_log(avccontext, AV_LOG_ERROR, "get_buffer() failed\n"); | |||||
| return ret; | |||||
| } | |||||
| if (vc->audio_channels > 8) { | |||||
| for (i = 0; i < vc->audio_channels; i++) | |||||
| channel_ptrs[i] = (float *)vc->frame.extended_data[i]; | |||||
| } else { | |||||
| for (i = 0; i < vc->audio_channels; i++) { | |||||
| int ch = ff_vorbis_channel_layout_offsets[vc->audio_channels - 1][i]; | |||||
| channel_ptrs[ch] = (float *)vc->frame.extended_data[i]; | |||||
| } | |||||
| } | |||||
| init_get_bits(gb, buf, buf_size*8); | init_get_bits(gb, buf, buf_size*8); | ||||
| if ((len = vorbis_parse_audio_packet(vc)) <= 0) | |||||
| if ((len = vorbis_parse_audio_packet(vc, channel_ptrs)) <= 0) | |||||
| return len; | return len; | ||||
| if (!vc->first_frame) { | if (!vc->first_frame) { | ||||
| @@ -1674,30 +1679,7 @@ static int vorbis_decode_frame(AVCodecContext *avccontext, void *data, | |||||
| av_dlog(NULL, "parsed %d bytes %d bits, returned %d samples (*ch*bits) \n", | av_dlog(NULL, "parsed %d bytes %d bits, returned %d samples (*ch*bits) \n", | ||||
| get_bits_count(gb) / 8, get_bits_count(gb) % 8, len); | get_bits_count(gb) / 8, get_bits_count(gb) % 8, len); | ||||
| /* get output buffer */ | |||||
| vc->frame.nb_samples = len; | vc->frame.nb_samples = len; | ||||
| if ((ret = avccontext->get_buffer(avccontext, &vc->frame)) < 0) { | |||||
| av_log(avccontext, AV_LOG_ERROR, "get_buffer() failed\n"); | |||||
| return ret; | |||||
| } | |||||
| if (vc->audio_channels > 8) { | |||||
| for (i = 0; i < vc->audio_channels; i++) | |||||
| channel_ptrs[i] = vc->channel_floors + i * len; | |||||
| } else { | |||||
| for (i = 0; i < vc->audio_channels; i++) | |||||
| channel_ptrs[i] = vc->channel_floors + | |||||
| len * ff_vorbis_channel_layout_offsets[vc->audio_channels - 1][i]; | |||||
| } | |||||
| if (avccontext->sample_fmt == AV_SAMPLE_FMT_FLT) | |||||
| vc->fmt_conv.float_interleave((float *)vc->frame.data[0], channel_ptrs, | |||||
| len, vc->audio_channels); | |||||
| else | |||||
| vc->fmt_conv.float_to_int16_interleave((int16_t *)vc->frame.data[0], | |||||
| channel_ptrs, len, | |||||
| vc->audio_channels); | |||||
| *got_frame_ptr = 1; | *got_frame_ptr = 1; | ||||
| *(AVFrame *)data = vc->frame; | *(AVFrame *)data = vc->frame; | ||||
| @@ -1738,7 +1720,6 @@ AVCodec ff_vorbis_decoder = { | |||||
| .capabilities = CODEC_CAP_DR1, | .capabilities = CODEC_CAP_DR1, | ||||
| .long_name = NULL_IF_CONFIG_SMALL("Vorbis"), | .long_name = NULL_IF_CONFIG_SMALL("Vorbis"), | ||||
| .channel_layouts = ff_vorbis_channel_layouts, | .channel_layouts = ff_vorbis_channel_layouts, | ||||
| .sample_fmts = (const enum AVSampleFormat[]) { | |||||
| AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE | |||||
| }, | |||||
| .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, | |||||
| AV_SAMPLE_FMT_NONE }, | |||||
| }; | }; | ||||