You've already forked FFmpeg
							
							
				mirror of
				https://github.com/FFmpeg/FFmpeg.git
				synced 2025-10-30 23:18:11 +02:00 
			
		
		
		
	huffman: add ff_huff_gen_len_table
The function will be used by utvideo as well. Signed-off-by: Luca Barbato <lu_zero@gentoo.org>
This commit is contained in:
		
				
					committed by
					
						 Luca Barbato
						Luca Barbato
					
				
			
			
				
	
			
			
			
						parent
						
							998f92d680
						
					
				
				
					commit
					5a582bd3b5
				
			
							
								
								
									
										2
									
								
								configure
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								configure
									
									
									
									
										vendored
									
									
								
							| @@ -1376,6 +1376,7 @@ eatgq_decoder_select="aandcttables" | ||||
| eatqi_decoder_select="aandcttables error_resilience mpegvideo" | ||||
| ffv1_decoder_select="golomb rangecoder" | ||||
| ffv1_encoder_select="rangecoder" | ||||
| ffvhuff_encoder_select="huffman" | ||||
| flac_decoder_select="golomb" | ||||
| flac_encoder_select="golomb lpc" | ||||
| flashsv_decoder_select="zlib" | ||||
| @@ -1397,6 +1398,7 @@ h264_dxva2_hwaccel_select="dxva2 h264_decoder" | ||||
| h264_vaapi_hwaccel_select="vaapi h264_decoder" | ||||
| h264_vda_hwaccel_select="vda h264_decoder" | ||||
| h264_vdpau_decoder_select="vdpau h264_decoder" | ||||
| huffyuv_encoder_select="huffman" | ||||
| iac_decoder_select="fft mdct sinewin" | ||||
| imc_decoder_select="fft mdct sinewin" | ||||
| jpegls_decoder_select="golomb" | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| /* | ||||
|  * Copyright (c) 2006 Konstantin Shishkov | ||||
|  * Copyright (c) 2007 Loren Merritt | ||||
|  * | ||||
|  * This file is part of Libav. | ||||
|  * | ||||
| @@ -30,6 +31,63 @@ | ||||
| /* symbol for Huffman tree node */ | ||||
| #define HNODE -1 | ||||
|  | ||||
| typedef struct { | ||||
|     uint64_t val; | ||||
|     int name; | ||||
| } HeapElem; | ||||
|  | ||||
| static void heap_sift(HeapElem *h, int root, int size) | ||||
| { | ||||
|     while (root * 2 + 1 < size) { | ||||
|         int child = root * 2 + 1; | ||||
|         if (child < size - 1 && h[child].val > h[child+1].val) | ||||
|             child++; | ||||
|         if (h[root].val > h[child].val) { | ||||
|             FFSWAP(HeapElem, h[root], h[child]); | ||||
|             root = child; | ||||
|         } else | ||||
|             break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| void ff_huff_gen_len_table(uint8_t *dst, const uint64_t *stats) | ||||
| { | ||||
|     HeapElem h[256]; | ||||
|     int up[2*256]; | ||||
|     int len[2*256]; | ||||
|     int offset, i, next; | ||||
|     int size = 256; | ||||
|  | ||||
|     for (offset = 1; ; offset <<= 1) { | ||||
|         for (i=0; i < size; i++) { | ||||
|             h[i].name = i; | ||||
|             h[i].val = (stats[i] << 8) + offset; | ||||
|         } | ||||
|         for (i = size / 2 - 1; i >= 0; i--) | ||||
|             heap_sift(h, i, size); | ||||
|  | ||||
|         for (next = size; next < size * 2 - 1; next++) { | ||||
|             // merge the two smallest entries, and put it back in the heap | ||||
|             uint64_t min1v = h[0].val; | ||||
|             up[h[0].name] = next; | ||||
|             h[0].val = INT64_MAX; | ||||
|             heap_sift(h, 0, size); | ||||
|             up[h[0].name] = next; | ||||
|             h[0].name = next; | ||||
|             h[0].val += min1v; | ||||
|             heap_sift(h, 0, size); | ||||
|         } | ||||
|  | ||||
|         len[2 * size - 2] = 0; | ||||
|         for (i = 2 * size - 3; i >= size; i--) | ||||
|             len[i] = len[up[i]] + 1; | ||||
|         for (i = 0; i < size; i++) { | ||||
|             dst[i] = len[up[i]] + 1; | ||||
|             if (dst[i] >= 32) break; | ||||
|         } | ||||
|         if (i==size) break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void get_tree_codes(uint32_t *bits, int16_t *lens, uint8_t *xlat, | ||||
|                            Node *nodes, int node, | ||||
|   | ||||
| @@ -42,4 +42,6 @@ typedef int (*HuffCmp)(const void *va, const void *vb); | ||||
| int ff_huff_build_tree(AVCodecContext *avctx, VLC *vlc, int nb_codes, | ||||
|                        Node *nodes, HuffCmp cmp, int flags); | ||||
|  | ||||
| void ff_huff_gen_len_table(uint8_t *dst, const uint64_t *stats); | ||||
|  | ||||
| #endif /* AVCODEC_HUFFMAN_H */ | ||||
|   | ||||
| @@ -33,6 +33,7 @@ | ||||
| #include "put_bits.h" | ||||
| #include "dsputil.h" | ||||
| #include "thread.h" | ||||
| #include "huffman.h" | ||||
|  | ||||
| #define VLC_BITS 11 | ||||
|  | ||||
| @@ -223,66 +224,6 @@ static int generate_bits_table(uint32_t *dst, const uint8_t *len_table) | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| #if CONFIG_HUFFYUV_ENCODER || CONFIG_FFVHUFF_ENCODER | ||||
| typedef struct { | ||||
|     uint64_t val; | ||||
|     int name; | ||||
| } HeapElem; | ||||
|  | ||||
| static void heap_sift(HeapElem *h, int root, int size) | ||||
| { | ||||
|     while (root * 2 + 1 < size) { | ||||
|         int child = root * 2 + 1; | ||||
|         if (child < size - 1 && h[child].val > h[child + 1].val) | ||||
|             child++; | ||||
|         if (h[root].val > h[child].val) { | ||||
|             FFSWAP(HeapElem, h[root], h[child]); | ||||
|             root = child; | ||||
|         } else | ||||
|             break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void generate_len_table(uint8_t *dst, const uint64_t *stats) | ||||
| { | ||||
|     HeapElem h[256]; | ||||
|     int up[2*256]; | ||||
|     int len[2*256]; | ||||
|     int offset, i, next; | ||||
|     int size = 256; | ||||
|  | ||||
|     for (offset = 1; ; offset <<= 1) { | ||||
|         for (i = 0; i < size; i++) { | ||||
|             h[i].name = i; | ||||
|             h[i].val = (stats[i] << 8) + offset; | ||||
|         } | ||||
|         for (i = size / 2 - 1; i >= 0; i--) | ||||
|             heap_sift(h, i, size); | ||||
|  | ||||
|         for (next = size; next < size * 2 - 1; next++) { | ||||
|             // merge the two smallest entries, and put it back in the heap | ||||
|             uint64_t min1v = h[0].val; | ||||
|             up[h[0].name] = next; | ||||
|             h[0].val = INT64_MAX; | ||||
|             heap_sift(h, 0, size); | ||||
|             up[h[0].name] = next; | ||||
|             h[0].name = next; | ||||
|             h[0].val += min1v; | ||||
|             heap_sift(h, 0, size); | ||||
|         } | ||||
|  | ||||
|         len[2 * size - 2] = 0; | ||||
|         for (i = 2 * size - 3; i >= size; i--) | ||||
|             len[i] = len[up[i]] + 1; | ||||
|         for (i = 0; i < size; i++) { | ||||
|             dst[i] = len[up[i]] + 1; | ||||
|             if (dst[i] >= 32) break; | ||||
|         } | ||||
|         if (i==size) break; | ||||
|     } | ||||
| } | ||||
| #endif /* CONFIG_HUFFYUV_ENCODER || CONFIG_FFVHUFF_ENCODER */ | ||||
|  | ||||
| static void generate_joint_tables(HYuvContext *s) | ||||
| { | ||||
|     uint16_t symbols[1 << VLC_BITS]; | ||||
| @@ -697,7 +638,7 @@ static av_cold int encode_init(AVCodecContext *avctx) | ||||
|     } | ||||
|  | ||||
|     for (i = 0; i < 3; i++) { | ||||
|         generate_len_table(s->len[i], s->stats[i]); | ||||
|         ff_huff_gen_len_table(s->len[i], s->stats[i]); | ||||
|  | ||||
|         if (generate_bits_table(s->bits[i], s->len[i]) < 0) { | ||||
|             return -1; | ||||
| @@ -1307,7 +1248,7 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, | ||||
|  | ||||
|     if (s->context) { | ||||
|         for (i = 0; i < 3; i++) { | ||||
|             generate_len_table(s->len[i], s->stats[i]); | ||||
|             ff_huff_gen_len_table(s->len[i], s->stats[i]); | ||||
|             if (generate_bits_table(s->bits[i], s->len[i]) < 0) | ||||
|                 return -1; | ||||
|             size += store_table(s, s->len[i], &pkt->data[size]); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user