Merge "vp8cx- alternate ssim function with optimizations"
diff --git a/build/make/gen_msvs_proj.sh b/build/make/gen_msvs_proj.sh
index becd958..c2ef44a 100755
--- a/build/make/gen_msvs_proj.sh
+++ b/build/make/gen_msvs_proj.sh
@@ -33,6 +33,7 @@
--proj-guid=GUID GUID to use for the project
--module-def=filename File containing export definitions (for DLLs)
--ver=version Version (7,8,9) of visual studio to generate for
+ --src-path-bare=dir Path to root of source tree
-Ipath/to/include Additional include directories
-DFLAG[=value] Preprocessor macros to define
-Lpath/to/lib Additional library search paths
@@ -191,6 +192,8 @@
;;
--lib) proj_kind="lib"
;;
+ --src-path-bare=*) src_path_bare="$optval"
+ ;;
--static-crt) use_static_runtime=true
;;
--ver=*)
@@ -335,6 +338,35 @@
case "$target" in
x86*)
case "$name" in
+ obj_int_extract)
+ tag Tool \
+ Name="VCCLCompilerTool" \
+ Optimization="0" \
+ AdditionalIncludeDirectories="$incs" \
+ PreprocessorDefinitions="WIN32;DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE" \
+ RuntimeLibrary="$debug_runtime" \
+ WarningLevel="3" \
+ Detect64BitPortabilityProblems="true" \
+ DebugInformationFormat="1" \
+ ;;
+ vpx)
+ tag Tool \
+ Name="VCPreBuildEventTool" \
+ CommandLine="call obj_int_extract.bat $src_path_bare" \
+
+ tag Tool \
+ Name="VCCLCompilerTool" \
+ Optimization="0" \
+ AdditionalIncludeDirectories="$incs" \
+ PreprocessorDefinitions="WIN32;_DEBUG;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;$defines" \
+ RuntimeLibrary="$debug_runtime" \
+ UsePrecompiledHeader="0" \
+ WarningLevel="3" \
+ DebugInformationFormat="1" \
+ Detect64BitPortabilityProblems="true" \
+
+ $uses_asm && tag Tool Name="YASM" IncludePaths="$incs" Debug="1"
+ ;;
*)
tag Tool \
Name="VCCLCompilerTool" \
@@ -358,6 +390,12 @@
case "$target" in
x86*)
case "$name" in
+ obj_int_extract)
+ tag Tool \
+ Name="VCLinkerTool" \
+ OutputFile="${name}.exe" \
+ GenerateDebugInformation="true" \
+ ;;
*)
tag Tool \
Name="VCLinkerTool" \
@@ -406,6 +444,34 @@
case "$target" in
x86*)
case "$name" in
+ obj_int_extract)
+ tag Tool \
+ Name="VCCLCompilerTool" \
+ AdditionalIncludeDirectories="$incs" \
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE" \
+ RuntimeLibrary="$release_runtime" \
+ UsePrecompiledHeader="0" \
+ WarningLevel="3" \
+ Detect64BitPortabilityProblems="true" \
+ DebugInformationFormat="0" \
+ ;;
+ vpx)
+ tag Tool \
+ Name="VCPreBuildEventTool" \
+ CommandLine="call obj_int_extract.bat $src_path_bare" \
+
+ tag Tool \
+ Name="VCCLCompilerTool" \
+ AdditionalIncludeDirectories="$incs" \
+ PreprocessorDefinitions="WIN32;NDEBUG;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;$defines" \
+ RuntimeLibrary="$release_runtime" \
+ UsePrecompiledHeader="0" \
+ WarningLevel="3" \
+ DebugInformationFormat="0" \
+ Detect64BitPortabilityProblems="true" \
+
+ $uses_asm && tag Tool Name="YASM" IncludePaths="$incs"
+ ;;
*)
tag Tool \
Name="VCCLCompilerTool" \
@@ -428,6 +494,12 @@
case "$target" in
x86*)
case "$name" in
+ obj_int_extract)
+ tag Tool \
+ Name="VCLinkerTool" \
+ OutputFile="${name}.exe" \
+ GenerateDebugInformation="true" \
+ ;;
*)
tag Tool \
Name="VCLinkerTool" \
diff --git a/build/make/obj_int_extract.c b/build/make/obj_int_extract.c
index 22c5cf2..01b3129 100644
--- a/build/make/obj_int_extract.c
+++ b/build/make/obj_int_extract.c
@@ -840,9 +840,18 @@
strtab_ptr = symtab_ptr + symtab_sz * 18;
if (nsections > 96)
- goto bail;
+ {
+ log_msg("Too many sections\n");
+ return 1;
+ }
- sectionlist = malloc(nsections * sizeof * sectionlist);
+ sectionlist = malloc(nsections * sizeof(sectionlist));
+
+ if (sectionlist == NULL)
+ {
+ log_msg("Allocating first level of section list failed\n");
+ return 1;
+ }
//log_msg("COFF: Found %u symbols in %u sections.\n", symtab_sz, nsections);
@@ -860,6 +869,12 @@
//log_msg("COFF: Parsing section %s\n",sectionname);
sectionlist[i] = malloc(strlen(sectionname) + 1);
+
+ if (sectionlist[i] == NULL)
+ {
+ log_msg("Allocating storage for %s failed\n", sectionname);
+ goto bail;
+ }
strcpy(sectionlist[i], sectionname);
if (!strcmp(sectionname, ".data")) sectionrawdata_ptr = get_le32(ptr + 20);
@@ -903,12 +918,14 @@
char name[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
strncpy(name, ptr, 8);
//log_msg("COFF: Parsing symbol %s\n",name);
+ /* +1 to avoid printing leading underscore */
printf("%-40s EQU ", name + 1);
}
else
{
//log_msg("COFF: Parsing symbol %s\n",
// buf + strtab_ptr + get_le32(ptr+4));
+ /* +1 to avoid printing leading underscore */
printf("%-40s EQU ", buf + strtab_ptr + get_le32(ptr + 4) + 1);
}
diff --git a/build/x86-msvs/obj_int_extract.bat b/build/x86-msvs/obj_int_extract.bat
new file mode 100644
index 0000000..1bb8653
--- /dev/null
+++ b/build/x86-msvs/obj_int_extract.bat
@@ -0,0 +1,15 @@
+REM Copyright (c) 2011 The WebM project authors. All Rights Reserved.
+REM
+REM Use of this source code is governed by a BSD-style license
+REM that can be found in the LICENSE file in the root of the source
+REM tree. An additional intellectual property rights grant can be found
+REM in the file PATENTS. All contributing project authors may
+REM be found in the AUTHORS file in the root of the source tree.
+echo on
+
+cl /I "./" /I "%1" /nologo /c "%1/vp8/common/asm_com_offsets.c"
+cl /I "./" /I "%1" /nologo /c "%1/vp8/decoder/asm_dec_offsets.c"
+cl /I "./" /I "%1" /nologo /c "%1/vp8/encoder/asm_enc_offsets.c"
+obj_int_extract.exe rvds "asm_com_offsets.obj" > "asm_com_offsets.asm"
+obj_int_extract.exe rvds "asm_dec_offsets.obj" > "asm_dec_offsets.asm"
+obj_int_extract.exe rvds "asm_enc_offsets.obj" > "asm_enc_offsets.asm"
diff --git a/libs.mk b/libs.mk
index 37ce0b1..350b310 100644
--- a/libs.mk
+++ b/libs.mk
@@ -9,7 +9,13 @@
##
-ASM:=$(if $(filter yes,$(CONFIG_GCC)),.asm.s,.asm)
+# ARM assembly files are written in RVCT-style. We use some make magic to
+# filter those files to allow GCC compilation
+ifeq ($(ARCH_ARM),yes)
+ ASM:=$(if $(filter yes,$(CONFIG_GCC)),.asm.s,.asm)
+else
+ ASM:=.asm
+endif
CODEC_SRCS-yes += libs.mk
@@ -126,6 +132,23 @@
ifeq ($(CONFIG_EXTERNAL_BUILD),yes)
ifeq ($(CONFIG_MSVS),yes)
+obj_int_extract.vcproj: $(SRC_PATH_BARE)/build/make/obj_int_extract.c
+ @cp $(SRC_PATH_BARE)/build/x86-msvs/obj_int_extract.bat .
+ @echo " [CREATE] $@"
+ $(SRC_PATH_BARE)/build/make/gen_msvs_proj.sh \
+ --exe \
+ --target=$(TOOLCHAIN) \
+ --name=obj_int_extract \
+ --ver=$(CONFIG_VS_VERSION) \
+ --proj-guid=E1360C65-D375-4335-8057-7ED99CC3F9B2 \
+ $(if $(CONFIG_STATIC_MSVCRT),--static-crt) \
+ --out=$@ $^ \
+ -I. \
+ -I"$(SRC_PATH_BARE)" \
+
+PROJECTS-$(BUILD_LIBVPX) += obj_int_extract.vcproj
+PROJECTS-$(BUILD_LIBVPX) += obj_int_extract.bat
+
vpx.def: $(call enabled,CODEC_EXPORTS)
@echo " [CREATE] $@"
$(SRC_PATH_BARE)/build/make/gen_msvs_def.sh\
@@ -135,15 +158,16 @@
vpx.vcproj: $(CODEC_SRCS) vpx.def
@echo " [CREATE] $@"
- $(SRC_PATH_BARE)/build/make/gen_msvs_proj.sh\
- --lib\
- --target=$(TOOLCHAIN)\
+ $(SRC_PATH_BARE)/build/make/gen_msvs_proj.sh \
+ --lib \
+ --target=$(TOOLCHAIN) \
$(if $(CONFIG_STATIC_MSVCRT),--static-crt) \
- --name=vpx\
- --proj-guid=DCE19DAF-69AC-46DB-B14A-39F0FAA5DB74\
- --module-def=vpx.def\
- --ver=$(CONFIG_VS_VERSION)\
- --out=$@ $(CFLAGS) $^\
+ --name=vpx \
+ --proj-guid=DCE19DAF-69AC-46DB-B14A-39F0FAA5DB74 \
+ --module-def=vpx.def \
+ --ver=$(CONFIG_VS_VERSION) \
+ --out=$@ $(CFLAGS) $^ \
+ --src-path-bare="$(SRC_PATH_BARE)" \
PROJECTS-$(BUILD_LIBVPX) += vpx.vcproj
@@ -207,36 +231,38 @@
#
# Add assembler dependencies for configuration and offsets
#
-$(filter %.s.o,$(OBJS-yes)): $(BUILD_PFX)vpx_config.asm
-$(filter %.asm.o,$(OBJS-yes)): $(BUILD_PFX)vpx_config.asm
+$(filter %.s.o,$(OBJS-yes)): $(BUILD_PFX)vpx_config.asm
+$(filter %$(ASM).o,$(OBJS-yes)): $(BUILD_PFX)vpx_config.asm
#
# Calculate platform- and compiler-specific offsets for hand coded assembly
#
-ifeq ($(ARCH_ARM), yes)
- asm_com_offsets.asm: obj_int_extract
- asm_com_offsets.asm: $(VP8_PREFIX)common/asm_com_offsets.c.o
+ifeq ($(CONFIG_EXTERNAL_BUILD),) # Visual Studio uses obj_int_extract.bat
+ ifeq ($(ARCH_ARM), yes)
+ asm_com_offsets.asm: obj_int_extract
+ asm_com_offsets.asm: $(VP8_PREFIX)common/asm_com_offsets.c.o
./obj_int_extract rvds $< $(ADS2GAS) > $@
- OBJS-yes += $(VP8_PREFIX)common/asm_com_offsets.c.o
- CLEAN-OBJS += asm_com_offsets.asm
- $(filter %$(ASM).o,$(OBJS-yes)): $(BUILD_PFX)asm_com_offsets.asm
+ OBJS-yes += $(VP8_PREFIX)common/asm_com_offsets.c.o
+ CLEAN-OBJS += asm_com_offsets.asm
+ $(filter %$(ASM).o,$(OBJS-yes)): $(BUILD_PFX)asm_com_offsets.asm
- ifeq ($(CONFIG_VP8_ENCODER), yes)
- asm_enc_offsets.asm: obj_int_extract
- asm_enc_offsets.asm: $(VP8_PREFIX)encoder/asm_enc_offsets.c.o
+ ifeq ($(CONFIG_VP8_ENCODER), yes)
+ asm_enc_offsets.asm: obj_int_extract
+ asm_enc_offsets.asm: $(VP8_PREFIX)encoder/asm_enc_offsets.c.o
./obj_int_extract rvds $< $(ADS2GAS) > $@
- OBJS-yes += $(VP8_PREFIX)encoder/asm_enc_offsets.c.o
- CLEAN-OBJS += asm_enc_offsets.asm
- $(filter %$(ASM).o,$(OBJS-yes)): $(BUILD_PFX)asm_enc_offsets.asm
- endif
+ OBJS-yes += $(VP8_PREFIX)encoder/asm_enc_offsets.c.o
+ CLEAN-OBJS += asm_enc_offsets.asm
+ $(filter %$(ASM).o,$(OBJS-yes)): $(BUILD_PFX)asm_enc_offsets.asm
+ endif
- ifeq ($(CONFIG_VP8_DECODER), yes)
- asm_dec_offsets.asm: obj_int_extract
- asm_dec_offsets.asm: $(VP8_PREFIX)decoder/asm_dec_offsets.c.o
+ ifeq ($(CONFIG_VP8_DECODER), yes)
+ asm_dec_offsets.asm: obj_int_extract
+ asm_dec_offsets.asm: $(VP8_PREFIX)decoder/asm_dec_offsets.c.o
./obj_int_extract rvds $< $(ADS2GAS) > $@
- OBJS-yes += $(VP8_PREFIX)decoder/asm_dec_offsets.c.o
- CLEAN-OBJS += asm_dec_offsets.asm
- $(filter %$(ASM).o,$(OBJS-yes)): $(BUILD_PFX)asm_dec_offsets.asm
+ OBJS-yes += $(VP8_PREFIX)decoder/asm_dec_offsets.c.o
+ CLEAN-OBJS += asm_dec_offsets.asm
+ $(filter %$(ASM).o,$(OBJS-yes)): $(BUILD_PFX)asm_dec_offsets.asm
+ endif
endif
endif
diff --git a/solution.mk b/solution.mk
index bef0088..782150f 100644
--- a/solution.mk
+++ b/solution.mk
@@ -13,8 +13,9 @@
@echo " [CREATE] $@"
$(SRC_PATH_BARE)/build/make/gen_msvs_sln.sh \
$(if $(filter %vpx.vcproj,$^),\
- $(foreach vcp,$(filter-out %vpx.vcproj,$^),\
+ $(foreach vcp,$(filter-out %vpx.vcproj %obj_int_extract.vcproj,$^),\
--dep=$(vcp:.vcproj=):vpx)) \
+ --dep=vpx:obj_int_extract \
--ver=$(CONFIG_VS_VERSION)\
--out=$@ $^
vpx.sln.mk: vpx.sln
diff --git a/vp8/encoder/ethreading.c b/vp8/encoder/ethreading.c
index 12d5f66..5c607a0 100644
--- a/vp8/encoder/ethreading.c
+++ b/vp8/encoder/ethreading.c
@@ -24,6 +24,35 @@
extern void vp8_build_block_offsets(MACROBLOCK *x);
extern void vp8_setup_block_ptrs(MACROBLOCK *x);
+#if CONFIG_MULTITHREAD
+
+extern void loopfilter_frame(VP8_COMP *cpi, VP8_COMMON *cm);
+
+static THREAD_FUNCTION loopfilter_thread(void *p_data)
+{
+ VP8_COMP *cpi = (VP8_COMP *)(((LPFTHREAD_DATA *)p_data)->ptr1);
+ VP8_COMMON *cm = &cpi->common;
+
+ while (1)
+ {
+ if (cpi->b_multi_threaded == 0)
+ break;
+
+ if (sem_wait(&cpi->h_event_start_lpf) == 0)
+ {
+ if (cpi->b_multi_threaded == FALSE) // we're shutting down
+ break;
+
+ loopfilter_frame(cpi, cm);
+
+ sem_post(&cpi->h_event_end_lpf);
+ }
+ }
+
+ return 0;
+}
+#endif
+
static
THREAD_FUNCTION thread_encoding_proc(void *p_data)
{
@@ -479,6 +508,15 @@
pthread_create(&cpi->h_encoding_thread[ithread], 0, thread_encoding_proc, ethd);
}
+ {
+ LPFTHREAD_DATA * lpfthd = &cpi->lpf_thread_data;
+
+ sem_init(&cpi->h_event_start_lpf, 0, 0);
+ sem_init(&cpi->h_event_end_lpf, 0, 0);
+
+ lpfthd->ptr1 = (void *)cpi;
+ pthread_create(&cpi->h_filter_thread, 0, loopfilter_thread, lpfthd);
+ }
}
}
@@ -500,9 +538,14 @@
sem_destroy(&cpi->h_event_start_encoding[i]);
}
+
+ sem_post(&cpi->h_event_start_lpf);
+ pthread_join(cpi->h_filter_thread, 0);
}
sem_destroy(&cpi->h_event_end_encoding);
+ sem_destroy(&cpi->h_event_end_lpf);
+ sem_destroy(&cpi->h_event_start_lpf);
//free thread related resources
vpx_free(cpi->h_event_start_encoding);
diff --git a/vp8/encoder/firstpass.c b/vp8/encoder/firstpass.c
index d2cc848..3030ed7 100644
--- a/vp8/encoder/firstpass.c
+++ b/vp8/encoder/firstpass.c
@@ -281,21 +281,6 @@
}
-extern size_t vp8_firstpass_stats_sz(unsigned int mb_count)
-{
- /* Calculate the size of a stats packet, which is dependent on the frame
- * resolution. The FIRSTPASS_STATS struct has a single element array,
- * motion_map, which is virtually expanded to have one element per
- * macroblock.
- */
- size_t stats_sz;
-
- stats_sz = sizeof(FIRSTPASS_STATS) + mb_count;
- stats_sz = (stats_sz + 7) & ~7;
- return stats_sz;
-}
-
-
void vp8_output_stats(const VP8_COMP *cpi,
struct vpx_codec_pkt_list *pktlist,
FIRSTPASS_STATS *stats)
@@ -303,18 +288,19 @@
struct vpx_codec_cx_pkt pkt;
pkt.kind = VPX_CODEC_STATS_PKT;
pkt.data.twopass_stats.buf = stats;
- pkt.data.twopass_stats.sz = vp8_firstpass_stats_sz(cpi->common.MBs);
+ 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.0f"
- " %12.4f\n",
+ " %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,
@@ -333,24 +319,17 @@
stats->count,
stats->duration);
fclose(fpfile);
-
-
- fpfile = fopen("fpmotionmap.stt", "a");
- if(fwrite(cpi->fp_motion_map, 1, cpi->common.MBs, fpfile));
- fclose(fpfile);
}
#endif
}
int vp8_input_stats(VP8_COMP *cpi, FIRSTPASS_STATS *fps)
{
- size_t stats_sz = vp8_firstpass_stats_sz(cpi->common.MBs);
-
if (cpi->stats_in >= cpi->stats_in_end)
return EOF;
*fps = *cpi->stats_in;
- cpi->stats_in = (void*)((char *)cpi->stats_in + stats_sz);
+ cpi->stats_in = (void*)((char *)cpi->stats_in + sizeof(FIRSTPASS_STATS));
return 1;
}
@@ -416,57 +395,9 @@
section->duration /= section->count;
}
-unsigned char *vp8_fpmm_get_pos(VP8_COMP *cpi)
-{
- return cpi->fp_motion_map_stats;
-}
-void vp8_fpmm_reset_pos(VP8_COMP *cpi, unsigned char *target_pos)
-{
- cpi->fp_motion_map_stats = target_pos;
-}
-
-void vp8_advance_fpmm(VP8_COMP *cpi, int count)
-{
- cpi->fp_motion_map_stats = (void*)((char*)cpi->fp_motion_map_stats +
- count * vp8_firstpass_stats_sz(cpi->common.MBs));
-}
-
-void vp8_input_fpmm(VP8_COMP *cpi)
-{
- unsigned char *fpmm = cpi->fp_motion_map;
- int MBs = cpi->common.MBs;
- int max_frames = cpi->active_arnr_frames;
- int i;
-
- for (i=0; i<max_frames; i++)
- {
- char *motion_map = (char*)cpi->fp_motion_map_stats
- + sizeof(FIRSTPASS_STATS);
-
- memcpy(fpmm, motion_map, MBs);
- fpmm += MBs;
- vp8_advance_fpmm(cpi, 1);
- }
-
- // Flag the use of weights in the temporal filter
- cpi->use_weighted_temporal_filter = 1;
-}
-
void vp8_init_first_pass(VP8_COMP *cpi)
{
vp8_zero_stats(cpi->total_stats);
-
-// TEMP debug code
-#ifdef OUTPUT_FPF
- {
- FILE *fpfile;
- fpfile = fopen("firstpass.stt", "w");
- fclose(fpfile);
- fpfile = fopen("fpmotionmap.stt", "wb");
- fclose(fpfile);
- }
-#endif
-
}
void vp8_end_first_pass(VP8_COMP *cpi)
@@ -583,8 +514,6 @@
MV zero_ref_mv = {0, 0};
- unsigned char *fp_motion_map_ptr = cpi->fp_motion_map;
-
vp8_clear_system_state(); //__asm emms;
x->src = * cpi->Source;
@@ -636,7 +565,6 @@
for (mb_col = 0; mb_col < cm->mb_cols; mb_col++)
{
int this_error;
- int zero_error;
int zz_to_best_ratio;
int gf_motion_error = INT_MAX;
int use_dc_pred = (mb_col || mb_row) && (!mb_col || !mb_row);
@@ -658,9 +586,6 @@
// Cumulative intra error total
intra_error += (long long)this_error;
- // Indicate default assumption of intra in the motion map
- *fp_motion_map_ptr = 0;
-
// Set up limit values for motion vectors to prevent them extending outside the UMV borders
x->mv_col_min = -((mb_col * 16) + (VP8BORDERINPIXELS - 16));
x->mv_col_max = ((cm->mb_cols - 1 - mb_col) * 16) + (VP8BORDERINPIXELS - 16);
@@ -679,9 +604,6 @@
d->bmi.mv.as_mv.row = 0;
d->bmi.mv.as_mv.col = 0;
- // Save (0,0) error for later use
- zero_error = motion_error;
-
// Test last reference frame using the previous best mv as the
// starting point (best reference) for the search
vp8_first_pass_motion_search(cpi, x, &best_ref_mv.as_mv,
@@ -796,25 +718,6 @@
else if (d->bmi.mv.as_mv.col < 0)
sum_in_vectors--;
}
-
- // Compute how close (0,0) predictor is to best
- // predictor in terms of their prediction error
- zz_to_best_ratio = (10*zero_error + this_error/2)
- / (this_error+!this_error);
-
- if ((zero_error < 50000) &&
- (zz_to_best_ratio <= 11) )
- *fp_motion_map_ptr = 1;
- else
- *fp_motion_map_ptr = 0;
- }
- else
- {
- // 0,0 mv was best
- if( zero_error<50000 )
- *fp_motion_map_ptr = 2;
- else
- *fp_motion_map_ptr = 1;
}
}
}
@@ -828,9 +731,6 @@
recon_yoffset += 16;
recon_uvoffset += 8;
-
- // Update the motion map
- fp_motion_map_ptr++;
}
// adjust to the next row of mbs
@@ -892,13 +792,10 @@
// than the full time between subsequent cpi->source_time_stamp s .
fps.duration = cpi->source_end_time_stamp - cpi->source_time_stamp;
- // don't want to do outputstats with a stack variable!
+ // don't want to do output stats with a stack variable!
memcpy(cpi->this_frame_stats,
&fps,
sizeof(FIRSTPASS_STATS));
- memcpy((char*)cpi->this_frame_stats + sizeof(FIRSTPASS_STATS),
- cpi->fp_motion_map,
- sizeof(cpi->fp_motion_map[0]) * cpi->common.MBs);
vp8_output_stats(cpi, cpi->output_pkt_list, cpi->this_frame_stats);
vp8_accumulate_stats(cpi->total_stats, &fps);
}
@@ -1351,8 +1248,6 @@
cpi->clip_bpe = cpi->bits_left /
DOUBLE_DIVIDE_CHECK(cpi->modified_error_total);
cpi->observed_bpe = cpi->clip_bpe;
-
- cpi->fp_motion_map_stats = (unsigned char *)cpi->stats_in;
}
void vp8_end_second_pass(VP8_COMP *cpi)
@@ -1360,7 +1255,7 @@
}
// This function gives and estimate of how badly we believe
-// the predicition quality is decaying from frame to frame.
+// the prediction quality is decaying from frame to frame.
double get_prediction_decay_rate(VP8_COMP *cpi, FIRSTPASS_STATS *next_frame)
{
double prediction_decay_rate;
@@ -1472,8 +1367,6 @@
int max_bits = frame_max_bits(cpi); // Max for a single frame
- unsigned char *fpmm_pos;
-
unsigned int allow_alt_ref =
cpi->oxcf.play_alternate && cpi->oxcf.lag_in_frames;
@@ -1482,8 +1375,6 @@
vp8_clear_system_state(); //__asm emms;
- fpmm_pos = vp8_fpmm_get_pos(cpi);
-
start_pos = cpi->stats_in;
vpx_memset(&next_frame, 0, sizeof(next_frame)); // assure clean
@@ -1780,20 +1671,6 @@
}
cpi->active_arnr_frames = frames_bwd + 1 + frames_fwd;
-
- {
- // Advance to & read in the motion map for those frames
- // to be considered for filtering based on the position
- // of the ARF
- vp8_fpmm_reset_pos(cpi, cpi->fp_motion_map_stats_save);
-
- // Position at the 'earliest' frame to be filtered
- vp8_advance_fpmm(cpi,
- cpi->baseline_gf_interval - frames_bwd);
-
- // Read / create a motion map for the region of interest
- vp8_input_fpmm(cpi);
- }
}
else
{
@@ -2023,9 +1900,6 @@
reset_fpf_position(cpi, start_pos);
}
-
- // Reset the First pass motion map file position
- vp8_fpmm_reset_pos(cpi, fpmm_pos);
}
// Allocate bits to a normal frame that is neither a gf an arf or a key frame.
@@ -2107,13 +1981,6 @@
if (EOF == vp8_input_stats(cpi, &this_frame))
return;
- vpx_memset(cpi->fp_motion_map, 0,
- cpi->oxcf.arnr_max_frames*cpi->common.MBs);
- cpi->fp_motion_map_stats_save = vp8_fpmm_get_pos(cpi);
-
- // Step over this frame's first pass motion map
- vp8_advance_fpmm(cpi, 1);
-
this_frame_error = this_frame.ssim_weighted_pred_err;
this_frame_intra_error = this_frame.intra_error;
this_frame_coded_error = this_frame.coded_error;
diff --git a/vp8/encoder/onyx_if.c b/vp8/encoder/onyx_if.c
index 5caaeb9..25e9149 100644
--- a/vp8/encoder/onyx_if.c
+++ b/vp8/encoder/onyx_if.c
@@ -283,12 +283,6 @@
vpx_free(cpi->active_map);
cpi->active_map = 0;
-#if !(CONFIG_REALTIME_ONLY)
- // Delete first pass motion map
- vpx_free(cpi->fp_motion_map);
- cpi->fp_motion_map = 0;
-#endif
-
vp8_de_alloc_frame_buffers(&cpi->common);
vp8_yv12_de_alloc_frame_buffer(&cpi->last_frame_uf);
@@ -1362,11 +1356,11 @@
#if !(CONFIG_REALTIME_ONLY)
vpx_free(cpi->total_stats);
- cpi->total_stats = vpx_calloc(1, vp8_firstpass_stats_sz(cpi->common.MBs));
+ cpi->total_stats = vpx_calloc(1, sizeof(FIRSTPASS_STATS));
vpx_free(cpi->this_frame_stats);
- cpi->this_frame_stats = vpx_calloc(1, vp8_firstpass_stats_sz(cpi->common.MBs));
+ cpi->this_frame_stats = vpx_calloc(1, sizeof(FIRSTPASS_STATS));
if(!cpi->total_stats || !cpi->this_frame_stats)
vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR,
@@ -1545,8 +1539,6 @@
#if VP8_TEMPORAL_ALT_REF
- cpi->use_weighted_temporal_filter = 0;
-
{
int i;
@@ -1929,12 +1921,6 @@
vpx_memset(cpi->active_map , 1, (cpi->common.mb_rows * cpi->common.mb_cols));
cpi->active_map_enabled = 0;
-#if !(CONFIG_REALTIME_ONLY)
- // Create the first pass motion map structure and set to 0
- // Allocate space for maximum of 15 buffers
- CHECK_MEM_ERROR(cpi->fp_motion_map, vpx_calloc(15*cpi->common.MBs, 1));
-#endif
-
#if 0
// Experimental code for lagged and one pass
// Initialise one_pass GF frames stats
@@ -2084,7 +2070,7 @@
}
else if (cpi->pass == 2)
{
- size_t packet_sz = vp8_firstpass_stats_sz(cpi->common.MBs);
+ size_t packet_sz = sizeof(FIRSTPASS_STATS);
int packets = oxcf->two_pass_stats_in.sz / packet_sz;
cpi->stats_in = oxcf->two_pass_stats_in.buf;
@@ -3285,6 +3271,89 @@
return force_recode;
}
+void loopfilter_frame(VP8_COMP *cpi, VP8_COMMON *cm)
+{
+ if (cm->no_lpf)
+ {
+ cm->filter_level = 0;
+ }
+ else
+ {
+ struct vpx_usec_timer timer;
+
+ vp8_clear_system_state();
+
+ vpx_usec_timer_start(&timer);
+ if (cpi->sf.auto_filter == 0)
+ vp8cx_pick_filter_level_fast(cpi->Source, cpi);
+
+ else
+ vp8cx_pick_filter_level(cpi->Source, cpi);
+
+ vpx_usec_timer_mark(&timer);
+ cpi->time_pick_lpf += vpx_usec_timer_elapsed(&timer);
+ }
+
+#if CONFIG_MULTITHREAD
+ sem_post(&cpi->h_event_end_lpf); /* signal that we have set filter_level */
+#endif
+
+ if (cm->filter_level > 0)
+ {
+ vp8cx_set_alt_lf_level(cpi, cm->filter_level);
+ vp8_loop_filter_frame(cm, &cpi->mb.e_mbd, cm->filter_level);
+ cm->last_filter_type = cm->filter_type;
+ cm->last_sharpness_level = cm->sharpness_level;
+ }
+
+ vp8_yv12_extend_frame_borders_ptr(cm->frame_to_show);
+
+ {
+ YV12_BUFFER_CONFIG *lst_yv12 = &cm->yv12_fb[cm->lst_fb_idx];
+ YV12_BUFFER_CONFIG *new_yv12 = &cm->yv12_fb[cm->new_fb_idx];
+ YV12_BUFFER_CONFIG *gld_yv12 = &cm->yv12_fb[cm->gld_fb_idx];
+ YV12_BUFFER_CONFIG *alt_yv12 = &cm->yv12_fb[cm->alt_fb_idx];
+ // At this point the new frame has been encoded.
+ // If any buffer copy / swapping is signaled it should be done here.
+ if (cm->frame_type == KEY_FRAME)
+ {
+ vp8_yv12_copy_frame_ptr(cm->frame_to_show, gld_yv12);
+ vp8_yv12_copy_frame_ptr(cm->frame_to_show, alt_yv12);
+ }
+ else // For non key frames
+ {
+ // Code to copy between reference buffers
+ if (cm->copy_buffer_to_arf)
+ {
+ if (cm->copy_buffer_to_arf == 1)
+ {
+ if (cm->refresh_last_frame)
+ // We copy new_frame here because last and new buffers will already have been swapped if cm->refresh_last_frame is set.
+ vp8_yv12_copy_frame_ptr(new_yv12, alt_yv12);
+ else
+ vp8_yv12_copy_frame_ptr(lst_yv12, alt_yv12);
+ }
+ else if (cm->copy_buffer_to_arf == 2)
+ vp8_yv12_copy_frame_ptr(gld_yv12, alt_yv12);
+ }
+
+ if (cm->copy_buffer_to_gf)
+ {
+ if (cm->copy_buffer_to_gf == 1)
+ {
+ if (cm->refresh_last_frame)
+ // We copy new_frame here because last and new buffers will already have been swapped if cm->refresh_last_frame is set.
+ vp8_yv12_copy_frame_ptr(new_yv12, gld_yv12);
+ else
+ vp8_yv12_copy_frame_ptr(lst_yv12, gld_yv12);
+ }
+ else if (cm->copy_buffer_to_gf == 2)
+ vp8_yv12_copy_frame_ptr(alt_yv12, gld_yv12);
+ }
+ }
+ }
+}
+
static void encode_frame_to_data_rate
(
VP8_COMP *cpi,
@@ -3835,8 +3904,8 @@
vp8_setup_key_frame(cpi);
// transform / motion compensation build reconstruction frame
-
vp8_encode_frame(cpi);
+
cpi->projected_frame_size -= vp8_estimate_entropy_savings(cpi);
cpi->projected_frame_size = (cpi->projected_frame_size > 0) ? cpi->projected_frame_size : 0;
@@ -4185,92 +4254,43 @@
else
cm->frame_to_show = &cm->yv12_fb[cm->new_fb_idx];
- if (cm->no_lpf)
+
+#if CONFIG_MULTITHREAD
+ if (cpi->b_multi_threaded)
{
- cm->filter_level = 0;
+ sem_post(&cpi->h_event_start_lpf); /* start loopfilter in separate thread */
}
else
+#endif
{
- struct vpx_usec_timer timer;
-
- vpx_usec_timer_start(&timer);
-
- if (cpi->sf.auto_filter == 0)
- vp8cx_pick_filter_level_fast(cpi->Source, cpi);
- else
- vp8cx_pick_filter_level(cpi->Source, cpi);
-
- vpx_usec_timer_mark(&timer);
-
- cpi->time_pick_lpf += vpx_usec_timer_elapsed(&timer);
+ loopfilter_frame(cpi, cm);
}
- if (cm->filter_level > 0)
- {
- vp8cx_set_alt_lf_level(cpi, cm->filter_level);
- vp8_loop_filter_frame(cm, &cpi->mb.e_mbd, cm->filter_level);
- cm->last_filter_type = cm->filter_type;
- cm->last_sharpness_level = cm->sharpness_level;
- }
-
- /* Move storing frame_type out of the above loop since it is also
- * needed in motion search besides loopfilter */
- cm->last_frame_type = cm->frame_type;
-
- vp8_yv12_extend_frame_borders_ptr(cm->frame_to_show);
-
if (cpi->oxcf.error_resilient_mode == 1)
{
cm->refresh_entropy_probs = 0;
}
+#if CONFIG_MULTITHREAD
+ /* wait that filter_level is picked so that we can continue with stream packing */
+ if (cpi->b_multi_threaded)
+ sem_wait(&cpi->h_event_end_lpf);
+#endif
+
// build the bitstream
vp8_pack_bitstream(cpi, dest, size);
+#if CONFIG_MULTITHREAD
+ /* wait for loopfilter thread done */
+ if (cpi->b_multi_threaded)
{
- YV12_BUFFER_CONFIG *lst_yv12 = &cm->yv12_fb[cm->lst_fb_idx];
- YV12_BUFFER_CONFIG *new_yv12 = &cm->yv12_fb[cm->new_fb_idx];
- YV12_BUFFER_CONFIG *gld_yv12 = &cm->yv12_fb[cm->gld_fb_idx];
- YV12_BUFFER_CONFIG *alt_yv12 = &cm->yv12_fb[cm->alt_fb_idx];
- // At this point the new frame has been encoded coded.
- // If any buffer copy / swaping is signalled it should be done here.
- if (cm->frame_type == KEY_FRAME)
- {
- vp8_yv12_copy_frame_ptr(cm->frame_to_show, gld_yv12);
- vp8_yv12_copy_frame_ptr(cm->frame_to_show, alt_yv12);
- }
- else // For non key frames
- {
- // Code to copy between reference buffers
- if (cm->copy_buffer_to_arf)
- {
- if (cm->copy_buffer_to_arf == 1)
- {
- if (cm->refresh_last_frame)
- // We copy new_frame here because last and new buffers will already have been swapped if cm->refresh_last_frame is set.
- vp8_yv12_copy_frame_ptr(new_yv12, alt_yv12);
- else
- vp8_yv12_copy_frame_ptr(lst_yv12, alt_yv12);
- }
- else if (cm->copy_buffer_to_arf == 2)
- vp8_yv12_copy_frame_ptr(gld_yv12, alt_yv12);
- }
-
- if (cm->copy_buffer_to_gf)
- {
- if (cm->copy_buffer_to_gf == 1)
- {
- if (cm->refresh_last_frame)
- // We copy new_frame here because last and new buffers will already have been swapped if cm->refresh_last_frame is set.
- vp8_yv12_copy_frame_ptr(new_yv12, gld_yv12);
- else
- vp8_yv12_copy_frame_ptr(lst_yv12, gld_yv12);
- }
- else if (cm->copy_buffer_to_gf == 2)
- vp8_yv12_copy_frame_ptr(alt_yv12, gld_yv12);
- }
- }
+ sem_wait(&cpi->h_event_end_lpf);
}
+#endif
+
+ /* Move storing frame_type out of the above loop since it is also
+ * needed in motion search besides loopfilter */
+ cm->last_frame_type = cm->frame_type;
// Update rate control heuristics
cpi->total_byte_count += (*size);
@@ -5105,7 +5125,9 @@
cpi->time_compress_data += vpx_usec_timer_elapsed(&cmptimer);
if (cpi->b_calculate_psnr && cpi->pass != 1 && cm->show_frame)
+ {
generate_psnr_packet(cpi);
+ }
#if CONFIG_PSNR
diff --git a/vp8/encoder/onyx_int.h b/vp8/encoder/onyx_int.h
index 6d0cbd9..0e53f68 100644
--- a/vp8/encoder/onyx_int.h
+++ b/vp8/encoder/onyx_int.h
@@ -496,11 +496,6 @@
struct vpx_codec_pkt_list *output_pkt_list;
int first_pass_done;
-#if !(CONFIG_REALTIME_ONLY)
- unsigned char *fp_motion_map;
- unsigned char *fp_motion_map_stats, *fp_motion_map_stats_save;
-#endif
-
#if 0
// Experimental code for lagged and one pass
ONEPASS_FRAMESTATS one_pass_frame_stats[MAX_LAG_BUFFERS];
@@ -604,12 +599,17 @@
int encoding_thread_count;
pthread_t *h_encoding_thread;
+ pthread_t h_filter_thread;
+
MB_ROW_COMP *mb_row_ei;
ENCODETHREAD_DATA *en_thread_data;
+ LPFTHREAD_DATA lpf_thread_data;
//events
sem_t *h_event_start_encoding;
sem_t h_event_end_encoding;
+ sem_t h_event_start_lpf;
+ sem_t h_event_end_lpf;
#endif
TOKENLIST *tplist;
@@ -642,8 +642,6 @@
YV12_BUFFER_CONFIG *frames[MAX_LAG_BUFFERS];
int fixed_divide[512];
#endif
- // Flag to indicate temporal filter method
- int use_weighted_temporal_filter;
#if CONFIG_PSNR
int count;
diff --git a/vp8/encoder/temporal_filter.c b/vp8/encoder/temporal_filter.c
index 0f8e654..fd36b22 100644
--- a/vp8/encoder/temporal_filter.c
+++ b/vp8/encoder/temporal_filter.c
@@ -287,8 +287,7 @@
int byte;
int frame;
int mb_col, mb_row;
- unsigned int filter_weight[MAX_LAG_BUFFERS];
- unsigned char *mm_ptr = cpi->fp_motion_map;
+ unsigned int filter_weight;
int mb_cols = cpi->common.mb_cols;
int mb_rows = cpi->common.mb_rows;
int MBs = cpi->common.MBs;
@@ -306,13 +305,6 @@
unsigned char *u_buffer = mbd->pre.u_buffer;
unsigned char *v_buffer = mbd->pre.v_buffer;
- if (!cpi->use_weighted_temporal_filter)
- {
- // Temporal filtering is unweighted
- for (frame = 0; frame < frame_count; frame++)
- filter_weight[frame] = 1;
- }
-
for (mb_row = 0; mb_row < mb_rows; mb_row++)
{
#if ALT_REF_MC_ENABLED
@@ -338,34 +330,9 @@
+ (VP8BORDERINPIXELS - 19);
#endif
- // Read & process macroblock weights from motion map
- if (cpi->use_weighted_temporal_filter)
- {
- weight_cap = 2;
-
- for (frame = alt_ref_index-1; frame >= 0; frame--)
- {
- w = *(mm_ptr + (frame+1)*MBs);
- filter_weight[frame] = w < weight_cap ? w : weight_cap;
- weight_cap = w;
- }
-
- filter_weight[alt_ref_index] = 2;
-
- weight_cap = 2;
-
- for (frame = alt_ref_index+1; frame < frame_count; frame++)
- {
- w = *(mm_ptr + frame*MBs);
- filter_weight[frame] = w < weight_cap ? w : weight_cap;
- weight_cap = w;
- }
-
- }
-
for (frame = 0; frame < frame_count; frame++)
{
- int err;
+ int err = 0;
if (cpi->frames[frame] == NULL)
continue;
@@ -374,28 +341,25 @@
mbd->block[0].bmi.mv.as_mv.col = 0;
#if ALT_REF_MC_ENABLED
- //if (filter_weight[frame] == 0)
- {
#define THRESH_LOW 10000
#define THRESH_HIGH 20000
- // Correlation has been lost try MC
- err = vp8_temporal_filter_find_matching_mb_c
- (cpi,
- cpi->frames[alt_ref_index],
- cpi->frames[frame],
- mb_y_offset,
- THRESH_LOW);
+ // Find best match in this frame by MC
+ err = vp8_temporal_filter_find_matching_mb_c
+ (cpi,
+ cpi->frames[alt_ref_index],
+ cpi->frames[frame],
+ mb_y_offset,
+ THRESH_LOW);
- if (filter_weight[frame] < 2)
- {
- // Set weight depending on error
- filter_weight[frame] = err<THRESH_LOW
- ? 2 : err<THRESH_HIGH ? 1 : 0;
- }
- }
#endif
- if (filter_weight[frame] != 0)
+ // Assign higher weight to matching MB if it's error
+ // score is lower. If not applying MC default behavior
+ // is to weight all MBs equal.
+ filter_weight = err<THRESH_LOW
+ ? 2 : err<THRESH_HIGH ? 1 : 0;
+
+ if (filter_weight != 0)
{
// Construct the predictors
vp8_temporal_filter_predictors_mb_c
@@ -415,7 +379,7 @@
predictor,
16,
strength,
- filter_weight[frame],
+ filter_weight,
accumulator,
count);
@@ -425,7 +389,7 @@
predictor + 256,
8,
strength,
- filter_weight[frame],
+ filter_weight,
accumulator + 256,
count + 256);
@@ -435,7 +399,7 @@
predictor + 320,
8,
strength,
- filter_weight[frame],
+ filter_weight,
accumulator + 320,
count + 320);
}
@@ -491,7 +455,6 @@
byte += stride - 8;
}
- mm_ptr++;
mb_y_offset += 16;
mb_uv_offset += 8;
}
diff --git a/vp8/vp8_cx_iface.c b/vp8/vp8_cx_iface.c
index a45a379..2622738 100644
--- a/vp8/vp8_cx_iface.c
+++ b/vp8/vp8_cx_iface.c
@@ -199,7 +199,7 @@
{
int mb_r = (cfg->g_h + 15) / 16;
int mb_c = (cfg->g_w + 15) / 16;
- size_t packet_sz = vp8_firstpass_stats_sz(mb_r * mb_c);
+ size_t packet_sz = sizeof(FIRSTPASS_STATS);
int n_packets = cfg->rc_twopass_stats_in.sz / packet_sz;
FIRSTPASS_STATS *stats;