⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 qdm2.c

📁 ffmpeg的完整源代码和作者自己写的文档。不但有在Linux的工程哦
💻 C
📖 第 1 页 / 共 5 页
字号:


/**
 * Process subpacket 10 if not null, else
 *
 * @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)
{
    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);
        fill_tone_level_array(q, 1);
    } else {
        fill_tone_level_array(q, 0);
    }
}


/**
 * Process subpacket 11
 *
 * @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)
{
    GetBitContext gb;

    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);

        if (c > 3)
            fill_coding_method_array (q->tone_level_idx, q->tone_level_idx_temp, q->coding_method,
                                      q->nb_channels, 8*c, q->superblocktype_2_3, q->cm_table_select);
    }

    synthfilt_build_sb_samples(q, &gb, length, 0, 8);
}


/**
 * Process subpacket 12
 *
 * @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)
{
    GetBitContext gb;

    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));
}

/*
 * Process new subpackets for synthesis filter
 *
 * @param q       context
 * @param list    list with synthesis filter packets (list D)
 */
static void process_synthesis_subpackets (QDM2Context *q, QDM2SubPNode *list)
{
    QDM2SubPNode *nodes[4];

    nodes[0] = qdm2_search_subpacket_type_in_list(list, 9);
    if (nodes[0] != NULL)
        process_subpacket_9(q, nodes[0]);

    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);
    else
        process_subpacket_10(q, NULL, 0);

    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));
    else
        process_subpacket_11(q, NULL, 0);

    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));
    else
        process_subpacket_12(q, NULL, 0);
}


/*
 * Decode superblock, fill packet lists.
 *
 * @param q    context
 */
static void qdm2_decode_super_block (QDM2Context *q)
{
    GetBitContext gb;
    QDM2SubPacket header, *packet;
    int i, packet_bytes, sub_packet_size, sub_packets_D;
    unsigned int next_index = 0;

    memset(q->tone_level_idx_hi1, 0, sizeof(q->tone_level_idx_hi1));
    memset(q->tone_level_idx_mid, 0, sizeof(q->tone_level_idx_mid));
    memset(q->tone_level_idx_hi2, 0, sizeof(q->tone_level_idx_hi2));

    q->sub_packets_B = 0;
    sub_packets_D = 0;

    average_quantized_coeffs(q); // average elements in quantized_coeffs[max_ch][10][8]

    init_get_bits(&gb, q->compressed_data, q->compressed_size*8);
    qdm2_decode_sub_packet_header(&gb, &header);

    if (header.type < 2 || header.type >= 8) {
        q->has_errors = 1;
        av_log(NULL,AV_LOG_ERROR,"bad superblock type\n");
        return;
    }

    q->superblocktype_2_3 = (header.type == 2 || header.type == 3);
    packet_bytes = (q->compressed_size - get_bits_count(&gb) / 8);

    init_get_bits(&gb, header.data, header.size*8);

    if (header.type == 2 || header.type == 4 || header.type == 5) {
        int csum = 257 * get_bits(&gb, 8) + 2 * get_bits(&gb, 8);

        csum = qdm2_packet_checksum(q->compressed_data, q->checksum_size, csum);

        if (csum != 0) {
            q->has_errors = 1;
            av_log(NULL,AV_LOG_ERROR,"bad packet checksum\n");
            return;
        }
    }

    q->sub_packet_list_B[0].packet = NULL;
    q->sub_packet_list_D[0].packet = NULL;

    for (i = 0; i < 6; i++)
        if (--q->fft_level_exp[i] < 0)
            q->fft_level_exp[i] = 0;

    for (i = 0; packet_bytes > 0; i++) {
        int j;

        q->sub_packet_list_A[i].next = NULL;

        if (i > 0) {
            q->sub_packet_list_A[i - 1].next = &q->sub_packet_list_A[i];

            /* seek to next block */
            init_get_bits(&gb, header.data, header.size*8);
            skip_bits(&gb, next_index*8);

            if (next_index >= header.size)
                break;
        }

        /* decode subpacket */
        packet = &q->sub_packets[i];
        qdm2_decode_sub_packet_header(&gb, packet);
        next_index = packet->size + get_bits_count(&gb) / 8;
        sub_packet_size = ((packet->size > 0xff) ? 1 : 0) + packet->size + 2;

        if (packet->type == 0)
            break;

        if (sub_packet_size > packet_bytes) {
            if (packet->type != 10 && packet->type != 11 && packet->type != 12)
                break;
            packet->size += packet_bytes - sub_packet_size;
        }

        packet_bytes -= sub_packet_size;

        /* add subpacket to 'all subpackets' list */
        q->sub_packet_list_A[i].packet = packet;

        /* add subpacket to related list */
        if (packet->type == 8) {
            SAMPLES_NEEDED_2("packet type 8");
            return;
        } else if (packet->type >= 9 && packet->type <= 12) {
            /* packets for MPEG Audio like Synthesis Filter */
            QDM2_LIST_ADD(q->sub_packet_list_D, sub_packets_D, packet);
        } else if (packet->type == 13) {
            for (j = 0; j < 6; j++)
                q->fft_level_exp[j] = get_bits(&gb, 6);
        } else if (packet->type == 14) {
            for (j = 0; j < 6; j++)
                q->fft_level_exp[j] = qdm2_get_vlc(&gb, &fft_level_exp_vlc, 0, 2);
        } else if (packet->type == 15) {
            SAMPLES_NEEDED_2("packet type 15")
            return;
        } else if (packet->type >= 16 && packet->type < 48 && !fft_subpackets[packet->type - 16]) {
            /* packets for FFT */
            QDM2_LIST_ADD(q->sub_packet_list_B, q->sub_packets_B, packet);
        }
    } // Packet bytes loop

/* **************************************************************** */
    if (q->sub_packet_list_D[0].packet != NULL) {
        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);
    }
