X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Fqdm2.c;h=1e0811c8612e7d56c8188b1cae42e7597afc614e;hb=5053a9a1ffd907ae1d189c03c7e86bb375a44ded;hp=0f4dd18966d0848481dfc617673d7f2e8167549b;hpb=4bac1bbc3bc6e102cd1e8bfd0a36db07d769dfea;p=ffmpeg diff --git a/libavcodec/qdm2.c b/libavcodec/qdm2.c index 0f4dd18966d..1e0811c8612 100644 --- a/libavcodec/qdm2.c +++ b/libavcodec/qdm2.c @@ -26,6 +26,7 @@ * @file * QDM2 decoder * @author Ewald Snel, Benjamin Larsson, Alex Beregszaszi, Roberto Togni + * * The decoder is not perfect yet, there are still some distortions * especially on files encoded with 16 or 8 subbands. */ @@ -34,11 +35,13 @@ #include #include -#define ALT_BITSTREAM_READER_LE +#define BITSTREAM_READER_LE +#include "libavutil/channel_layout.h" #include "avcodec.h" #include "get_bits.h" -#include "dsputil.h" +#include "internal.h" #include "rdft.h" +#include "mpegaudiodsp.h" #include "mpegaudio.h" #include "qdm2data.h" @@ -67,14 +70,13 @@ do { \ #define SB_DITHERING_NOISE(sb,noise_idx) (noise_table[(noise_idx)++] * sb_noise_attenuation[(sb)]) -#define BITS_LEFT(length,gb) ((length) - get_bits_count ((gb))) - #define SAMPLES_NEEDED \ av_log (NULL,AV_LOG_INFO,"This file triggers some untested code. Please contact the developers.\n"); #define SAMPLES_NEEDED_2(why) \ av_log (NULL,AV_LOG_INFO,"This file triggers some missing code. Please contact the developers.\nPosition: %s\n",why); +#define QDM2_MAX_FRAME_SIZE 512 typedef int8_t sb_int8_array[2][30][64]; @@ -137,7 +139,6 @@ typedef struct { /// Parameters built from header parameters, do not change during playback int group_order; ///< order of frame group int fft_order; ///< order of FFT (actually fftorder+1) - int fft_frame_size; ///< size of fft frame, in components (1 comples = re + im) int frame_size; ///< size of data frame int frequency_range; int sub_sampling; ///< subsampling: 0=25%, 1=50%, 2=100% */ @@ -167,12 +168,14 @@ typedef struct { /// I/O data const uint8_t *compressed_data; int compressed_size; - float output_buffer[1024]; + float output_buffer[QDM2_MAX_FRAME_SIZE * 2]; /// Synthesis filter - DECLARE_ALIGNED(16, MPA_INT, synth_buf)[MPA_MAX_CHANNELS][512*2]; + MPADSPContext mpadsp; + DECLARE_ALIGNED(32, float, synth_buf)[MPA_MAX_CHANNELS][512*2]; int synth_buf_offset[MPA_MAX_CHANNELS]; - DECLARE_ALIGNED(16, int32_t, sb_samples)[MPA_MAX_CHANNELS][128][SBLIMIT]; + DECLARE_ALIGNED(32, float, sb_samples)[MPA_MAX_CHANNELS][128][SBLIMIT]; + DECLARE_ALIGNED(32, float, samples)[MPA_MAX_CHANNELS * MPA_FRAME_SIZE]; /// Mixed temporary data used in decoding float tone_level[MPA_MAX_CHANNELS][30][64]; @@ -195,8 +198,6 @@ typedef struct { } QDM2Context; -static uint8_t empty_buffer[FF_INPUT_BUFFER_PADDING_SIZE]; - static VLC vlc_tab_level; static VLC vlc_tab_diff; static VLC vlc_tab_run; @@ -329,11 +330,6 @@ static av_cold void qdm2_init_vlc(void) } } - -/* for floating point to fixed point conversion */ -static const float f2i_scale = (float) (1 << (FRAC_BITS - 15)); - - static int qdm2_get_vlc (GetBitContext *gb, VLC *vlc, int flag, int depth) { int value; @@ -482,8 +478,8 @@ static void build_sb_samples_from_noise (QDM2Context *q, int sb) for (ch = 0; ch < q->nb_channels; ch++) for (j = 0; j < 64; j++) { - q->sb_samples[ch][j * 2][sb] = (int32_t)(f2i_scale * SB_DITHERING_NOISE(sb,q->noise_idx) * q->tone_level[ch][sb][j] + .5); - q->sb_samples[ch][j * 2 + 1][sb] = (int32_t)(f2i_scale * SB_DITHERING_NOISE(sb,q->noise_idx) * q->tone_level[ch][sb][j] + .5); + q->sb_samples[ch][j * 2][sb] = SB_DITHERING_NOISE(sb,q->noise_idx) * q->tone_level[ch][sb][j]; + q->sb_samples[ch][j * 2 + 1][sb] = SB_DITHERING_NOISE(sb,q->noise_idx) * q->tone_level[ch][sb][j]; } } @@ -501,7 +497,7 @@ static void fix_coding_method_array (int sb, int channels, sb_int8_array coding_ int j,k; int ch; int run, case_val; - int switchtable[23] = {0,5,1,5,5,5,5,5,2,5,5,5,5,5,5,5,3,5,5,5,5,5,4}; + static const int switchtable[23] = {0,5,1,5,5,5,5,5,2,5,5,5,5,5,5,5,3,5,5,5,5,5,4}; for (ch = 0; ch < channels; ch++) { for (j = 0; j < 64; ) { @@ -546,10 +542,6 @@ static void fill_tone_level_array (QDM2Context *q, int flag) int i, sb, ch, sb_used; int tmp, tab; - // This should never happen - if (q->nb_channels <= 0) - return; - for (ch = 0; ch < q->nb_channels; ch++) for (sb = 0; sb < 30; sb++) for (i = 0; i < 8; i++) { @@ -645,10 +637,6 @@ static void fill_coding_method_array (sb_int8_array tone_level_idx, sb_int8_arra int add1, add2, add3, add4; int64_t multres; - // This should never happen - if (nb_channels <= 0) - return; - if (!superblocktype_2_3) { /* This case is untested, no samples available */ SAMPLES_NEEDED @@ -791,10 +779,10 @@ static void synthfilt_build_sb_samples (QDM2Context *q, GetBitContext *gb, int l else if (sb >= 24) joined_stereo = 1; else - joined_stereo = (BITS_LEFT(length,gb) >= 1) ? get_bits1 (gb) : 0; + joined_stereo = (get_bits_left(gb) >= 1) ? get_bits1 (gb) : 0; if (joined_stereo) { - if (BITS_LEFT(length,gb) >= 16) + if (get_bits_left(gb) >= 16) for (j = 0; j < 16; j++) sign_bits[j] = get_bits1 (gb); @@ -807,14 +795,14 @@ static void synthfilt_build_sb_samples (QDM2Context *q, GetBitContext *gb, int l } for (ch = 0; ch < channels; ch++) { - zero_encoding = (BITS_LEFT(length,gb) >= 1) ? get_bits1(gb) : 0; + zero_encoding = (get_bits_left(gb) >= 1) ? get_bits1(gb) : 0; type34_predictor = 0.0; type34_first = 1; for (j = 0; j < 128; ) { switch (q->coding_method[ch][sb][j / 2]) { case 8: - if (BITS_LEFT(length,gb) >= 10) { + if (get_bits_left(gb) >= 10) { if (zero_encoding) { for (k = 0; k < 5; k++) { if ((j + 2 * k) >= 128) @@ -836,7 +824,7 @@ static void synthfilt_build_sb_samples (QDM2Context *q, GetBitContext *gb, int l break; case 10: - if (BITS_LEFT(length,gb) >= 1) { + if (get_bits_left(gb) >= 1) { float f = 0.81; if (get_bits1(gb)) @@ -850,7 +838,7 @@ static void synthfilt_build_sb_samples (QDM2Context *q, GetBitContext *gb, int l break; case 16: - if (BITS_LEFT(length,gb) >= 10) { + if (get_bits_left(gb) >= 10) { if (zero_encoding) { for (k = 0; k < 5; k++) { if ((j + k) >= 128) @@ -870,7 +858,7 @@ static void synthfilt_build_sb_samples (QDM2Context *q, GetBitContext *gb, int l break; case 24: - if (BITS_LEFT(length,gb) >= 7) { + if (get_bits_left(gb) >= 7) { n = get_bits(gb, 7); for (k = 0; k < 3; k++) samples[k] = (random_dequant_type24[n][k] - 2.0) * 0.5; @@ -882,24 +870,32 @@ static void synthfilt_build_sb_samples (QDM2Context *q, GetBitContext *gb, int l break; case 30: - if (BITS_LEFT(length,gb) >= 4) - samples[0] = type30_dequant[qdm2_get_vlc(gb, &vlc_tab_type30, 0, 1)]; - else + if (get_bits_left(gb) >= 4) { + unsigned index = qdm2_get_vlc(gb, &vlc_tab_type30, 0, 1); + if (index < FF_ARRAY_ELEMS(type30_dequant)) { + samples[0] = type30_dequant[index]; + } else + samples[0] = SB_DITHERING_NOISE(sb,q->noise_idx); + } else samples[0] = SB_DITHERING_NOISE(sb,q->noise_idx); run = 1; break; case 34: - if (BITS_LEFT(length,gb) >= 7) { + if (get_bits_left(gb) >= 7) { if (type34_first) { type34_div = (float)(1 << get_bits(gb, 2)); samples[0] = ((float)get_bits(gb, 5) - 16.0) / 15.0; type34_predictor = samples[0]; type34_first = 0; } else { - samples[0] = type34_delta[qdm2_get_vlc(gb, &vlc_tab_type34, 0, 1)] / type34_div + type34_predictor; - type34_predictor = samples[0]; + unsigned index = qdm2_get_vlc(gb, &vlc_tab_type34, 0, 1); + if (index < FF_ARRAY_ELEMS(type34_delta)) { + samples[0] = type34_delta[index] / type34_div + type34_predictor; + type34_predictor = samples[0]; + } else + samples[0] = SB_DITHERING_NOISE(sb,q->noise_idx); } } else { samples[0] = SB_DITHERING_NOISE(sb,q->noise_idx); @@ -923,11 +919,11 @@ static void synthfilt_build_sb_samples (QDM2Context *q, GetBitContext *gb, int l for (chs = 0; chs < q->nb_channels; chs++) for (k = 0; k < run; k++) if ((j + k) < 128) - q->sb_samples[chs][j + k][sb] = (int32_t)(f2i_scale * q->tone_level[chs][sb][((j + k)/2)] * tmp[k][chs] + .5); + q->sb_samples[chs][j + k][sb] = q->tone_level[chs][sb][((j + k)/2)] * tmp[k][chs]; } else { for (k = 0; k < run; k++) if ((j + k) < 128) - q->sb_samples[ch][j + k][sb] = (int32_t)(f2i_scale * q->tone_level[ch][sb][(j + k)/2] * samples[k] + .5); + q->sb_samples[ch][j + k][sb] = q->tone_level[ch][sb][(j + k)/2] * samples[k]; } j += run; @@ -944,24 +940,23 @@ static void synthfilt_build_sb_samples (QDM2Context *q, GetBitContext *gb, int l * * @param quantized_coeffs pointer to quantized_coeffs[ch][0] * @param gb bitreader context - * @param length packet length in bits */ -static void init_quantized_coeffs_elem0 (int8_t *quantized_coeffs, GetBitContext *gb, int length) +static void init_quantized_coeffs_elem0 (int8_t *quantized_coeffs, GetBitContext *gb) { int i, k, run, level, diff; - if (BITS_LEFT(length,gb) < 16) + if (get_bits_left(gb) < 16) return; level = qdm2_get_vlc(gb, &vlc_tab_level, 0, 2); quantized_coeffs[0] = level; for (i = 0; i < 7; ) { - if (BITS_LEFT(length,gb) < 16) + if (get_bits_left(gb) < 16) break; run = qdm2_get_vlc(gb, &vlc_tab_run, 0, 1) + 1; - if (BITS_LEFT(length,gb) < 16) + if (get_bits_left(gb) < 16) break; diff = qdm2_get_se_vlc(&vlc_tab_diff, gb, 2); @@ -981,16 +976,15 @@ static void init_quantized_coeffs_elem0 (int8_t *quantized_coeffs, GetBitContext * * @param q context * @param gb bitreader context - * @param length packet length in bits */ -static void init_tone_level_dequantization (QDM2Context *q, GetBitContext *gb, int length) +static void init_tone_level_dequantization (QDM2Context *q, GetBitContext *gb) { int sb, j, k, n, ch; for (ch = 0; ch < q->nb_channels; ch++) { - init_quantized_coeffs_elem0(q->quantized_coeffs[ch][0], gb, length); + init_quantized_coeffs_elem0(q->quantized_coeffs[ch][0], gb); - if (BITS_LEFT(length,gb) < 16) { + if (get_bits_left(gb) < 16) { memset(q->quantized_coeffs[ch][0], 0, 8); break; } @@ -1001,11 +995,11 @@ static void init_tone_level_dequantization (QDM2Context *q, GetBitContext *gb, i for (sb = 0; sb < n; sb++) for (ch = 0; ch < q->nb_channels; ch++) for (j = 0; j < 8; j++) { - if (BITS_LEFT(length,gb) < 1) + if (get_bits_left(gb) < 1) break; if (get_bits1(gb)) { for (k=0; k < 8; k++) { - if (BITS_LEFT(length,gb) < 16) + if (get_bits_left(gb) < 16) break; q->tone_level_idx_hi1[ch][sb][j][k] = qdm2_get_vlc(gb, &vlc_tab_tone_level_idx_hi1, 0, 2); } @@ -1019,7 +1013,7 @@ static void init_tone_level_dequantization (QDM2Context *q, GetBitContext *gb, i for (sb = 0; sb < n; sb++) for (ch = 0; ch < q->nb_channels; ch++) { - if (BITS_LEFT(length,gb) < 16) + if (get_bits_left(gb) < 16) break; q->tone_level_idx_hi2[ch][sb] = qdm2_get_vlc(gb, &vlc_tab_tone_level_idx_hi2, 0, 2); if (sb > 19) @@ -1034,7 +1028,7 @@ static void init_tone_level_dequantization (QDM2Context *q, GetBitContext *gb, i for (sb = 0; sb < n; sb++) for (ch = 0; ch < q->nb_channels; ch++) for (j = 0; j < 8; j++) { - if (BITS_LEFT(length,gb) < 16) + if (get_bits_left(gb) < 16) break; q->tone_level_idx_mid[ch][sb][j] = qdm2_get_vlc(gb, &vlc_tab_tone_level_idx_mid, 0, 2) - 32; } @@ -1083,16 +1077,14 @@ static void process_subpacket_9 (QDM2Context *q, QDM2SubPNode *node) * * @param q context * @param node pointer to node with packet - * @param length packet length in bits */ -static void process_subpacket_10 (QDM2Context *q, QDM2SubPNode *node, int length) +static void process_subpacket_10 (QDM2Context *q, QDM2SubPNode *node) { GetBitContext gb; - init_get_bits(&gb, ((node == NULL) ? empty_buffer : node->packet->data), ((node == NULL) ? 0 : node->packet->size*8)); - - if (length != 0) { - init_tone_level_dequantization(q, &gb, length); + if (node) { + init_get_bits(&gb, node->packet->data, node->packet->size * 8); + init_tone_level_dequantization(q, &gb); fill_tone_level_array(q, 1); } else { fill_tone_level_array(q, 0); @@ -1105,13 +1097,17 @@ static void process_subpacket_10 (QDM2Context *q, QDM2SubPNode *node, int length * * @param q context * @param node pointer to node with packet - * @param length packet length in bit */ -static void process_subpacket_11 (QDM2Context *q, QDM2SubPNode *node, int length) +static void process_subpacket_11 (QDM2Context *q, QDM2SubPNode *node) { GetBitContext gb; + int length = 0; + + if (node) { + length = node->packet->size * 8; + init_get_bits(&gb, node->packet->data, length); + } - init_get_bits(&gb, ((node == NULL) ? empty_buffer : node->packet->data), ((node == NULL) ? 0 : node->packet->size*8)); if (length >= 32) { int c = get_bits (&gb, 13); @@ -1129,13 +1125,17 @@ static void process_subpacket_11 (QDM2Context *q, QDM2SubPNode *node, int length * * @param q context * @param node pointer to node with packet - * @param length packet length in bits */ -static void process_subpacket_12 (QDM2Context *q, QDM2SubPNode *node, int length) +static void process_subpacket_12 (QDM2Context *q, QDM2SubPNode *node) { GetBitContext gb; + int length = 0; + + if (node) { + length = node->packet->size * 8; + init_get_bits(&gb, node->packet->data, length); + } - init_get_bits(&gb, ((node == NULL) ? empty_buffer : node->packet->data), ((node == NULL) ? 0 : node->packet->size*8)); synthfilt_build_sb_samples(q, &gb, length, 8, QDM2_SB_USED(q->sub_sampling)); } @@ -1155,21 +1155,21 @@ static void process_synthesis_subpackets (QDM2Context *q, QDM2SubPNode *list) nodes[1] = qdm2_search_subpacket_type_in_list(list, 10); if (nodes[1] != NULL) - process_subpacket_10(q, nodes[1], nodes[1]->packet->size << 3); + process_subpacket_10(q, nodes[1]); else - process_subpacket_10(q, NULL, 0); + process_subpacket_10(q, NULL); nodes[2] = qdm2_search_subpacket_type_in_list(list, 11); if (nodes[0] != NULL && nodes[1] != NULL && nodes[2] != NULL) - process_subpacket_11(q, nodes[2], (nodes[2]->packet->size << 3)); + process_subpacket_11(q, nodes[2]); else - process_subpacket_11(q, NULL, 0); + process_subpacket_11(q, NULL); nodes[3] = qdm2_search_subpacket_type_in_list(list, 12); if (nodes[0] != NULL && nodes[1] != NULL && nodes[3] != NULL) - process_subpacket_12(q, nodes[3], (nodes[3]->packet->size << 3)); + process_subpacket_12(q, nodes[3]); else - process_subpacket_12(q, NULL, 0); + process_subpacket_12(q, NULL); } @@ -1231,6 +1231,11 @@ static void qdm2_decode_super_block (QDM2Context *q) for (i = 0; packet_bytes > 0; i++) { int j; + if (i >= FF_ARRAY_ELEMS(q->sub_packet_list_A)) { + SAMPLES_NEEDED_2("too many packet bytes"); + return; + } + q->sub_packet_list_A[i].next = NULL; if (i > 0) { @@ -1291,9 +1296,9 @@ static void qdm2_decode_super_block (QDM2Context *q) process_synthesis_subpackets(q, q->sub_packet_list_D); q->do_synth_filter = 1; } else if (q->do_synth_filter) { - process_subpacket_10(q, NULL, 0); - process_subpacket_11(q, NULL, 0); - process_subpacket_12(q, NULL, 0); + process_subpacket_10(q, NULL); + process_subpacket_11(q, NULL); + process_subpacket_12(q, NULL); } /* **************************************************************** */ } @@ -1355,6 +1360,8 @@ static void qdm2_fft_decode_tones (QDM2Context *q, int duration, GetBitContext * return; local_int_14 = (offset >> local_int_8); + if (local_int_14 >= FF_ARRAY_ELEMS(fft_level_index_table)) + return; if (q->nb_channels > 1) { channel = get_bits1(gb); @@ -1585,13 +1592,17 @@ static void qdm2_fft_tone_synthesizer (QDM2Context *q, int sub_packet) static void qdm2_calculate_fft (QDM2Context *q, int channel, int sub_packet) { const float gain = (q->channels == 1 && q->nb_channels == 2) ? 0.5f : 1.0f; + float *out = q->output_buffer + channel; int i; q->fft.complex[channel][0].re *= 2.0f; q->fft.complex[channel][0].im = 0.0f; q->rdft_ctx.rdft_calc(&q->rdft_ctx, (FFTSample *)q->fft.complex[channel]); /* add samples to output buffer */ - for (i = 0; i < ((q->fft_frame_size + 15) & ~15); i++) - q->output_buffer[q->channels * i + channel] += ((float *) q->fft.complex[channel])[i] * gain; + for (i = 0; i < FFALIGN(q->fft_size, 8); i++) { + out[0] += q->fft.complex[channel][i].re * gain; + out[q->channels] += q->fft.complex[channel][i].im * gain; + out += 2 * q->channels; + } } @@ -1601,7 +1612,6 @@ static void qdm2_calculate_fft (QDM2Context *q, int channel, int sub_packet) */ static void qdm2_synthesis_filter (QDM2Context *q, int index) { - OUT_INT samples[MPA_MAX_CHANNELS * MPA_FRAME_SIZE]; int i, k, ch, sb_used, sub_sampling, dither_state = 0; /* copy sb_samples */ @@ -1613,11 +1623,12 @@ static void qdm2_synthesis_filter (QDM2Context *q, int index) q->sb_samples[ch][(8 * index) + i][k] = 0; for (ch = 0; ch < q->nb_channels; ch++) { - OUT_INT *samples_ptr = samples + ch; + float *samples_ptr = q->samples + ch; for (i = 0; i < 8; i++) { - ff_mpa_synth_filter_fixed(q->synth_buf[ch], &(q->synth_buf_offset[ch]), - ff_mpa_synth_window_fixed, &dither_state, + ff_mpa_synth_filter_float(&q->mpadsp, + q->synth_buf[ch], &(q->synth_buf_offset[ch]), + ff_mpa_synth_window_float, &dither_state, samples_ptr, q->nb_channels, q->sb_samples[ch][(8 * index) + i]); samples_ptr += 32 * q->nb_channels; @@ -1629,7 +1640,7 @@ static void qdm2_synthesis_filter (QDM2Context *q, int index) for (ch = 0; ch < q->channels; ch++) for (i = 0; i < q->frame_size; i++) - q->output_buffer[q->channels * i + ch] += (float)(samples[q->nb_channels * sub_sampling * i + ch] >> (sizeof(OUT_INT)*8-16)); + q->output_buffer[q->channels * i + ch] += (1 << 23) * q->samples[q->nb_channels * sub_sampling * i + ch]; } @@ -1646,7 +1657,7 @@ static av_cold void qdm2_init(QDM2Context *q) { initialized = 1; qdm2_init_vlc(); - ff_mpa_synth_init_fixed(ff_mpa_synth_window_fixed); + ff_mpa_synth_init_float(ff_mpa_synth_window_float); softclip_table_init(); rnd_table_init(); init_noise_samples(); @@ -1655,52 +1666,6 @@ static av_cold void qdm2_init(QDM2Context *q) { } -#if 0 -static void dump_context(QDM2Context *q) -{ - int i; -#define PRINT(a,b) av_log(NULL,AV_LOG_DEBUG," %s = %d\n", a, b); - PRINT("compressed_data",q->compressed_data); - PRINT("compressed_size",q->compressed_size); - PRINT("frame_size",q->frame_size); - PRINT("checksum_size",q->checksum_size); - PRINT("channels",q->channels); - PRINT("nb_channels",q->nb_channels); - PRINT("fft_frame_size",q->fft_frame_size); - PRINT("fft_size",q->fft_size); - PRINT("sub_sampling",q->sub_sampling); - PRINT("fft_order",q->fft_order); - PRINT("group_order",q->group_order); - PRINT("group_size",q->group_size); - PRINT("sub_packet",q->sub_packet); - PRINT("frequency_range",q->frequency_range); - PRINT("has_errors",q->has_errors); - PRINT("fft_tone_end",q->fft_tone_end); - PRINT("fft_tone_start",q->fft_tone_start); - PRINT("fft_coefs_index",q->fft_coefs_index); - PRINT("coeff_per_sb_select",q->coeff_per_sb_select); - PRINT("cm_table_select",q->cm_table_select); - PRINT("noise_idx",q->noise_idx); - - for (i = q->fft_tone_start; i < q->fft_tone_end; i++) - { - FFTTone *t = &q->fft_tones[i]; - - av_log(NULL,AV_LOG_DEBUG,"Tone (%d) dump:\n", i); - av_log(NULL,AV_LOG_DEBUG," level = %f\n", t->level); -// PRINT(" level", t->level); - PRINT(" phase", t->phase); - PRINT(" phase_shift", t->phase_shift); - PRINT(" duration", t->duration); - PRINT(" samples_im", t->samples_im); - PRINT(" samples_re", t->samples_re); - PRINT(" table", t->table); - } - -} -#endif - - /** * Init parameters from codec extradata */ @@ -1799,6 +1764,10 @@ static av_cold int qdm2_decode_init(AVCodecContext *avctx) avctx->channels = s->nb_channels = s->channels = AV_RB32(extradata); extradata += 4; + if (s->channels <= 0 || s->channels > MPA_MAX_CHANNELS) + return AVERROR_INVALIDDATA; + avctx->channel_layout = avctx->channels == 2 ? AV_CH_LAYOUT_STEREO : + AV_CH_LAYOUT_MONO; avctx->sample_rate = AV_RB32(extradata); extradata += 4; @@ -1813,13 +1782,18 @@ static av_cold int qdm2_decode_init(AVCodecContext *avctx) extradata += 4; s->checksum_size = AV_RB32(extradata); + if (s->checksum_size >= 1U << 28) { + av_log(avctx, AV_LOG_ERROR, "data block size too large (%u)\n", s->checksum_size); + return AVERROR_INVALIDDATA; + } s->fft_order = av_log2(s->fft_size) + 1; - s->fft_frame_size = 2 * s->fft_size; // complex has two floats // something like max decodable tones s->group_order = av_log2(s->group_size) + 1; s->frame_size = s->group_size / 16; // 16 iterations per super block + if (s->frame_size > QDM2_MAX_FRAME_SIZE) + return AVERROR_INVALIDDATA; s->sub_sampling = s->fft_order - 7; s->frequency_range = 255 / (1 << (2 - s->sub_sampling)); @@ -1861,14 +1835,18 @@ static av_cold int qdm2_decode_init(AVCodecContext *avctx) av_log(avctx, AV_LOG_ERROR, "Unknown FFT order (%d), contact the developers!\n", s->fft_order); return -1; } + if (s->fft_size != (1 << (s->fft_order - 1))) { + av_log(avctx, AV_LOG_ERROR, "FFT size %d not power of 2.\n", s->fft_size); + return AVERROR_INVALIDDATA; + } ff_rdft_init(&s->rdft_ctx, s->fft_order, IDFT_C2R); + ff_mpadsp_init(&s->mpadsp); qdm2_init(s); avctx->sample_fmt = AV_SAMPLE_FMT_S16; -// dump_context(s); return 0; } @@ -1892,8 +1870,6 @@ static int qdm2_decode (QDM2Context *q, const uint8_t *in, int16_t *out) q->compressed_data = in; q->compressed_size = q->checksum_size; -// dump_context(q); - /* copy old block, clear new block of output samples */ memmove(q->output_buffer, &q->output_buffer[frame_size], frame_size * sizeof(float)); memset(&q->output_buffer[frame_size], 0, frame_size * sizeof(float)); @@ -1945,23 +1921,28 @@ static int qdm2_decode (QDM2Context *q, const uint8_t *in, int16_t *out) } -static int qdm2_decode_frame(AVCodecContext *avctx, - void *data, int *data_size, - AVPacket *avpkt) +static int qdm2_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame_ptr, AVPacket *avpkt) { + AVFrame *frame = data; const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; QDM2Context *s = avctx->priv_data; - int16_t *out = data; - int i; + int16_t *out; + int i, ret; if(!buf) return 0; if(buf_size < s->checksum_size) return -1; - av_log(avctx, AV_LOG_DEBUG, "decode(%d): %p[%d] -> %p[%d]\n", - buf_size, buf, s->checksum_size, data, *data_size); + /* get output buffer */ + frame->nb_samples = 16 * s->frame_size; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) { + av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); + return ret; + } + out = (int16_t *)frame->data[0]; for (i = 0; i < 16; i++) { if (qdm2_decode(s, buf, out) < 0) @@ -1969,19 +1950,20 @@ static int qdm2_decode_frame(AVCodecContext *avctx, out += s->channels * s->frame_size; } - *data_size = (uint8_t*)out - (uint8_t*)data; + *got_frame_ptr = 1; return s->checksum_size; } AVCodec ff_qdm2_decoder = { - .name = "qdm2", - .type = AVMEDIA_TYPE_AUDIO, - .id = CODEC_ID_QDM2, + .name = "qdm2", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_QDM2, .priv_data_size = sizeof(QDM2Context), - .init = qdm2_decode_init, - .close = qdm2_decode_close, - .decode = qdm2_decode_frame, - .long_name = NULL_IF_CONFIG_SMALL("QDesign Music Codec 2"), + .init = qdm2_decode_init, + .close = qdm2_decode_close, + .decode = qdm2_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("QDesign Music Codec 2"), };