extern void compress_huffman(FILE *fin, char ArchiveName[200], int fileCount) { unsigned long int *frequency = (unsigned long int*)calloc(CHARS_NUM, sizeof(unsigned long int)); count_frequency(fin, frequency); huff_node_t *root = build_huff_tree(frequency); int **codes = (int**)malloc(CHARS_NUM * sizeof(int*)), *code_lengths = (int*)calloc(CHARS_NUM, sizeof(int)); _codes(root, codes, code_lengths); FILE *fout = fopen(strncat(ArchiveName, ".vlt", 4), "w"); fprintf(fout, "UPA File Archive\nsign: UPA\nHUFF\n1\n%d\n", fileCount); codify(fin, root, codes, code_lengths, fout); }
/** * nodes size must be 2*nb_codes * first nb_codes nodes.count must be set */ int ff_huff_build_tree(AVCodecContext *avctx, VLC *vlc, int nb_codes, Node *nodes, HuffCmp cmp, int flags) { int i, j; int cur_node; int64_t sum = 0; for(i = 0; i < nb_codes; i++) { nodes[i].sym = i; nodes[i].n0 = -2; sum += nodes[i].count; } if(sum >> 31) { av_log(avctx, AV_LOG_ERROR, "Too high symbol frequencies. Tree construction is not possible\n"); return -1; } qsort(nodes, nb_codes, sizeof(Node), cmp); cur_node = nb_codes; nodes[nb_codes*2-1].count = 0; for(i = 0; i < nb_codes * 2 - 1; i += 2) { nodes[cur_node].sym = HNODE; nodes[cur_node].count = nodes[i].count + nodes[i+1].count; nodes[cur_node].n0 = i; for(j = cur_node; j > 0; j--) { if(nodes[j].count > nodes[j-1].count || (nodes[j].count == nodes[j-1].count && (!(flags & FF_HUFFMAN_FLAG_HNODE_FIRST) || nodes[j].n0 == j - 1 || nodes[j].n0 == j - 2 || (nodes[j].sym != HNODE && nodes[j-1].sym != HNODE)))) break; FFSWAP(Node, nodes[j], nodes[j-1]); } cur_node++; } if(build_huff_tree(vlc, nodes, nb_codes * 2 - 2, flags) < 0) { av_log(avctx, AV_LOG_ERROR, "Error building tree\n"); return -1; } return 0; }
/** * nodes size must be 2*nb_codes * first nb_codes nodes.count must be set */ int ff_huff_build_tree(AVCodecContext *avctx, VLC *vlc, int nb_codes, Node *nodes, HuffCmp cmp, int flags) { int i, j; int cur_node; int64_t sum = 0; for(i = 0; i < nb_codes; i++){ nodes[i].sym = i; nodes[i].n0 = -2; sum += nodes[i].count; } if(sum >> 31) { av_log(avctx, AV_LOG_ERROR, "Too high symbol frequencies. Tree construction is not possible\n"); return -1; } qsort(nodes, nb_codes, sizeof(Node), cmp); cur_node = nb_codes; nodes[nb_codes*2-1].count = 0; for(i = 0; i < nb_codes*2-1; i += 2){ uint32_t cur_count = nodes[i].count + nodes[i+1].count; // find correct place to insert new node, and // make space for the new node while at it for(j = cur_node; j > i + 2; j--){ if(cur_count > nodes[j-1].count || (cur_count == nodes[j-1].count && !(flags & FF_HUFFMAN_FLAG_HNODE_FIRST))) break; nodes[j] = nodes[j - 1]; } nodes[j].sym = HNODE; nodes[j].count = cur_count; nodes[j].n0 = i; cur_node++; } if(build_huff_tree(vlc, nodes, nb_codes*2-2, flags) < 0){ av_log(avctx, AV_LOG_ERROR, "Error building tree\n"); return -1; } return 0; }