/* * This is the compress routine. It shows the basic algorithm for * the compression programs used in this article. First, an input * characters is loaded. The modeling routines are called to * convert the character to a symbol, which has a high, low and * range. Finally, the arithmetic coder module is called to * output the symbols to the bit stream. */ void compress() { int i; char c; SYMBOL s; FILE *compressed_file; static char *input = "GLIB BATES"; compressed_file=fopen( "software/benchmarks/data/test.cmp", "wb" ); if ( compressed_file == NULL ) error_exit( "Could not open output file" ); puts( "Compressing..." ); initialize_output_bitstream(); initialize_arithmetic_encoder(); for ( i=0 ; ; ) { c = input[ i++ ]; convert_int_to_symbol( c, &s ); encode_symbol( compressed_file, &s ); if ( c == '\0' ) break; } flush_arithmetic_encoder( compressed_file ); flush_output_bitstream( compressed_file ); fclose( compressed_file); }
/* * The main procedure is similar to the main found in ARITH1E.C. It has * to initialize the coder and the model. It then sits in a loop reading * input symbols and encoding them. One difference is that every 256 * symbols a compression check is performed. If the compression ratio * falls below 10%, a flush character is encoded. This flushes the encod * ing model, and will cause the decoder to flush its model when the * file is being expanded. The second difference is that each symbol is * repeatedly encoded until a successful encoding occurs. When trying to * encode a character in a particular order, the model may have to * transmit an ESCAPE character. If this is the case, the character has * to be retransmitted using a lower order. This process repeats until a * successful match is found of the symbol in a particular context. * Usually this means going down no further than the order -1 model. * However, the FLUSH and DONE symbols drop back to the order -2 model. * */ void CompressFile(FILE *input,BIT_FILE *output,int argc,char *argv[]) { SYMBOL s; int c; int escaped; int flush = 0; long int text_count = 0; initialize_options( argc, argv ); initialize_model(); initialize_arithmetic_encoder(); for ( ; ; ) { if ( ( ++text_count & 0x0ff ) == 0 ) flush = check_compression( input, output ); if ( !flush ) c = getc( input ); else c = FLUSH; if ( c == EOF ) c = DONE; do { escaped = convert_int_to_symbol( c, &s); encode_symbol( output, &s ); } while ( escaped ); if ( c == DONE ) break; if ( c == FLUSH ) { flush_model(); flush = 0; } update_model( c ); add_character_to_model( c ); } flush_arithmetic_encoder( output ); }
static int encode_frame(AVCodecContext *avctx, AVPacket *avpkt, const AVFrame *frame, int *got_packet_ptr) { MscEncoderContext * mscEncoderContext; MscCodecContext * mscContext; uint32_t arithBytesEncoded; PutBitContext pb; int mb_y, mb_x, value, lastNonZero, max, arithCoderIndex = -1, keyFrame; // initialize arithmetic encoder registers initialize_arithmetic_encoder(); mscEncoderContext = avctx->priv_data; mscContext = &mscEncoderContext->mscContext; init_put_bits(&pb, mscEncoderContext->arithBuff, mscEncoderContext->arithBuffSize); keyFrame = isKeyFrame(avctx->frame_number); if (avctx->frame_number == 0) { av_image_alloc(mscContext->referenceFrame->data, mscContext->referenceFrame->linesize, frame->width, frame->height, frame->format, 128); } avctx->coded_frame->reference = 0; avctx->coded_frame->key_frame = 1; avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; int * qmatrix = keyFrame ? mscContext->q_intra_matrix : mscContext->q_non_intra_matrix; for (mb_x = 0; mb_x < mscContext->mb_width; mb_x++) { for (mb_y = 0; mb_y < mscContext->mb_height; mb_y++) { get_blocks(mscEncoderContext, frame, mb_x, mb_y, mscContext->block); if (!keyFrame) { get_blocks(mscEncoderContext, mscContext->referenceFrame, mb_x, mb_y, mscContext->tmpBlock); diff_blocks(mscContext->block, mscContext->tmpBlock); } for (int n = 0; n < 6; ++n) { // if (avctx->frame_number == 1 && mb_x == 0 && mb_y == 0) { // av_log(avctx, AV_LOG_INFO, "Block x=%d, y=%d, n=%d\n", mb_x, mb_y, n); // print_debug_block(avctx, mscContext->block[n]); // } mscContext->dsp.fdct(mscContext->block[n]); // if (avctx->frame_number == 0 && mb_x == 0 && mb_y == 0) { // av_log(avctx, AV_LOG_INFO, "DCT block x=%d, y=%d, n=%d\n", mb_x, mb_y, n); // print_debug_block(avctx, mscContext->block[n]); // } lastNonZero = quantize(mscContext->block[n], qmatrix, &max); av_assert1(lastNonZero < 64); // if (overflow) { // clip_coeffs(m, m->block[n], m->block_last_index[n]); // av_log(avctx, AV_LOG_WARNING, "Overflow detected, frame: %d, mb_x: %d, mb_y: %d, n: %d\n", // avctx->frame_number, mb_x, mb_y, n); // } // if (avctx->frame_number == 0 && mb_x == 3 && mb_y == 0) { // av_log(avctx, AV_LOG_INFO, "DCT quantized block x=%d, y=%d, n=%d\n", mb_x, mb_y, n); // print_debug_block(avctx, mscContext->block[n]); // } encode_arith_symbol(&mscContext->lastZeroCodingModel, &pb, lastNonZero); if (lastNonZero > 0) { arithCoderIndex = get_arith_model_index(max); encode_arith_symbol(&mscContext->arithModelIndexCodingModel, &pb, arithCoderIndex); } for (int i = 0; i <= lastNonZero; ++i) { int arithCoderBits = i == 0 ? ARITH_CODER_BITS : arithCoderIndex; value = mscContext->block[n][scantab[i]] + mscContext->arithModelAddValue[arithCoderBits]; encode_arith_symbol(&mscContext->arithModels[arithCoderBits], &pb, value); } dequantize(mscContext->block[n], mscContext, keyFrame); } if (keyFrame) { idct_put_block(mscContext, mscContext->referenceFrame, mb_x, mb_y); } else { idct_add_block(mscContext, mscContext->referenceFrame, mb_x, mb_y); } } } emms_c(); // flush arithmetic encoder flush_arithmetic_encoder(&pb); flush_put_bits(&pb); arithBytesEncoded = pb.buf_ptr - pb.buf; // alocate packet if ((value = ff_alloc_packet(avpkt, arithBytesEncoded)) < 0) { return value; } avpkt->flags |= AV_PKT_FLAG_KEY; // store encoded data memcpy(avpkt->data, mscEncoderContext->arithBuff, arithBytesEncoded); *got_packet_ptr = 1; return 0; }
/** * Compresses the input text and writes the compressed data to a file. * @param[in] filename name and path of the file to compress. * @param[in] compressed name and path of the compressed output file. * @param[in] algorithm the algorithm that will be used to build the suffix tree (Ukkonnen or Kurtz). * @param[in] see if see will be used. */ static void zip(char *filename, char *compressed, BOOL algorithm, int parts, BOOL see) { Uchar *origText, *prevText = NULL; Uint origTextLen, partTextLen, currentTextLen; FILE *compressed_file; int i, part; fsmTree_t stree = NULL, prevTree = NULL; BOOL alloc = False; #ifdef WIN32 HANDLE hndl; origText = (Uchar *) file2String(filename, &origTextLen, &hndl); #else origText = (Uchar *) file2String(filename, &origTextLen); #endif if(origText == NULL) { fprintf(stderr,"Cannot open file %s\n", filename); exit(EXIT_FAILURE); } /*if(textLen > MAXTEXTLEN) { fprintf(stderr,"Sorry, textlen = %lu is larger than maximal textlen = %lu\n", (Showuint) textLen,(Showuint) MAXTEXTLEN); exit(EXIT_FAILURE); }*/ if (!compressed) { CALLOC(compressed, Uchar, strlen(filename) + 5); strcpy(compressed, filename); strcat(compressed, ".ctx"); alloc = True; } compressed_file = fopen(compressed, "wb"); if (!compressed_file) { printf( "Could not open output file"); exit(1); } if (alloc) FREE(compressed); buildAlpha(origText, origTextLen); printf ("Alphasize: %ld\n", alphasize); printf("Algorithm %d\n", algorithm); setMaxCount(); /* write magic number */ putc(MAGIC >> 8, compressed_file); putc(MAGIC, compressed_file); /* write # of parts */ putc(parts, compressed_file); initialize_output_bitstream(); initialize_arithmetic_encoder(); writeAlphabet(compressed_file); currentTextLen = 0; for (part = 1; part <= parts; part++) { printf("---------- part %d ---------------\n", part); if (part != parts) { partTextLen = floor(origTextLen / parts); } else { partTextLen = origTextLen - (floor(origTextLen / parts) * (parts - 1)); } if (part > 1) { prevText = text; prevTree = stree; } textlen = partTextLen; CALLOC(text, Uchar, textlen); reversestring(origText + currentTextLen, textlen, text); if (algorithm == UKKONEN) { suffixTree_t tree = initSuffixTree(); buildSuffixTree(tree); printf("Tree built\n"); pruneSuffixTree(tree); stree = fsmSuffixTree(tree); } else { stree = buildSTree(); printf("Tree built\n"); } /*if (part > 1) { copyStatistics(prevTree, stree, prevText); FREE(prevText); freeFsmTree(prevTree); }*/ DEBUGCODE(printf("gamma hits: %d gamma Misses: %d\n", getHits(), getMisses())); printf("height: %ld\n", getHeight(stree)); /* write textlen */ for (i=3; i>=0; i--) { writeByte(textlen >> (8 * i), compressed_file); } printf ("Textlen: %ld\n", textlen); writeFsmTree(stree, compressed_file); printf("FSM...\n"); makeFsm(stree); DEBUGCODE(printFsmTree(stree)); printf("Encoding...\n"); encode(stree, compressed_file, origText + currentTextLen, partTextLen, see); currentTextLen += partTextLen; } FREE(text); freeFsmTree(stree); flush_arithmetic_encoder(compressed_file); flush_output_bitstream(compressed_file); #ifdef WIN32 freetextspace(origText, hndl); #else freetextspace(origText, origTextLen); #endif fclose(compressed_file); }