s/CODE([0-9][0-9])/.code $1/;
# No AREA required
- s/^\s*AREA.*$/.text/;
+ # But ALIGNs in AREA must be obeyed
+ s/^\s*AREA.*ALIGN=([0-9])$/.text\n.p2align $1/;
+ # If no ALIGN, strip the AREA and align to 4 bytes
+ s/^\s*AREA.*$/.text\n.p2align 2/;
# DCD to .word
# This one is for incoming symbols
s/CODE([0-9][0-9])/.code $1/;
# No AREA required
- s/^\s*AREA.*$/.text/;
+ # But ALIGNs in AREA must be obeyed
+ s/^\s*AREA.*ALIGN=([0-9])$/.text\n.p2align $1/;
+ # If no ALIGN, strip the AREA and align to 4 bytes
+ s/^\s*AREA.*$/.text\n.p2align 2/;
# DCD to .word
# This one is for incoming symbols
# on arm, isa versions are supersets
enabled armv7a && soft_enable armv7 ### DEBUG
enabled armv7 && soft_enable armv6
- enabled armv6 && soft_enable armv5te
- enabled armv6 && soft_enable fast_unaligned
+ enabled armv7 || enabled armv6 && soft_enable armv5te
+ enabled armv7 || enabled armv6 && soft_enable fast_unaligned
enabled iwmmxt2 && soft_enable iwmmxt
enabled iwmmxt && soft_enable armv5te
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DEC_INIT
/* Initialize codec */
flags = VPX_CODEC_USE_ERROR_CONCEALMENT;
-res = vpx_codec_dec_init(&codec, interface, NULL, flags);
+res = vpx_codec_dec_init(&codec, interface, &dec_cfg, flags);
if(res)
die_codec(&codec, "Failed to initialize decoder");
parsed as follows:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ USAGE
-if(argc!=4 && argc != 5)
- die("Usage: %s <infile> <outfile> <N-M|N/M|L,S>\n", argv[0]);
+if(argc < 4 || argc > 6)
+ die("Usage: %s <infile> <outfile> [-t <num threads>] <N-M|N/M|L,S>\n",
+ argv[0]);
{
char *nptr;
- n = strtol(argv[3], &nptr, 0);
+ int arg_num = 3;
+ if (argc == 6 && strncmp(argv[arg_num++], "-t", 2) == 0)
+ dec_cfg.threads = strtol(argv[arg_num++], NULL, 0);
+ n = strtol(argv[arg_num], &nptr, 0);
mode = (*nptr == '\0' || *nptr == ',') ? 2 : (*nptr == '-') ? 1 : 0;
m = strtol(nptr+1, NULL, 0);
seed = (m > 0) ? m : (unsigned int)time(NULL);
srand(seed);thrown_frame = 0;
printf("Seed: %u\n", seed);
+printf("Threads: %d\n", dec_cfg.threads);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ USAGE
unsigned int seed;
int thrown=0, kept=0;
int thrown_frame=0, kept_frame=0;
+vpx_codec_dec_cfg_t dec_cfg = {0};
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ EXTRA_VARS
$(qexec)echo "local: *; };" >> $@
CLEAN-OBJS += libvpx.ver
-$(addprefix $(DIST_DIR)/,$(LIBVPX_SO_SYMLINKS)):
+$(addprefix $(DIST_DIR)/,$(LIBVPX_SO_SYMLINKS)): $(DIST_DIR)/$(LIBSUBDIR)/$(LIBVPX_SO)
@echo " [LN] $@"
$(qexec)ln -sf $(LIBVPX_SO) $@
for (i = 0; i < NUM_YV12_BUFFERS; i++)
{
- oci->fb_idx_ref_cnt[0] = 0;
+ oci->fb_idx_ref_cnt[i] = 0;
oci->yv12_fb[i].flags = 0;
if (vp8_yv12_alloc_frame_buffer(&oci->yv12_fb[i], width, height, VP8BORDERINPIXELS) < 0)
{
ldr r4, [sp, #36] ; width
mov r12, r3 ; outer-loop counter
- sub r2, r2, r4 ; src increment for height loop
- ;;IF ARCHITECTURE=6
- pld [r0]
- ;;ENDIF
+ add r7, r2, r4 ; preload next row
+ pld [r0, r7]
+
+ sub r2, r2, r4 ; src increment for height loop
ldr r5, [r11] ; load up filter coefficients
add r0, r0, r2 ; move to next input row
subs r12, r12, #1
- ;;IF ARCHITECTURE=6
- pld [r0]
- ;;ENDIF
+ add r9, r2, r4, lsl #1 ; adding back block width
+ pld [r0, r9] ; preload next row
add r11, r11, #2 ; move over to next column
mov r1, r11
;push {r4-r7}
;preload
- pld [r0]
- pld [r0, r1]
- pld [r0, r1, lsl #1]
+ pld [r0, #31] ; preload for next 16x16 block
ands r4, r0, #15
beq copy_mem16x16_fast
ldrneb r6, [r0, #2]
ldrneb r7, [r0, #3]
+ pld [r0, #31] ; preload for next 16x16 block
+
bne copy_mem16x16_1_loop
ldmia sp!, {r4 - r7}
ldrne r6, [r0, #8]
ldrne r7, [r0, #12]
+ pld [r0, #31] ; preload for next 16x16 block
+
bne copy_mem16x16_4_loop
ldmia sp!, {r4 - r7}
add r2, r2, r3
+ pld [r0, #31] ; preload for next 16x16 block
bne copy_mem16x16_8_loop
ldmia sp!, {r4 - r7}
;stm r2, {r4-r7}
add r2, r2, r3
+ pld [r0, #31] ; preload for next 16x16 block
bne copy_mem16x16_fast_loop
ldmia sp!, {r4 - r7}
EXPORT |vp8_filter_block2d_first_pass_armv6|
+ EXPORT |vp8_filter_block2d_first_pass_16x16_armv6|
+ EXPORT |vp8_filter_block2d_first_pass_8x8_armv6|
EXPORT |vp8_filter_block2d_second_pass_armv6|
EXPORT |vp8_filter4_block2d_second_pass_armv6|
EXPORT |vp8_filter_block2d_first_pass_only_armv6|
add r12, r3, #16 ; square off the output
sub sp, sp, #4
- ;;IF ARCHITECTURE=6
- ;pld [r0, #-2]
- ;;pld [r0, #30]
- ;;ENDIF
-
ldr r4, [r11] ; load up packed filter coefficients
ldr r5, [r11, #4]
ldr r6, [r11, #8]
bne width_loop_1st_6
- ;;add r9, r2, #30 ; attempt to load 2 adjacent cache lines
- ;;IF ARCHITECTURE=6
- ;pld [r0, r2]
- ;;pld [r0, r9]
- ;;ENDIF
-
ldr r1, [sp] ; load and update dst address
subs r7, r7, #0x10000
add r0, r0, r2 ; move to next input line
+
add r1, r1, #2 ; move over to next column
str r1, [sp]
ENDP
+; --------------------------
+; 16x16 version
+; -----------------------------
+|vp8_filter_block2d_first_pass_16x16_armv6| PROC
+ stmdb sp!, {r4 - r11, lr}
+
+ ldr r11, [sp, #40] ; vp8_filter address
+ ldr r7, [sp, #36] ; output height
+
+ add r4, r2, #18 ; preload next low
+ pld [r0, r4]
+
+ sub r2, r2, r3 ; inside loop increments input array,
+ ; so the height loop only needs to add
+ ; r2 - width to the input pointer
+
+ mov r3, r3, lsl #1 ; multiply width by 2 because using shorts
+ add r12, r3, #16 ; square off the output
+ sub sp, sp, #4
+
+ ldr r4, [r11] ; load up packed filter coefficients
+ ldr r5, [r11, #4]
+ ldr r6, [r11, #8]
+
+ str r1, [sp] ; push destination to stack
+ mov r7, r7, lsl #16 ; height is top part of counter
+
+; six tap filter
+|height_loop_1st_16_6|
+ ldrb r8, [r0, #-2] ; load source data
+ ldrb r9, [r0, #-1]
+ ldrb r10, [r0], #2
+ orr r7, r7, r3, lsr #2 ; construct loop counter
+
+|width_loop_1st_16_6|
+ ldrb r11, [r0, #-1]
+
+ pkhbt lr, r8, r9, lsl #16 ; r9 | r8
+ pkhbt r8, r9, r10, lsl #16 ; r10 | r9
+
+ ldrb r9, [r0]
+
+ smuad lr, lr, r4 ; apply the filter
+ pkhbt r10, r10, r11, lsl #16 ; r11 | r10
+ smuad r8, r8, r4
+ pkhbt r11, r11, r9, lsl #16 ; r9 | r11
+
+ smlad lr, r10, r5, lr
+ ldrb r10, [r0, #1]
+ smlad r8, r11, r5, r8
+ ldrb r11, [r0, #2]
+
+ sub r7, r7, #1
+
+ pkhbt r9, r9, r10, lsl #16 ; r10 | r9
+ pkhbt r10, r10, r11, lsl #16 ; r11 | r10
+
+ smlad lr, r9, r6, lr
+ smlad r11, r10, r6, r8
+
+ ands r10, r7, #0xff ; test loop counter
+
+ add lr, lr, #0x40 ; round_shift_and_clamp
+ ldrneb r8, [r0, #-2] ; load data for next loop
+ usat lr, #8, lr, asr #7
+ add r11, r11, #0x40
+ ldrneb r9, [r0, #-1]
+ usat r11, #8, r11, asr #7
+
+ strh lr, [r1], r12 ; result is transposed and stored, which
+ ; will make second pass filtering easier.
+ ldrneb r10, [r0], #2
+ strh r11, [r1], r12
+
+ bne width_loop_1st_16_6
+
+ ldr r1, [sp] ; load and update dst address
+ subs r7, r7, #0x10000
+ add r0, r0, r2 ; move to next input line
+
+ add r11, r2, #34 ; adding back block width(=16)
+ pld [r0, r11] ; preload next low
+
+ add r1, r1, #2 ; move over to next column
+ str r1, [sp]
+
+ bne height_loop_1st_16_6
+
+ add sp, sp, #4
+ ldmia sp!, {r4 - r11, pc}
+
+ ENDP
+
+; --------------------------
+; 8x8 version
+; -----------------------------
+|vp8_filter_block2d_first_pass_8x8_armv6| PROC
+ stmdb sp!, {r4 - r11, lr}
+
+ ldr r11, [sp, #40] ; vp8_filter address
+ ldr r7, [sp, #36] ; output height
+
+ add r4, r2, #10 ; preload next low
+ pld [r0, r4]
+
+ sub r2, r2, r3 ; inside loop increments input array,
+ ; so the height loop only needs to add
+ ; r2 - width to the input pointer
+
+ mov r3, r3, lsl #1 ; multiply width by 2 because using shorts
+ add r12, r3, #16 ; square off the output
+ sub sp, sp, #4
+
+ ldr r4, [r11] ; load up packed filter coefficients
+ ldr r5, [r11, #4]
+ ldr r6, [r11, #8]
+
+ str r1, [sp] ; push destination to stack
+ mov r7, r7, lsl #16 ; height is top part of counter
+
+; six tap filter
+|height_loop_1st_8_6|
+ ldrb r8, [r0, #-2] ; load source data
+ ldrb r9, [r0, #-1]
+ ldrb r10, [r0], #2
+ orr r7, r7, r3, lsr #2 ; construct loop counter
+
+|width_loop_1st_8_6|
+ ldrb r11, [r0, #-1]
+
+ pkhbt lr, r8, r9, lsl #16 ; r9 | r8
+ pkhbt r8, r9, r10, lsl #16 ; r10 | r9
+
+ ldrb r9, [r0]
+
+ smuad lr, lr, r4 ; apply the filter
+ pkhbt r10, r10, r11, lsl #16 ; r11 | r10
+ smuad r8, r8, r4
+ pkhbt r11, r11, r9, lsl #16 ; r9 | r11
+
+ smlad lr, r10, r5, lr
+ ldrb r10, [r0, #1]
+ smlad r8, r11, r5, r8
+ ldrb r11, [r0, #2]
+
+ sub r7, r7, #1
+
+ pkhbt r9, r9, r10, lsl #16 ; r10 | r9
+ pkhbt r10, r10, r11, lsl #16 ; r11 | r10
+
+ smlad lr, r9, r6, lr
+ smlad r11, r10, r6, r8
+
+ ands r10, r7, #0xff ; test loop counter
+
+ add lr, lr, #0x40 ; round_shift_and_clamp
+ ldrneb r8, [r0, #-2] ; load data for next loop
+ usat lr, #8, lr, asr #7
+ add r11, r11, #0x40
+ ldrneb r9, [r0, #-1]
+ usat r11, #8, r11, asr #7
+
+ strh lr, [r1], r12 ; result is transposed and stored, which
+ ; will make second pass filtering easier.
+ ldrneb r10, [r0], #2
+ strh r11, [r1], r12
+
+ bne width_loop_1st_8_6
+
+ ldr r1, [sp] ; load and update dst address
+ subs r7, r7, #0x10000
+ add r0, r0, r2 ; move to next input line
+
+ add r11, r2, #18 ; adding back block width(=8)
+ pld [r0, r11] ; preload next low
+
+ add r1, r1, #2 ; move over to next column
+ str r1, [sp]
+
+ bne height_loop_1st_8_6
+
+ add sp, sp, #4
+ ldmia sp!, {r4 - r11, pc}
+
+ ENDP
+
;---------------------------------
; r0 short *src_ptr,
; r1 unsigned char *output_ptr,
|vp8_filter_block2d_first_pass_only_armv6| PROC
stmdb sp!, {r4 - r11, lr}
+ add r7, r2, r3 ; preload next low
+ add r7, r7, #2
+ pld [r0, r7]
+
ldr r4, [sp, #36] ; output pitch
ldr r11, [sp, #40] ; HFilter address
sub sp, sp, #8
bne width_loop_1st_only_6
- ;;add r9, r2, #30 ; attempt to load 2 adjacent cache lines
- ;;IF ARCHITECTURE=6
- ;pld [r0, r2]
- ;;pld [r0, r9]
- ;;ENDIF
-
ldr lr, [sp] ; load back output pitch
ldr r12, [sp, #4] ; load back output pitch
subs r7, r7, #1
add r0, r0, r12 ; updata src for next loop
+
+ add r11, r12, r3 ; preload next low
+ add r11, r11, #2
+ pld [r0, r11]
+
add r1, r1, lr ; update dst for next loop
bne height_loop_1st_only_6
subs count, count, #1
- ;pld [src]
- ;pld [src, pstep]
- ;pld [src, pstep, lsl #1]
- ;pld [src, pstep, lsl #2]
- ;pld [src, pstep, lsl #3]
-
ldrne r9, [src], pstep ; p3
ldrne r10, [src], pstep ; p2
ldrne r11, [src], pstep ; p1
sub src, src, #4 ; move src pointer down by 4
ldr count, [sp, #40] ; count for 8-in-parallel
ldr r12, [sp, #36] ; load thresh address
+ pld [src, #23] ; preload for next block
sub sp, sp, #16 ; create temp buffer
ldr r6, [src], pstep ; load source data
ldr r4, [r2], #4 ; flimit
+ pld [src, #23]
ldr r7, [src], pstep
ldr r2, [r3], #4 ; limit
+ pld [src, #23]
ldr r8, [src], pstep
uadd8 r4, r4, r4 ; flimit * 2
ldr r3, [r12], #4 ; thresh
+ pld [src, #23]
ldr lr, [src], pstep
mov count, count, lsl #1 ; 4-in-parallel
uadd8 r4, r4, r2 ; flimit * 2 + limit
sub src, src, #4
subs count, count, #1
+ pld [src, #23] ; preload for next block
ldrne r6, [src], pstep ; load source data
+ pld [src, #23]
ldrne r7, [src], pstep
+ pld [src, #23]
ldrne r8, [src], pstep
+ pld [src, #23]
ldrne lr, [src], pstep
bne MBVnext8
; load soure data to r7, r8, r9, r10
ldrh r3, [src, #-2]
+ pld [src, #23] ; preload for next block
ldrh r4, [src], pstep
uadd8 r12, r12, r12 ; flimit * 2
ldrh r5, [src, #-2]
+ pld [src, #23]
ldrh r6, [src], pstep
uadd8 r12, r12, r7 ; flimit * 2 + limit
pkhbt r7, r3, r4, lsl #16
ldrh r3, [src, #-2]
+ pld [src, #23]
ldrh r4, [src], pstep
ldr r11, [sp, #40] ; count (r11) for 8-in-parallel
pkhbt r8, r5, r6, lsl #16
ldrh r5, [src, #-2]
+ pld [src, #23]
ldrh r6, [src], pstep
mov r11, r11, lsl #1 ; 4-in-parallel
; load soure data to r7, r8, r9, r10
ldrneh r3, [src, #-2]
+ pld [src, #23] ; preload for next block
ldrneh r4, [src], pstep
ldrneh r5, [src, #-2]
+ pld [src, #23]
ldrneh r6, [src], pstep
pkhbt r7, r3, r4, lsl #16
ldrneh r3, [src, #-2]
+ pld [src, #23]
ldrneh r4, [src], pstep
pkhbt r8, r5, r6, lsl #16
ldrneh r5, [src, #-2]
+ pld [src, #23]
ldrneh r6, [src], pstep
bne simple_vnext8
beq skip_firstpass_filter
;first-pass filter
- ldr r12, _filter8_coeff_
+ adr r12, filter8_coeff
sub r0, r0, r1, lsl #1
+ add r3, r1, #10 ; preload next low
+ pld [r0, r3]
+
add r2, r12, r2, lsl #4 ;calculate filter location
add r0, r0, #3 ;adjust src only for loading convinience
add r0, r0, r1 ; move to next input line
+ add r11, r1, #18 ; preload next low. adding back block width(=8), which is subtracted earlier
+ pld [r0, r11]
+
bne first_pass_hloop_v6
;second pass filter
cmp r3, #0
beq skip_secondpass_filter
- ldr r12, _filter8_coeff_
+ adr r12, filter8_coeff
add lr, r12, r3, lsl #4 ;calculate filter location
mov r2, #0x00080000
;-----------------
;One word each is reserved. Label filter_coeff can be used to access the data.
;Data address: filter_coeff, filter_coeff+4, filter_coeff+8 ...
-_filter8_coeff_
- DCD filter8_coeff
filter8_coeff
DCD 0x00000000, 0x00000080, 0x00000000, 0x00000000
DCD 0xfffa0000, 0x000c007b, 0x0000ffff, 0x00000000
const short *vp8_filter
);
+// 8x8
+extern void vp8_filter_block2d_first_pass_8x8_armv6
+(
+ unsigned char *src_ptr,
+ short *output_ptr,
+ unsigned int src_pixels_per_line,
+ unsigned int output_width,
+ unsigned int output_height,
+ const short *vp8_filter
+);
+
+// 16x16
+extern void vp8_filter_block2d_first_pass_16x16_armv6
+(
+ unsigned char *src_ptr,
+ short *output_ptr,
+ unsigned int src_pixels_per_line,
+ unsigned int output_width,
+ unsigned int output_height,
+ const short *vp8_filter
+);
+
extern void vp8_filter_block2d_second_pass_armv6
(
short *src_ptr,
{
if (yoffset & 0x1)
{
- vp8_filter_block2d_first_pass_armv6(src_ptr - src_pixels_per_line, FData + 1, src_pixels_per_line, 8, 11, HFilter);
+ vp8_filter_block2d_first_pass_8x8_armv6(src_ptr - src_pixels_per_line, FData + 1, src_pixels_per_line, 8, 11, HFilter);
vp8_filter4_block2d_second_pass_armv6(FData + 2, dst_ptr, dst_pitch, 8, VFilter);
}
else
{
- vp8_filter_block2d_first_pass_armv6(src_ptr - (2 * src_pixels_per_line), FData, src_pixels_per_line, 8, 13, HFilter);
+ vp8_filter_block2d_first_pass_8x8_armv6(src_ptr - (2 * src_pixels_per_line), FData, src_pixels_per_line, 8, 13, HFilter);
vp8_filter_block2d_second_pass_armv6(FData + 2, dst_ptr, dst_pitch, 8, VFilter);
}
}
{
if (yoffset & 0x1)
{
- vp8_filter_block2d_first_pass_armv6(src_ptr - src_pixels_per_line, FData + 1, src_pixels_per_line, 16, 19, HFilter);
+ vp8_filter_block2d_first_pass_16x16_armv6(src_ptr - src_pixels_per_line, FData + 1, src_pixels_per_line, 16, 19, HFilter);
vp8_filter4_block2d_second_pass_armv6(FData + 2, dst_ptr, dst_pitch, 16, VFilter);
}
else
{
- vp8_filter_block2d_first_pass_armv6(src_ptr - (2 * src_pixels_per_line), FData, src_pixels_per_line, 16, 21, HFilter);
+ vp8_filter_block2d_first_pass_16x16_armv6(src_ptr - (2 * src_pixels_per_line), FData, src_pixels_per_line, 16, 21, HFilter);
vp8_filter_block2d_second_pass_armv6(FData + 2, dst_ptr, dst_pitch, 16, VFilter);
}
}
|vp8_bilinear_predict16x16_neon| PROC
push {r4-r5, lr}
- ldr r12, _bifilter16_coeff_
+ adr r12, bifilter16_coeff
ldr r4, [sp, #12] ;load parameters from stack
ldr r5, [sp, #16] ;load parameters from stack
;-----------------
-_bifilter16_coeff_
- DCD bifilter16_coeff
bifilter16_coeff
DCD 128, 0, 112, 16, 96, 32, 80, 48, 64, 64, 48, 80, 32, 96, 16, 112
|vp8_bilinear_predict4x4_neon| PROC
push {r4, lr}
- ldr r12, _bifilter4_coeff_
+ adr r12, bifilter4_coeff
ldr r4, [sp, #8] ;load parameters from stack
ldr lr, [sp, #12] ;load parameters from stack
;-----------------
-_bifilter4_coeff_
- DCD bifilter4_coeff
bifilter4_coeff
DCD 128, 0, 112, 16, 96, 32, 80, 48, 64, 64, 48, 80, 32, 96, 16, 112
|vp8_bilinear_predict8x4_neon| PROC
push {r4, lr}
- ldr r12, _bifilter8x4_coeff_
+ adr r12, bifilter8x4_coeff
ldr r4, [sp, #8] ;load parameters from stack
ldr lr, [sp, #12] ;load parameters from stack
;-----------------
-_bifilter8x4_coeff_
- DCD bifilter8x4_coeff
bifilter8x4_coeff
DCD 128, 0, 112, 16, 96, 32, 80, 48, 64, 64, 48, 80, 32, 96, 16, 112
|vp8_bilinear_predict8x8_neon| PROC
push {r4, lr}
- ldr r12, _bifilter8_coeff_
+ adr r12, bifilter8_coeff
ldr r4, [sp, #8] ;load parameters from stack
ldr lr, [sp, #12] ;load parameters from stack
;-----------------
-_bifilter8_coeff_
- DCD bifilter8_coeff
bifilter8_coeff
DCD 128, 0, 112, 16, 96, 32, 80, 48, 64, 64, 48, 80, 32, 96, 16, 112
;result of the multiplication that is needed in IDCT.
|vp8_short_idct4x4llm_neon| PROC
- ldr r12, _idct_coeff_
+ adr r12, idct_coeff
vld1.16 {q1, q2}, [r0]
vld1.16 {d0}, [r12]
;-----------------
-_idct_coeff_
- DCD idct_coeff
idct_coeff
DCD 0x4e7b4e7b, 0x8a8c8a8c
PRESERVE8
AREA ||.text||, CODE, READONLY, ALIGN=2
+
+filter16_coeff
+ DCD 0, 0, 128, 0, 0, 0, 0, 0
+ DCD 0, -6, 123, 12, -1, 0, 0, 0
+ DCD 2, -11, 108, 36, -8, 1, 0, 0
+ DCD 0, -9, 93, 50, -6, 0, 0, 0
+ DCD 3, -16, 77, 77, -16, 3, 0, 0
+ DCD 0, -6, 50, 93, -9, 0, 0, 0
+ DCD 1, -8, 36, 108, -11, 2, 0, 0
+ DCD 0, -1, 12, 123, -6, 0, 0, 0
+
; r0 unsigned char *src_ptr,
; r1 int src_pixels_per_line,
; r2 int xoffset,
|vp8_sixtap_predict16x16_neon| PROC
push {r4-r5, lr}
- ldr r12, _filter16_coeff_
+ adr r12, filter16_coeff
ldr r4, [sp, #12] ;load parameters from stack
ldr r5, [sp, #16] ;load parameters from stack
ENDP
;-----------------
-
-_filter16_coeff_
- DCD filter16_coeff
-filter16_coeff
- DCD 0, 0, 128, 0, 0, 0, 0, 0
- DCD 0, -6, 123, 12, -1, 0, 0, 0
- DCD 2, -11, 108, 36, -8, 1, 0, 0
- DCD 0, -9, 93, 50, -6, 0, 0, 0
- DCD 3, -16, 77, 77, -16, 3, 0, 0
- DCD 0, -6, 50, 93, -9, 0, 0, 0
- DCD 1, -8, 36, 108, -11, 2, 0, 0
- DCD 0, -1, 12, 123, -6, 0, 0, 0
-
END
PRESERVE8
AREA ||.text||, CODE, READONLY, ALIGN=2
+
+filter4_coeff
+ DCD 0, 0, 128, 0, 0, 0, 0, 0
+ DCD 0, -6, 123, 12, -1, 0, 0, 0
+ DCD 2, -11, 108, 36, -8, 1, 0, 0
+ DCD 0, -9, 93, 50, -6, 0, 0, 0
+ DCD 3, -16, 77, 77, -16, 3, 0, 0
+ DCD 0, -6, 50, 93, -9, 0, 0, 0
+ DCD 1, -8, 36, 108, -11, 2, 0, 0
+ DCD 0, -1, 12, 123, -6, 0, 0, 0
+
; r0 unsigned char *src_ptr,
; r1 int src_pixels_per_line,
; r2 int xoffset,
|vp8_sixtap_predict_neon| PROC
push {r4, lr}
- ldr r12, _filter4_coeff_
+ adr r12, filter4_coeff
ldr r4, [sp, #8] ;load parameters from stack
ldr lr, [sp, #12] ;load parameters from stack
;-----------------
-_filter4_coeff_
- DCD filter4_coeff
-filter4_coeff
- DCD 0, 0, 128, 0, 0, 0, 0, 0
- DCD 0, -6, 123, 12, -1, 0, 0, 0
- DCD 2, -11, 108, 36, -8, 1, 0, 0
- DCD 0, -9, 93, 50, -6, 0, 0, 0
- DCD 3, -16, 77, 77, -16, 3, 0, 0
- DCD 0, -6, 50, 93, -9, 0, 0, 0
- DCD 1, -8, 36, 108, -11, 2, 0, 0
- DCD 0, -1, 12, 123, -6, 0, 0, 0
-
END
PRESERVE8
AREA ||.text||, CODE, READONLY, ALIGN=2
+
+filter8_coeff
+ DCD 0, 0, 128, 0, 0, 0, 0, 0
+ DCD 0, -6, 123, 12, -1, 0, 0, 0
+ DCD 2, -11, 108, 36, -8, 1, 0, 0
+ DCD 0, -9, 93, 50, -6, 0, 0, 0
+ DCD 3, -16, 77, 77, -16, 3, 0, 0
+ DCD 0, -6, 50, 93, -9, 0, 0, 0
+ DCD 1, -8, 36, 108, -11, 2, 0, 0
+ DCD 0, -1, 12, 123, -6, 0, 0, 0
+
; r0 unsigned char *src_ptr,
; r1 int src_pixels_per_line,
; r2 int xoffset,
|vp8_sixtap_predict8x4_neon| PROC
push {r4-r5, lr}
- ldr r12, _filter8_coeff_
+ adr r12, filter8_coeff
ldr r4, [sp, #12] ;load parameters from stack
ldr r5, [sp, #16] ;load parameters from stack
;-----------------
-_filter8_coeff_
- DCD filter8_coeff
-filter8_coeff
- DCD 0, 0, 128, 0, 0, 0, 0, 0
- DCD 0, -6, 123, 12, -1, 0, 0, 0
- DCD 2, -11, 108, 36, -8, 1, 0, 0
- DCD 0, -9, 93, 50, -6, 0, 0, 0
- DCD 3, -16, 77, 77, -16, 3, 0, 0
- DCD 0, -6, 50, 93, -9, 0, 0, 0
- DCD 1, -8, 36, 108, -11, 2, 0, 0
- DCD 0, -1, 12, 123, -6, 0, 0, 0
-
END
PRESERVE8
AREA ||.text||, CODE, READONLY, ALIGN=2
+
+filter8_coeff
+ DCD 0, 0, 128, 0, 0, 0, 0, 0
+ DCD 0, -6, 123, 12, -1, 0, 0, 0
+ DCD 2, -11, 108, 36, -8, 1, 0, 0
+ DCD 0, -9, 93, 50, -6, 0, 0, 0
+ DCD 3, -16, 77, 77, -16, 3, 0, 0
+ DCD 0, -6, 50, 93, -9, 0, 0, 0
+ DCD 1, -8, 36, 108, -11, 2, 0, 0
+ DCD 0, -1, 12, 123, -6, 0, 0, 0
+
; r0 unsigned char *src_ptr,
; r1 int src_pixels_per_line,
; r2 int xoffset,
|vp8_sixtap_predict8x8_neon| PROC
push {r4-r5, lr}
- ldr r12, _filter8_coeff_
+ adr r12, filter8_coeff
ldr r4, [sp, #12] ;load parameters from stack
ldr r5, [sp, #16] ;load parameters from stack
;-----------------
-_filter8_coeff_
- DCD filter8_coeff
-filter8_coeff
- DCD 0, 0, 128, 0, 0, 0, 0, 0
- DCD 0, -6, 123, 12, -1, 0, 0, 0
- DCD 2, -11, 108, 36, -8, 1, 0, 0
- DCD 0, -9, 93, 50, -6, 0, 0, 0
- DCD 3, -16, 77, 77, -16, 3, 0, 0
- DCD 0, -6, 50, 93, -9, 0, 0, 0
- DCD 1, -8, 36, 108, -11, 2, 0, 0
- DCD 0, -1, 12, 123, -6, 0, 0, 0
-
END
/* Update probabilities for the nodes in the token entropy tree.
Generated file included by entropy.c */
-const vp8_prob vp8_coef_update_probs [BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [vp8_coef_tokens-1] =
+const vp8_prob vp8_coef_update_probs [BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [ENTROPY_NODES] =
{
{
{
--- /dev/null
+/*
+ * Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "defaultcoefcounts.h"
+
+/* Generated file, included by entropy.c */
+
+const unsigned int vp8_default_coef_counts[BLOCK_TYPES]
+ [COEF_BANDS]
+ [PREV_COEF_CONTEXTS]
+ [MAX_ENTROPY_TOKENS] =
+{
+
+ {
+ /* Block Type ( 0 ) */
+ {
+ /* Coeff Band ( 0 ) */
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
+ },
+ {
+ /* Coeff Band ( 1 ) */
+ {30190, 26544, 225, 24, 4, 0, 0, 0, 0, 0, 0, 4171593,},
+ {26846, 25157, 1241, 130, 26, 6, 1, 0, 0, 0, 0, 149987,},
+ {10484, 9538, 1006, 160, 36, 18, 0, 0, 0, 0, 0, 15104,},
+ },
+ {
+ /* Coeff Band ( 2 ) */
+ {25842, 40456, 1126, 83, 11, 2, 0, 0, 0, 0, 0, 0,},
+ {9338, 8010, 512, 73, 7, 3, 2, 0, 0, 0, 0, 43294,},
+ {1047, 751, 149, 31, 13, 6, 1, 0, 0, 0, 0, 879,},
+ },
+ {
+ /* Coeff Band ( 3 ) */
+ {26136, 9826, 252, 13, 0, 0, 0, 0, 0, 0, 0, 0,},
+ {8134, 5574, 191, 14, 2, 0, 0, 0, 0, 0, 0, 35302,},
+ { 605, 677, 116, 9, 1, 0, 0, 0, 0, 0, 0, 611,},
+ },
+ {
+ /* Coeff Band ( 4 ) */
+ {10263, 15463, 283, 17, 0, 0, 0, 0, 0, 0, 0, 0,},
+ {2773, 2191, 128, 9, 2, 2, 0, 0, 0, 0, 0, 10073,},
+ { 134, 125, 32, 4, 0, 2, 0, 0, 0, 0, 0, 50,},
+ },
+ {
+ /* Coeff Band ( 5 ) */
+ {10483, 2663, 23, 1, 0, 0, 0, 0, 0, 0, 0, 0,},
+ {2137, 1251, 27, 1, 1, 0, 0, 0, 0, 0, 0, 14362,},
+ { 116, 156, 14, 2, 1, 0, 0, 0, 0, 0, 0, 190,},
+ },
+ {
+ /* Coeff Band ( 6 ) */
+ {40977, 27614, 412, 28, 0, 0, 0, 0, 0, 0, 0, 0,},
+ {6113, 5213, 261, 22, 3, 0, 0, 0, 0, 0, 0, 26164,},
+ { 382, 312, 50, 14, 2, 0, 0, 0, 0, 0, 0, 345,},
+ },
+ {
+ /* Coeff Band ( 7 ) */
+ { 0, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
+ { 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 319,},
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8,},
+ },
+ },
+ {
+ /* Block Type ( 1 ) */
+ {
+ /* Coeff Band ( 0 ) */
+ {3268, 19382, 1043, 250, 93, 82, 49, 26, 17, 8, 25, 82289,},
+ {8758, 32110, 5436, 1832, 827, 668, 420, 153, 24, 0, 3, 52914,},
+ {9337, 23725, 8487, 3954, 2107, 1836, 1069, 399, 59, 0, 0, 18620,},
+ },
+ {
+ /* Coeff Band ( 1 ) */
+ {12419, 8420, 452, 62, 9, 1, 0, 0, 0, 0, 0, 0,},
+ {11715, 8705, 693, 92, 15, 7, 2, 0, 0, 0, 0, 53988,},
+ {7603, 8585, 2306, 778, 270, 145, 39, 5, 0, 0, 0, 9136,},
+ },
+ {
+ /* Coeff Band ( 2 ) */
+ {15938, 14335, 1207, 184, 55, 13, 4, 1, 0, 0, 0, 0,},
+ {7415, 6829, 1138, 244, 71, 26, 7, 0, 0, 0, 0, 9980,},
+ {1580, 1824, 655, 241, 89, 46, 10, 2, 0, 0, 0, 429,},
+ },
+ {
+ /* Coeff Band ( 3 ) */
+ {19453, 5260, 201, 19, 0, 0, 0, 0, 0, 0, 0, 0,},
+ {9173, 3758, 213, 22, 1, 1, 0, 0, 0, 0, 0, 9820,},
+ {1689, 1277, 276, 51, 17, 4, 0, 0, 0, 0, 0, 679,},
+ },
+ {
+ /* Coeff Band ( 4 ) */
+ {12076, 10667, 620, 85, 19, 9, 5, 0, 0, 0, 0, 0,},
+ {4665, 3625, 423, 55, 19, 9, 0, 0, 0, 0, 0, 5127,},
+ { 415, 440, 143, 34, 20, 7, 2, 0, 0, 0, 0, 101,},
+ },
+ {
+ /* Coeff Band ( 5 ) */
+ {12183, 4846, 115, 11, 1, 0, 0, 0, 0, 0, 0, 0,},
+ {4226, 3149, 177, 21, 2, 0, 0, 0, 0, 0, 0, 7157,},
+ { 375, 621, 189, 51, 11, 4, 1, 0, 0, 0, 0, 198,},
+ },
+ {
+ /* Coeff Band ( 6 ) */
+ {61658, 37743, 1203, 94, 10, 3, 0, 0, 0, 0, 0, 0,},
+ {15514, 11563, 903, 111, 14, 5, 0, 0, 0, 0, 0, 25195,},
+ { 929, 1077, 291, 78, 14, 7, 1, 0, 0, 0, 0, 507,},
+ },
+ {
+ /* Coeff Band ( 7 ) */
+ { 0, 990, 15, 3, 0, 0, 0, 0, 0, 0, 0, 0,},
+ { 0, 412, 13, 0, 0, 0, 0, 0, 0, 0, 0, 1641,},
+ { 0, 18, 7, 1, 0, 0, 0, 0, 0, 0, 0, 30,},
+ },
+ },
+ {
+ /* Block Type ( 2 ) */
+ {
+ /* Coeff Band ( 0 ) */
+ { 953, 24519, 628, 120, 28, 12, 4, 0, 0, 0, 0, 2248798,},
+ {1525, 25654, 2647, 617, 239, 143, 42, 5, 0, 0, 0, 66837,},
+ {1180, 11011, 3001, 1237, 532, 448, 239, 54, 5, 0, 0, 7122,},
+ },
+ {
+ /* Coeff Band ( 1 ) */
+ {1356, 2220, 67, 10, 4, 1, 0, 0, 0, 0, 0, 0,},
+ {1450, 2544, 102, 18, 4, 3, 0, 0, 0, 0, 0, 57063,},
+ {1182, 2110, 470, 130, 41, 21, 0, 0, 0, 0, 0, 6047,},
+ },
+ {
+ /* Coeff Band ( 2 ) */
+ { 370, 3378, 200, 30, 5, 4, 1, 0, 0, 0, 0, 0,},
+ { 293, 1006, 131, 29, 11, 0, 0, 0, 0, 0, 0, 5404,},
+ { 114, 387, 98, 23, 4, 8, 1, 0, 0, 0, 0, 236,},
+ },
+ {
+ /* Coeff Band ( 3 ) */
+ { 579, 194, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
+ { 395, 213, 5, 1, 0, 0, 0, 0, 0, 0, 0, 4157,},
+ { 119, 122, 4, 0, 0, 0, 0, 0, 0, 0, 0, 300,},
+ },
+ {
+ /* Coeff Band ( 4 ) */
+ { 38, 557, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
+ { 21, 114, 12, 1, 0, 0, 0, 0, 0, 0, 0, 427,},
+ { 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7,},
+ },
+ {
+ /* Coeff Band ( 5 ) */
+ { 52, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
+ { 18, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 652,},
+ { 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30,},
+ },
+ {
+ /* Coeff Band ( 6 ) */
+ { 640, 569, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
+ { 25, 77, 2, 0, 0, 0, 0, 0, 0, 0, 0, 517,},
+ { 4, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,},
+ },
+ {
+ /* Coeff Band ( 7 ) */
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
+ },
+ },
+ {
+ /* Block Type ( 3 ) */
+ {
+ /* Coeff Band ( 0 ) */
+ {2506, 20161, 2707, 767, 261, 178, 107, 30, 14, 3, 0, 100694,},
+ {8806, 36478, 8817, 3268, 1280, 850, 401, 114, 42, 0, 0, 58572,},
+ {11003, 27214, 11798, 5716, 2482, 2072, 1048, 175, 32, 0, 0, 19284,},
+ },
+ {
+ /* Coeff Band ( 1 ) */
+ {9738, 11313, 959, 205, 70, 18, 11, 1, 0, 0, 0, 0,},
+ {12628, 15085, 1507, 273, 52, 19, 9, 0, 0, 0, 0, 54280,},
+ {10701, 15846, 5561, 1926, 813, 570, 249, 36, 0, 0, 0, 6460,},
+ },
+ {
+ /* Coeff Band ( 2 ) */
+ {6781, 22539, 2784, 634, 182, 123, 20, 4, 0, 0, 0, 0,},
+ {6263, 11544, 2649, 790, 259, 168, 27, 5, 0, 0, 0, 20539,},
+ {3109, 4075, 2031, 896, 457, 386, 158, 29, 0, 0, 0, 1138,},
+ },
+ {
+ /* Coeff Band ( 3 ) */
+ {11515, 4079, 465, 73, 5, 14, 2, 0, 0, 0, 0, 0,},
+ {9361, 5834, 650, 96, 24, 8, 4, 0, 0, 0, 0, 22181,},
+ {4343, 3974, 1360, 415, 132, 96, 14, 1, 0, 0, 0, 1267,},
+ },
+ {
+ /* Coeff Band ( 4 ) */
+ {4787, 9297, 823, 168, 44, 12, 4, 0, 0, 0, 0, 0,},
+ {3619, 4472, 719, 198, 60, 31, 3, 0, 0, 0, 0, 8401,},
+ {1157, 1175, 483, 182, 88, 31, 8, 0, 0, 0, 0, 268,},
+ },
+ {
+ /* Coeff Band ( 5 ) */
+ {8299, 1226, 32, 5, 1, 0, 0, 0, 0, 0, 0, 0,},
+ {3502, 1568, 57, 4, 1, 1, 0, 0, 0, 0, 0, 9811,},
+ {1055, 1070, 166, 29, 6, 1, 0, 0, 0, 0, 0, 527,},
+ },
+ {
+ /* Coeff Band ( 6 ) */
+ {27414, 27927, 1989, 347, 69, 26, 0, 0, 0, 0, 0, 0,},
+ {5876, 10074, 1574, 341, 91, 24, 4, 0, 0, 0, 0, 21954,},
+ {1571, 2171, 778, 324, 124, 65, 16, 0, 0, 0, 0, 979,},
+ },
+ {
+ /* Coeff Band ( 7 ) */
+ { 0, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
+ { 0, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 459,},
+ { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13,},
+ },
+ },
+};
* be found in the AUTHORS file in the root of the source tree.
*/
+#ifndef __DEFAULTCOEFCOUNTS_H
+#define __DEFAULTCOEFCOUNTS_H
-/* Generated file, included by entropy.c */
+#include "entropy.h"
-static const unsigned int default_coef_counts [BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [vp8_coef_tokens] =
-{
+extern const unsigned int vp8_default_coef_counts[BLOCK_TYPES]
+ [COEF_BANDS]
+ [PREV_COEF_CONTEXTS]
+ [MAX_ENTROPY_TOKENS];
- {
- /* Block Type ( 0 ) */
- {
- /* Coeff Band ( 0 ) */
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
- },
- {
- /* Coeff Band ( 1 ) */
- {30190, 26544, 225, 24, 4, 0, 0, 0, 0, 0, 0, 4171593,},
- {26846, 25157, 1241, 130, 26, 6, 1, 0, 0, 0, 0, 149987,},
- {10484, 9538, 1006, 160, 36, 18, 0, 0, 0, 0, 0, 15104,},
- },
- {
- /* Coeff Band ( 2 ) */
- {25842, 40456, 1126, 83, 11, 2, 0, 0, 0, 0, 0, 0,},
- {9338, 8010, 512, 73, 7, 3, 2, 0, 0, 0, 0, 43294,},
- {1047, 751, 149, 31, 13, 6, 1, 0, 0, 0, 0, 879,},
- },
- {
- /* Coeff Band ( 3 ) */
- {26136, 9826, 252, 13, 0, 0, 0, 0, 0, 0, 0, 0,},
- {8134, 5574, 191, 14, 2, 0, 0, 0, 0, 0, 0, 35302,},
- { 605, 677, 116, 9, 1, 0, 0, 0, 0, 0, 0, 611,},
- },
- {
- /* Coeff Band ( 4 ) */
- {10263, 15463, 283, 17, 0, 0, 0, 0, 0, 0, 0, 0,},
- {2773, 2191, 128, 9, 2, 2, 0, 0, 0, 0, 0, 10073,},
- { 134, 125, 32, 4, 0, 2, 0, 0, 0, 0, 0, 50,},
- },
- {
- /* Coeff Band ( 5 ) */
- {10483, 2663, 23, 1, 0, 0, 0, 0, 0, 0, 0, 0,},
- {2137, 1251, 27, 1, 1, 0, 0, 0, 0, 0, 0, 14362,},
- { 116, 156, 14, 2, 1, 0, 0, 0, 0, 0, 0, 190,},
- },
- {
- /* Coeff Band ( 6 ) */
- {40977, 27614, 412, 28, 0, 0, 0, 0, 0, 0, 0, 0,},
- {6113, 5213, 261, 22, 3, 0, 0, 0, 0, 0, 0, 26164,},
- { 382, 312, 50, 14, 2, 0, 0, 0, 0, 0, 0, 345,},
- },
- {
- /* Coeff Band ( 7 ) */
- { 0, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
- { 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 319,},
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8,},
- },
- },
- {
- /* Block Type ( 1 ) */
- {
- /* Coeff Band ( 0 ) */
- {3268, 19382, 1043, 250, 93, 82, 49, 26, 17, 8, 25, 82289,},
- {8758, 32110, 5436, 1832, 827, 668, 420, 153, 24, 0, 3, 52914,},
- {9337, 23725, 8487, 3954, 2107, 1836, 1069, 399, 59, 0, 0, 18620,},
- },
- {
- /* Coeff Band ( 1 ) */
- {12419, 8420, 452, 62, 9, 1, 0, 0, 0, 0, 0, 0,},
- {11715, 8705, 693, 92, 15, 7, 2, 0, 0, 0, 0, 53988,},
- {7603, 8585, 2306, 778, 270, 145, 39, 5, 0, 0, 0, 9136,},
- },
- {
- /* Coeff Band ( 2 ) */
- {15938, 14335, 1207, 184, 55, 13, 4, 1, 0, 0, 0, 0,},
- {7415, 6829, 1138, 244, 71, 26, 7, 0, 0, 0, 0, 9980,},
- {1580, 1824, 655, 241, 89, 46, 10, 2, 0, 0, 0, 429,},
- },
- {
- /* Coeff Band ( 3 ) */
- {19453, 5260, 201, 19, 0, 0, 0, 0, 0, 0, 0, 0,},
- {9173, 3758, 213, 22, 1, 1, 0, 0, 0, 0, 0, 9820,},
- {1689, 1277, 276, 51, 17, 4, 0, 0, 0, 0, 0, 679,},
- },
- {
- /* Coeff Band ( 4 ) */
- {12076, 10667, 620, 85, 19, 9, 5, 0, 0, 0, 0, 0,},
- {4665, 3625, 423, 55, 19, 9, 0, 0, 0, 0, 0, 5127,},
- { 415, 440, 143, 34, 20, 7, 2, 0, 0, 0, 0, 101,},
- },
- {
- /* Coeff Band ( 5 ) */
- {12183, 4846, 115, 11, 1, 0, 0, 0, 0, 0, 0, 0,},
- {4226, 3149, 177, 21, 2, 0, 0, 0, 0, 0, 0, 7157,},
- { 375, 621, 189, 51, 11, 4, 1, 0, 0, 0, 0, 198,},
- },
- {
- /* Coeff Band ( 6 ) */
- {61658, 37743, 1203, 94, 10, 3, 0, 0, 0, 0, 0, 0,},
- {15514, 11563, 903, 111, 14, 5, 0, 0, 0, 0, 0, 25195,},
- { 929, 1077, 291, 78, 14, 7, 1, 0, 0, 0, 0, 507,},
- },
- {
- /* Coeff Band ( 7 ) */
- { 0, 990, 15, 3, 0, 0, 0, 0, 0, 0, 0, 0,},
- { 0, 412, 13, 0, 0, 0, 0, 0, 0, 0, 0, 1641,},
- { 0, 18, 7, 1, 0, 0, 0, 0, 0, 0, 0, 30,},
- },
- },
- {
- /* Block Type ( 2 ) */
- {
- /* Coeff Band ( 0 ) */
- { 953, 24519, 628, 120, 28, 12, 4, 0, 0, 0, 0, 2248798,},
- {1525, 25654, 2647, 617, 239, 143, 42, 5, 0, 0, 0, 66837,},
- {1180, 11011, 3001, 1237, 532, 448, 239, 54, 5, 0, 0, 7122,},
- },
- {
- /* Coeff Band ( 1 ) */
- {1356, 2220, 67, 10, 4, 1, 0, 0, 0, 0, 0, 0,},
- {1450, 2544, 102, 18, 4, 3, 0, 0, 0, 0, 0, 57063,},
- {1182, 2110, 470, 130, 41, 21, 0, 0, 0, 0, 0, 6047,},
- },
- {
- /* Coeff Band ( 2 ) */
- { 370, 3378, 200, 30, 5, 4, 1, 0, 0, 0, 0, 0,},
- { 293, 1006, 131, 29, 11, 0, 0, 0, 0, 0, 0, 5404,},
- { 114, 387, 98, 23, 4, 8, 1, 0, 0, 0, 0, 236,},
- },
- {
- /* Coeff Band ( 3 ) */
- { 579, 194, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
- { 395, 213, 5, 1, 0, 0, 0, 0, 0, 0, 0, 4157,},
- { 119, 122, 4, 0, 0, 0, 0, 0, 0, 0, 0, 300,},
- },
- {
- /* Coeff Band ( 4 ) */
- { 38, 557, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
- { 21, 114, 12, 1, 0, 0, 0, 0, 0, 0, 0, 427,},
- { 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7,},
- },
- {
- /* Coeff Band ( 5 ) */
- { 52, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
- { 18, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 652,},
- { 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30,},
- },
- {
- /* Coeff Band ( 6 ) */
- { 640, 569, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
- { 25, 77, 2, 0, 0, 0, 0, 0, 0, 0, 0, 517,},
- { 4, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,},
- },
- {
- /* Coeff Band ( 7 ) */
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
- },
- },
- {
- /* Block Type ( 3 ) */
- {
- /* Coeff Band ( 0 ) */
- {2506, 20161, 2707, 767, 261, 178, 107, 30, 14, 3, 0, 100694,},
- {8806, 36478, 8817, 3268, 1280, 850, 401, 114, 42, 0, 0, 58572,},
- {11003, 27214, 11798, 5716, 2482, 2072, 1048, 175, 32, 0, 0, 19284,},
- },
- {
- /* Coeff Band ( 1 ) */
- {9738, 11313, 959, 205, 70, 18, 11, 1, 0, 0, 0, 0,},
- {12628, 15085, 1507, 273, 52, 19, 9, 0, 0, 0, 0, 54280,},
- {10701, 15846, 5561, 1926, 813, 570, 249, 36, 0, 0, 0, 6460,},
- },
- {
- /* Coeff Band ( 2 ) */
- {6781, 22539, 2784, 634, 182, 123, 20, 4, 0, 0, 0, 0,},
- {6263, 11544, 2649, 790, 259, 168, 27, 5, 0, 0, 0, 20539,},
- {3109, 4075, 2031, 896, 457, 386, 158, 29, 0, 0, 0, 1138,},
- },
- {
- /* Coeff Band ( 3 ) */
- {11515, 4079, 465, 73, 5, 14, 2, 0, 0, 0, 0, 0,},
- {9361, 5834, 650, 96, 24, 8, 4, 0, 0, 0, 0, 22181,},
- {4343, 3974, 1360, 415, 132, 96, 14, 1, 0, 0, 0, 1267,},
- },
- {
- /* Coeff Band ( 4 ) */
- {4787, 9297, 823, 168, 44, 12, 4, 0, 0, 0, 0, 0,},
- {3619, 4472, 719, 198, 60, 31, 3, 0, 0, 0, 0, 8401,},
- {1157, 1175, 483, 182, 88, 31, 8, 0, 0, 0, 0, 268,},
- },
- {
- /* Coeff Band ( 5 ) */
- {8299, 1226, 32, 5, 1, 0, 0, 0, 0, 0, 0, 0,},
- {3502, 1568, 57, 4, 1, 1, 0, 0, 0, 0, 0, 9811,},
- {1055, 1070, 166, 29, 6, 1, 0, 0, 0, 0, 0, 527,},
- },
- {
- /* Coeff Band ( 6 ) */
- {27414, 27927, 1989, 347, 69, 26, 0, 0, 0, 0, 0, 0,},
- {5876, 10074, 1574, 341, 91, 24, 4, 0, 0, 0, 0, 21954,},
- {1571, 2171, 778, 324, 124, 65, 16, 0, 0, 0, 0, 979,},
- },
- {
- /* Coeff Band ( 7 ) */
- { 0, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
- { 0, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 459,},
- { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13,},
- },
- },
-};
+#endif //__DEFAULTCOEFCOUNTS_H
-DCT_VAL_CATEGORY5, -DCT_VAL_CATEGORY6 /* 10 = CAT_FIVE */
};
-struct vp8_token_struct vp8_coef_encodings[vp8_coef_tokens];
+struct vp8_token_struct vp8_coef_encodings[MAX_ENTROPY_TOKENS];
/* Trees for extra bits. Probabilities are constant and
do not depend on previously encoded bits */
do
{
- unsigned int branch_ct [vp8_coef_tokens-1] [2];
+ unsigned int branch_ct [ENTROPY_NODES] [2];
vp8_tree_probs_from_distribution(
- vp8_coef_tokens, vp8_coef_encodings, vp8_coef_tree,
- pc->fc.coef_probs [h][i][k], branch_ct, default_coef_counts [h][i][k],
+ MAX_ENTROPY_TOKENS, vp8_coef_encodings, vp8_coef_tree,
+ pc->fc.coef_probs[h][i][k],
+ branch_ct,
+ vp8_default_coef_counts[h][i][k],
256, 1);
}
#define DCT_VAL_CATEGORY6 10 /* 67+ Extra Bits 11+1 */
#define DCT_EOB_TOKEN 11 /* EOB Extra Bits 0+0 */
-#define vp8_coef_tokens 12
-#define MAX_ENTROPY_TOKENS vp8_coef_tokens
+#define MAX_ENTROPY_TOKENS 12
#define ENTROPY_NODES 11
extern const vp8_tree_index vp8_coef_tree[];
-extern struct vp8_token_struct vp8_coef_encodings[vp8_coef_tokens];
+extern struct vp8_token_struct vp8_coef_encodings[MAX_ENTROPY_TOKENS];
typedef struct
{
/*# define DC_TOKEN_CONTEXTS 3*/ /* 00, 0!0, !0!0 */
# define PREV_COEF_CONTEXTS 3
-extern DECLARE_ALIGNED(16, const unsigned char, vp8_prev_token_class[vp8_coef_tokens]);
+extern DECLARE_ALIGNED(16, const unsigned char, vp8_prev_token_class[MAX_ENTROPY_TOKENS]);
-extern const vp8_prob vp8_coef_update_probs [BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [vp8_coef_tokens-1];
+extern const vp8_prob vp8_coef_update_probs [BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [ENTROPY_NODES];
struct VP8Common;
int token_partitions; // how many token partitions to create for multi core decoding
int encode_breakout; // early breakout encode threshold : for video conf recommend 800
- int error_resilient_mode; // if running over udp networks provides decodable frames after a
- // dropped packet
+ unsigned int error_resilient_mode; // Bitfield defining the error
+ // resiliency features to enable. Can provide
+ // decodable frames after losses in previous
+ // frames and decodable partitions after
+ // losses in the same frame.
int arnr_max_frames;
int arnr_strength ;
#define NUM_YV12_BUFFERS 4
+#define MAX_PARTITIONS 9
+
typedef struct frame_contexts
{
vp8_prob bmode_prob [VP8_BINTRAMODES-1];
vp8_prob ymode_prob [VP8_YMODES-1]; /* interframe intra mode probs */
vp8_prob uv_mode_prob [VP8_UV_MODES-1];
vp8_prob sub_mv_ref_prob [VP8_SUBMVREFS-1];
- vp8_prob coef_probs [BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [vp8_coef_tokens-1];
+ vp8_prob coef_probs [BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [ENTROPY_NODES];
MV_CONTEXT mvc[2];
MV_CONTEXT pre_mvc[2]; /* not to caculate the mvcost for the frame if mvc doesn't change. */
} FRAME_CONTEXT;
#include "vpx_scale/yv12config.h"
#include "ppflags.h"
#include "vpx_ports/mem.h"
+#include "vpx/vpx_codec.h"
typedef void *VP8D_PTR;
typedef struct
int postprocess;
int max_threads;
int error_concealment;
+ int input_partition;
} VP8D_CONFIG;
typedef enum
{
int vp8dx_receive_compressed_data(VP8D_PTR comp, unsigned long size, const unsigned char *dest, INT64 time_stamp);
int vp8dx_get_raw_frame(VP8D_PTR comp, YV12_BUFFER_CONFIG *sd, INT64 *time_stamp, INT64 *time_end_stamp, vp8_ppflags_t *flags);
- int vp8dx_get_reference(VP8D_PTR comp, VP8_REFFRAME ref_frame_flag, YV12_BUFFER_CONFIG *sd);
- int vp8dx_set_reference(VP8D_PTR comp, VP8_REFFRAME ref_frame_flag, YV12_BUFFER_CONFIG *sd);
+ vpx_codec_err_t vp8dx_get_reference(VP8D_PTR comp, VP8_REFFRAME ref_frame_flag, YV12_BUFFER_CONFIG *sd);
+ vpx_codec_err_t vp8dx_set_reference(VP8D_PTR comp, VP8_REFFRAME ref_frame_flag, YV12_BUFFER_CONFIG *sd);
VP8D_PTR vp8dx_create_decompressor(VP8D_CONFIG *oxcf);
YV12_BUFFER_CONFIG *post = &oci->post_proc_buffer;
int width = post->y_width;
int height = post->y_height;
- int mb_cols = width >> 4;
unsigned char *y_buffer = oci->post_proc_buffer.y_buffer;
int y_stride = oci->post_proc_buffer.y_stride;
MODE_INFO *mi = oci->mi;
{
case 0 : /* mv_top_bottom */
{
- B_MODE_INFO *bmi = &mi->bmi[0];
+ union b_mode_info *bmi = &mi->bmi[0];
MV *mv = &bmi->mv.as_mv;
x1 = x0 + 8 + (mv->col >> 3);
}
case 1 : /* mv_left_right */
{
- B_MODE_INFO *bmi = &mi->bmi[0];
+ union b_mode_info *bmi = &mi->bmi[0];
MV *mv = &bmi->mv.as_mv;
x1 = x0 + 4 + (mv->col >> 3);
}
case 2 : /* mv_quarters */
{
- B_MODE_INFO *bmi = &mi->bmi[0];
+ union b_mode_info *bmi = &mi->bmi[0];
MV *mv = &bmi->mv.as_mv;
x1 = x0 + 4 + (mv->col >> 3);
}
default :
{
- B_MODE_INFO *bmi = mi->bmi;
+ union b_mode_info *bmi = mi->bmi;
int bx0, by0;
for (by0 = y0; by0 < (y0+16); by0 += 4)
{
int by, bx;
unsigned char *yl, *ul, *vl;
- B_MODE_INFO *bmi = mi->bmi;
+ union b_mode_info *bmi = mi->bmi;
yl = y_ptr + x;
ul = u_ptr + (x>>1);
if ((ppflags->display_b_modes_flag & (1<<mi->mbmi.mode))
|| (ppflags->display_mb_modes_flag & B_PRED))
{
- Y = B_PREDICTION_MODE_colors[bmi->mode][0];
- U = B_PREDICTION_MODE_colors[bmi->mode][1];
- V = B_PREDICTION_MODE_colors[bmi->mode][2];
+ Y = B_PREDICTION_MODE_colors[bmi->as_mode][0];
+ U = B_PREDICTION_MODE_colors[bmi->as_mode][1];
+ V = B_PREDICTION_MODE_colors[bmi->as_mode][2];
POSTPROC_INVOKE(RTCD_VTABLE(oci), blend_b)
(yl+bx, ul+(bx>>1), vl+(bx>>1), Y, U, V, 0xc000, y_stride);
ldr r1, [sp, #4] ; stride
- ldr r12, _CONSTANTS_
+ adr r12, cospi8sqrt2minus1 ; pointer to the first constant
vmul.i16 q1, q3, q5 ;input for short_idct4x4llm_neon
vmul.i16 q2, q4, q6
ENDP ; |vp8_dequant_idct_add_neon|
; Constant Pool
-_CONSTANTS_ DCD cospi8sqrt2minus1
cospi8sqrt2minus1 DCD 0x4e7b4e7b
sinpi8sqrt2 DCD 0x8a8c8a8c
ldr r1, [sp, #4]
vld1.32 {d31[1]}, [r12]
- ldr r2, _CONSTANTS_
+ adr r2, cospi8sqrt2minus1 ; pointer to the first constant
ldrh r12, [r1], #2 ; lo *dc
ldrh r1, [r1] ; hi *dc
ENDP ; |idct_dequant_dc_full_2x_neon|
; Constant Pool
-_CONSTANTS_ DCD cospi8sqrt2minus1
cospi8sqrt2minus1 DCD 0x4e7b
; because the lowest bit in 0x8a8c is 0, we can pre-shift this
sinpi8sqrt2 DCD 0x4546
vld1.32 {d31[0]}, [r2]
vld1.32 {d31[1]}, [r12]
- ldr r2, _CONSTANTS_
+ adr r2, cospi8sqrt2minus1 ; pointer to the first constant
; dequant: q[i] = q[i] * dq[i]
vmul.i16 q2, q2, q0
ENDP ; |idct_dequant_full_2x_neon|
; Constant Pool
-_CONSTANTS_ DCD cospi8sqrt2minus1
cospi8sqrt2minus1 DCD 0x4e7b
; because the lowest bit in 0x8a8c is 0, we can pre-shift this
sinpi8sqrt2 DCD 0x4546
int count;
unsigned int range;
+ split = 1 + (((br->range - 1) * probability) >> 8);
+
+ if(br->count < 0)
+ vp8dx_bool_decoder_fill(br);
+
value = br->value;
count = br->count;
- range = br->range;
- split = 1 + (((range - 1) * probability) >> 8);
bigsplit = (VP8_BD_VALUE)split << (VP8_BD_VALUE_SIZE - 8);
range = split;
br->value = value;
br->count = count;
br->range = range;
- if(count < 0)
- vp8dx_bool_decoder_fill(br);
+
return bit;
}
unsigned int mb_idx)
{
int eobtotal = 0;
- int i, do_clamp = xd->mode_info_context->mbmi.need_to_clamp_mvs;
+ MB_PREDICTION_MODE mode;
+ int i;
if (xd->mode_info_context->mbmi.mb_skip_coeff)
{
}
/* Perform temporary clamping of the MV to be used for prediction */
- if (do_clamp)
+ if (xd->mode_info_context->mbmi.need_to_clamp_mvs)
{
clamp_mvs(xd);
}
- eobtotal |= (xd->mode_info_context->mbmi.mode == B_PRED ||
- xd->mode_info_context->mbmi.mode == SPLITMV);
- if (!eobtotal)
+ mode = xd->mode_info_context->mbmi.mode;
+
+ if (eobtotal == 0 && mode != B_PRED && mode != SPLITMV)
{
/* Special case: Force the loopfilter to skip when eobtotal and
* mb_skip_coeff are zero.
{
RECON_INVOKE(&pbi->common.rtcd.recon, build_intra_predictors_mbuv)(xd);
- if (xd->mode_info_context->mbmi.mode != B_PRED)
+ if (mode != B_PRED)
{
RECON_INVOKE(&pbi->common.rtcd.recon,
build_intra_predictors_mby)(xd);
} else {
vp8_intra_prediction_down_copy(xd);
-
-
-
}
}
else
#if CONFIG_ERROR_CONCEALMENT
if (pbi->ec_enabled &&
- (mb_idx > pbi->mvs_corrupt_from_mb ||
+ (mb_idx >= pbi->mvs_corrupt_from_mb ||
vp8dx_bool_error(xd->current_bc)))
{
/* MB with corrupt residuals or corrupt mode/motion vectors.
* Better to use the predictor as reconstruction.
*/
+ vpx_memset(xd->qcoeff, 0, sizeof(xd->qcoeff));
vp8_conceal_corrupt_mb(xd);
return;
}
#endif
/* dequantization and idct */
- if (xd->mode_info_context->mbmi.mode != B_PRED && xd->mode_info_context->mbmi.mode != SPLITMV)
- {
- BLOCKD *b = &xd->block[24];
-
- DEQUANT_INVOKE(&pbi->dequant, block)(b);
-
- /* do 2nd order transform on the dc block */
- if (xd->eobs[24] > 1)
- {
- IDCT_INVOKE(RTCD_VTABLE(idct), iwalsh16)(&b->dqcoeff[0], b->diff);
- ((int *)b->qcoeff)[0] = 0;
- ((int *)b->qcoeff)[1] = 0;
- ((int *)b->qcoeff)[2] = 0;
- ((int *)b->qcoeff)[3] = 0;
- ((int *)b->qcoeff)[4] = 0;
- ((int *)b->qcoeff)[5] = 0;
- ((int *)b->qcoeff)[6] = 0;
- ((int *)b->qcoeff)[7] = 0;
- }
- else
- {
- IDCT_INVOKE(RTCD_VTABLE(idct), iwalsh1)(&b->dqcoeff[0], b->diff);
- ((int *)b->qcoeff)[0] = 0;
- }
-
- DEQUANT_INVOKE (&pbi->dequant, dc_idct_add_y_block)
- (xd->qcoeff, xd->block[0].dequant,
- xd->predictor, xd->dst.y_buffer,
- xd->dst.y_stride, xd->eobs, xd->block[24].diff);
- }
- else if (xd->mode_info_context->mbmi.mode == B_PRED)
+ if (mode == B_PRED)
{
for (i = 0; i < 16; i++)
{
-
BLOCKD *b = &xd->block[i];
RECON_INVOKE(RTCD_VTABLE(recon), intra4x4_predict)
(b, b->bmi.as_mode, b->predictor);
}
}
- else
+ else if (mode == SPLITMV)
{
DEQUANT_INVOKE (&pbi->dequant, idct_add_y_block)
(xd->qcoeff, xd->block[0].dequant,
xd->predictor, xd->dst.y_buffer,
xd->dst.y_stride, xd->eobs);
}
+ else
+ {
+ BLOCKD *b = &xd->block[24];
+
+ DEQUANT_INVOKE(&pbi->dequant, block)(b);
+
+ /* do 2nd order transform on the dc block */
+ if (xd->eobs[24] > 1)
+ {
+ IDCT_INVOKE(RTCD_VTABLE(idct), iwalsh16)(&b->dqcoeff[0], b->diff);
+ ((int *)b->qcoeff)[0] = 0;
+ ((int *)b->qcoeff)[1] = 0;
+ ((int *)b->qcoeff)[2] = 0;
+ ((int *)b->qcoeff)[3] = 0;
+ ((int *)b->qcoeff)[4] = 0;
+ ((int *)b->qcoeff)[5] = 0;
+ ((int *)b->qcoeff)[6] = 0;
+ ((int *)b->qcoeff)[7] = 0;
+ }
+ else
+ {
+ IDCT_INVOKE(RTCD_VTABLE(idct), iwalsh1)(&b->dqcoeff[0], b->diff);
+ ((int *)b->qcoeff)[0] = 0;
+ }
+
+ DEQUANT_INVOKE (&pbi->dequant, dc_idct_add_y_block)
+ (xd->qcoeff, xd->block[0].dequant,
+ xd->predictor, xd->dst.y_buffer,
+ xd->dst.y_stride, xd->eobs, xd->block[24].diff);
+ }
DEQUANT_INVOKE (&pbi->dequant, idct_add_uv_block)
(xd->qcoeff+16*16, xd->block[16].dequant,
return size;
}
+static void setup_token_decoder_partition_input(VP8D_COMP *pbi)
+{
+ vp8_reader *bool_decoder = &pbi->bc2;
+ int part_idx = 1;
+
+ TOKEN_PARTITION multi_token_partition =
+ (TOKEN_PARTITION)vp8_read_literal(&pbi->bc, 2);
+ assert(vp8dx_bool_error(&pbi->bc) ||
+ multi_token_partition == pbi->common.multi_token_partition);
+ if (pbi->num_partitions > 2)
+ {
+ CHECK_MEM_ERROR(pbi->mbc, vpx_malloc((pbi->num_partitions - 1) *
+ sizeof(vp8_reader)));
+ bool_decoder = pbi->mbc;
+ }
+
+ for (; part_idx < pbi->num_partitions; ++part_idx)
+ {
+ if (vp8dx_start_decode(bool_decoder,
+ pbi->partitions[part_idx],
+ pbi->partition_sizes[part_idx]))
+ vpx_internal_error(&pbi->common.error, VPX_CODEC_MEM_ERROR,
+ "Failed to allocate bool decoder %d",
+ part_idx);
+
+ bool_decoder++;
+ }
+
+#if CONFIG_MULTITHREAD
+ /* Clamp number of decoder threads */
+ if (pbi->decoding_thread_count > pbi->num_partitions - 1)
+ pbi->decoding_thread_count = pbi->num_partitions - 1;
+#endif
+}
static void setup_token_decoder(VP8D_COMP *pbi,
const unsigned char *cx_data)
const unsigned char *partition;
/* Parse number of token partitions to use */
- pc->multi_token_partition = (TOKEN_PARTITION)vp8_read_literal(&pbi->bc, 2);
+ const TOKEN_PARTITION multi_token_partition =
+ (TOKEN_PARTITION)vp8_read_literal(&pbi->bc, 2);
+ /* Only update the multi_token_partition field if we are sure the value
+ * is correct. */
+ if (!pbi->ec_enabled || !vp8dx_bool_error(&pbi->bc))
+ pc->multi_token_partition = multi_token_partition;
+
num_part = 1 << pc->multi_token_partition;
/* Set up pointers to the first partition */
VP8_COMMON *const pc = & pbi->common;
MACROBLOCKD *const xd = & pbi->mb;
const unsigned char *data = (const unsigned char *)pbi->Source;
- const unsigned char *const data_end = data + pbi->source_sz;
+ const unsigned char *data_end = data + pbi->source_sz;
ptrdiff_t first_partition_length_in_bytes;
int mb_row;
int i, j, k, l;
const int *const mb_feature_data_bits = vp8_mb_feature_data_bits;
+ if (pbi->input_partition)
+ {
+ data = pbi->partitions[0];
+ data_end = data + pbi->partition_sizes[0];
+ }
+
/* start with no corruption of current frame */
xd->corrupted = 0;
pc->yv12_fb[pc->new_fb_idx].corrupted = 0;
}
}
- setup_token_decoder(pbi, data + first_partition_length_in_bytes);
+ if (pbi->input_partition)
+ {
+ setup_token_decoder_partition_input(pbi);
+ }
+ else
+ {
+ setup_token_decoder(pbi, data + first_partition_length_in_bytes);
+ }
xd->current_bc = &pbi->bc2;
/* Read the default quantizers. */
fclose(z);
}
-
{
/* read coef probability tree */
-
for (i = 0; i < BLOCK_TYPES; i++)
for (j = 0; j < COEF_BANDS; j++)
for (k = 0; k < PREV_COEF_CONTEXTS; k++)
- for (l = 0; l < MAX_ENTROPY_TOKENS - 1; l++)
+ for (l = 0; l < ENTROPY_NODES; l++)
{
vp8_prob *const p = pc->fc.coef_probs [i][j][k] + l;
}
}
-
stop_token_decoder(pbi);
/* Collect information about decoder corruption. */
mi->mbmi.mode = SPLITMV;
mi->mbmi.uv_mode = DC_PRED;
mi->mbmi.partitioning = 3;
+ mi->mbmi.segment_id = 0;
estimate_mb_mvs(block_overlaps,
mi,
mb_to_left_edge,
mb->mb_to_top_edge,
mb->mb_to_bottom_edge);
}
+ else
+ {
+ mv->as_int = 0;
+ mi->bmi[row*4 + col].as_mode = NEW4X4;
+ mi->mbmi.need_to_clamp_mvs = 0;
+ }
}
}
}
mb->mode_info_context->mbmi.mode = SPLITMV;
mb->mode_info_context->mbmi.uv_mode = DC_PRED;
mb->mode_info_context->mbmi.partitioning = 3;
+ mb->mode_info_context->mbmi.segment_id = 0;
}
void vp8_conceal_corrupt_mb(MACROBLOCKD *xd)
pbi->ec_enabled = 0;
#endif
+ pbi->input_partition = oxcf->input_partition;
+
return (VP8D_PTR) pbi;
}
}
-int vp8dx_get_reference(VP8D_PTR ptr, VP8_REFFRAME ref_frame_flag, YV12_BUFFER_CONFIG *sd)
+vpx_codec_err_t vp8dx_get_reference(VP8D_PTR ptr, VP8_REFFRAME ref_frame_flag, YV12_BUFFER_CONFIG *sd)
{
VP8D_COMP *pbi = (VP8D_COMP *) ptr;
VP8_COMMON *cm = &pbi->common;
ref_fb_idx = cm->gld_fb_idx;
else if (ref_frame_flag == VP8_ALT_FLAG)
ref_fb_idx = cm->alt_fb_idx;
- else
- return -1;
+ else{
+ vpx_internal_error(&pbi->common.error, VPX_CODEC_ERROR,
+ "Invalid reference frame");
+ return pbi->common.error.error_code;
+ }
- vp8_yv12_copy_frame_ptr(&cm->yv12_fb[ref_fb_idx], sd);
+ if(cm->yv12_fb[ref_fb_idx].y_height != sd->y_height ||
+ cm->yv12_fb[ref_fb_idx].y_width != sd->y_width ||
+ cm->yv12_fb[ref_fb_idx].uv_height != sd->uv_height ||
+ cm->yv12_fb[ref_fb_idx].uv_width != sd->uv_width){
+ vpx_internal_error(&pbi->common.error, VPX_CODEC_ERROR,
+ "Incorrect buffer dimensions");
+ }
+ else
+ vp8_yv12_copy_frame_ptr(&cm->yv12_fb[ref_fb_idx], sd);
- return 0;
+ return pbi->common.error.error_code;
}
-int vp8dx_set_reference(VP8D_PTR ptr, VP8_REFFRAME ref_frame_flag, YV12_BUFFER_CONFIG *sd)
+vpx_codec_err_t vp8dx_set_reference(VP8D_PTR ptr, VP8_REFFRAME ref_frame_flag, YV12_BUFFER_CONFIG *sd)
{
VP8D_COMP *pbi = (VP8D_COMP *) ptr;
VP8_COMMON *cm = &pbi->common;
ref_fb_ptr = &cm->gld_fb_idx;
else if (ref_frame_flag == VP8_ALT_FLAG)
ref_fb_ptr = &cm->alt_fb_idx;
- else
- return -1;
-
- /* Find an empty frame buffer. */
- free_fb = get_free_fb(cm);
- /* Decrease fb_idx_ref_cnt since it will be increased again in
- * ref_cnt_fb() below. */
- cm->fb_idx_ref_cnt[free_fb]--;
+ else{
+ vpx_internal_error(&pbi->common.error, VPX_CODEC_ERROR,
+ "Invalid reference frame");
+ return pbi->common.error.error_code;
+ }
- /* Manage the reference counters and copy image. */
- ref_cnt_fb (cm->fb_idx_ref_cnt, ref_fb_ptr, free_fb);
- vp8_yv12_copy_frame_ptr(sd, &cm->yv12_fb[*ref_fb_ptr]);
+ if(cm->yv12_fb[*ref_fb_ptr].y_height != sd->y_height ||
+ cm->yv12_fb[*ref_fb_ptr].y_width != sd->y_width ||
+ cm->yv12_fb[*ref_fb_ptr].uv_height != sd->uv_height ||
+ cm->yv12_fb[*ref_fb_ptr].uv_width != sd->uv_width){
+ vpx_internal_error(&pbi->common.error, VPX_CODEC_ERROR,
+ "Incorrect buffer dimensions");
+ }
+ else{
+ /* Find an empty frame buffer. */
+ free_fb = get_free_fb(cm);
+ /* Decrease fb_idx_ref_cnt since it will be increased again in
+ * ref_cnt_fb() below. */
+ cm->fb_idx_ref_cnt[free_fb]--;
+
+ /* Manage the reference counters and copy image. */
+ ref_cnt_fb (cm->fb_idx_ref_cnt, ref_fb_ptr, free_fb);
+ vp8_yv12_copy_frame_ptr(sd, &cm->yv12_fb[*ref_fb_ptr]);
+ }
- return 0;
+ return pbi->common.error.error_code;
}
/*For ARM NEON, d8-d15 are callee-saved registers, and need to be saved by us.*/
pbi->common.error.error_code = VPX_CODEC_OK;
- if (size == 0)
+ if (pbi->input_partition && !(source == NULL && size == 0))
{
- /* This is used to signal that we are missing frames.
- * We do not know if the missing frame(s) was supposed to update
- * any of the reference buffers, but we act conservative and
- * mark only the last buffer as corrupted.
- */
- cm->yv12_fb[cm->lst_fb_idx].corrupted = 1;
-
- /* If error concealment is disabled we won't signal missing frames to
- * the decoder.
+ /* Store a pointer to this partition and return. We haven't
+ * received the complete frame yet, so we will wait with decoding.
*/
- if (!pbi->ec_enabled)
+ pbi->partitions[pbi->num_partitions] = source;
+ pbi->partition_sizes[pbi->num_partitions] = size;
+ pbi->source_sz += size;
+ pbi->num_partitions++;
+ if (pbi->num_partitions > (1<<pbi->common.multi_token_partition) + 1)
+ pbi->common.multi_token_partition++;
+ if (pbi->common.multi_token_partition > EIGHT_PARTITION)
{
- /* Signal that we have no frame to show. */
- cm->show_frame = 0;
-
- /* Nothing more to do. */
- return 0;
+ pbi->common.error.error_code = VPX_CODEC_UNSUP_BITSTREAM;
+ pbi->common.error.setjmp = 0;
+ return -1;
}
+ return 0;
}
+ else
+ {
+ if (!pbi->input_partition)
+ {
+ pbi->Source = source;
+ pbi->source_sz = size;
+ }
+ if (pbi->source_sz == 0)
+ {
+ /* This is used to signal that we are missing frames.
+ * We do not know if the missing frame(s) was supposed to update
+ * any of the reference buffers, but we act conservative and
+ * mark only the last buffer as corrupted.
+ */
+ cm->yv12_fb[cm->lst_fb_idx].corrupted = 1;
+
+ /* If error concealment is disabled we won't signal missing frames to
+ * the decoder.
+ */
+ if (!pbi->ec_enabled)
+ {
+ /* Signal that we have no frame to show. */
+ cm->show_frame = 0;
+
+ /* Nothing more to do. */
+ return 0;
+ }
+ }
#if HAVE_ARMV7
#if CONFIG_RUNTIME_CPU_DETECT
- if (cm->rtcd.flags & HAS_NEON)
+ if (cm->rtcd.flags & HAS_NEON)
#endif
- {
- vp8_push_neon(dx_store_reg);
- }
+ {
+ vp8_push_neon(dx_store_reg);
+ }
#endif
- cm->new_fb_idx = get_free_fb (cm);
+ cm->new_fb_idx = get_free_fb (cm);
- if (setjmp(pbi->common.error.jmp))
- {
+ if (setjmp(pbi->common.error.jmp))
+ {
#if HAVE_ARMV7
#if CONFIG_RUNTIME_CPU_DETECT
- if (cm->rtcd.flags & HAS_NEON)
+ if (cm->rtcd.flags & HAS_NEON)
#endif
- {
- vp8_pop_neon(dx_store_reg);
- }
+ {
+ vp8_pop_neon(dx_store_reg);
+ }
#endif
- pbi->common.error.setjmp = 0;
+ pbi->common.error.setjmp = 0;
- /* We do not know if the missing frame(s) was supposed to update
- * any of the reference buffers, but we act conservative and
- * mark only the last buffer as corrupted.
- */
- cm->yv12_fb[cm->lst_fb_idx].corrupted = 1;
+ /* We do not know if the missing frame(s) was supposed to update
+ * any of the reference buffers, but we act conservative and
+ * mark only the last buffer as corrupted.
+ */
+ cm->yv12_fb[cm->lst_fb_idx].corrupted = 1;
- if (cm->fb_idx_ref_cnt[cm->new_fb_idx] > 0)
- cm->fb_idx_ref_cnt[cm->new_fb_idx]--;
- return -1;
- }
-
- pbi->common.error.setjmp = 1;
+ if (cm->fb_idx_ref_cnt[cm->new_fb_idx] > 0)
+ cm->fb_idx_ref_cnt[cm->new_fb_idx]--;
+ return -1;
+ }
- /*cm->current_video_frame++;*/
- pbi->Source = source;
- pbi->source_sz = size;
+ pbi->common.error.setjmp = 1;
+ }
retcode = vp8_decode_frame(pbi);
pbi->ready_for_new_data = 0;
pbi->last_time_stamp = time_stamp;
+ pbi->num_partitions = 0;
+ if (pbi->input_partition)
+ pbi->common.multi_token_partition = 0;
+ pbi->source_sz = 0;
#if 0
{
const unsigned char *Source;
unsigned int source_sz;
+ const unsigned char *partitions[MAX_PARTITIONS];
+ unsigned int partition_sizes[MAX_PARTITIONS];
+ unsigned int num_partitions;
#if CONFIG_MULTITHREAD
/* variable for threading */
unsigned int mvs_corrupt_from_mb;
#endif
int ec_enabled;
+ int input_partition;
} VP8D_COMP;
#include "detokenize.h"
#include "vp8/common/reconinter.h"
#include "reconintra_mt.h"
+#if CONFIG_ERROR_CONCEALMENT
+#include "error_concealment.h"
+#endif
extern void mb_init_dequantizer(VP8D_COMP *pbi, MACROBLOCKD *xd);
extern void clamp_mvs(MACROBLOCKD *xd);
vp8_build_inter_predictors_mb(xd);
}
+#if CONFIG_ERROR_CONCEALMENT
+ if (pbi->ec_enabled &&
+ (mb_row * pbi->common.mb_cols + mb_col >= pbi->mvs_corrupt_from_mb ||
+ vp8dx_bool_error(xd->current_bc)))
+ {
+ /* MB with corrupt residuals or corrupt mode/motion vectors.
+ * Better to use the predictor as reconstruction.
+ */
+ vpx_memset(xd->qcoeff, 0, sizeof(xd->qcoeff));
+ vp8_conceal_corrupt_mb(xd);
+ return;
+ }
+#endif
+
/* dequantization and idct */
if (xd->mode_info_context->mbmi.mode != B_PRED && xd->mode_info_context->mbmi.mode != SPLITMV)
{
update_blockd_bmi(xd);
- /* Distance of Mb to the various image edges.
- * These are specified to 8th pel as they are always compared to values that are in 1/8th pel units
+ /* Distance of MB to the various image edges.
+ * These are specified to 8th pel as they are always
+ * compared to values that are in 1/8th pel units.
*/
xd->mb_to_left_edge = -((mb_col * 16) << 3);
xd->mb_to_right_edge = ((pc->mb_cols - 1 - mb_col) * 16) << 3;
+#if CONFIG_ERROR_CONCEALMENT
+ if (pbi->ec_enabled &&
+ (xd->mode_info_context->mbmi.ref_frame ==
+ INTRA_FRAME) &&
+ vp8dx_bool_error(xd->current_bc))
+ {
+ /* We have an intra block with corrupt coefficients,
+ * better to conceal with an inter block.
+ * Interpolate MVs from neighboring MBs
+ *
+ * Note that for the first mb with corrupt residual
+ * in a frame, we might not discover that before
+ * decoding the residual. That happens after this
+ * check, and therefore no inter concealment will be
+ * done.
+ */
+ vp8_interpolate_motion(xd,
+ mb_row, mb_col,
+ pc->mb_rows, pc->mb_cols,
+ pc->mode_info_stride);
+ }
+#endif
+
+
xd->dst.y_buffer = pc->yv12_fb[dst_fb_idx].y_buffer + recon_yoffset;
xd->dst.u_buffer = pc->yv12_fb[dst_fb_idx].u_buffer + recon_uvoffset;
xd->dst.v_buffer = pc->yv12_fb[dst_fb_idx].v_buffer + recon_uvoffset;
update_blockd_bmi(xd);
- /* Distance of Mb to the various image edges.
- * These are specified to 8th pel as they are always compared to values that are in 1/8th pel units
+ /* Distance of MB to the various image edges.
+ * These are specified to 8th pel as they are always compared to
+ * values that are in 1/8th pel units.
*/
xd->mb_to_left_edge = -((mb_col * 16) << 3);
xd->mb_to_right_edge = ((pc->mb_cols - 1 - mb_col) * 16) << 3;
+#if CONFIG_ERROR_CONCEALMENT
+ if (pbi->ec_enabled &&
+ (xd->mode_info_context->mbmi.ref_frame == INTRA_FRAME) &&
+ vp8dx_bool_error(xd->current_bc))
+ {
+ /* We have an intra block with corrupt coefficients, better
+ * to conceal with an inter block. Interpolate MVs from
+ * neighboring MBs
+ *
+ * Note that for the first mb with corrupt residual in a
+ * frame, we might not discover that before decoding the
+ * residual. That happens after this check, and therefore no
+ * inter concealment will be done.
+ */
+ vp8_interpolate_motion(xd,
+ mb_row, mb_col,
+ pc->mb_rows, pc->mb_cols,
+ pc->mode_info_stride);
+ }
+#endif
+
+
xd->dst.y_buffer = pc->yv12_fb[dst_fb_idx].y_buffer + recon_yoffset;
xd->dst.u_buffer = pc->yv12_fb[dst_fb_idx].u_buffer + recon_uvoffset;
xd->dst.v_buffer = pc->yv12_fb[dst_fb_idx].v_buffer + recon_uvoffset;
#include "vp8/common/systemdependent.h"
#include <assert.h>
#include <stdio.h>
+#include <limits.h>
#include "vp8/common/pragmas.h"
+#include "vpx/vpx_encoder.h"
#include "vpx_mem/vpx_mem.h"
#include "bitstream.h"
+#include "vp8/common/defaultcoefcounts.h"
const int vp8cx_base_skip_false_prob[128] =
{
#ifdef ENTROPY_STATS
int intra_mode_stats[10][10][10];
-static unsigned int tree_update_hist [BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [vp8_coef_tokens-1] [2];
+static unsigned int tree_update_hist [BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [ENTROPY_NODES] [2];
extern unsigned int active_section;
#endif
unsigned int shift;
vp8_writer *w = &cpi->bc2;
*size = 3 * (num_part - 1);
+ cpi->partition_sz[0] += *size;
ptr = cx_data + (*size);
for (i = 0; i < num_part; i++)
vp8_stop_encode(w);
*size += w->pos;
+ /* The first partition size is set earlier */
+ cpi->partition_sz[i + 1] = w->pos;
+
if (i < (num_part - 1))
{
write_partition_size(cx_data, w->pos);
m++; // skip L prediction border
}
}
-int vp8_estimate_entropy_savings(VP8_COMP *cpi)
+
+/* This function is used for debugging probability trees. */
+static void print_prob_tree(vp8_prob
+ coef_probs[BLOCK_TYPES][COEF_BANDS][PREV_COEF_CONTEXTS][ENTROPY_NODES])
{
+ /* print coef probability tree */
+ int i,j,k,l;
+ FILE* f = fopen("enc_tree_probs.txt", "a");
+ fprintf(f, "{\n");
+ for (i = 0; i < BLOCK_TYPES; i++)
+ {
+ fprintf(f, " {\n");
+ for (j = 0; j < COEF_BANDS; j++)
+ {
+ fprintf(f, " {\n");
+ for (k = 0; k < PREV_COEF_CONTEXTS; k++)
+ {
+ fprintf(f, " {");
+ for (l = 0; l < ENTROPY_NODES; l++)
+ {
+ fprintf(f, "%3u, ",
+ (unsigned int)(coef_probs [i][j][k][l]));
+ }
+ fprintf(f, " }\n");
+ }
+ fprintf(f, " }\n");
+ }
+ fprintf(f, " }\n");
+ }
+ fprintf(f, "}\n");
+ fclose(f);
+}
+
+static void sum_probs_over_prev_coef_context(
+ const unsigned int probs[PREV_COEF_CONTEXTS][MAX_ENTROPY_TOKENS],
+ unsigned int* out)
+{
+ int i, j;
+ for (i=0; i < MAX_ENTROPY_TOKENS; ++i)
+ {
+ for (j=0; j < PREV_COEF_CONTEXTS; ++j)
+ {
+ const int tmp = out[i];
+ out[i] += probs[j][i];
+ /* check for wrap */
+ if (out[i] < tmp)
+ out[i] = UINT_MAX;
+ }
+ }
+}
+
+static int prob_update_savings(const unsigned int *ct,
+ const vp8_prob oldp, const vp8_prob newp,
+ const vp8_prob upd)
+{
+ const int old_b = vp8_cost_branch(ct, oldp);
+ const int new_b = vp8_cost_branch(ct, newp);
+ const int update_b = 8 +
+ ((vp8_cost_one(upd) - vp8_cost_zero(upd)) >> 8);
+
+ return old_b - new_b - update_b;
+}
+
+static int independent_coef_context_savings(VP8_COMP *cpi)
+{
+ int savings = 0;
int i = 0;
+ do
+ {
+ int j = 0;
+ do
+ {
+ int k = 0;
+ unsigned int prev_coef_count_sum[MAX_ENTROPY_TOKENS] = {0};
+ int prev_coef_savings[MAX_ENTROPY_TOKENS] = {0};
+ /* Calculate new probabilities given the constraint that
+ * they must be equal over the prev coef contexts
+ */
+ if (cpi->common.frame_type == KEY_FRAME)
+ {
+ /* Reset to default probabilities at key frames */
+ sum_probs_over_prev_coef_context(vp8_default_coef_counts[i][j],
+ prev_coef_count_sum);
+ }
+ else
+ {
+ sum_probs_over_prev_coef_context(cpi->coef_counts[i][j],
+ prev_coef_count_sum);
+ }
+ do
+ {
+ /* at every context */
+
+ /* calc probs and branch cts for this frame only */
+ //vp8_prob new_p [ENTROPY_NODES];
+ //unsigned int branch_ct [ENTROPY_NODES] [2];
+
+ int t = 0; /* token/prob index */
+
+ vp8_tree_probs_from_distribution(
+ MAX_ENTROPY_TOKENS, vp8_coef_encodings, vp8_coef_tree,
+ cpi->frame_coef_probs[i][j][k],
+ cpi->frame_branch_ct [i][j][k],
+ prev_coef_count_sum,
+ 256, 1);
+
+ do
+ {
+ const unsigned int *ct = cpi->frame_branch_ct [i][j][k][t];
+ const vp8_prob newp = cpi->frame_coef_probs [i][j][k][t];
+ const vp8_prob oldp = cpi->common.fc.coef_probs [i][j][k][t];
+ const vp8_prob upd = vp8_coef_update_probs [i][j][k][t];
+ const int s = prob_update_savings(ct, oldp, newp, upd);
+
+ if (cpi->common.frame_type != KEY_FRAME ||
+ (cpi->common.frame_type == KEY_FRAME && newp != oldp))
+ prev_coef_savings[t] += s;
+ }
+ while (++t < ENTROPY_NODES);
+ }
+ while (++k < PREV_COEF_CONTEXTS);
+ k = 0;
+ do
+ {
+ /* We only update probabilities if we can save bits, except
+ * for key frames where we have to update all probabilities
+ * to get the equal probabilities across the prev coef
+ * contexts.
+ */
+ if (prev_coef_savings[k] > 0 ||
+ cpi->common.frame_type == KEY_FRAME)
+ savings += prev_coef_savings[k];
+ }
+ while (++k < ENTROPY_NODES);
+ }
+ while (++j < COEF_BANDS);
+ }
+ while (++i < BLOCK_TYPES);
+ return savings;
+}
+
+static int default_coef_context_savings(VP8_COMP *cpi)
+{
+ int savings = 0;
+ int i = 0;
+ do
+ {
+ int j = 0;
+ do
+ {
+ int k = 0;
+ do
+ {
+ /* at every context */
+
+ /* calc probs and branch cts for this frame only */
+ //vp8_prob new_p [ENTROPY_NODES];
+ //unsigned int branch_ct [ENTROPY_NODES] [2];
+
+ int t = 0; /* token/prob index */
+
+
+ vp8_tree_probs_from_distribution(
+ MAX_ENTROPY_TOKENS, vp8_coef_encodings, vp8_coef_tree,
+ cpi->frame_coef_probs [i][j][k],
+ cpi->frame_branch_ct [i][j][k],
+ cpi->coef_counts [i][j][k],
+ 256, 1
+ );
+
+ do
+ {
+ const unsigned int *ct = cpi->frame_branch_ct [i][j][k][t];
+ const vp8_prob newp = cpi->frame_coef_probs [i][j][k][t];
+ const vp8_prob oldp = cpi->common.fc.coef_probs [i][j][k][t];
+ const vp8_prob upd = vp8_coef_update_probs [i][j][k][t];
+ const int s = prob_update_savings(ct, oldp, newp, upd);
+
+ if (s > 0)
+ {
+ savings += s;
+ }
+ }
+ while (++t < ENTROPY_NODES);
+ }
+ while (++k < PREV_COEF_CONTEXTS);
+ }
+ while (++j < COEF_BANDS);
+ }
+ while (++i < BLOCK_TYPES);
+ return savings;
+}
+
+int vp8_estimate_entropy_savings(VP8_COMP *cpi)
+{
int savings = 0;
const int *const rfct = cpi->count_mb_ref_frame_usage;
}
- do
- {
- int j = 0;
-
- do
- {
- int k = 0;
-
- do
- {
- /* at every context */
-
- /* calc probs and branch cts for this frame only */
- //vp8_prob new_p [vp8_coef_tokens-1];
- //unsigned int branch_ct [vp8_coef_tokens-1] [2];
-
- int t = 0; /* token/prob index */
-
- vp8_tree_probs_from_distribution(
- vp8_coef_tokens, vp8_coef_encodings, vp8_coef_tree,
- cpi->frame_coef_probs [i][j][k], cpi->frame_branch_ct [i][j][k], cpi->coef_counts [i][j][k],
- 256, 1
- );
-
- do
- {
- const unsigned int *ct = cpi->frame_branch_ct [i][j][k][t];
- const vp8_prob newp = cpi->frame_coef_probs [i][j][k][t];
-
- const vp8_prob old = cpi->common.fc.coef_probs [i][j][k][t];
- const vp8_prob upd = vp8_coef_update_probs [i][j][k][t];
-
- const int old_b = vp8_cost_branch(ct, old);
- const int new_b = vp8_cost_branch(ct, newp);
-
- const int update_b = 8 +
- ((vp8_cost_one(upd) - vp8_cost_zero(upd)) >> 8);
-
- const int s = old_b - new_b - update_b;
-
- if (s > 0)
- savings += s;
-
-
- }
- while (++t < vp8_coef_tokens - 1);
-
+ if (cpi->oxcf.error_resilient_mode & VPX_ERROR_RESILIENT_PARTITIONS)
+ savings += independent_coef_context_savings(cpi);
+ else
+ savings += default_coef_context_savings(cpi);
- }
- while (++k < PREV_COEF_CONTEXTS);
- }
- while (++j < COEF_BANDS);
- }
- while (++i < BLOCK_TYPES);
return savings;
}
vp8_clear_system_state(); //__asm emms;
-
do
{
int j = 0;
do
{
int k = 0;
-
+ int prev_coef_savings[ENTROPY_NODES] = {0};
+ if (cpi->oxcf.error_resilient_mode & VPX_ERROR_RESILIENT_PARTITIONS)
+ {
+ for (k = 0; k < PREV_COEF_CONTEXTS; ++k)
+ {
+ int t; /* token/prob index */
+ for (t = 0; t < ENTROPY_NODES; ++t)
+ {
+ const unsigned int *ct = cpi->frame_branch_ct [i][j]
+ [k][t];
+ const vp8_prob newp = cpi->frame_coef_probs[i][j][k][t];
+ const vp8_prob oldp = cpi->common.fc.coef_probs[i][j]
+ [k][t];
+ const vp8_prob upd = vp8_coef_update_probs[i][j][k][t];
+
+ prev_coef_savings[t] +=
+ prob_update_savings(ct, oldp, newp, upd);
+ }
+ }
+ k = 0;
+ }
do
{
//note: use result from vp8_estimate_entropy_savings, so no need to call vp8_tree_probs_from_distribution here.
/* at every context */
/* calc probs and branch cts for this frame only */
- //vp8_prob new_p [vp8_coef_tokens-1];
- //unsigned int branch_ct [vp8_coef_tokens-1] [2];
+ //vp8_prob new_p [ENTROPY_NODES];
+ //unsigned int branch_ct [ENTROPY_NODES] [2];
int t = 0; /* token/prob index */
//vp8_tree_probs_from_distribution(
- // vp8_coef_tokens, vp8_coef_encodings, vp8_coef_tree,
+ // MAX_ENTROPY_TOKENS, vp8_coef_encodings, vp8_coef_tree,
// new_p, branch_ct, (unsigned int *)cpi->coef_counts [i][j][k],
// 256, 1
// );
do
{
- const unsigned int *ct = cpi->frame_branch_ct [i][j][k][t];
const vp8_prob newp = cpi->frame_coef_probs [i][j][k][t];
vp8_prob *Pold = cpi->common.fc.coef_probs [i][j][k] + t;
- const vp8_prob old = *Pold;
const vp8_prob upd = vp8_coef_update_probs [i][j][k][t];
- const int old_b = vp8_cost_branch(ct, old);
- const int new_b = vp8_cost_branch(ct, newp);
+ int s = prev_coef_savings[t];
+ int u = 0;
- const int update_b = 8 +
- ((vp8_cost_one(upd) - vp8_cost_zero(upd)) >> 8);
+ if (!(cpi->oxcf.error_resilient_mode &
+ VPX_ERROR_RESILIENT_PARTITIONS))
+ {
+ s = prob_update_savings(
+ cpi->frame_branch_ct [i][j][k][t],
+ *Pold, newp, upd);
+ }
- const int s = old_b - new_b - update_b;
- const int u = s > 0 ? 1 : 0;
+ if (s > 0)
+ u = 1;
+
+ /* Force updates on key frames if the new is different,
+ * so that we can be sure we end up with equal probabilities
+ * over the prev coef contexts.
+ */
+ if ((cpi->oxcf.error_resilient_mode &
+ VPX_ERROR_RESILIENT_PARTITIONS) &&
+ cpi->common.frame_type == KEY_FRAME && newp != *Pold)
+ u = 1;
vp8_write(w, u, upd);
}
}
- while (++t < vp8_coef_tokens - 1);
+ while (++t < ENTROPY_NODES);
/* Accum token counts for generation of default statistics */
#ifdef ENTROPY_STATS
{
context_counters [i][j][k][t] += cpi->coef_counts [i][j][k][t];
}
- while (++t < vp8_coef_tokens);
+ while (++t < MAX_ENTROPY_TOKENS);
#endif
vp8_write_bit(bc, pc->ref_frame_sign_bias[ALTREF_FRAME]);
}
+ if (cpi->oxcf.error_resilient_mode & VPX_ERROR_RESILIENT_PARTITIONS)
+ {
+ if (pc->frame_type == KEY_FRAME)
+ pc->refresh_entropy_probs = 1;
+ else
+ pc->refresh_entropy_probs = 0;
+ }
+
vp8_write_bit(bc, pc->refresh_entropy_probs);
if (pc->frame_type != KEY_FRAME)
}
*size = VP8_HEADER_SIZE + extra_bytes_packed + cpi->bc.pos;
+ cpi->partition_sz[0] = *size;
if (pc->multi_token_partition != ONE_PARTITION)
{
vp8_stop_encode(&cpi->bc2);
*size += cpi->bc2.pos;
+ cpi->partition_sz[1] = cpi->bc2.pos;
}
}
FILE *f = fopen("context.c", "a");
int Sum;
fprintf(f, "\n/* Update probabilities for token entropy tree. */\n\n");
- fprintf(f, "const vp8_prob tree_update_probs[BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [vp8_coef_tokens-1] = {\n");
+ fprintf(f, "const vp8_prob tree_update_probs[BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [ENTROPY_NODES] = {\n");
for (i = 0; i < BLOCK_TYPES; i++)
{
{
fprintf(f, " {");
- for (l = 0; l < MAX_ENTROPY_TOKENS - 1; l++)
+ for (l = 0; l < ENTROPY_NODES; l++)
{
Sum = tree_update_hist[i][j][k][l][0] + tree_update_hist[i][j][k][l][1];
unsigned char *active_ptr;
MV_CONTEXT *mvc;
- unsigned int token_costs[BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [vp8_coef_tokens];
+ unsigned int token_costs[BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [MAX_ENTROPY_TOKENS];
int optimize;
int q_index;
{
#if USE_ACT_INDEX
x->rdmult += *(x->mb_activity_ptr) * (x->rdmult >> 2);
- x->errorperbit = x->rdmult/x->rddiv;
+ x->errorperbit = x->rdmult * 100 /(110 * x->rddiv);
+ x->errorperbit += (x->errorperbit==0);
#else
INT64 a;
INT64 b;
b = (2*act) + cpi->activity_avg;
x->rdmult = (unsigned int)(((INT64)x->rdmult*b + (a>>1))/a);
- x->errorperbit = x->rdmult/x->rddiv;
-
+ x->errorperbit = x->rdmult * 100 /(110 * x->rddiv);
+ x->errorperbit += (x->errorperbit==0);
#endif
// Activity based Zbin adjustment
#include "encodeintra.h"
#include "vp8/common/setupintrarecon.h"
#include "mcomp.h"
+#include "firstpass.h"
#include "vpx_scale/vpxscale.h"
#include "encodemb.h"
#include "vp8/common/extend.h"
extern const int vp8_gf_boost_qadjustment[QINDEX_RANGE];
-#define IIFACTOR 1.4
+#define IIFACTOR 1.5
#define IIKFACTOR1 1.40
#define IIKFACTOR2 1.5
#define RMAX 14.0
#define POW1 (double)cpi->oxcf.two_pass_vbrbias/100.0
#define POW2 (double)cpi->oxcf.two_pass_vbrbias/100.0
+#define NEW_BOOST 1
+
static int vscale_lookup[7] = {0, 1, 1, 2, 2, 3, 3};
static int hscale_lookup[7] = {0, 0, 1, 1, 2, 2, 3};
return 1;
}
+// Read frame stats at an offset from the current position
+static int read_frame_stats( VP8_COMP *cpi,
+ FIRSTPASS_STATS *frame_stats,
+ int offset )
+{
+ FIRSTPASS_STATS * fps_ptr = cpi->twopass.stats_in;
+
+ // Check legality of offset
+ if ( offset >= 0 )
+ {
+ if ( &fps_ptr[offset] >= cpi->twopass.stats_in_end )
+ return EOF;
+ }
+ else if ( offset < 0 )
+ {
+ if ( &fps_ptr[offset] < cpi->twopass.stats_in_start )
+ return EOF;
+ }
+
+ *frame_stats = fps_ptr[offset];
+ return 1;
+}
+
+static int input_stats(VP8_COMP *cpi, FIRSTPASS_STATS *fps)
+{
+ if (cpi->twopass.stats_in >= cpi->twopass.stats_in_end)
+ return EOF;
+
+ *fps = *cpi->twopass.stats_in;
+ cpi->twopass.stats_in =
+ (void*)((char *)cpi->twopass.stats_in + sizeof(FIRSTPASS_STATS));
+ return 1;
+}
+
+static void output_stats(const VP8_COMP *cpi,
+ struct vpx_codec_pkt_list *pktlist,
+ FIRSTPASS_STATS *stats)
+{
+ struct vpx_codec_cx_pkt pkt;
+ pkt.kind = VPX_CODEC_STATS_PKT;
+ pkt.data.twopass_stats.buf = stats;
+ pkt.data.twopass_stats.sz = sizeof(FIRSTPASS_STATS);
+ vpx_codec_pkt_list_add(pktlist, &pkt);
+
+// TEMP debug code
+#if OUTPUT_FPF
+
+ {
+ FILE *fpfile;
+ fpfile = fopen("firstpass.stt", "a");
+
+ fprintf(fpfile, "%12.0f %12.0f %12.0f %12.4f %12.4f %12.4f %12.4f"
+ " %12.4f %12.4f %12.4f %12.4f %12.4f %12.4f %12.4f %12.4f"
+ " %12.0f %12.4f\n",
+ stats->frame,
+ stats->intra_error,
+ stats->coded_error,
+ stats->ssim_weighted_pred_err,
+ stats->pcnt_inter,
+ stats->pcnt_motion,
+ stats->pcnt_second_ref,
+ stats->pcnt_neutral,
+ stats->MVr,
+ stats->mvr_abs,
+ stats->MVc,
+ stats->mvc_abs,
+ stats->MVrv,
+ stats->MVcv,
+ stats->mv_in_out_count,
+ stats->count,
+ stats->duration);
+ fclose(fpfile);
+ }
+#endif
+}
+
+static void zero_stats(FIRSTPASS_STATS *section)
+{
+ section->frame = 0.0;
+ section->intra_error = 0.0;
+ section->coded_error = 0.0;
+ section->ssim_weighted_pred_err = 0.0;
+ section->pcnt_inter = 0.0;
+ section->pcnt_motion = 0.0;
+ section->pcnt_second_ref = 0.0;
+ section->pcnt_neutral = 0.0;
+ section->MVr = 0.0;
+ section->mvr_abs = 0.0;
+ section->MVc = 0.0;
+ section->mvc_abs = 0.0;
+ section->MVrv = 0.0;
+ section->MVcv = 0.0;
+ section->mv_in_out_count = 0.0;
+ section->count = 0.0;
+ section->duration = 1.0;
+}
+
+static void accumulate_stats(FIRSTPASS_STATS *section, FIRSTPASS_STATS *frame)
+{
+ section->frame += frame->frame;
+ section->intra_error += frame->intra_error;
+ section->coded_error += frame->coded_error;
+ section->ssim_weighted_pred_err += frame->ssim_weighted_pred_err;
+ section->pcnt_inter += frame->pcnt_inter;
+ section->pcnt_motion += frame->pcnt_motion;
+ section->pcnt_second_ref += frame->pcnt_second_ref;
+ section->pcnt_neutral += frame->pcnt_neutral;
+ section->MVr += frame->MVr;
+ section->mvr_abs += frame->mvr_abs;
+ section->MVc += frame->MVc;
+ section->mvc_abs += frame->mvc_abs;
+ section->MVrv += frame->MVrv;
+ section->MVcv += frame->MVcv;
+ section->mv_in_out_count += frame->mv_in_out_count;
+ section->count += frame->count;
+ section->duration += frame->duration;
+}
+
+static void avg_stats(FIRSTPASS_STATS *section)
+{
+ if (section->count < 1.0)
+ return;
+
+ section->intra_error /= section->count;
+ section->coded_error /= section->count;
+ section->ssim_weighted_pred_err /= section->count;
+ section->pcnt_inter /= section->count;
+ section->pcnt_second_ref /= section->count;
+ section->pcnt_neutral /= section->count;
+ section->pcnt_motion /= section->count;
+ section->MVr /= section->count;
+ section->mvr_abs /= section->count;
+ section->MVc /= section->count;
+ section->mvc_abs /= section->count;
+ section->MVrv /= section->count;
+ section->MVcv /= section->count;
+ section->mv_in_out_count /= section->count;
+ section->duration /= section->count;
+}
+
// Calculate a modified Error used in distributing bits between easier and harder frames
static double calculate_modified_err(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame)
{
int max_bits;
// For CBR we need to also consider buffer fullness.
+ // If we are running below the optimal level then we need to gradually tighten up on max_bits.
if (cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER)
{
- max_bits = 2 * cpi->av_per_frame_bandwidth;
- max_bits -= cpi->buffered_av_per_frame_bandwidth;
- max_bits *= ((double)cpi->oxcf.two_pass_vbrmax_section / 100.0);
- }
- // VBR
- else
- {
- // For VBR base this on the bits and frames left plus the two_pass_vbrmax_section rate passed in by the user
- max_bits = (int)(((double)cpi->twopass.bits_left / (cpi->twopass.total_stats->count - (double)cpi->common.current_video_frame)) * ((double)cpi->oxcf.two_pass_vbrmax_section / 100.0));
- }
+ double buffer_fullness_ratio = (double)cpi->buffer_level / DOUBLE_DIVIDE_CHECK((double)cpi->oxcf.optimal_buffer_level);
- // Trap case where we are out of bits
- if (max_bits < 0)
- max_bits = 0;
-
- return max_bits;
-}
+ // For CBR base this on the target average bits per frame plus the maximum sedction rate passed in by the user
+ max_bits = (int)(cpi->av_per_frame_bandwidth * ((double)cpi->oxcf.two_pass_vbrmax_section / 100.0));
+ // If our buffer is below the optimum level
+ if (buffer_fullness_ratio < 1.0)
+ {
+ // The lower of max_bits / 4 or cpi->av_per_frame_bandwidth / 4.
+ int min_max_bits = ((cpi->av_per_frame_bandwidth >> 2) < (max_bits >> 2)) ? cpi->av_per_frame_bandwidth >> 2 : max_bits >> 2;
-static int gf_group_max_bits(VP8_COMP *cpi)
-{
- // Max allocation for a golden frame group
- int max_bits;
+ max_bits = (int)(max_bits * buffer_fullness_ratio);
- // For CBR we need to also consider buffer fullness.
- if (cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER)
- {
- max_bits = cpi->av_per_frame_bandwidth * cpi->baseline_gf_interval;
- if (max_bits > cpi->oxcf.optimal_buffer_level)
- {
- max_bits -= cpi->oxcf.optimal_buffer_level;
- max_bits += cpi->buffer_level;
+ if (max_bits < min_max_bits)
+ max_bits = min_max_bits; // Lowest value we will set ... which should allow the buffer to refil.
}
- else
- {
- max_bits -= (cpi->buffered_av_per_frame_bandwidth
- - cpi->av_per_frame_bandwidth)
- * cpi->baseline_gf_interval;
- }
-
- max_bits *= ((double)cpi->oxcf.two_pass_vbrmax_section / 100.0);
}
+ // VBR
else
{
// For VBR base this on the bits and frames left plus the two_pass_vbrmax_section rate passed in by the user
max_bits = (int)(((double)cpi->twopass.bits_left / (cpi->twopass.total_stats->count - (double)cpi->common.current_video_frame)) * ((double)cpi->oxcf.two_pass_vbrmax_section / 100.0));
- max_bits *= cpi->baseline_gf_interval;
}
-
// Trap case where we are out of bits
if (max_bits < 0)
max_bits = 0;
return max_bits;
}
-
-static void output_stats(const VP8_COMP *cpi,
- struct vpx_codec_pkt_list *pktlist,
- FIRSTPASS_STATS *stats)
-{
- struct vpx_codec_cx_pkt pkt;
- pkt.kind = VPX_CODEC_STATS_PKT;
- pkt.data.twopass_stats.buf = stats;
- pkt.data.twopass_stats.sz = sizeof(FIRSTPASS_STATS);
- vpx_codec_pkt_list_add(pktlist, &pkt);
-
-// TEMP debug code
-#if OUTPUT_FPF
-
- {
- FILE *fpfile;
- fpfile = fopen("firstpass.stt", "a");
-
- fprintf(fpfile, "%12.0f %12.0f %12.0f %12.4f %12.4f %12.4f %12.4f"
- " %12.4f %12.4f %12.4f %12.4f %12.4f %12.4f %12.4f %12.4f"
- " %12.0f %12.4f\n",
- stats->frame,
- stats->intra_error,
- stats->coded_error,
- stats->ssim_weighted_pred_err,
- stats->pcnt_inter,
- stats->pcnt_motion,
- stats->pcnt_second_ref,
- stats->pcnt_neutral,
- stats->MVr,
- stats->mvr_abs,
- stats->MVc,
- stats->mvc_abs,
- stats->MVrv,
- stats->MVcv,
- stats->mv_in_out_count,
- stats->count,
- stats->duration);
- fclose(fpfile);
- }
-#endif
-}
-
-static int input_stats(VP8_COMP *cpi, FIRSTPASS_STATS *fps)
-{
- if (cpi->twopass.stats_in >= cpi->twopass.stats_in_end)
- return EOF;
-
- *fps = *cpi->twopass.stats_in;
- cpi->twopass.stats_in =
- (void*)((char *)cpi->twopass.stats_in + sizeof(FIRSTPASS_STATS));
- return 1;
-}
-
-static void zero_stats(FIRSTPASS_STATS *section)
-{
- section->frame = 0.0;
- section->intra_error = 0.0;
- section->coded_error = 0.0;
- section->ssim_weighted_pred_err = 0.0;
- section->pcnt_inter = 0.0;
- section->pcnt_motion = 0.0;
- section->pcnt_second_ref = 0.0;
- section->pcnt_neutral = 0.0;
- section->MVr = 0.0;
- section->mvr_abs = 0.0;
- section->MVc = 0.0;
- section->mvc_abs = 0.0;
- section->MVrv = 0.0;
- section->MVcv = 0.0;
- section->mv_in_out_count = 0.0;
- section->count = 0.0;
- section->duration = 1.0;
-}
-static void accumulate_stats(FIRSTPASS_STATS *section, FIRSTPASS_STATS *frame)
-{
- section->frame += frame->frame;
- section->intra_error += frame->intra_error;
- section->coded_error += frame->coded_error;
- section->ssim_weighted_pred_err += frame->ssim_weighted_pred_err;
- section->pcnt_inter += frame->pcnt_inter;
- section->pcnt_motion += frame->pcnt_motion;
- section->pcnt_second_ref += frame->pcnt_second_ref;
- section->pcnt_neutral += frame->pcnt_neutral;
- section->MVr += frame->MVr;
- section->mvr_abs += frame->mvr_abs;
- section->MVc += frame->MVc;
- section->mvc_abs += frame->mvc_abs;
- section->MVrv += frame->MVrv;
- section->MVcv += frame->MVcv;
- section->mv_in_out_count += frame->mv_in_out_count;
- section->count += frame->count;
- section->duration += frame->duration;
-}
-static void avg_stats(FIRSTPASS_STATS *section)
-{
- if (section->count < 1.0)
- return;
-
- section->intra_error /= section->count;
- section->coded_error /= section->count;
- section->ssim_weighted_pred_err /= section->count;
- section->pcnt_inter /= section->count;
- section->pcnt_second_ref /= section->count;
- section->pcnt_neutral /= section->count;
- section->pcnt_motion /= section->count;
- section->MVr /= section->count;
- section->mvr_abs /= section->count;
- section->MVc /= section->count;
- section->mvc_abs /= section->count;
- section->MVrv /= section->count;
- section->MVcv /= section->count;
- section->mv_in_out_count /= section->count;
- section->duration /= section->count;
-}
-
void vp8_init_first_pass(VP8_COMP *cpi)
{
zero_stats(cpi->twopass.total_stats);
//cpi->twopass.est_max_qcorrection_factor /= adjustment_rate;
- cpi->twopass.est_max_qcorrection_factor = (cpi->twopass.est_max_qcorrection_factor < 0.1) ? 0.1 : (cpi->twopass.est_max_qcorrection_factor > 10.0) ? 10.0 : cpi->twopass.est_max_qcorrection_factor;
+ cpi->twopass.est_max_qcorrection_factor =
+ (cpi->twopass.est_max_qcorrection_factor < 0.1)
+ ? 0.1
+ : (cpi->twopass.est_max_qcorrection_factor > 10.0)
+ ? 10.0 : cpi->twopass.est_max_qcorrection_factor;
}
// Corrections for higher compression speed settings (reduced compression expected)
* speed_correction * cpi->twopass.est_max_qcorrection_factor
* cpi->twopass.section_max_qfactor
* (double)vp8_bits_per_mb[INTER_FRAME][Q] / 1.0);
- //bits_per_mb_at_this_q = (int)(.5 + correction_factor * speed_correction * cpi->twopass.est_max_qcorrection_factor * (double)vp8_bits_per_mb[INTER_FRAME][Q] / 1.0);
if (bits_per_mb_at_this_q <= target_norm_bits_per_mb)
break;
double motion_decay;
double motion_pct = next_frame->pcnt_motion;
-
// Initial basis is the % mbs inter coded
prediction_decay_rate = next_frame->pcnt_inter;
return trans_to_still;
}
+// This function detects a flash through the high relative pcnt_second_ref
+// score in the frame following a flash frame. The offset passed in should
+// reflect this
+static BOOL detect_flash( VP8_COMP *cpi, int offset )
+{
+ FIRSTPASS_STATS next_frame;
+
+ BOOL flash_detected = FALSE;
+
+ // Read the frame data.
+ // The return is FALSE (no flash detected) if not a valid frame
+ if ( read_frame_stats(cpi, &next_frame, offset) != EOF )
+ {
+ // What we are looking for here is a situation where there is a
+ // brief break in prediction (such as a flash) but subsequent frames
+ // are reasonably well predicted by an earlier (pre flash) frame.
+ // The recovery after a flash is indicated by a high pcnt_second_ref
+ // comapred to pcnt_inter.
+ if ( (next_frame.pcnt_second_ref > next_frame.pcnt_inter) &&
+ (next_frame.pcnt_second_ref >= 0.5 ) )
+ {
+ flash_detected = TRUE;
+
+ /*if (1)
+ {
+ FILE *f = fopen("flash.stt", "a");
+ fprintf(f, "%8.0f %6.2f %6.2f\n",
+ next_frame.frame,
+ next_frame.pcnt_inter,
+ next_frame.pcnt_second_ref);
+ fclose(f);
+ }*/
+ }
+ }
+
+ return flash_detected;
+}
+
+// Update the motion related elements to the GF arf boost calculation
+static void accumulate_frame_motion_stats(
+ VP8_COMP *cpi,
+ FIRSTPASS_STATS * this_frame,
+ double * this_frame_mv_in_out,
+ double * mv_in_out_accumulator,
+ double * abs_mv_in_out_accumulator,
+ double * mv_ratio_accumulator )
+{
+ //double this_frame_mv_in_out;
+ double this_frame_mvr_ratio;
+ double this_frame_mvc_ratio;
+ double motion_pct;
+
+ // Accumulate motion stats.
+ motion_pct = this_frame->pcnt_motion;
+
+ // Accumulate Motion In/Out of frame stats
+ *this_frame_mv_in_out = this_frame->mv_in_out_count * motion_pct;
+ *mv_in_out_accumulator += this_frame->mv_in_out_count * motion_pct;
+ *abs_mv_in_out_accumulator +=
+ fabs(this_frame->mv_in_out_count * motion_pct);
+
+ // Accumulate a measure of how uniform (or conversely how random)
+ // the motion field is. (A ratio of absmv / mv)
+ if (motion_pct > 0.05)
+ {
+ this_frame_mvr_ratio = fabs(this_frame->mvr_abs) /
+ DOUBLE_DIVIDE_CHECK(fabs(this_frame->MVr));
+
+ this_frame_mvc_ratio = fabs(this_frame->mvc_abs) /
+ DOUBLE_DIVIDE_CHECK(fabs(this_frame->MVc));
+
+ *mv_ratio_accumulator +=
+ (this_frame_mvr_ratio < this_frame->mvr_abs)
+ ? (this_frame_mvr_ratio * motion_pct)
+ : this_frame->mvr_abs * motion_pct;
+
+ *mv_ratio_accumulator +=
+ (this_frame_mvc_ratio < this_frame->mvc_abs)
+ ? (this_frame_mvc_ratio * motion_pct)
+ : this_frame->mvc_abs * motion_pct;
+
+ }
+}
+
+// Calculate a baseline boost number for the current frame.
+static double calc_frame_boost(
+ VP8_COMP *cpi,
+ FIRSTPASS_STATS * this_frame,
+ double this_frame_mv_in_out )
+{
+ double frame_boost;
+
+ // Underlying boost factor is based on inter intra error ratio
+ if (this_frame->intra_error > cpi->twopass.gf_intra_err_min)
+ frame_boost = (IIFACTOR * this_frame->intra_error /
+ DOUBLE_DIVIDE_CHECK(this_frame->coded_error));
+ else
+ frame_boost = (IIFACTOR * cpi->twopass.gf_intra_err_min /
+ DOUBLE_DIVIDE_CHECK(this_frame->coded_error));
+
+ // Increase boost for frames where new data coming into frame
+ // (eg zoom out). Slightly reduce boost if there is a net balance
+ // of motion out of the frame (zoom in).
+ // The range for this_frame_mv_in_out is -1.0 to +1.0
+ if (this_frame_mv_in_out > 0.0)
+ frame_boost += frame_boost * (this_frame_mv_in_out * 2.0);
+ // In extreme case boost is halved
+ else
+ frame_boost += frame_boost * (this_frame_mv_in_out / 2.0);
+
+ // Clip to maximum
+ if (frame_boost > GF_RMAX)
+ frame_boost = GF_RMAX;
+
+ return frame_boost;
+}
+
+#if NEW_BOOST
+static int calc_arf_boost(
+ VP8_COMP *cpi,
+ int offset,
+ int f_frames,
+ int b_frames,
+ int *f_boost,
+ int *b_boost )
+{
+ FIRSTPASS_STATS this_frame;
+
+ int i;
+ double boost_score = 0.0;
+ double fwd_boost_score = 0.0;
+ double mv_ratio_accumulator = 0.0;
+ double decay_accumulator = 1.0;
+ double this_frame_mv_in_out = 0.0;
+ double mv_in_out_accumulator = 0.0;
+ double abs_mv_in_out_accumulator = 0.0;
+ double r;
+ BOOL flash_detected = FALSE;
+
+ // Search forward from the proposed arf/next gf position
+ for ( i = 0; i < f_frames; i++ )
+ {
+ if ( read_frame_stats(cpi, &this_frame, (i+offset)) == EOF )
+ break;
+
+ // Update the motion related elements to the boost calculation
+ accumulate_frame_motion_stats( cpi, &this_frame,
+ &this_frame_mv_in_out, &mv_in_out_accumulator,
+ &abs_mv_in_out_accumulator, &mv_ratio_accumulator );
+
+ // Calculate the baseline boost number for this frame
+ r = calc_frame_boost( cpi, &this_frame, this_frame_mv_in_out );
+
+ // We want to discount the the flash frame itself and the recovery
+ // frame that follows as both will have poor scores.
+ flash_detected = detect_flash(cpi, (i+offset)) ||
+ detect_flash(cpi, (i+offset+1));
+
+ // Cumulative effect of prediction quality decay
+ if ( !flash_detected )
+ {
+ decay_accumulator =
+ decay_accumulator *
+ get_prediction_decay_rate(cpi, &this_frame);
+ decay_accumulator =
+ decay_accumulator < 0.1 ? 0.1 : decay_accumulator;
+ }
+ boost_score += (decay_accumulator * r);
+
+ // Break out conditions.
+ if ( (!flash_detected) &&
+ ((mv_ratio_accumulator > 100.0) ||
+ (abs_mv_in_out_accumulator > 3.0) ||
+ (mv_in_out_accumulator < -2.0) ) )
+ {
+ break;
+ }
+ }
+
+ *f_boost = (int)(boost_score * 100.0) >> 4;
+
+ // Reset for backward looking loop
+ boost_score = 0.0;
+ mv_ratio_accumulator = 0.0;
+ decay_accumulator = 1.0;
+ this_frame_mv_in_out = 0.0;
+ mv_in_out_accumulator = 0.0;
+ abs_mv_in_out_accumulator = 0.0;
+
+ // Search forward from the proposed arf/next gf position
+ for ( i = -1; i >= -b_frames; i-- )
+ {
+ if ( read_frame_stats(cpi, &this_frame, (i+offset)) == EOF )
+ break;
+
+ // Update the motion related elements to the boost calculation
+ accumulate_frame_motion_stats( cpi, &this_frame,
+ &this_frame_mv_in_out, &mv_in_out_accumulator,
+ &abs_mv_in_out_accumulator, &mv_ratio_accumulator );
+
+ // Calculate the baseline boost number for this frame
+ r = calc_frame_boost( cpi, &this_frame, this_frame_mv_in_out );
+
+ // We want to discount the the flash frame itself and the recovery
+ // frame that follows as both will have poor scores.
+ flash_detected = detect_flash(cpi, (i+offset)) ||
+ detect_flash(cpi, (i+offset+1));
+
+ // Cumulative effect of prediction quality decay
+ if ( !flash_detected )
+ {
+ decay_accumulator =
+ decay_accumulator *
+ get_prediction_decay_rate(cpi, &this_frame);
+ decay_accumulator =
+ decay_accumulator < 0.1 ? 0.1 : decay_accumulator;
+ }
+
+ boost_score += (decay_accumulator * r);
+
+ // Break out conditions.
+ if ( (!flash_detected) &&
+ ((mv_ratio_accumulator > 100.0) ||
+ (abs_mv_in_out_accumulator > 3.0) ||
+ (mv_in_out_accumulator < -2.0) ) )
+ {
+ break;
+ }
+ }
+ *b_boost = (int)(boost_score * 100.0) >> 4;
+
+ return (*f_boost + *b_boost);
+}
+#endif
+
// Analyse and define a gf/arf group .
static void define_gf_group(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame)
{
FIRSTPASS_STATS next_frame;
FIRSTPASS_STATS *start_pos;
int i;
+ double r;
double boost_score = 0.0;
double old_boost_score = 0.0;
double gf_group_err = 0.0;
double gf_first_frame_err = 0.0;
double mod_frame_err = 0.0;
- double mv_accumulator_rabs = 0.0;
- double mv_accumulator_cabs = 0.0;
double mv_ratio_accumulator = 0.0;
double decay_accumulator = 1.0;
- double boost_factor = IIFACTOR;
double loop_decay_rate = 1.00; // Starting decay rate
double this_frame_mv_in_out = 0.0;
double abs_mv_in_out_accumulator = 0.0;
double mod_err_per_mb_accumulator = 0.0;
- int max_group_bits;
+ int max_bits = frame_max_bits(cpi); // Max for a single frame
unsigned int allow_alt_ref =
cpi->oxcf.play_alternate && cpi->oxcf.lag_in_frames;
+ int alt_boost = 0;
+ int f_boost = 0;
+ int b_boost = 0;
+ BOOL flash_detected;
+
cpi->twopass.gf_group_bits = 0;
cpi->twopass.gf_decay_rate = 0;
vpx_memset(&next_frame, 0, sizeof(next_frame)); // assure clean
- // Preload the stats for the next frame.
+ // Load stats for the current frame.
mod_frame_err = calculate_modified_err(cpi, this_frame);
// Note the error of the frame at the start of the group (this will be
((cpi->twopass.frames_to_key - i) < MIN_GF_INTERVAL)) &&
(i < cpi->twopass.frames_to_key))
{
- double r;
- double this_frame_mvr_ratio;
- double this_frame_mvc_ratio;
- //double motion_pct = next_frame.pcnt_motion;
- double motion_pct;
-
i++; // Increment the loop counter
// Accumulate error score of frames in this gf group
if (EOF == input_stats(cpi, &next_frame))
break;
- // Accumulate motion stats.
- motion_pct = next_frame.pcnt_motion;
- mv_accumulator_rabs += fabs(next_frame.mvr_abs * motion_pct);
- mv_accumulator_cabs += fabs(next_frame.mvc_abs * motion_pct);
+ // Test for the case where there is a brief flash but the prediction
+ // quality back to an earlier frame is then restored.
+ flash_detected = detect_flash(cpi, 0);
- //Accumulate Motion In/Out of frame stats
- this_frame_mv_in_out =
- next_frame.mv_in_out_count * motion_pct;
- mv_in_out_accumulator +=
- next_frame.mv_in_out_count * motion_pct;
- abs_mv_in_out_accumulator +=
- fabs(next_frame.mv_in_out_count * motion_pct);
+ // Update the motion related elements to the boost calculation
+ accumulate_frame_motion_stats( cpi, &next_frame,
+ &this_frame_mv_in_out, &mv_in_out_accumulator,
+ &abs_mv_in_out_accumulator, &mv_ratio_accumulator );
- // If there is a significant amount of motion
- if (motion_pct > 0.05)
- {
- this_frame_mvr_ratio = fabs(next_frame.mvr_abs) /
- DOUBLE_DIVIDE_CHECK(fabs(next_frame.MVr));
-
- this_frame_mvc_ratio = fabs(next_frame.mvc_abs) /
- DOUBLE_DIVIDE_CHECK(fabs(next_frame.MVc));
-
- mv_ratio_accumulator +=
- (this_frame_mvr_ratio < next_frame.mvr_abs)
- ? (this_frame_mvr_ratio * motion_pct)
- : next_frame.mvr_abs * motion_pct;
+ // Calculate a baseline boost number for this frame
+ r = calc_frame_boost( cpi, &next_frame, this_frame_mv_in_out );
- mv_ratio_accumulator +=
- (this_frame_mvc_ratio < next_frame.mvc_abs)
- ? (this_frame_mvc_ratio * motion_pct)
- : next_frame.mvc_abs * motion_pct;
- }
- else
+ // Cumulative effect of prediction quality decay
+ if ( !flash_detected )
{
- mv_ratio_accumulator += 0.0;
- this_frame_mvr_ratio = 1.0;
- this_frame_mvc_ratio = 1.0;
+ loop_decay_rate = get_prediction_decay_rate(cpi, &next_frame);
+ decay_accumulator = decay_accumulator * loop_decay_rate;
+ decay_accumulator =
+ decay_accumulator < 0.1 ? 0.1 : decay_accumulator;
}
-
- // Underlying boost factor is based on inter intra error ratio
- r = ( boost_factor *
- ( next_frame.intra_error /
- DOUBLE_DIVIDE_CHECK(next_frame.coded_error)));
-
- if (next_frame.intra_error > cpi->twopass.gf_intra_err_min)
- r = (IIKFACTOR2 * next_frame.intra_error /
- DOUBLE_DIVIDE_CHECK(next_frame.coded_error));
- else
- r = (IIKFACTOR2 * cpi->twopass.gf_intra_err_min /
- DOUBLE_DIVIDE_CHECK(next_frame.coded_error));
-
- // Increase boost for frames where new data coming into frame
- // (eg zoom out). Slightly reduce boost if there is a net balance
- // of motion out of the frame (zoom in).
- // The range for this_frame_mv_in_out is -1.0 to +1.0
- if (this_frame_mv_in_out > 0.0)
- r += r * (this_frame_mv_in_out * 2.0);
- // In extreme case boost is halved
- else
- r += r * (this_frame_mv_in_out / 2.0);
-
- if (r > GF_RMAX)
- r = GF_RMAX;
-
- loop_decay_rate = get_prediction_decay_rate(cpi, &next_frame);
-
- // Cumulative effect of decay
- decay_accumulator = decay_accumulator * loop_decay_rate;
- decay_accumulator = decay_accumulator < 0.1 ? 0.1 : decay_accumulator;
-
boost_score += (decay_accumulator * r);
// Break clause to detect very still sections after motion
// For example a staic image after a fade or other transition.
if ( detect_transition_to_still( cpi, i, 5,
- loop_decay_rate, decay_accumulator ) )
+ loop_decay_rate,
+ decay_accumulator ) )
{
allow_alt_ref = FALSE;
boost_score = old_boost_score;
}
// Break out conditions.
- if ( /* i>4 || */
+ if (
// Break at cpi->max_gf_interval unless almost totally static
(i >= cpi->max_gf_interval && (decay_accumulator < 0.995)) ||
(
// Dont break out very close to a key frame
((cpi->twopass.frames_to_key - i) >= MIN_GF_INTERVAL) &&
((boost_score > 20.0) || (next_frame.pcnt_inter < 0.75)) &&
+ (!flash_detected) &&
((mv_ratio_accumulator > 100.0) ||
(abs_mv_in_out_accumulator > 3.0) ||
(mv_in_out_accumulator < -2.0) ||
boost_score = max_boost;
}
- cpi->gfu_boost = (int)(boost_score * 100.0) >> 4;
-
// Dont allow conventional gf too near the next kf
if ((cpi->twopass.frames_to_key - i) < MIN_GF_INTERVAL)
{
}
}
+ cpi->gfu_boost = (int)(boost_score * 100.0) >> 4;
+
+#if NEW_BOOST
+ // Alterrnative boost calculation for alt ref
+ alt_boost = calc_arf_boost( cpi, 0, (i-1), (i-1), &f_boost, &b_boost );
+#endif
+
// Should we use the alternate refernce frame
if (allow_alt_ref &&
(i >= MIN_GF_INTERVAL) &&
// dont use ARF very near next kf
(i <= (cpi->twopass.frames_to_key - MIN_GF_INTERVAL)) &&
- (((next_frame.pcnt_inter > 0.75) &&
- ((mv_in_out_accumulator / (double)i > -0.2) || (mv_in_out_accumulator > -2.0)) &&
- //(cpi->gfu_boost>150) &&
- (cpi->gfu_boost > 100) &&
- //(cpi->gfu_boost>AF_THRESH2) &&
- //((cpi->gfu_boost/i)>AF_THRESH) &&
- //(decay_accumulator > 0.5) &&
- (cpi->twopass.gf_decay_rate <= (ARF_DECAY_THRESH + (cpi->gfu_boost / 200)))
- )
- )
- )
+#if NEW_BOOST
+ ((next_frame.pcnt_inter > 0.75) ||
+ (next_frame.pcnt_second_ref > 0.5)) &&
+ ((mv_in_out_accumulator / (double)i > -0.2) ||
+ (mv_in_out_accumulator > -2.0)) &&
+ (b_boost > 100) &&
+ (f_boost > 100) )
+#else
+ (next_frame.pcnt_inter > 0.75) &&
+ ((mv_in_out_accumulator / (double)i > -0.2) ||
+ (mv_in_out_accumulator > -2.0)) &&
+ (cpi->gfu_boost > 100) &&
+ (cpi->twopass.gf_decay_rate <=
+ (ARF_DECAY_THRESH + (cpi->gfu_boost / 200))) )
+#endif
{
int Boost;
int allocation_chunks;
- int Q = (cpi->oxcf.fixed_q < 0) ? cpi->last_q[INTER_FRAME] : cpi->oxcf.fixed_q;
+ int Q = (cpi->oxcf.fixed_q < 0)
+ ? cpi->last_q[INTER_FRAME] : cpi->oxcf.fixed_q;
int tmp_q;
int arf_frame_bits = 0;
int group_bits;
+#if NEW_BOOST
+ cpi->gfu_boost = alt_boost;
+#endif
+
// Estimate the bits to be allocated to the group as a whole
- if ((cpi->twopass.kf_group_bits > 0) && (cpi->twopass.kf_group_error_left > 0))
- group_bits = (int)((double)cpi->twopass.kf_group_bits * (gf_group_err / (double)cpi->twopass.kf_group_error_left));
+ if ((cpi->twopass.kf_group_bits > 0) &&
+ (cpi->twopass.kf_group_error_left > 0))
+ {
+ group_bits = (int)((double)cpi->twopass.kf_group_bits *
+ (gf_group_err / (double)cpi->twopass.kf_group_error_left));
+ }
else
group_bits = 0;
// Boost for arf frame
+#if NEW_BOOST
+ Boost = (alt_boost * GFQ_ADJUSTMENT) / 100;
+#else
Boost = (cpi->gfu_boost * 3 * GFQ_ADJUSTMENT) / (2 * 100);
+#endif
Boost += (i * 50);
+
+ // Set max and minimum boost and hence minimum allocation
+ if (Boost > ((cpi->baseline_gf_interval + 1) * 200))
+ Boost = ((cpi->baseline_gf_interval + 1) * 200);
+ else if (Boost < 125)
+ Boost = 125;
+
allocation_chunks = (i * 100) + Boost;
// Normalize Altboost and allocations chunck down to prevent overflow
allocation_chunks /= 2;
}
- // Calculate the number of bits to be spent on the arf based on the boost number
- arf_frame_bits = (int)((double)Boost * (group_bits / (double)allocation_chunks));
+ // Calculate the number of bits to be spent on the arf based on the
+ // boost number
+ arf_frame_bits = (int)((double)Boost * (group_bits /
+ (double)allocation_chunks));
- // Estimate if there are enough bits available to make worthwhile use of an arf.
+ // Estimate if there are enough bits available to make worthwhile use
+ // of an arf.
tmp_q = estimate_q(cpi, mod_frame_err, (int)arf_frame_bits);
- // Only use an arf if it is likely we will be able to code it at a lower Q than the surrounding frames.
+ // Only use an arf if it is likely we will be able to code
+ // it at a lower Q than the surrounding frames.
if (tmp_q < cpi->worst_quality)
{
int half_gf_int;
cpi->source_alt_ref_pending = TRUE;
- // For alt ref frames the error score for the end frame of the group (the alt ref frame) should not contribute to the group total and hence
- // the number of bit allocated to the group. Rather it forms part of the next group (it is the GF at the start of the next group)
- gf_group_err -= mod_frame_err;
+ // For alt ref frames the error score for the end frame of the
+ // group (the alt ref frame) should not contribute to the group
+ // total and hence the number of bit allocated to the group.
+ // Rather it forms part of the next group (it is the GF at the
+ // start of the next group)
+ // gf_group_err -= mod_frame_err;
+
+ // For alt ref frames alt ref frame is technically part of the
+ // GF frame for the next group but we always base the error
+ // calculation and bit allocation on the current group of frames.
- // Set the interval till the next gf or arf. For ARFs this is the number of frames to be coded before the future frame that is coded as an ARF.
+ // Set the interval till the next gf or arf.
+ // For ARFs this is the number of frames to be coded before the
+ // future frame that is coded as an ARF.
// The future frame itself is part of the next group
- cpi->baseline_gf_interval = i - 1;
+ cpi->baseline_gf_interval = i;
// Define the arnr filter width for this group of frames:
// We only filter frames that lie within a distance of half
// Note: this_frame->frame has been updated in the loop
// so it now points at the ARF frame.
half_gf_int = cpi->baseline_gf_interval >> 1;
- frames_after_arf = cpi->twopass.total_stats->count - this_frame->frame - 1;
+ frames_after_arf = cpi->twopass.total_stats->count -
+ this_frame->frame - 1;
switch (cpi->oxcf.arnr_type)
{
cpi->baseline_gf_interval = i;
}
- // Now decide how many bits should be allocated to the GF group as a proportion of those remaining in the kf group.
- // The final key frame group in the clip is treated as a special case where cpi->twopass.kf_group_bits is tied to cpi->twopass.bits_left.
- // This is also important for short clips where there may only be one key frame.
- if (cpi->twopass.frames_to_key >= (int)(cpi->twopass.total_stats->count - cpi->common.current_video_frame))
+ // Now decide how many bits should be allocated to the GF group as a
+ // proportion of those remaining in the kf group.
+ // The final key frame group in the clip is treated as a special case
+ // where cpi->twopass.kf_group_bits is tied to cpi->twopass.bits_left.
+ // This is also important for short clips where there may only be one
+ // key frame.
+ if (cpi->twopass.frames_to_key >= (int)(cpi->twopass.total_stats->count -
+ cpi->common.current_video_frame))
{
- cpi->twopass.kf_group_bits = (cpi->twopass.bits_left > 0) ? cpi->twopass.bits_left : 0;
+ cpi->twopass.kf_group_bits =
+ (cpi->twopass.bits_left > 0) ? cpi->twopass.bits_left : 0;
}
// Calculate the bits to be allocated to the group as a whole
- if ((cpi->twopass.kf_group_bits > 0) && (cpi->twopass.kf_group_error_left > 0))
- cpi->twopass.gf_group_bits = (int)((double)cpi->twopass.kf_group_bits * (gf_group_err / (double)cpi->twopass.kf_group_error_left));
+ if ((cpi->twopass.kf_group_bits > 0) &&
+ (cpi->twopass.kf_group_error_left > 0))
+ {
+ cpi->twopass.gf_group_bits =
+ (int)((double)cpi->twopass.kf_group_bits *
+ (gf_group_err / (double)cpi->twopass.kf_group_error_left));
+ }
else
cpi->twopass.gf_group_bits = 0;
- cpi->twopass.gf_group_bits = (cpi->twopass.gf_group_bits < 0) ? 0 : (cpi->twopass.gf_group_bits > cpi->twopass.kf_group_bits) ? cpi->twopass.kf_group_bits : cpi->twopass.gf_group_bits;
+ cpi->twopass.gf_group_bits =
+ (cpi->twopass.gf_group_bits < 0)
+ ? 0
+ : (cpi->twopass.gf_group_bits > cpi->twopass.kf_group_bits)
+ ? cpi->twopass.kf_group_bits : cpi->twopass.gf_group_bits;
- // Clip cpi->twopass.gf_group_bits based on user supplied data rate variability limit (cpi->oxcf.two_pass_vbrmax_section)
- max_group_bits = gf_group_max_bits(cpi);
- if (cpi->twopass.gf_group_bits > max_group_bits)
- cpi->twopass.gf_group_bits = max_group_bits;
+ // Clip cpi->twopass.gf_group_bits based on user supplied data rate
+ // variability limit (cpi->oxcf.two_pass_vbrmax_section)
+ if (cpi->twopass.gf_group_bits > max_bits * cpi->baseline_gf_interval)
+ cpi->twopass.gf_group_bits = max_bits * cpi->baseline_gf_interval;
// Reset the file position
reset_fpf_position(cpi, start_pos);
// Assign bits to the arf or gf.
for (i = 0; i <= (cpi->source_alt_ref_pending && cpi->common.frame_type != KEY_FRAME); i++) {
int Boost;
- int frames_in_section;
int allocation_chunks;
int Q = (cpi->oxcf.fixed_q < 0) ? cpi->last_q[INTER_FRAME] : cpi->oxcf.fixed_q;
int gf_bits;
// For ARF frames
if (cpi->source_alt_ref_pending && i == 0)
{
+#if NEW_BOOST
+ Boost = (alt_boost * GFQ_ADJUSTMENT) / 100;
+#else
Boost = (cpi->gfu_boost * 3 * GFQ_ADJUSTMENT) / (2 * 100);
- //Boost += (cpi->baseline_gf_interval * 25);
+#endif
Boost += (cpi->baseline_gf_interval * 50);
// Set max and minimum boost and hence minimum allocation
else if (Boost < 125)
Boost = 125;
- frames_in_section = cpi->baseline_gf_interval + 1;
- allocation_chunks = (frames_in_section * 100) + Boost;
+ allocation_chunks =
+ ((cpi->baseline_gf_interval + 1) * 100) + Boost;
}
// Else for standard golden frames
else
else if (Boost < 125)
Boost = 125;
- frames_in_section = cpi->baseline_gf_interval;
- allocation_chunks = (frames_in_section * 100) + (Boost - 100);
+ allocation_chunks =
+ (cpi->baseline_gf_interval * 100) + (Boost - 100);
}
// Normalize Altboost and allocations chunck down to prevent overflow
allocation_chunks /= 2;
}
- // Calculate the number of bits to be spent on the gf or arf based on the boost number
- gf_bits = (int)((double)Boost * (cpi->twopass.gf_group_bits / (double)allocation_chunks));
+ // Calculate the number of bits to be spent on the gf or arf based on
+ // the boost number
+ gf_bits = (int)((double)Boost *
+ (cpi->twopass.gf_group_bits /
+ (double)allocation_chunks));
// If the frame that is to be boosted is simpler than the average for
// the gf/arf group then use an alternative calculation
}
}
+ // Apply an additional limit for CBR
+ if (cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER)
+ {
+ if (cpi->twopass.gf_bits > (cpi->buffer_level >> 1))
+ cpi->twopass.gf_bits = cpi->buffer_level >> 1;
+ }
+
// Dont allow a negative value for gf_bits
if (gf_bits < 0)
gf_bits = 0;
if (cpi->twopass.gf_group_bits < 0)
cpi->twopass.gf_group_bits = 0;
- // Set aside some bits for a mid gf sequence boost
- if ((cpi->gfu_boost > 150) && (cpi->baseline_gf_interval > 5))
{
- int pct_extra = (cpi->gfu_boost - 100) / 50;
- pct_extra = (pct_extra > 10) ? 10 : pct_extra;
+#if NEW_BOOST
+ int boost = (cpi->source_alt_ref_pending)
+ ? b_boost : cpi->gfu_boost;
+#else
+ int boost = cpi->gfu_boost;
+#endif
+ // Set aside some bits for a mid gf sequence boost
+ if ((boost > 150) && (cpi->baseline_gf_interval > 5))
+ {
+ int pct_extra = (boost - 100) / 50;
+ pct_extra = (pct_extra > 10) ? 10 : pct_extra;
- cpi->twopass.mid_gf_extra_bits = (cpi->twopass.gf_group_bits * pct_extra) / 100;
- cpi->twopass.gf_group_bits -= cpi->twopass.mid_gf_extra_bits;
+ cpi->twopass.mid_gf_extra_bits =
+ (cpi->twopass.gf_group_bits * pct_extra) / 100;
+ cpi->twopass.gf_group_bits -= cpi->twopass.mid_gf_extra_bits;
+ }
+ else
+ cpi->twopass.mid_gf_extra_bits = 0;
}
- else
- cpi->twopass.mid_gf_extra_bits = 0;
}
// Adjustment to estimate_max_q based on a measure of complexity of the section
bestmv->as_mv.row = br << 1;
bestmv->as_mv.col = bc << 1;
- if ((abs(bestmv->as_mv.col - ref_mv->as_mv.col) > MAX_FULL_PEL_VAL) ||
- (abs(bestmv->as_mv.row - ref_mv->as_mv.row) > MAX_FULL_PEL_VAL))
+ if ((abs(bestmv->as_mv.col - ref_mv->as_mv.col) > (MAX_FULL_PEL_VAL<<3)) ||
+ (abs(bestmv->as_mv.row - ref_mv->as_mv.row) > (MAX_FULL_PEL_VAL<<3)))
return INT_MAX;
return besterr;
#define MAX_MVSEARCH_STEPS 8 // The maximum number of steps in a step search given the largest allowed initial step
-#define MAX_FULL_PEL_VAL ((1 << (MAX_MVSEARCH_STEPS+3)) - 8) // Max full pel mv specified in 1/8 pel units
+#define MAX_FULL_PEL_VAL ((1 << (MAX_MVSEARCH_STEPS)) - 1) // Max full pel mv specified in 1 pel units
#define MAX_FIRST_STEP (1 << (MAX_MVSEARCH_STEPS-1)) // Maximum size of the first step in full pel units
extern void print_mode_context(void);
cpi->rolling_actual_bits = cpi->av_per_frame_bandwidth;
cpi->long_rolling_target_bits = cpi->av_per_frame_bandwidth;
cpi->long_rolling_actual_bits = cpi->av_per_frame_bandwidth;
- cpi->buffered_av_per_frame_bandwidth = cpi->av_per_frame_bandwidth;
cpi->total_actual_bits = 0;
cpi->total_target_vs_actual = 0;
break;
}
- if (cpi->pass == 0 && cpi->oxcf.end_usage != USAGE_STREAM_FROM_SERVER)
+ if (cpi->pass == 0)
cpi->auto_worst_q = 1;
cpi->oxcf.worst_allowed_q = q_trans[oxcf->worst_allowed_q];
size_t packet_sz = sizeof(FIRSTPASS_STATS);
int packets = oxcf->two_pass_stats_in.sz / packet_sz;
- cpi->twopass.stats_in = oxcf->two_pass_stats_in.buf;
+ cpi->twopass.stats_in_start = oxcf->two_pass_stats_in.buf;
+ cpi->twopass.stats_in = cpi->twopass.stats_in_start;
cpi->twopass.stats_in_end = (void*)((char *)cpi->twopass.stats_in
+ (packets - 1) * packet_sz);
vp8_init_second_pass(cpi);
// For CBR if the buffer reaches its maximum level then we can no longer
// save up bits for later frames so we might as well use them up
// on the current frame.
- if (cpi->pass == 2
- && (cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER) &&
+ if ((cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER) &&
(cpi->buffer_level >= cpi->oxcf.optimal_buffer_level) && cpi->buffered_mode)
{
int Adjustment = cpi->active_worst_quality / 4; // Max adjustment is 1/4
}
else
{
- if(cpi->pass != 2)
- Q = cpi->avg_frame_qindex;
-
cpi->active_best_quality = inter_minq[Q];
// For the constant/constrained quality mode we dont want
(cpi->active_worst_quality < cpi->worst_quality) &&
(cpi->projected_frame_size > frame_over_shoot_limit))
{
- /* step down active_worst_quality such that the corresponding
- * active_best_quality will be equal to the current
- * active_worst_quality + 1
- */
- int i;
+ int over_size_percent = ((cpi->projected_frame_size - frame_over_shoot_limit) * 100) / frame_over_shoot_limit;
- for(i=cpi->active_worst_quality; i<cpi->worst_quality; i++)
- if(inter_minq[i] >= cpi->active_worst_quality + 1)
- break;
- cpi->active_worst_quality = i;
+ // If so is there any scope for relaxing it
+ while ((cpi->active_worst_quality < cpi->worst_quality) && (over_size_percent > 0))
+ {
+ cpi->active_worst_quality++;
+ top_index = cpi->active_worst_quality;
+ over_size_percent = (int)(over_size_percent * 0.96); // Assume 1 qstep = about 4% on frame size.
+ }
// If we have updated the active max Q do not call vp8_update_rate_correction_factors() this loop.
active_worst_qchanged = TRUE;
update_reference_frames(cm);
- if (cpi->oxcf.error_resilient_mode == 1)
+ if (cpi->oxcf.error_resilient_mode)
{
cm->refresh_entropy_probs = 0;
}
// Update the buffer level variable.
// Non-viewable frames are a special case and are treated as pure overhead.
- if ( cm->show_frame )
- cpi->bits_off_target += cpi->av_per_frame_bandwidth;
- cpi->bits_off_target -= cpi->projected_frame_size;
+ if ( !cm->show_frame )
+ cpi->bits_off_target -= cpi->projected_frame_size;
+ else
+ cpi->bits_off_target += cpi->av_per_frame_bandwidth - cpi->projected_frame_size;
// Rolling monitors of whether we are over or underspending used to help regulate min and Max Q in two pass.
cpi->rolling_target_bits = ((cpi->rolling_target_bits * 3) + cpi->this_frame_target + 2) / 4;
// Debug stats
cpi->total_target_vs_actual += (cpi->this_frame_target - cpi->projected_frame_size);
- // Update the buffered average bitrate
- {
- long long numerator;
-
- numerator = cpi->oxcf.maximum_buffer_size
- - cpi->buffered_av_per_frame_bandwidth
- + cpi->projected_frame_size;
- numerator *= cpi->buffered_av_per_frame_bandwidth;
- cpi->buffered_av_per_frame_bandwidth = numerator
- / cpi->oxcf.maximum_buffer_size;
- }
-
- {
- long long tmp = (long long)cpi->buffered_av_per_frame_bandwidth
- * cpi->oxcf.maximum_buffer_size
- / cpi->av_per_frame_bandwidth;
- cpi->buffer_level = cpi->oxcf.maximum_buffer_size
- - tmp
- + cpi->oxcf.optimal_buffer_level;
- }
-
- // Accumulate overshoot error.
- cpi->accumulated_overshoot +=
- (cpi->projected_frame_size > cpi->av_per_frame_bandwidth)
- ? cpi->projected_frame_size - cpi->av_per_frame_bandwidth
- : 0;
-
+ cpi->buffer_level = cpi->bits_off_target;
// Update bits left to the kf and gf groups to account for overshoot or undershoot on these frames
if (cm->frame_type == KEY_FRAME)
int per_frame_bandwidth; // Current section per frame bandwidth target
int av_per_frame_bandwidth; // Average frame size target for clip
int min_frame_bandwidth; // Minimum allocation that should be used for any frame
- int buffered_av_per_frame_bandwidth; // Average bitrate over the last buffer
- int buffered_av_per_frame_bandwidth_rem; // Average bitrate remainder
- int accumulated_overshoot; // Accumulated # of bits spent > target
-
int inter_frame_target;
double output_frame_rate;
long long last_time_stamp_seen;
unsigned int MVcount [2] [MVvals]; /* (row,col) MV cts this frame */
- unsigned int coef_counts [BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [vp8_coef_tokens]; /* for this frame */
- //DECLARE_ALIGNED(16, int, coef_counts_backup [BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [vp8_coef_tokens]); //not used any more
+ unsigned int coef_counts [BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [MAX_ENTROPY_TOKENS]; /* for this frame */
+ //DECLARE_ALIGNED(16, int, coef_counts_backup [BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [MAX_ENTROPY_TOKENS]); //not used any more
//save vp8_tree_probs_from_distribution result for each frame to avoid repeat calculation
- vp8_prob frame_coef_probs [BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [vp8_coef_tokens-1];
- unsigned int frame_branch_ct [BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [vp8_coef_tokens-1][2];
+ vp8_prob frame_coef_probs [BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [ENTROPY_NODES];
+ unsigned int frame_branch_ct [BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [ENTROPY_NODES][2];
int gfu_boost;
int kf_boost;
#endif
TOKENLIST *tplist;
+ unsigned int partition_sz[MAX_PARTITIONS];
// end of multithread data
unsigned int this_iiratio;
FIRSTPASS_STATS *total_stats;
FIRSTPASS_STATS *this_frame_stats;
- FIRSTPASS_STATS *stats_in, *stats_in_end;
+ FIRSTPASS_STATS *stats_in, *stats_in_end, *stats_in_start;
int first_pass_done;
long long bits_left;
long long clip_bits_total;
unsigned char *gf_active_flags;
int gf_active_count;
+ int output_partition;
+
//Store last frame's MV info for next frame MV prediction
int_mv *lfmv;
int *lf_ref_frame_sign_bias;
/* adjust mvp to make sure it is within MV range */
vp8_clamp_mv(&mvp,
- best_ref_mv.as_mv.col - MAX_FULL_PEL_VAL,
- best_ref_mv.as_mv.col + MAX_FULL_PEL_VAL,
- best_ref_mv.as_mv.row - MAX_FULL_PEL_VAL,
- best_ref_mv.as_mv.row + MAX_FULL_PEL_VAL);
+ best_ref_mv.as_mv.col - (MAX_FULL_PEL_VAL<<3),
+ best_ref_mv.as_mv.col + (MAX_FULL_PEL_VAL<<3),
+ best_ref_mv.as_mv.row - (MAX_FULL_PEL_VAL<<3),
+ best_ref_mv.as_mv.row + (MAX_FULL_PEL_VAL<<3));
}
switch (this_mode)
mvp.as_int = best_ref_mv.as_int;
}
- col_min = (best_ref_mv.as_mv.col - MAX_FULL_PEL_VAL) >>3;
- col_max = (best_ref_mv.as_mv.col + MAX_FULL_PEL_VAL) >>3;
- row_min = (best_ref_mv.as_mv.row - MAX_FULL_PEL_VAL) >>3;
- row_max = (best_ref_mv.as_mv.row + MAX_FULL_PEL_VAL) >>3;
+ col_min = (best_ref_mv.as_mv.col < 0)?(-((abs(best_ref_mv.as_mv.col))>>3) - MAX_FULL_PEL_VAL)
+ :((best_ref_mv.as_mv.col>>3) - MAX_FULL_PEL_VAL);
+ col_max = (best_ref_mv.as_mv.col < 0)?(-((abs(best_ref_mv.as_mv.col))>>3) + MAX_FULL_PEL_VAL)
+ :((best_ref_mv.as_mv.col>>3) + MAX_FULL_PEL_VAL);
+ row_min = (best_ref_mv.as_mv.row < 0)?(-((abs(best_ref_mv.as_mv.row))>>3) - MAX_FULL_PEL_VAL)
+ :((best_ref_mv.as_mv.row>>3) - MAX_FULL_PEL_VAL);
+ row_max = (best_ref_mv.as_mv.row < 0)?(-((abs(best_ref_mv.as_mv.row))>>3) + MAX_FULL_PEL_VAL)
+ :((best_ref_mv.as_mv.row>>3) + MAX_FULL_PEL_VAL);
// Get intersection of UMV window and valid MV window to reduce # of checks in diamond search.
if (x->mv_col_min < col_min )
// jbb chg: 20100118 - not so any more with this overquant stuff allow high values
// with lots of intra coming in.
int max_filter_level = MAX_LOOP_FILTER ;//* 3 / 4;
+ (void)base_qindex;
if (cpi->twopass.section_intra_rating > 8)
max_filter_level = MAX_LOOP_FILTER * 3 / 4;
- (void) cpi;
- (void) base_qindex;
-
return max_filter_level;
}
int best_err = 0;
int filt_err = 0;
- int min_filter_level = 0;
- int max_filter_level = MAX_LOOP_FILTER * 3 / 4; // PGW August 2006: Highest filter values almost always a bad idea
+ int min_filter_level = get_min_filter_level(cpi, cm->base_qindex);
+ int max_filter_level = get_max_filter_level(cpi, cm->base_qindex);
int filt_val;
int best_filt_val = cm->filter_level;
else
cm->sharpness_level = cpi->oxcf.Sharpness;
- // Enforce a minimum filter level based upon Q
- min_filter_level = get_min_filter_level(cpi, cm->base_qindex);
- max_filter_level = get_max_filter_level(cpi, cm->base_qindex);
-
// Start the search at the previous frame filter level unless it is now out of range.
if (cm->filter_level < min_filter_level)
cm->filter_level = min_filter_level;
int best_err = 0;
int filt_err = 0;
- int min_filter_level;
- int max_filter_level;
+ int min_filter_level = get_min_filter_level(cpi, cm->base_qindex);
+ int max_filter_level = get_max_filter_level(cpi, cm->base_qindex);
int filter_step;
int filt_high = 0;
else
cm->sharpness_level = cpi->oxcf.Sharpness;
- // Enforce a minimum filter level based upon Q
- min_filter_level = get_min_filter_level(cpi, cm->base_qindex);
- max_filter_level = get_max_filter_level(cpi, cm->base_qindex);
-
// Start the search at the previous frame filter level unless it is now out of range.
filt_mid = cm->filter_level;
static void calc_pframe_target_size(VP8_COMP *cpi)
{
- int min_frame_target, max_frame_target;
+ int min_frame_target;
int Adjustment;
- min_frame_target = 1;
+ min_frame_target = 0;
if (cpi->pass == 2)
{
if (min_frame_target < (cpi->av_per_frame_bandwidth >> 5))
min_frame_target = cpi->av_per_frame_bandwidth >> 5;
-
- max_frame_target = INT_MAX;
}
- else
- {
- if (min_frame_target < cpi->per_frame_bandwidth / 4)
- min_frame_target = cpi->per_frame_bandwidth / 4;
+ else if (min_frame_target < cpi->per_frame_bandwidth / 4)
+ min_frame_target = cpi->per_frame_bandwidth / 4;
- /* Don't allow the target to completely deplete the buffer. */
- max_frame_target = cpi->buffer_level + cpi->av_per_frame_bandwidth;
- if(max_frame_target < min_frame_target)
- max_frame_target = min_frame_target;
- }
// Special alt reference frame case
if (cpi->common.refresh_alt_ref_frame)
}
}
-
- if (cpi->pass==0 && cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER){
- /* determine the accumulated error to apply to this frame. Apply
- * more of the error when we've been undershooting, less when
- * we've been overshooting
- */
- long long adjust;
- int bitrate_error;
-
- bitrate_error = cpi->av_per_frame_bandwidth
- - cpi->buffered_av_per_frame_bandwidth;
-
- adjust = cpi->accumulated_overshoot;
- adjust *= cpi->av_per_frame_bandwidth + bitrate_error;
- adjust /= cpi->oxcf.maximum_buffer_size;
- if (adjust > (cpi->this_frame_target - min_frame_target))
- adjust = (cpi->this_frame_target - min_frame_target);
- else if (adjust < 0)
- adjust = 0;
-
- cpi->this_frame_target -= adjust;
- cpi->accumulated_overshoot -= adjust;
- }
-
- if(cpi->this_frame_target > max_frame_target)
- cpi->this_frame_target = max_frame_target;
}
};
static void fill_token_costs(
- unsigned int c [BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [vp8_coef_tokens],
- const vp8_prob p [BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [vp8_coef_tokens-1]
+ unsigned int c [BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [MAX_ENTROPY_TOKENS],
+ const vp8_prob p [BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [ENTROPY_NODES]
)
{
int i, j, k;
(cpi->RDMULT * rd_iifactor[cpi->twopass.next_iiratio]) >> 4;
}
- cpi->mb.errorperbit = (cpi->RDMULT / 100);
+ cpi->mb.errorperbit = (cpi->RDMULT / 110);
cpi->mb.errorperbit += (cpi->mb.errorperbit==0);
vp8_set_speed_features(cpi);
if (bsi.segment_rd < best_rd)
{
- int col_min = (best_ref_mv->as_mv.col - MAX_FULL_PEL_VAL) >>3;
- int col_max = (best_ref_mv->as_mv.col + MAX_FULL_PEL_VAL) >>3;
- int row_min = (best_ref_mv->as_mv.row - MAX_FULL_PEL_VAL) >>3;
- int row_max = (best_ref_mv->as_mv.row + MAX_FULL_PEL_VAL) >>3;
+ int col_min = (best_ref_mv->as_mv.col < 0)?(-((abs(best_ref_mv->as_mv.col))>>3) - MAX_FULL_PEL_VAL)
+ :((best_ref_mv->as_mv.col>>3) - MAX_FULL_PEL_VAL);
+ int col_max = (best_ref_mv->as_mv.col < 0)?(-((abs(best_ref_mv->as_mv.col))>>3) + MAX_FULL_PEL_VAL)
+ :((best_ref_mv->as_mv.col>>3) + MAX_FULL_PEL_VAL);
+ int row_min = (best_ref_mv->as_mv.row < 0)?(-((abs(best_ref_mv->as_mv.row))>>3) - MAX_FULL_PEL_VAL)
+ :((best_ref_mv->as_mv.row>>3) - MAX_FULL_PEL_VAL);
+ int row_max = (best_ref_mv->as_mv.row < 0)?(-((abs(best_ref_mv->as_mv.row))>>3) + MAX_FULL_PEL_VAL)
+ :((best_ref_mv->as_mv.row>>3) + MAX_FULL_PEL_VAL);
int tmp_col_min = x->mv_col_min;
int tmp_col_max = x->mv_col_max;
/* adjust mvp to make sure it is within MV range */
vp8_clamp_mv(&mvp,
- best_ref_mv.as_mv.col - MAX_FULL_PEL_VAL,
- best_ref_mv.as_mv.col + MAX_FULL_PEL_VAL,
- best_ref_mv.as_mv.row - MAX_FULL_PEL_VAL,
- best_ref_mv.as_mv.row + MAX_FULL_PEL_VAL);
+ best_ref_mv.as_mv.col - (MAX_FULL_PEL_VAL<<3),
+ best_ref_mv.as_mv.col + (MAX_FULL_PEL_VAL<<3),
+ best_ref_mv.as_mv.row - (MAX_FULL_PEL_VAL<<3),
+ best_ref_mv.as_mv.row + (MAX_FULL_PEL_VAL<<3));
}
// Check to see if the testing frequency for this mode is at its max
int sadpb = x->sadperbit16;
- int col_min = (best_ref_mv.as_mv.col - MAX_FULL_PEL_VAL) >>3;
- int col_max = (best_ref_mv.as_mv.col + MAX_FULL_PEL_VAL) >>3;
- int row_min = (best_ref_mv.as_mv.row - MAX_FULL_PEL_VAL) >>3;
- int row_max = (best_ref_mv.as_mv.row + MAX_FULL_PEL_VAL) >>3;
+ int col_min = (best_ref_mv.as_mv.col < 0)?(-((abs(best_ref_mv.as_mv.col))>>3) - MAX_FULL_PEL_VAL)
+ :((best_ref_mv.as_mv.col>>3) - MAX_FULL_PEL_VAL);
+ int col_max = (best_ref_mv.as_mv.col < 0)?(-((abs(best_ref_mv.as_mv.col))>>3) + MAX_FULL_PEL_VAL)
+ :((best_ref_mv.as_mv.col>>3) + MAX_FULL_PEL_VAL);
+ int row_min = (best_ref_mv.as_mv.row < 0)?(-((abs(best_ref_mv.as_mv.row))>>3) - MAX_FULL_PEL_VAL)
+ :((best_ref_mv.as_mv.row>>3) - MAX_FULL_PEL_VAL);
+ int row_max = (best_ref_mv.as_mv.row < 0)?(-((abs(best_ref_mv.as_mv.row))>>3) + MAX_FULL_PEL_VAL)
+ :((best_ref_mv.as_mv.row>>3) + MAX_FULL_PEL_VAL);
int tmp_col_min = x->mv_col_min;
int tmp_col_max = x->mv_col_max;
compressions, then generating context.c = initial stats. */
#ifdef ENTROPY_STATS
-_int64 context_counters[BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [vp8_coef_tokens];
+_int64 context_counters[BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [MAX_ENTROPY_TOKENS];
#endif
void vp8_stuff_mb(VP8_COMP *cpi, MACROBLOCKD *x, TOKENEXTRA **t) ;
void vp8_fix_contexts(MACROBLOCKD *x);
fprintf(f, "\n/* *** GENERATED FILE: DO NOT EDIT *** */\n\n");
- fprintf(f, "int Contexts[BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [vp8_coef_tokens];\n\n");
+ fprintf(f, "int Contexts[BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [MAX_ENTROPY_TOKENS];\n\n");
- fprintf(f, "const int default_contexts[BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [vp8_coef_tokens] = {");
+ fprintf(f, "const int default_contexts[BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [MAX_ENTROPY_TOKENS] = {");
# define Comma( X) (X? ",":"")
fprintf(f, "%s %d", Comma(t), y);
}
- while (++t < vp8_coef_tokens);
+ while (++t < MAX_ENTROPY_TOKENS);
fprintf(f, "}");
}
void init_context_counters();
void print_context_counters();
-extern _int64 context_counters[BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [vp8_coef_tokens];
+extern _int64 context_counters[BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [MAX_ENTROPY_TOKENS];
#endif
extern const int *vp8_dct_value_cost_ptr;
VP8_COMMON_SRCS-yes += common/coefupdateprobs.h
VP8_COMMON_SRCS-yes += common/debugmodes.c
VP8_COMMON_SRCS-yes += common/defaultcoefcounts.h
+VP8_COMMON_SRCS-yes += common/defaultcoefcounts.c
VP8_COMMON_SRCS-yes += common/entropy.c
VP8_COMMON_SRCS-yes += common/entropymode.c
VP8_COMMON_SRCS-yes += common/entropymv.c
VP8_COMMON_SRCS-$(HAVE_SSE2) += common/x86/postproc_sse2.asm
endif
+# common (c)
VP8_COMMON_SRCS-$(ARCH_ARM) += common/asm_com_offsets.c
VP8_COMMON_SRCS-$(ARCH_ARM) += common/arm/arm_systemdependent.c
-# common (c)
-VP8_COMMON_SRCS-$(HAVE_ARMV6) += common/arm/bilinearfilter_arm.c
-VP8_COMMON_SRCS-$(HAVE_ARMV6) += common/arm/bilinearfilter_arm.h
-VP8_COMMON_SRCS-$(HAVE_ARMV6) += common/arm/filter_arm.c
-VP8_COMMON_SRCS-$(HAVE_ARMV6) += common/arm/loopfilter_arm.c
-VP8_COMMON_SRCS-$(HAVE_ARMV6) += common/arm/reconintra_arm.c
+VP8_COMMON_SRCS-$(ARCH_ARM) += common/arm/bilinearfilter_arm.c
+VP8_COMMON_SRCS-$(ARCH_ARM) += common/arm/bilinearfilter_arm.h
+VP8_COMMON_SRCS-$(ARCH_ARM) += common/arm/filter_arm.c
+VP8_COMMON_SRCS-$(ARCH_ARM) += common/arm/loopfilter_arm.c
+VP8_COMMON_SRCS-$(ARCH_ARM) += common/arm/reconintra_arm.c
# common (armv6)
VP8_COMMON_SRCS-$(HAVE_ARMV6) += common/arm/armv6/bilinearfilter_v6$(ASM)
if (ctx->base.init_flags & VPX_CODEC_USE_PSNR)
((VP8_COMP *)ctx->cpi)->b_calculate_psnr = 1;
+ if (ctx->base.init_flags & VPX_CODEC_USE_OUTPUT_PARTITION)
+ ((VP8_COMP *)ctx->cpi)->output_partition = 1;
+
/* Convert API flags to internal codec lib flags */
lib_flags = (flags & VPX_EFLAG_FORCE_KF) ? FRAMEFLAGS_KEY : 0;
round = 1000000 * ctx->cfg.g_timebase.num / 2 - 1;
delta = (dst_end_time_stamp - dst_time_stamp);
pkt.kind = VPX_CODEC_CX_FRAME_PKT;
- pkt.data.frame.buf = cx_data;
- pkt.data.frame.sz = size;
pkt.data.frame.pts =
(dst_time_stamp * ctx->cfg.g_timebase.den + round)
/ ctx->cfg.g_timebase.num / 10000000;
pkt.data.frame.duration = 0;
}
- vpx_codec_pkt_list_add(&ctx->pkt_list.head, &pkt);
+ if (cpi->output_partition)
+ {
+ int i;
+ const int num_partitions =
+ (1 << cpi->common.multi_token_partition) + 1;
+ for (i = 0; i < num_partitions; ++i)
+ {
+ pkt.data.frame.buf = cx_data;
+ pkt.data.frame.sz = cpi->partition_sz[i];
+ pkt.data.frame.partition_id = i;
+ /* don't set the fragment bit for the last partition */
+ if (i < num_partitions - 1)
+ pkt.data.frame.flags |= VPX_FRAME_IS_FRAGMENT;
+ vpx_codec_pkt_list_add(&ctx->pkt_list.head, &pkt);
+ cx_data += cpi->partition_sz[i];
+ cx_data_sz -= cpi->partition_sz[i];
+ }
+ }
+ else
+ {
+ pkt.data.frame.buf = cx_data;
+ pkt.data.frame.sz = size;
+ pkt.data.frame.partition_id = -1;
+ vpx_codec_pkt_list_add(&ctx->pkt_list.head, &pkt);
+ cx_data += size;
+ cx_data_sz -= size;
+ }
//printf("timestamp: %lld, duration: %d\n", pkt->data.frame.pts, pkt->data.frame.duration);
- cx_data += size;
- cx_data_sz -= size;
}
}
}
{
"WebM Project VP8 Encoder" VERSION_STRING,
VPX_CODEC_INTERNAL_ABI_VERSION,
- VPX_CODEC_CAP_ENCODER | VPX_CODEC_CAP_PSNR,
+ VPX_CODEC_CAP_ENCODER | VPX_CODEC_CAP_PSNR |
+ VPX_CODEC_CAP_OUTPUT_PARTITION,
/* vpx_codec_caps_t caps; */
vp8e_init, /* vpx_codec_init_fn_t init; */
vp8e_destroy, /* vpx_codec_destroy_fn_t destroy; */
oxcf.max_threads = ctx->cfg.threads;
oxcf.error_concealment =
(ctx->base.init_flags & VPX_CODEC_USE_ERROR_CONCEALMENT);
+ oxcf.input_partition =
+ (ctx->base.init_flags & VPX_CODEC_USE_INPUT_PARTITION);
optr = vp8dx_create_decompressor(&oxcf);
image2yuvconfig(&frame->img, &sd);
- vp8dx_set_reference(ctx->pbi, frame->frame_type, &sd);
- return VPX_CODEC_OK;
+ return vp8dx_set_reference(ctx->pbi, frame->frame_type, &sd);
}
else
return VPX_CODEC_INVALID_PARAM;
image2yuvconfig(&frame->img, &sd);
- vp8dx_get_reference(ctx->pbi, frame->frame_type, &sd);
- return VPX_CODEC_OK;
+ return vp8dx_get_reference(ctx->pbi, frame->frame_type, &sd);
}
else
return VPX_CODEC_INVALID_PARAM;
{
"WebM Project VP8 Decoder" VERSION_STRING,
VPX_CODEC_INTERNAL_ABI_VERSION,
- VPX_CODEC_CAP_DECODER | VP8_CAP_POSTPROC | VP8_CAP_ERROR_CONCEALMENT,
+ VPX_CODEC_CAP_DECODER | VP8_CAP_POSTPROC | VP8_CAP_ERROR_CONCEALMENT |
+ VPX_CODEC_CAP_INPUT_PARTITION,
/* vpx_codec_caps_t caps; */
vp8_init, /* vpx_codec_init_fn_t init; */
vp8_destroy, /* vpx_codec_destroy_fn_t destroy; */
# encoder
VP8_CX_SRCS-$(ARCH_ARM) += encoder/arm/arm_csystemdependent.c
-VP8_CX_SRCS-$(HAVE_ARMV7) += encoder/arm/quantize_arm.c
-VP8_CX_SRCS-$(HAVE_ARMV7) += encoder/arm/picklpf_arm.c
-VP8_CX_SRCS-$(HAVE_ARMV6) += encoder/arm/dct_arm.c
-VP8_CX_SRCS-$(HAVE_ARMV6) += encoder/arm/variance_arm.c
-VP8_CX_SRCS-$(HAVE_ARMV6) += encoder/arm/variance_arm.h
-VP8_CX_SRCS-$(HAVE_ARMV5TE) += encoder/arm/boolhuff_arm.c
-
-VP8_CX_SRCS_REMOVE-$(HAVE_ARMV5TE) += encoder/boolhuff.c
+VP8_CX_SRCS-$(ARCH_ARM) += encoder/arm/quantize_arm.c
+VP8_CX_SRCS-$(ARCH_ARM) += encoder/arm/picklpf_arm.c
+VP8_CX_SRCS-$(ARCH_ARM) += encoder/arm/dct_arm.c
+VP8_CX_SRCS-$(ARCH_ARM) += encoder/arm/variance_arm.c
+VP8_CX_SRCS-$(ARCH_ARM) += encoder/arm/variance_arm.h
#File list for armv5te
# encoder
+VP8_CX_SRCS-$(HAVE_ARMV5TE) += encoder/arm/boolhuff_arm.c
+VP8_CX_SRCS_REMOVE-$(HAVE_ARMV5TE) += encoder/boolhuff.c
VP8_CX_SRCS-$(HAVE_ARMV5TE) += encoder/arm/armv5te/boolhuff_armv5te$(ASM)
VP8_CX_SRCS-$(HAVE_ARMV5TE) += encoder/arm/armv5te/vp8_packtokens_armv5$(ASM)
VP8_CX_SRCS-$(HAVE_ARMV5TE) += encoder/arm/armv5te/vp8_packtokens_mbrow_armv5$(ASM)
VP8_DX_SRCS-$(ARCH_ARM) += decoder/arm/arm_dsystemdependent.c
VP8_CX_SRCS-$(ARCH_ARM) += decoder/asm_dec_offsets.c
-VP8_DX_SRCS-$(HAVE_ARMV6) += decoder/arm/dequantize_arm.c
+VP8_DX_SRCS-$(ARCH_ARM) += decoder/arm/dequantize_arm.c
#File list for armv6
VP8_DX_SRCS-$(HAVE_ARMV6) += decoder/arm/armv6/dequant_dc_idct_v6$(ASM)
else if ((flags & VPX_CODEC_USE_ERROR_CONCEALMENT) &&
!(iface->caps & VPX_CODEC_CAP_ERROR_CONCEALMENT))
res = VPX_CODEC_INCAPABLE;
+ else if ((flags & VPX_CODEC_USE_INPUT_PARTITION) &&
+ !(iface->caps & VPX_CODEC_CAP_INPUT_PARTITION))
+ res = VPX_CODEC_INCAPABLE;
else if (!(iface->caps & VPX_CODEC_CAP_DECODER))
res = VPX_CODEC_INCAPABLE;
else
else if ((flags & VPX_CODEC_USE_PSNR)
&& !(iface->caps & VPX_CODEC_CAP_PSNR))
res = VPX_CODEC_INCAPABLE;
+ else if ((flags & VPX_CODEC_USE_OUTPUT_PARTITION)
+ && !(iface->caps & VPX_CODEC_CAP_OUTPUT_PARTITION))
+ res = VPX_CODEC_INCAPABLE;
else
{
ctx->iface = iface;
*/
#ifndef VP8_H
#define VP8_H
-#include "vpx/vpx_codec_impl_top.h"
+#include "vpx_codec_impl_top.h"
/*!\brief Control functions
*
DECLSPEC_DEPRECATED extern vpx_codec_iface_t vpx_codec_vp8_algo DEPRECATED;
#endif
-#include "vpx/vpx_codec_impl_bottom.h"
+#include "vpx_codec_impl_bottom.h"
#endif
*/
#ifndef VP8CX_H
#define VP8CX_H
-#include "vpx/vpx_codec_impl_top.h"
+#include "vpx_codec_impl_top.h"
/*!\name Algorithm interface for VP8
*
VPX_CTRL_USE_TYPE(VP8E_GET_LAST_QUANTIZER_64, int *)
/*! @} - end defgroup vp8_encoder */
-#include "vpx/vpx_codec_impl_bottom.h"
+#include "vpx_codec_impl_bottom.h"
#endif
*/
#ifndef VP8DX_H
#define VP8DX_H
-#include "vpx/vpx_codec_impl_top.h"
+#include "vpx_codec_impl_top.h"
/*!\name Algorithm interface for VP8
*
/*! @} - end defgroup vp8_decoder */
-#include "vpx/vpx_codec_impl_bottom.h"
+#include "vpx_codec_impl_bottom.h"
#endif
*/
#ifndef VP8E_H
#define VP8E_H
-#include "vpx/vpx_codec_impl_top.h"
+#include "vpx_codec_impl_top.h"
#if defined(VPX_CODEC_DISABLE_COMPAT) && VPX_CODEC_DISABLE_COMPAT
#error "Backwards compatibility disabled: don't include vp8e.h"
* #VPX_DL_BEST_QUALITY constants to that parameter instead.
*/
VPX_CTRL_USE_TYPE_DEPRECATED(VP8E_SET_ENCODING_MODE, vp8e_encoding_mode)
-#include "vpx/vpx_codec_impl_bottom.h"
+#include "vpx_codec_impl_bottom.h"
#endif
#define VPX_CODEC_CAP_POSTPROC 0x40000 /**< Can postprocess decoded frame */
#define VPX_CODEC_CAP_ERROR_CONCEALMENT 0x80000 /**< Can conceal errors due to
packet loss */
+#define VPX_CODEC_CAP_INPUT_PARTITION 0x100000 /**< Can receive encoded frames
+ one partition at a time */
/*! \brief Initialization-time Feature Enabling
*
#define VPX_CODEC_USE_POSTPROC 0x10000 /**< Postprocess decoded frame */
#define VPX_CODEC_USE_ERROR_CONCEALMENT 0x20000 /**< Conceal errors in decoded
frames */
+#define VPX_CODEC_USE_INPUT_PARTITION 0x40000 /**< The input frame should be
+ passed to the decoder one
+ partition at a time */
/*!\brief Stream properties
*
* generated, as appropriate. Encoded data \ref MUST be passed in DTS (decode
* time stamp) order. Frames produced will always be in PTS (presentation
* time stamp) order.
+ * If the decoder is configured with VPX_CODEC_USE_INPUT_PARTITION enabled,
+ * data and data_sz must contain at most one encoded partition. When no more
+ * data is available, this function should be called with NULL as data and 0
+ * as data_sz. The memory passed to this function must be available until
+ * the frame has been decoded.
*
* \param[in] ctx Pointer to this instance's context
* \param[in] data Pointer to this block of new coded data. If
*/
#define VPX_CODEC_CAP_PSNR 0x10000 /**< Can issue PSNR packets */
+ /*! Can output one partition at a time. Each partition is returned in its
+ * own VPX_CODEC_CX_FRAME_PKT, with the FRAME_IS_FRAGMENT flag set for
+ * every partition but the last. In this mode all frames are always
+ * returned partition by partition.
+ */
+#define VPX_CODEC_CAP_OUTPUT_PARTITION 0x20000
+
/*! \brief Initialization-time Feature Enabling
*
* The available flags are specified by VPX_CODEC_USE_* defines.
*/
#define VPX_CODEC_USE_PSNR 0x10000 /**< Calculate PSNR on each frame */
+#define VPX_CODEC_USE_OUTPUT_PARTITION 0x20000 /**< Make the encoder output one
+ partition at a time. */
/*!\brief Generic fixed size buffer structure
this one) */
#define VPX_FRAME_IS_INVISIBLE 0x4 /**< frame should be decoded but will not
be shown */
+#define VPX_FRAME_IS_FRAGMENT 0x8 /**< this is a fragment of the encoded
+ frame */
+ /*!\brief Error Resilient flags
+ *
+ * These flags define which error resilient features to enable in the
+ * encoder. The flags are specified through the
+ * vpx_codec_enc_cfg::g_error_resilient variable.
+ */
+ typedef uint32_t vpx_codec_er_flags_t;
+#define VPX_ERROR_RESILIENT_DEFAULT 0x1 /**< Improve resiliency against
+ losses of whole frames */
+#define VPX_ERROR_RESILIENT_PARTITIONS 0x2 /**< The frame partitions are
+ independently decodable by the
+ bool decoder, meaning that
+ partitions can be decoded even
+ though earlier partitions have
+ been lost. Note that intra
+ predicition is still done over
+ the partition boundary. */
/*!\brief Encoder output packet variants
*
unsigned long duration; /**< duration to show frame
(in timebase units) */
vpx_codec_frame_flags_t flags; /**< flags for this frame */
+ int partition_id; /**< the partition id
+ defines the decoding order
+ of the partitions. Only
+ applicable when "output partition"
+ mode is enabled. First partition
+ has id 0.*/
+
} frame; /**< data for compressed frame packet */
struct vpx_fixed_buf twopass_stats; /**< data for two-pass packet */
struct vpx_psnr_pkt
struct vpx_rational g_timebase;
- /*!\brief Enable error resilient mode.
+ /*!\brief Enable error resilient modes.
*
- * Error resilient mode indicates to the encoder that it should take
- * measures appropriate for streaming over lossy or noisy links, if
- * possible. Set to 1 to enable this feature, 0 to disable it.
+ * The error resilient bitfield indicates to the encoder which features
+ * it should enable to take measures for streaming over lossy or noisy
+ * links.
*/
- unsigned int g_error_resilient;
+ vpx_codec_er_flags_t g_error_resilient;
/*!\brief Multi-pass Encoding Mode
#include <stdarg.h>
#include <string.h>
#include <limits.h>
+#include <assert.h>
#include "vpx/vpx_encoder.h"
#if USE_POSIX_MMAP
#include <sys/types.h>
"Stream frame rate (rate/scale)");
static const arg_def_t use_ivf = ARG_DEF(NULL, "ivf", 0,
"Output IVF (default is WebM)");
+static const arg_def_t q_hist_n = ARG_DEF(NULL, "q-hist", 1,
+ "Show quantizer histogram (n-buckets)");
+static const arg_def_t rate_hist_n = ARG_DEF(NULL, "rate-hist", 1,
+ "Show rate histogram (n-buckets)");
static const arg_def_t *main_args[] =
{
&debugmode,
&outputfile, &codecarg, &passes, &pass_arg, &fpf_name, &limit, &deadline,
&best_dl, &good_dl, &rt_dl,
- &verbosearg, &psnrarg, &use_ivf,
+ &verbosearg, &psnrarg, &use_ivf, &q_hist_n, &rate_hist_n,
NULL
};
exit(EXIT_FAILURE);
}
+
+#define HIST_BAR_MAX 40
+struct hist_bucket
+{
+ int low, high, count;
+};
+
+
+static int merge_hist_buckets(struct hist_bucket *bucket,
+ int *buckets_,
+ int max_buckets)
+{
+ int small_bucket = 0, merge_bucket = INT_MAX, big_bucket=0;
+ int buckets = *buckets_;
+ int i;
+
+ /* Find the extrema for this list of buckets */
+ big_bucket = small_bucket = 0;
+ for(i=0; i < buckets; i++)
+ {
+ if(bucket[i].count < bucket[small_bucket].count)
+ small_bucket = i;
+ if(bucket[i].count > bucket[big_bucket].count)
+ big_bucket = i;
+ }
+
+ /* If we have too many buckets, merge the smallest with an ajacent
+ * bucket.
+ */
+ while(buckets > max_buckets)
+ {
+ int last_bucket = buckets - 1;
+
+ // merge the small bucket with an adjacent one.
+ if(small_bucket == 0)
+ merge_bucket = 1;
+ else if(small_bucket == last_bucket)
+ merge_bucket = last_bucket - 1;
+ else if(bucket[small_bucket - 1].count < bucket[small_bucket + 1].count)
+ merge_bucket = small_bucket - 1;
+ else
+ merge_bucket = small_bucket + 1;
+
+ assert(abs(merge_bucket - small_bucket) <= 1);
+ assert(small_bucket < buckets);
+ assert(big_bucket < buckets);
+ assert(merge_bucket < buckets);
+
+ if(merge_bucket < small_bucket)
+ {
+ bucket[merge_bucket].high = bucket[small_bucket].high;
+ bucket[merge_bucket].count += bucket[small_bucket].count;
+ }
+ else
+ {
+ bucket[small_bucket].high = bucket[merge_bucket].high;
+ bucket[small_bucket].count += bucket[merge_bucket].count;
+ merge_bucket = small_bucket;
+ }
+
+ assert(bucket[merge_bucket].low != bucket[merge_bucket].high);
+
+ buckets--;
+
+ /* Remove the merge_bucket from the list, and find the new small
+ * and big buckets while we're at it
+ */
+ big_bucket = small_bucket = 0;
+ for(i=0; i < buckets; i++)
+ {
+ if(i > merge_bucket)
+ bucket[i] = bucket[i+1];
+
+ if(bucket[i].count < bucket[small_bucket].count)
+ small_bucket = i;
+ if(bucket[i].count > bucket[big_bucket].count)
+ big_bucket = i;
+ }
+
+ }
+
+ *buckets_ = buckets;
+ return bucket[big_bucket].count;
+}
+
+
+static void show_histogram(const struct hist_bucket *bucket,
+ int buckets,
+ int total,
+ int scale)
+{
+ const char *pat1, *pat2;
+ int i;
+
+ switch((int)(log(bucket[buckets-1].high)/log(10))+1)
+ {
+ case 1:
+ case 2:
+ pat1 = "%4d %2s: ";
+ pat2 = "%4d-%2d: ";
+ break;
+ case 3:
+ pat1 = "%5d %3s: ";
+ pat2 = "%5d-%3d: ";
+ break;
+ case 4:
+ pat1 = "%6d %4s: ";
+ pat2 = "%6d-%4d: ";
+ break;
+ case 5:
+ pat1 = "%7d %5s: ";
+ pat2 = "%7d-%5d: ";
+ break;
+ case 6:
+ pat1 = "%8d %6s: ";
+ pat2 = "%8d-%6d: ";
+ break;
+ case 7:
+ pat1 = "%9d %7s: ";
+ pat2 = "%9d-%7d: ";
+ break;
+ default:
+ pat1 = "%12d %10s: ";
+ pat2 = "%12d-%10d: ";
+ break;
+ }
+
+ for(i=0; i<buckets; i++)
+ {
+ int len;
+ int j;
+ float pct;
+
+ pct = 100.0 * (float)bucket[i].count / (float)total;
+ len = HIST_BAR_MAX * bucket[i].count / scale;
+ if(len < 1)
+ len = 1;
+ assert(len <= HIST_BAR_MAX);
+
+ if(bucket[i].low == bucket[i].high)
+ fprintf(stderr, pat1, bucket[i].low, "");
+ else
+ fprintf(stderr, pat2, bucket[i].low, bucket[i].high);
+
+ for(j=0; j<HIST_BAR_MAX; j++)
+ fprintf(stderr, j<len?"=":" ");
+ fprintf(stderr, "\t%5d (%6.2f%%)\n",bucket[i].count,pct);
+ }
+}
+
+
+static void show_q_histogram(const int counts[64], int max_buckets)
+{
+ struct hist_bucket bucket[64];
+ int buckets = 0;
+ int total = 0;
+ int scale;
+ int i;
+
+
+ for(i=0; i<64; i++)
+ {
+ if(counts[i])
+ {
+ bucket[buckets].low = bucket[buckets].high = i;
+ bucket[buckets].count = counts[i];
+ buckets++;
+ total += counts[i];
+ }
+ }
+
+ fprintf(stderr, "\nQuantizer Selection:\n");
+ scale = merge_hist_buckets(bucket, &buckets, max_buckets);
+ show_histogram(bucket, buckets, total, scale);
+}
+
+
+#define RATE_BINS (100)
+struct rate_hist
+{
+ int64_t *pts;
+ int *sz;
+ int samples;
+ int frames;
+ struct hist_bucket bucket[RATE_BINS];
+ int total;
+};
+
+
+static void init_rate_histogram(struct rate_hist *hist,
+ const vpx_codec_enc_cfg_t *cfg,
+ const vpx_rational_t *fps)
+{
+ int i;
+
+ /* Determine the number of samples in the buffer. Use the file's framerate
+ * to determine the number of frames in rc_buf_sz milliseconds, with an
+ * adjustment (5/4) to account for alt-refs
+ */
+ hist->samples = cfg->rc_buf_sz * 5 / 4 * fps->num / fps->den / 1000;
+ hist->pts = calloc(hist->samples, sizeof(*hist->pts));
+ hist->sz = calloc(hist->samples, sizeof(*hist->sz));
+ for(i=0; i<RATE_BINS; i++)
+ {
+ hist->bucket[i].low = INT_MAX;
+ hist->bucket[i].high = 0;
+ hist->bucket[i].count = 0;
+ }
+}
+
+
+static void destroy_rate_histogram(struct rate_hist *hist)
+{
+ free(hist->pts);
+ free(hist->sz);
+}
+
+
+static void update_rate_histogram(struct rate_hist *hist,
+ const vpx_codec_enc_cfg_t *cfg,
+ const vpx_codec_cx_pkt_t *pkt)
+{
+ int i, idx;
+ int64_t now, then, sum_sz = 0, avg_bitrate;
+
+ now = pkt->data.frame.pts * 1000
+ * (uint64_t)cfg->g_timebase.num / (uint64_t)cfg->g_timebase.den;
+
+ idx = hist->frames++ % hist->samples;
+ hist->pts[idx] = now;
+ hist->sz[idx] = pkt->data.frame.sz;
+
+ if(now < cfg->rc_buf_initial_sz)
+ return;
+
+ then = now;
+
+ /* Sum the size over the past rc_buf_sz ms */
+ for(i = hist->frames; i > 0 && hist->frames - i < hist->samples; i--)
+ {
+ int i_idx = (i-1) % hist->samples;
+
+ then = hist->pts[i_idx];
+ if(now - then > cfg->rc_buf_sz)
+ break;
+ sum_sz += hist->sz[i_idx];
+ }
+
+ if (now == then)
+ return;
+
+ avg_bitrate = sum_sz * 8 * 1000 / (now - then);
+ idx = avg_bitrate * (RATE_BINS/2) / (cfg->rc_target_bitrate * 1000);
+ if(idx < 0)
+ idx = 0;
+ if(idx > RATE_BINS-1)
+ idx = RATE_BINS-1;
+ if(hist->bucket[idx].low > avg_bitrate)
+ hist->bucket[idx].low = avg_bitrate;
+ if(hist->bucket[idx].high < avg_bitrate)
+ hist->bucket[idx].high = avg_bitrate;
+ hist->bucket[idx].count++;
+ hist->total++;
+}
+
+
+static void show_rate_histogram(struct rate_hist *hist,
+ const vpx_codec_enc_cfg_t *cfg,
+ int max_buckets)
+{
+ int i, scale;
+ int buckets = 0;
+
+ for(i = 0; i < RATE_BINS; i++)
+ {
+ if(hist->bucket[i].low == INT_MAX)
+ continue;
+ hist->bucket[buckets++] = hist->bucket[i];
+ }
+
+ fprintf(stderr, "\nRate (over %dms window):\n", cfg->rc_buf_sz);
+ scale = merge_hist_buckets(hist->bucket, &buckets, max_buckets);
+ show_histogram(hist->bucket, buckets, hist->total, scale);
+}
+
#define ARG_CTRL_CNT_MAX 10
int main(int argc, const char **argv_)
double psnr_totals[4] = {0, 0, 0, 0};
int psnr_count = 0;
stereo_format_t stereo_fmt = STEREO_FORMAT_MONO;
+ int counts[64]={0};
+ int show_q_hist_buckets=0;
+ int show_rate_hist_buckets=0;
+ struct rate_hist rate_hist={0};
exec_name = argv_[0];
ebml.last_pts_ms = -1;
out_fn = arg.val;
else if (arg_match(&arg, &debugmode, argi))
ebml.debug = 1;
+ else if (arg_match(&arg, &q_hist_n, argi))
+ show_q_hist_buckets = arg_parse_uint(&arg);
+ else if (arg_match(&arg, &rate_hist_n, argi))
+ show_rate_hist_buckets = arg_parse_uint(&arg);
else
argj++;
}
else
vpx_img_alloc(&raw, arg_use_i420 ? VPX_IMG_FMT_I420 : VPX_IMG_FMT_YV12,
cfg.g_w, cfg.g_h, 1);
+
+ init_rate_histogram(&rate_hist, &cfg, &arg_framerate);
}
outfile = strcmp(out_fn, "-") ? fopen(out_fn, "wb")
vpx_usec_timer_mark(&timer);
cx_time += vpx_usec_timer_elapsed(&timer);
ctx_exit_on_error(&encoder, "Failed to encode frame");
+
+ if(cfg.g_pass != VPX_RC_FIRST_PASS)
+ {
+ int q;
+
+ vpx_codec_control(&encoder, VP8E_GET_LAST_QUANTIZER_64, &q);
+ ctx_exit_on_error(&encoder, "Failed to read quantizer");
+ counts[q]++;
+ }
+
got_data = 0;
while ((pkt = vpx_codec_get_cx_data(&encoder, &iter)))
fprintf(stderr, " %6luF",
(unsigned long)pkt->data.frame.sz);
+ update_rate_histogram(&rate_hist, &cfg, pkt);
if(write_webm)
{
/* Update the hash */
vpx_codec_destroy(&encoder);
fclose(infile);
+ if (file_type == FILE_TYPE_Y4M)
+ y4m_input_close(&y4m);
if(write_webm)
{
write_webm_file_footer(&ebml, hash);
+ free(ebml.cue_list);
+ ebml.cue_list = NULL;
}
else
{
break;
}
+ if (show_q_hist_buckets)
+ show_q_histogram(counts, show_q_hist_buckets);
+
+ if (show_rate_hist_buckets)
+ show_rate_histogram(&rate_hist, &cfg, show_rate_hist_buckets);
+ destroy_rate_histogram(&rate_hist);
+
vpx_img_free(&raw);
free(argv);
return EXIT_SUCCESS;