/* **************************************************************** */
}


static void qdm2_fft_init_coefficient (QDM2Context *q, int sub_packet,
                       int offset, int duration, int channel,
                       int exp, int phase)
{
    if (q->fft_coefs_min_index[duration] < 0)
        q->fft_coefs_min_index[duration] = q->fft_coefs_index;

    q->fft_coefs[q->fft_coefs_index].sub_packet = ((sub_packet >= 16) ? (sub_packet - 16) : sub_packet);
    q->fft_coefs[q->fft_coefs_index].channel = channel;
    q->fft_coefs[q->fft_coefs_index].offset = offset;
    q->fft_coefs[q->fft_coefs_index].exp = exp;
    q->fft_coefs[q->fft_coefs_index].phase = phase;
    q->fft_coefs_index++;
}


static void qdm2_fft_decode_tones (QDM2Context *q, int duration, GetBitContext *gb, int b)
{
    int channel, stereo, phase, exp;
    int local_int_4,  local_int_8,  stereo_phase,  local_int_10;
    int local_int_14, stereo_exp, local_int_20, local_int_28;
    int n, offset;

    local_int_4 = 0;
    local_int_28 = 0;
    local_int_20 = 2;
    local_int_8 = (4 - duration);
    local_int_10 = 1 << (q->group_order - duration - 1);
    offset = 1;

    while (1) {
        if (q->superblocktype_2_3) {
            while ((n = qdm2_get_vlc(gb, &vlc_tab_fft_tone_offset[local_int_8], 1, 2)) < 2) {
                offset = 1;
                if (n == 0) {
                    local_int_4 += local_int_10;
                    local_int_28 += (1 << local_int_8);
                } else {
                    local_int_4 += 8*local_int_10;
                    local_int_28 += (8 << local_int_8);
                }
            }
            offset += (n - 2);
        } else {
            offset += qdm2_get_vlc(gb, &vlc_tab_fft_tone_offset[local_int_8], 1, 2);
            while (offset >= (local_int_10 - 1)) {
                offset += (1 - (local_int_10 - 1));
                local_int_4  += local_int_10;
                local_int_28 += (1 << local_int_8);
            }
        }

        if (local_int_4 >= q->group_size)
            return;

        local_int_14 = (offset >> local_int_8);

        if (q->nb_channels > 1) {
            channel = get_bits1(gb);
            stereo = get_bits1(gb);
        } else {
            channel = 0;
            stereo = 0;
        }

        exp = qdm2_get_vlc(gb, (b ? &fft_level_exp_vlc : &fft_level_exp_alt_vlc), 0, 2);
        exp += q->fft_level_exp[fft_level_index_table[local_int_14]];
        exp = (exp < 0) ? 0 : exp;

        phase = get_bits(gb, 3);
        stereo_exp = 0;
        stereo_phase = 0;

        if (stereo) {
            stereo_exp = (exp - qdm2_get_vlc(gb, &fft_stereo_exp_vlc, 0, 1));
            stereo_phase = (phase - qdm2_get_vlc(gb, &fft_stereo_phase_vlc, 0, 1));
            if (stereo_phase < 0)
                stereo_phase += 8;
        }

        if (q->frequency_range > (local_int_14 + 1)) {
            int sub_packet = (local_int_20 + local_int_28);

            qdm2_fft_init_coefficient(q, sub_packet, offset, duration, channel, exp, phase);
            if (stereo)
                qdm2_fft_init_coefficient(q, sub_packet, offset, duration, (1 - channel), stereo_exp, stereo_phase);
        }

        offset++;
    }
}


static void qdm2_decode_fft_packets (QDM2Context *q)
{
    int i, j, min, max, value, type, unknown_flag;
    GetBitContext gb;

    if (q->sub_packet_list_B[0].packet == NULL)
        return;

    /* reset minimum indices for FFT coefficients */
    q->fft_coefs_index = 0;
    for (i=0; i < 5; i++)
        q->fft_coefs_min_index[i] = -1;

    /* process subpackets ordered by type, largest type first */
    for (i = 0, max = 256; i < q->sub_packets_B; i++) {
        QDM2SubPacket *packet;

        /* find subpacket with largest type less than max */
        for (j = 0, min = 0, packet = NULL; j < q->sub_packets_B; j++) {
            value = q->sub_packet_list_B[j].packet->type;
            if (value > min && value < max) {
                min = value;
                packet = q->sub_packet_list_B[j].packet;
            }
        }

        max = min;

        /* check for errors (?) */
        if (i == 0 && (packet->type < 16 || packet->type >= 48 || fft_subpackets[packet->type - 16]))
            return;

        /* decode FFT tones */
        init_get_bits (&gb, packet->data, packet->size*8);

        if (packet->type >= 32 && packet->type < 48 && !fft_subpackets[packet->type - 16])
            unknown_flag = 1;
        else
            unknown_flag = 0;

        type = packet->type;

        if ((type >= 17 && type < 24) || (type >= 33 && type < 40)) {
            int duration = q->sub_sampling + 5 - (type & 15);

            if (duration >= 0 && duration < 4)
                qdm2_fft_decode_tones(q, duration, &gb, unknown_flag);
        } else if (type == 31) {
            for (j=0; j < 4; j++)
                qdm2_fft_decode_tones(q, j, &gb, unknown_flag);
        } else if (type == 46) {
            for (j=0; j < 6; j++)
                q->fft_level_exp[j] = get_bits(&gb, 6);
            for (j=0; j < 4; j++)
            qdm2_fft_decode_tones(q, j, &gb, unknown_flag);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -