Merge "Cleaning up vp9_dthread.{c, h}."diff --git a/build/make/Makefile b/build/make/Makefile
index dd7fb4a..0c5ff64 100644
--- a/build/make/Makefile
+++ b/build/make/Makefile
@@ -147,6 +147,15 @@
$(if $(quiet),@echo " [CXX] $@")
$(qexec)$(CXX) $(INTERNAL_CFLAGS) $(CXXFLAGS) -c -o $@ $<
+$(BUILD_PFX)%.cpp.d: %.cpp
+ $(if $(quiet),@echo " [DEP] $@")
+ $(qexec)mkdir -p $(dir $@)
+ $(qexec)$(CXX) $(INTERNAL_CFLAGS) $(CXXFLAGS) -M $< | $(fmt_deps) > $@
+
+$(BUILD_PFX)%.cpp.o: %.cpp
+ $(if $(quiet),@echo " [CXX] $@")
+ $(qexec)$(CXX) $(INTERNAL_CFLAGS) $(CXXFLAGS) -c -o $@ $<
+
$(BUILD_PFX)%.asm.d: %.asm
$(if $(quiet),@echo " [DEP] $@")
$(qexec)mkdir -p $(dir $@)
@@ -218,7 +227,7 @@
find_file1=$(word 1,$(wildcard $(subst //,/,$(addsuffix /$(1),$(2)))))
find_file=$(foreach f,$(1),$(call find_file1,$(strip $(f)),$(strip $(2))) )
-obj_pats=.c=.c.o $(AS_SFX)=$(AS_SFX).o .cc=.cc.o
+obj_pats=.c=.c.o $(AS_SFX)=$(AS_SFX).o .cc=.cc.o .cpp=.cpp.o
objs=$(addprefix $(BUILD_PFX),$(foreach p,$(obj_pats),$(filter %.o,$(1:$(p))) ))
install_map_templates=$(eval $(call install_map_template,$(1),$(2)))
diff --git a/configure b/configure
index ff350cc..01c421d 100755
--- a/configure
+++ b/configure
@@ -704,13 +704,11 @@
enabled postproc || die "postproc_visualizer requires postproc to be enabled"
fi
- # Enable WebM IO by default.
- soft_enable webm_io
-
# Enable unit tests by default if we have a working C++ compiler.
case "$toolchain" in
*-vs*)
soft_enable unit_tests
+ soft_enable webm_io
;;
*-android-*)
# GTestLog must be modified to use Android logging utilities.
@@ -726,13 +724,21 @@
check_cxx "$@" <<EOF && soft_enable unit_tests
int z;
EOF
+ check_cxx "$@" <<EOF && soft_enable webm_io
+int z;
+EOF
;;
*)
enabled pthread_h && check_cxx "$@" <<EOF && soft_enable unit_tests
int z;
EOF
+ check_cxx "$@" <<EOF && soft_enable webm_io
+int z;
+EOF
;;
esac
+ # libwebm needs to be linked with C++ standard library
+ enabled webm_io && LD=${CXX}
}
diff --git a/examples.mk b/examples.mk
index fa5d66c..91b9801 100644
--- a/examples.mk
+++ b/examples.mk
@@ -15,6 +15,16 @@
third_party/libyuv/source/scale.c \
third_party/libyuv/source/cpu_id.c
+LIBWEBM_MUXER_SRCS += third_party/libwebm/mkvmuxer.cpp \
+ third_party/libwebm/mkvmuxerutil.cpp \
+ third_party/libwebm/mkvwriter.cpp \
+ third_party/libwebm/mkvmuxer.hpp \
+ third_party/libwebm/mkvmuxertypes.hpp \
+ third_party/libwebm/mkvmuxerutil.hpp \
+ third_party/libwebm/mkvparser.hpp \
+ third_party/libwebm/mkvwriter.hpp \
+ third_party/libwebm/webmids.hpp
+
# List of examples to build. UTILS are tools meant for distribution
# while EXAMPLES demonstrate specific portions of the API.
UTILS-$(CONFIG_DECODERS) += vpxdec.c
@@ -53,10 +63,8 @@
vpxenc.SRCS += vpxstats.c vpxstats.h
vpxenc.SRCS += $(LIBYUV_SRCS)
ifeq ($(CONFIG_WEBM_IO),yes)
- vpxenc.SRCS += third_party/libmkv/EbmlIDs.h
- vpxenc.SRCS += third_party/libmkv/EbmlWriter.c
- vpxenc.SRCS += third_party/libmkv/EbmlWriter.h
- vpxenc.SRCS += webmenc.c webmenc.h
+ vpxenc.SRCS += $(LIBWEBM_MUXER_SRCS)
+ vpxenc.SRCS += webmenc.cc webmenc.h
endif
vpxenc.GUID = 548DEC74-7A15-4B2B-AFC3-AA102E7C25C1
vpxenc.DESCRIPTION = Full featured encoder
diff --git a/examples/vpx_temporal_scalable_patterns.c b/examples/vpx_temporal_scalable_patterns.c
index 5cb4ee9..07dd318 100644
--- a/examples/vpx_temporal_scalable_patterns.c
+++ b/examples/vpx_temporal_scalable_patterns.c
@@ -526,7 +526,7 @@
// Enable error resilient mode.
cfg.g_error_resilient = 1;
cfg.g_lag_in_frames = 0;
- cfg.kf_mode = VPX_KF_DISABLED;
+ cfg.kf_mode = VPX_KF_AUTO;
// Disable automatic keyframe placement.
cfg.kf_min_dist = cfg.kf_max_dist = 3000;
diff --git a/vp8/encoder/onyx_if.c b/vp8/encoder/onyx_if.c
index ef37c0e..32c5997 100644
--- a/vp8/encoder/onyx_if.c
+++ b/vp8/encoder/onyx_if.c
@@ -1761,8 +1761,11 @@
}
+#ifndef M_LOG2_E
#define M_LOG2_E 0.693147180559945309417
+#endif
#define log2f(x) (log (x) / (float) M_LOG2_E)
+
static void cal_mvsadcosts(int *mvsadcost[2])
{
int i = 1;
diff --git a/vp9/common/vp9_mvref_common.c b/vp9/common/vp9_mvref_common.c
index 1aab362..61682c4 100644
--- a/vp9/common/vp9_mvref_common.c
+++ b/vp9/common/vp9_mvref_common.c
@@ -195,7 +195,7 @@
int block, int mi_row, int mi_col) {
const int *ref_sign_bias = cm->ref_frame_sign_bias;
int i, refmv_count = 0;
- const MODE_INFO *prev_mi = cm->prev_mi
+ const MODE_INFO *prev_mi = cm->coding_use_prev_mi && cm->prev_mi
? cm->prev_mi_grid_visible[mi_row * xd->mi_stride + mi_col]
: NULL;
const MB_MODE_INFO *const prev_mbmi = prev_mi ? &prev_mi->mbmi : NULL;
diff --git a/vp9/common/vp9_onyxc_int.h b/vp9/common/vp9_onyxc_int.h
index fe9cc9e..77f563f 100644
--- a/vp9/common/vp9_onyxc_int.h
+++ b/vp9/common/vp9_onyxc_int.h
@@ -284,15 +284,15 @@
xd->left_available = (mi_col > tile->mi_col_start);
}
-static INLINE MODE_INFO *get_prev_mi(VP9_COMMON *cm) {
- const int use_prev_mi = cm->coding_use_prev_mi &&
- cm->width == cm->last_width &&
- cm->height == cm->last_height &&
- !cm->intra_only &&
- cm->last_show_frame;
+static INLINE void set_prev_mi(VP9_COMMON *cm) {
+ const int use_prev_in_find_mv_refs = cm->width == cm->last_width &&
+ cm->height == cm->last_height &&
+ !cm->intra_only &&
+ cm->last_show_frame;
// Special case: set prev_mi to NULL when the previous mode info
// context cannot be used.
- return use_prev_mi ? &cm->prev_mip[cm->mi_stride + 1] : NULL;
+ cm->prev_mi = use_prev_in_find_mv_refs ?
+ cm->prev_mip + cm->mi_stride + 1 : NULL;
}
static INLINE int frame_is_intra_only(const VP9_COMMON *const cm) {
diff --git a/vp9/common/x86/vp9_copy_sse2.asm b/vp9/common/x86/vp9_copy_sse2.asm
index dd522c6..b263837 100644
--- a/vp9/common/x86/vp9_copy_sse2.asm
+++ b/vp9/common/x86/vp9_copy_sse2.asm
@@ -133,10 +133,14 @@
movh m3, [srcq+r5q]
lea srcq, [srcq+src_strideq*4]
%ifidn %1, avg
- pavgb m0, [dstq]
- pavgb m1, [dstq+dst_strideq]
- pavgb m2, [dstq+dst_strideq*2]
- pavgb m3, [dstq+r6q]
+ movh m4, [dstq]
+ movh m5, [dstq+dst_strideq]
+ movh m6, [dstq+dst_strideq*2]
+ movh m7, [dstq+r6q]
+ pavgb m0, m4
+ pavgb m1, m5
+ pavgb m2, m6
+ pavgb m3, m7
%endif
movh [dstq ], m0
movh [dstq+dst_strideq ], m1
diff --git a/vp9/decoder/vp9_decodeframe.c b/vp9/decoder/vp9_decodeframe.c
index 9b63961..022a429 100644
--- a/vp9/decoder/vp9_decodeframe.c
+++ b/vp9/decoder/vp9_decodeframe.c
@@ -1296,7 +1296,11 @@
}
init_macroblockd(cm, &pbi->mb);
- cm->prev_mi = get_prev_mi(cm);
+
+ if (cm->coding_use_prev_mi)
+ set_prev_mi(cm);
+ else
+ cm->prev_mi = NULL;
setup_plane_dequants(cm, xd, cm->base_qindex);
vp9_setup_block_planes(xd, cm->subsampling_x, cm->subsampling_y);
diff --git a/vp9/encoder/vp9_encodeframe.c b/vp9/encoder/vp9_encodeframe.c
index 61a5022..34ea88c 100644
--- a/vp9/encoder/vp9_encodeframe.c
+++ b/vp9/encoder/vp9_encodeframe.c
@@ -103,34 +103,31 @@
};
static unsigned int get_sby_perpixel_variance(VP9_COMP *cpi,
- MACROBLOCK *x,
+ const struct buf_2d *ref,
BLOCK_SIZE bs) {
- unsigned int var, sse;
- var = cpi->fn_ptr[bs].vf(x->plane[0].src.buf, x->plane[0].src.stride,
- VP9_VAR_OFFS, 0, &sse);
+ unsigned int sse;
+ const unsigned int var = cpi->fn_ptr[bs].vf(ref->buf, ref->stride,
+ VP9_VAR_OFFS, 0, &sse);
return ROUND_POWER_OF_TWO(var, num_pels_log2_lookup[bs]);
}
static unsigned int get_sby_perpixel_diff_variance(VP9_COMP *cpi,
- MACROBLOCK *x,
- int mi_row,
- int mi_col,
+ const struct buf_2d *ref,
+ int mi_row, int mi_col,
BLOCK_SIZE bs) {
- const YV12_BUFFER_CONFIG *yv12 = get_ref_frame_buffer(cpi, LAST_FRAME);
- int offset = (mi_row * MI_SIZE) * yv12->y_stride + (mi_col * MI_SIZE);
- unsigned int var, sse;
- var = cpi->fn_ptr[bs].vf(x->plane[0].src.buf,
- x->plane[0].src.stride,
- yv12->y_buffer + offset,
- yv12->y_stride,
- &sse);
+ const YV12_BUFFER_CONFIG *last = get_ref_frame_buffer(cpi, LAST_FRAME);
+ const uint8_t* last_y = &last->y_buffer[mi_row * MI_SIZE * last->y_stride +
+ mi_col * MI_SIZE];
+ unsigned int sse;
+ const unsigned int var = cpi->fn_ptr[bs].vf(ref->buf, ref->stride,
+ last_y, last->y_stride, &sse);
return ROUND_POWER_OF_TWO(var, num_pels_log2_lookup[bs]);
}
static BLOCK_SIZE get_rd_var_based_fixed_partition(VP9_COMP *cpi,
int mi_row,
int mi_col) {
- unsigned int var = get_sby_perpixel_diff_variance(cpi, &cpi->mb,
+ unsigned int var = get_sby_perpixel_diff_variance(cpi, &cpi->mb.plane[0].src,
mi_row, mi_col,
BLOCK_64X64);
if (var < 8)
@@ -146,7 +143,7 @@
static BLOCK_SIZE get_nonrd_var_based_fixed_partition(VP9_COMP *cpi,
int mi_row,
int mi_col) {
- unsigned int var = get_sby_perpixel_diff_variance(cpi, &cpi->mb,
+ unsigned int var = get_sby_perpixel_diff_variance(cpi, &cpi->mb.plane[0].src,
mi_row, mi_col,
BLOCK_64X64);
if (var < 4)
@@ -1013,12 +1010,16 @@
// Set to zero to make sure we do not use the previous encoded frame stats
mbmi->skip = 0;
- x->source_variance = get_sby_perpixel_variance(cpi, x, bsize);
+ x->source_variance = get_sby_perpixel_variance(cpi, &x->plane[0].src, bsize);
+
+ // Save rdmult before it might be changed, so it can be restored later.
+ orig_rdmult = x->rdmult;
+ if (cpi->oxcf.tuning == VP8_TUNE_SSIM)
+ activity_masking(cpi, x);
if (aq_mode == VARIANCE_AQ) {
const int energy = bsize <= BLOCK_16X16 ? x->mb_energy
: vp9_block_energy(cpi, x, bsize);
-
if (cm->frame_type == KEY_FRAME ||
cpi->refresh_alt_ref_frame ||
(cpi->refresh_golden_frame && !cpi->rc.is_src_frame_alt_ref)) {
@@ -1031,14 +1032,6 @@
rdmult_ratio = vp9_vaq_rdmult_ratio(energy);
vp9_init_plane_quantizers(cpi, x);
- }
-
- // Save rdmult before it might be changed, so it can be restored later.
- orig_rdmult = x->rdmult;
- if (cpi->oxcf.tuning == VP8_TUNE_SSIM)
- activity_masking(cpi, x);
-
- if (aq_mode == VARIANCE_AQ) {
vp9_clear_system_state();
x->rdmult = (int)round(x->rdmult * rdmult_ratio);
} else if (aq_mode == COMPLEXITY_AQ) {
@@ -1070,14 +1063,11 @@
totaldist, bsize, ctx, best_rd);
}
- if (aq_mode == VARIANCE_AQ) {
- x->rdmult = orig_rdmult;
- if (*totalrate != INT_MAX) {
- vp9_clear_system_state();
- *totalrate = (int)round(*totalrate * rdmult_ratio);
- }
- } else if (aq_mode == COMPLEXITY_AQ || aq_mode == CYCLIC_REFRESH_AQ) {
- x->rdmult = orig_rdmult;
+ x->rdmult = orig_rdmult;
+
+ if (aq_mode == VARIANCE_AQ && *totalrate != INT_MAX) {
+ vp9_clear_system_state();
+ *totalrate = (int)round(*totalrate * rdmult_ratio);
}
}
@@ -1483,8 +1473,8 @@
const int pre_offset = (mi_row * MI_SIZE) * pre_stride +
(mi_col * MI_SIZE);
const uint8_t *pre_src = cpi->Last_Source->y_buffer + pre_offset;
- const int thr_32x32 = cpi->sf.source_var_thresh;
- const int thr_64x64 = thr_32x32 << 1;
+ const unsigned int thr_32x32 = cpi->sf.source_var_thresh;
+ const unsigned int thr_64x64 = thr_32x32 << 1;
int i, j;
int index;
diff d32[4];
@@ -2234,7 +2224,7 @@
if (cpi->sf.disable_split_var_thresh && partition_none_allowed) {
unsigned int source_variancey;
vp9_setup_src_planes(x, cpi->Source, mi_row, mi_col);
- source_variancey = get_sby_perpixel_variance(cpi, x, bsize);
+ source_variancey = get_sby_perpixel_variance(cpi, &x->plane[0].src, bsize);
if (source_variancey < cpi->sf.disable_split_var_thresh) {
do_split = 0;
if (source_variancey < cpi->sf.disable_split_var_thresh / 2)
@@ -3266,7 +3256,7 @@
if (cpi->oxcf.tuning == VP8_TUNE_SSIM)
build_activity_map(cpi);
- cm->prev_mi = get_prev_mi(cm);
+ set_prev_mi(cm);
if (sf->use_nonrd_pick_mode) {
// Initialize internal buffer pointers for rtc coding, where non-RD
@@ -3284,9 +3274,9 @@
}
vp9_zero(x->zcoeff_blk);
- if (cpi->sf.partition_search_type == SOURCE_VAR_BASED_PARTITION &&
+ if (sf->partition_search_type == SOURCE_VAR_BASED_PARTITION &&
cm->current_video_frame > 0) {
- int check_freq = cpi->sf.search_type_check_frequency;
+ int check_freq = sf->search_type_check_frequency;
if ((cm->current_video_frame - 1) % check_freq == 0) {
cpi->use_large_partition_rate = 0;
@@ -3303,7 +3293,7 @@
if ((cm->current_video_frame - 1) % check_freq >= 1) {
if (cpi->use_large_partition_rate < 15)
- cpi->sf.partition_search_type = FIXED_PARTITION;
+ sf->partition_search_type = FIXED_PARTITION;
}
}
}
diff --git a/vp9/encoder/vp9_encodemb.c b/vp9/encoder/vp9_encodemb.c
index 5e98e4e..2bea93f 100644
--- a/vp9/encoder/vp9_encodemb.c
+++ b/vp9/encoder/vp9_encodemb.c
@@ -105,9 +105,8 @@
return pt;
}
-static void optimize_b(int plane, int block, BLOCK_SIZE plane_bsize,
- TX_SIZE tx_size, MACROBLOCK *mb,
- ENTROPY_CONTEXT *a, ENTROPY_CONTEXT *l) {
+static int optimize_b(MACROBLOCK *mb, int plane, int block,
+ BLOCK_SIZE plane_bsize, TX_SIZE tx_size, int ctx) {
MACROBLOCKD *const xd = &mb->e_mbd;
struct macroblock_plane *p = &mb->plane[plane];
struct macroblockd_plane *pd = &xd->plane[plane];
@@ -172,12 +171,10 @@
if (next < default_eob) {
band = band_translate[i + 1];
pt = trellis_get_coeff_context(scan, nb, i, t0, token_cache);
- rate0 +=
- mb->token_costs[tx_size][type][ref][band][0][pt]
- [tokens[next][0].token];
- rate1 +=
- mb->token_costs[tx_size][type][ref][band][0][pt]
- [tokens[next][1].token];
+ rate0 += mb->token_costs[tx_size][type][ref][band][0][pt]
+ [tokens[next][0].token];
+ rate1 += mb->token_costs[tx_size][type][ref][band][0][pt]
+ [tokens[next][1].token];
}
UPDATE_RD_COST();
/* And pick the best. */
@@ -274,15 +271,14 @@
/* Now pick the best path through the whole trellis. */
band = band_translate[i + 1];
- pt = combine_entropy_contexts(*a, *l);
rate0 = tokens[next][0].rate;
rate1 = tokens[next][1].rate;
error0 = tokens[next][0].error;
error1 = tokens[next][1].error;
t0 = tokens[next][0].token;
t1 = tokens[next][1].token;
- rate0 += mb->token_costs[tx_size][type][ref][band][0][pt][t0];
- rate1 += mb->token_costs[tx_size][type][ref][band][0][pt][t1];
+ rate0 += mb->token_costs[tx_size][type][ref][band][0][ctx][t0];
+ rate1 += mb->token_costs[tx_size][type][ref][band][0][ctx][t1];
UPDATE_RD_COST();
best = rd_cost1 < rd_cost0;
final_eob = i0 - 1;
@@ -303,7 +299,7 @@
final_eob++;
mb->plane[plane].eobs[block] = final_eob;
- *a = *l = (final_eob > 0);
+ return final_eob;
}
static INLINE void fdct32x32(int rd_transform,
@@ -393,7 +389,8 @@
vp9_xform_quant(x, plane, block, plane_bsize, tx_size);
if (x->optimize && (!x->skip_recode || !x->skip_optimize)) {
- optimize_b(plane, block, plane_bsize, tx_size, x, a, l);
+ const int ctx = combine_entropy_contexts(*a, *l);
+ *a = *l = optimize_b(x, plane, block, plane_bsize, tx_size, ctx) > 0;
} else {
*a = *l = p->eobs[block] > 0;
}
diff --git a/vp9/encoder/vp9_firstpass.c b/vp9/encoder/vp9_firstpass.c
index db32ef8..3324b9c 100644
--- a/vp9/encoder/vp9_firstpass.c
+++ b/vp9/encoder/vp9_firstpass.c
@@ -981,8 +981,6 @@
oxcf->target_bandwidth / 10000000.0);
}
- cpi->output_framerate = oxcf->framerate;
-
// Calculate a minimum intra value to be used in determining the IIratio
// scores used in the second pass. We have this minimum to make sure
// that clips that are static but "low complexity" in the intra domain
diff --git a/vp9/encoder/vp9_mcomp.c b/vp9/encoder/vp9_mcomp.c
index f7a02a4..37201a9 100644
--- a/vp9/encoder/vp9_mcomp.c
+++ b/vp9/encoder/vp9_mcomp.c
@@ -993,20 +993,21 @@
const MV fcenter_mv = {center_mv->row >> 3, center_mv->col >> 3};
const int *mvjsadcost = x->nmvjointsadcost;
int *mvsadcost[2] = {x->nmvsadcost[0], x->nmvsadcost[1]};
- const uint8_t *best_address;
+ const uint8_t *best_address, *in_what_ref;
int best_sad = INT_MAX;
int best_site = 0;
int last_site = 0;
int i, j, step;
clamp_mv(ref_mv, x->mv_col_min, x->mv_col_max, x->mv_row_min, x->mv_row_max);
- best_address = get_buf_from_mv(in_what, ref_mv);
+ in_what_ref = get_buf_from_mv(in_what, ref_mv);
+ best_address = in_what_ref;
*num00 = 0;
*best_mv = *ref_mv;
// Check the starting position
best_sad = fn_ptr->sdf(what->buf, what->stride,
- in_what->buf, in_what->stride, 0x7fffffff) +
+ best_address, in_what->stride, 0x7fffffff) +
mvsad_err_cost(best_mv, &fcenter_mv, mvjsadcost, mvsadcost, sad_per_bit);
i = 1;
@@ -1060,7 +1061,7 @@
break;
};
#endif
- } else if (best_address == in_what->buf) {
+ } else if (best_address == in_what_ref) {
(*num00)++;
}
}
diff --git a/vp9/encoder/vp9_onyx_if.c b/vp9/encoder/vp9_onyx_if.c
index 0ac9d5f..871d057 100644
--- a/vp9/encoder/vp9_onyx_if.c
+++ b/vp9/encoder/vp9_onyx_if.c
@@ -633,9 +633,8 @@
int vbr_max_bits;
oxcf->framerate = framerate < 0.1 ? 30 : framerate;
- cpi->output_framerate = cpi->oxcf.framerate;
rc->av_per_frame_bandwidth = (int)(oxcf->target_bandwidth /
- cpi->output_framerate);
+ oxcf->framerate);
rc->min_frame_bandwidth = (int)(rc->av_per_frame_bandwidth *
oxcf->two_pass_vbrmin_section / 100);
@@ -906,7 +905,9 @@
cpi->ext_refresh_frame_context_pending = 0;
}
+#ifndef M_LOG2_E
#define M_LOG2_E 0.693147180559945309417
+#endif
#define log2f(x) (log (x) / (float) M_LOG2_E)
static void cal_nmvjointsadcost(int *mvjointsadcost) {
@@ -1386,8 +1387,6 @@
cm->error.setjmp = 0;
- vp9_zero(cpi->common.counts.uv_mode);
-
#ifdef MODE_TEST_HIT_STATS
vp9_zero(cpi->mode_test_hits);
#endif
@@ -2658,6 +2657,7 @@
get_ref_frame_flags(cpi);
+ cm->last_frame_type = cm->frame_type;
vp9_rc_postencode_update(cpi, *size);
if (cm->frame_type == KEY_FRAME) {
diff --git a/vp9/encoder/vp9_onyx_int.h b/vp9/encoder/vp9_onyx_int.h
index 18203f9..126711e 100644
--- a/vp9/encoder/vp9_onyx_int.h
+++ b/vp9/encoder/vp9_onyx_int.h
@@ -376,7 +376,6 @@
int active_arnr_frames; // <= cpi->oxcf.arnr_max_frames
int active_arnr_strength; // <= cpi->oxcf.arnr_max_strength
- double output_framerate;
int64_t last_time_stamp_seen;
int64_t last_end_time_stamp_seen;
int64_t first_time_stamp_ever;
diff --git a/vp9/encoder/vp9_ratectrl.c b/vp9/encoder/vp9_ratectrl.c
index 3420816..00489cd 100644
--- a/vp9/encoder/vp9_ratectrl.c
+++ b/vp9/encoder/vp9_ratectrl.c
@@ -367,8 +367,8 @@
// Calculate required scaling factor based on target frame size and size of
// frame produced using previous Q.
- target_bits_per_mb =
- ((uint64_t)target_bits_per_frame << BPER_MB_NORMBITS) / cm->MBs;
+ target_bits_per_mb =
+ ((uint64_t)target_bits_per_frame << BPER_MB_NORMBITS) / cm->MBs;
i = active_best_quality;
@@ -1065,11 +1065,10 @@
}
void vp9_rc_postencode_update(VP9_COMP *cpi, uint64_t bytes_used) {
- VP9_COMMON *const cm = &cpi->common;
+ const VP9_COMMON *const cm = &cpi->common;
const VP9_CONFIG *const oxcf = &cpi->oxcf;
RATE_CONTROL *const rc = &cpi->rc;
- cm->last_frame_type = cm->frame_type;
// Update rate control heuristics
rc->projected_frame_size = (int)(bytes_used << 3);
@@ -1258,17 +1257,25 @@
static int calc_iframe_target_size_one_pass_cbr(const VP9_COMP *cpi) {
const RATE_CONTROL *rc = &cpi->rc;
+ const VP9_CONFIG *oxcf = &cpi->oxcf;
+ const SVC *const svc = &cpi->svc;
int target;
-
if (cpi->common.current_video_frame == 0) {
target = ((cpi->oxcf.starting_buffer_level / 2) > INT_MAX)
? INT_MAX : (int)(cpi->oxcf.starting_buffer_level / 2);
} else {
- const int initial_boost = 32;
- int kf_boost = MAX(initial_boost, (int)(2 * cpi->output_framerate - 16));
- if (rc->frames_since_key < cpi->output_framerate / 2) {
+ int kf_boost = 32;
+ double framerate = oxcf->framerate;
+ if (svc->number_temporal_layers > 1 &&
+ oxcf->end_usage == USAGE_STREAM_FROM_SERVER) {
+ // Use the layer framerate for temporal layers CBR mode.
+ const LAYER_CONTEXT *lc = &svc->layer_context[svc->temporal_layer_id];
+ framerate = lc->framerate;
+ }
+ kf_boost = MAX(kf_boost, (int)(2 * framerate - 16));
+ if (rc->frames_since_key < framerate / 2) {
kf_boost = (int)(kf_boost * rc->frames_since_key /
- (cpi->output_framerate / 2));
+ (framerate / 2));
}
target = ((16 + kf_boost) * rc->av_per_frame_bandwidth) >> 4;
}
diff --git a/vp9/encoder/vp9_ratectrl.h b/vp9/encoder/vp9_ratectrl.h
index 7693c2b..0b12a4c 100644
--- a/vp9/encoder/vp9_ratectrl.h
+++ b/vp9/encoder/vp9_ratectrl.h
@@ -125,8 +125,7 @@
// Post encode update of the rate control parameters based
// on bytes used
-void vp9_rc_postencode_update(struct VP9_COMP *cpi,
- uint64_t bytes_used);
+void vp9_rc_postencode_update(struct VP9_COMP *cpi, uint64_t bytes_used);
// Post encode update of the rate control parameters for dropped frames
void vp9_rc_postencode_update_drop_frame(struct VP9_COMP *cpi);
diff --git a/vp9/encoder/vp9_rdopt.c b/vp9/encoder/vp9_rdopt.c
index 1d70c1f..1b4cc51 100644
--- a/vp9/encoder/vp9_rdopt.c
+++ b/vp9/encoder/vp9_rdopt.c
@@ -81,7 +81,7 @@
const scan_order *so;
};
-const MODE_DEFINITION vp9_mode_order[MAX_MODES] = {
+static const MODE_DEFINITION vp9_mode_order[MAX_MODES] = {
{NEARESTMV, {LAST_FRAME, NONE}},
{NEARESTMV, {ALTREF_FRAME, NONE}},
{NEARESTMV, {GOLDEN_FRAME, NONE}},
@@ -121,7 +121,7 @@
{D45_PRED, {INTRA_FRAME, NONE}},
};
-const REF_DEFINITION vp9_ref_order[MAX_REFS] = {
+static const REF_DEFINITION vp9_ref_order[MAX_REFS] = {
{{LAST_FRAME, NONE}},
{{GOLDEN_FRAME, NONE}},
{{ALTREF_FRAME, NONE}},
@@ -134,8 +134,9 @@
// certain modes are assumed to be based on 8x8 blocks.
// This table is used to correct for blocks size.
// The factors here are << 2 (2 = x0.5, 32 = x8 etc).
-static int rd_thresh_block_size_factor[BLOCK_SIZES] =
- {2, 3, 3, 4, 6, 6, 8, 12, 12, 16, 24, 24, 32};
+static const uint8_t rd_thresh_block_size_factor[BLOCK_SIZES] = {
+ 2, 3, 3, 4, 6, 6, 8, 12, 12, 16, 24, 24, 32
+};
static int raster_block_offset(BLOCK_SIZE plane_bsize,
int raster_block, int stride) {
@@ -192,7 +193,7 @@
}
}
-static const int rd_iifactor[32] = {
+static const uint8_t rd_iifactor[32] = {
4, 4, 3, 2, 1, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
@@ -2267,7 +2268,7 @@
int_mv *ref_mv,
int_mv *second_ref_mv,
int64_t comp_pred_diff[REFERENCE_MODES],
- int64_t tx_size_diff[TX_MODES],
+ const int64_t tx_size_diff[TX_MODES],
int64_t best_filter_diff[SWITCHABLE_FILTER_CONTEXTS]) {
MACROBLOCKD *const xd = &x->e_mbd;
@@ -3145,7 +3146,7 @@
int64_t best_filter_rd[SWITCHABLE_FILTER_CONTEXTS];
int64_t best_filter_diff[SWITCHABLE_FILTER_CONTEXTS];
MB_MODE_INFO best_mbmode = { 0 };
- int mode_index, best_mode_index = 0;
+ int mode_index, best_mode_index = -1;
unsigned int ref_costs_single[MAX_REF_FRAMES], ref_costs_comp[MAX_REF_FRAMES];
vp9_prob comp_mode_p;
int64_t best_intra_rd = INT64_MAX;
@@ -3302,7 +3303,7 @@
// Look at the reference frame of the best mode so far and set the
// skip mask to look at a subset of the remaining modes.
- if (mode_index == mode_skip_start && best_rd < INT64_MAX) {
+ if (mode_index == mode_skip_start && best_mode_index >= 0) {
switch (vp9_mode_order[best_mode_index].ref_frame[0]) {
case INTRA_FRAME:
break;
@@ -3339,6 +3340,7 @@
comp_pred = second_ref_frame > INTRA_FRAME;
if (comp_pred) {
if ((mode_search_skip_flags & FLAG_SKIP_COMP_BESTINTRA) &&
+ best_mode_index >=0 &&
vp9_mode_order[best_mode_index].ref_frame[0] == INTRA_FRAME)
continue;
if ((mode_search_skip_flags & FLAG_SKIP_COMP_REFMISMATCH) &&
@@ -3366,7 +3368,8 @@
// one of the neighboring directional modes
if ((mode_search_skip_flags & FLAG_SKIP_INTRA_BESTINTER) &&
(this_mode >= D45_PRED && this_mode <= TM_PRED)) {
- if (vp9_mode_order[best_mode_index].ref_frame[0] > INTRA_FRAME)
+ if (best_mode_index >= 0 &&
+ vp9_mode_order[best_mode_index].ref_frame[0] > INTRA_FRAME)
continue;
}
if (mode_search_skip_flags & FLAG_SKIP_INTRA_DIRMISMATCH) {
@@ -3654,7 +3657,7 @@
break;
}
- if (best_rd >= best_rd_so_far)
+ if (best_mode_index < 0 || best_rd >= best_rd_so_far)
return INT64_MAX;
// If we used an estimate for the uv intra rd in the loop above...
@@ -3768,8 +3771,7 @@
VP9_ALT_FLAG };
int64_t best_rd = best_rd_so_far;
int64_t best_yrd = best_rd_so_far; // FIXME(rbultje) more precise
- int64_t best_tx_rd[TX_MODES];
- int64_t best_tx_diff[TX_MODES];
+ static const int64_t best_tx_diff[TX_MODES] = { 0 };
int64_t best_pred_diff[REFERENCE_MODES];
int64_t best_pred_rd[REFERENCE_MODES];
int64_t best_filter_rd[SWITCHABLE_FILTER_CONTEXTS];
@@ -3781,10 +3783,10 @@
int64_t best_inter_rd = INT64_MAX;
MV_REFERENCE_FRAME best_inter_ref_frame = LAST_FRAME;
INTERP_FILTER tmp_best_filter = SWITCHABLE;
- int rate_uv_intra[TX_SIZES], rate_uv_tokenonly[TX_SIZES];
- int64_t dist_uv[TX_SIZES];
- int skip_uv[TX_SIZES];
- MB_PREDICTION_MODE mode_uv[TX_SIZES] = { 0 };
+ int rate_uv_intra, rate_uv_tokenonly;
+ int64_t dist_uv;
+ int skip_uv;
+ MB_PREDICTION_MODE mode_uv = DC_PRED;
int intra_cost_penalty = 20 * vp9_dc_quant(cm->base_qindex, cm->y_dc_delta_q);
int_mv seg_mvs[4][MAX_REF_FRAMES];
b_mode_info best_bmodes[4];
@@ -3806,12 +3808,9 @@
for (i = 0; i < REFERENCE_MODES; ++i)
best_pred_rd[i] = INT64_MAX;
- for (i = 0; i < TX_MODES; i++)
- best_tx_rd[i] = INT64_MAX;
for (i = 0; i < SWITCHABLE_FILTER_CONTEXTS; i++)
best_filter_rd[i] = INT64_MAX;
- for (i = 0; i < TX_SIZES; i++)
- rate_uv_intra[i] = INT_MAX;
+ rate_uv_intra = INT_MAX;
*returnrate = INT_MAX;
@@ -3845,7 +3844,6 @@
int rate2 = 0, rate_y = 0, rate_uv = 0;
int64_t distortion2 = 0, distortion_y = 0, distortion_uv = 0;
int skippable = 0;
- int64_t tx_cache[TX_MODES];
int i;
int this_skip2 = 0;
int64_t total_sse = INT_MAX;
@@ -3968,9 +3966,6 @@
xd->plane[i].pre[1] = yv12_mb[second_ref_frame][i];
}
- for (i = 0; i < TX_MODES; ++i)
- tx_cache[i] = INT64_MAX;
-
#ifdef MODE_TEST_HIT_STATS
// TEST/DEBUG CODE
// Keep a rcord of the number of test hits at each size
@@ -3986,21 +3981,18 @@
rate2 += intra_cost_penalty;
distortion2 += distortion_y;
- if (rate_uv_intra[TX_4X4] == INT_MAX) {
+ if (rate_uv_intra == INT_MAX) {
choose_intra_uv_mode(cpi, ctx, bsize, TX_4X4,
- &rate_uv_intra[TX_4X4],
- &rate_uv_tokenonly[TX_4X4],
- &dist_uv[TX_4X4], &skip_uv[TX_4X4],
- &mode_uv[TX_4X4]);
+ &rate_uv_intra,
+ &rate_uv_tokenonly,
+ &dist_uv, &skip_uv,
+ &mode_uv);
}
- rate2 += rate_uv_intra[TX_4X4];
- rate_uv = rate_uv_tokenonly[TX_4X4];
- distortion2 += dist_uv[TX_4X4];
- distortion_uv = dist_uv[TX_4X4];
- mbmi->uv_mode = mode_uv[TX_4X4];
- tx_cache[ONLY_4X4] = RDCOST(x->rdmult, x->rddiv, rate2, distortion2);
- for (i = 0; i < TX_MODES; ++i)
- tx_cache[i] = tx_cache[ONLY_4X4];
+ rate2 += rate_uv_intra;
+ rate_uv = rate_uv_tokenonly;
+ distortion2 += dist_uv;
+ distortion_uv = dist_uv;
+ mbmi->uv_mode = mode_uv;
} else {
int rate;
int64_t distortion;
@@ -4163,10 +4155,6 @@
distortion2 += distortion_uv;
skippable = skippable && uv_skippable;
total_sse += uv_sse;
-
- tx_cache[ONLY_4X4] = RDCOST(x->rdmult, x->rddiv, rate2, distortion2);
- for (i = 0; i < TX_MODES; ++i)
- tx_cache[i] = tx_cache[ONLY_4X4];
}
}
@@ -4324,23 +4312,6 @@
}
}
- /* keep record of best txfm size */
- tx_cache[ALLOW_8X8] = tx_cache[ONLY_4X4];
- tx_cache[ALLOW_16X16] = tx_cache[ALLOW_8X8];
- tx_cache[ALLOW_32X32] = tx_cache[ALLOW_16X16];
- if (!mode_excluded && this_rd != INT64_MAX) {
- for (i = 0; i < TX_MODES && tx_cache[i] < INT64_MAX; i++) {
- int64_t adj_rd = INT64_MAX;
- if (ref_frame > INTRA_FRAME)
- adj_rd = this_rd + tx_cache[i] - tx_cache[cm->tx_mode];
- else
- adj_rd = this_rd;
-
- if (adj_rd < best_tx_rd[i])
- best_tx_rd[i] = adj_rd;
- }
- }
-
if (early_term)
break;
@@ -4355,14 +4326,12 @@
if (cpi->sf.use_uv_intra_rd_estimate) {
// Do Intra UV best rd mode selection if best mode choice above was intra.
if (vp9_ref_order[best_mode_index].ref_frame[0] == INTRA_FRAME) {
- TX_SIZE uv_tx_size;
*mbmi = best_mbmode;
- uv_tx_size = get_uv_tx_size(mbmi);
- rd_pick_intra_sbuv_mode(cpi, x, ctx, &rate_uv_intra[uv_tx_size],
- &rate_uv_tokenonly[uv_tx_size],
- &dist_uv[uv_tx_size],
- &skip_uv[uv_tx_size],
- BLOCK_8X8, uv_tx_size);
+ rd_pick_intra_sbuv_mode(cpi, x, ctx, &rate_uv_intra,
+ &rate_uv_tokenonly,
+ &dist_uv,
+ &skip_uv,
+ BLOCK_8X8, TX_4X4);
}
}
@@ -4424,15 +4393,8 @@
}
if (cm->interp_filter == SWITCHABLE)
assert(best_filter_diff[SWITCHABLE_FILTERS] == 0);
- for (i = 0; i < TX_MODES; i++) {
- if (best_tx_rd[i] == INT64_MAX)
- best_tx_diff[i] = 0;
- else
- best_tx_diff[i] = best_rd - best_tx_rd[i];
- }
} else {
vp9_zero(best_filter_diff);
- vp9_zero(best_tx_diff);
}
set_ref_ptrs(cm, xd, mbmi->ref_frame[0], mbmi->ref_frame[1]);
diff --git a/vp9/encoder/vp9_speed_features.c b/vp9/encoder/vp9_speed_features.c
index d6b6174..adad800 100644
--- a/vp9/encoder/vp9_speed_features.c
+++ b/vp9/encoder/vp9_speed_features.c
@@ -269,9 +269,6 @@
sf->partition_search_type = SOURCE_VAR_BASED_PARTITION;
sf->search_type_check_frequency = 50;
sf->source_var_thresh = 360;
-
- sf->use_nonrd_pick_mode = 1;
- sf->search_method = FAST_DIAMOND;
}
if (speed >= 7) {
diff --git a/vp9/encoder/vp9_speed_features.h b/vp9/encoder/vp9_speed_features.h
index 72f548a..5542297 100644
--- a/vp9/encoder/vp9_speed_features.h
+++ b/vp9/encoder/vp9_speed_features.h
@@ -344,7 +344,7 @@
int search_type_check_frequency;
// The threshold used in SOURCE_VAR_BASED_PARTITION search type.
- int source_var_thresh;
+ unsigned int source_var_thresh;
} SPEED_FEATURES;
struct VP9_COMP;
diff --git a/vp9/encoder/vp9_svc_layercontext.c b/vp9/encoder/vp9_svc_layercontext.c
index c2b6263..9b3fc6e 100644
--- a/vp9/encoder/vp9_svc_layercontext.c
+++ b/vp9/encoder/vp9_svc_layercontext.c
@@ -178,7 +178,6 @@
cpi->oxcf.starting_buffer_level = lc->starting_buffer_level;
cpi->oxcf.optimal_buffer_level = lc->optimal_buffer_level;
cpi->oxcf.maximum_buffer_size = lc->maximum_buffer_size;
- cpi->output_framerate = lc->framerate;
// Reset the frames_since_key and frames_to_key counters to their values
// before the layer restore. Keep these defined for the stream (not layer).
if (cpi->svc.number_temporal_layers > 1) {
@@ -197,7 +196,6 @@
lc->starting_buffer_level = oxcf->starting_buffer_level;
lc->optimal_buffer_level = oxcf->optimal_buffer_level;
lc->maximum_buffer_size = oxcf->maximum_buffer_size;
- lc->framerate = cpi->output_framerate;
}
void vp9_init_second_pass_spatial_svc(VP9_COMP *cpi) {
diff --git a/vpxenc.c b/vpxenc.c
index 00d3e3e..cb91d94 100644
--- a/vpxenc.c
+++ b/vpxenc.c
@@ -123,55 +123,6 @@
return 0;
}
-#if CONFIG_WEBM_IO
-/* Murmur hash derived from public domain reference implementation at
- * http:// sites.google.com/site/murmurhash/
- */
-static unsigned int murmur(const void *key, int len, unsigned int seed) {
- const unsigned int m = 0x5bd1e995;
- const int r = 24;
-
- unsigned int h = seed ^ len;
-
- const unsigned char *data = (const unsigned char *)key;
-
- while (len >= 4) {
- unsigned int k;
-
- k = (unsigned int)data[0];
- k |= (unsigned int)data[1] << 8;
- k |= (unsigned int)data[2] << 16;
- k |= (unsigned int)data[3] << 24;
-
- k *= m;
- k ^= k >> r;
- k *= m;
-
- h *= m;
- h ^= k;
-
- data += 4;
- len -= 4;
- }
-
- switch (len) {
- case 3:
- h ^= data[2] << 16;
- case 2:
- h ^= data[1] << 8;
- case 1:
- h ^= data[0];
- h *= m;
- };
-
- h ^= h >> 13;
- h *= m;
- h ^= h >> 15;
-
- return h;
-}
-#endif // CONFIG_WEBM_IO
-
static const arg_def_t debugmode = ARG_DEF("D", "debug", 0,
"Debug mode (makes output deterministic)");
static const arg_def_t outputfile = ARG_DEF("o", "output", 1,
@@ -619,7 +570,6 @@
FILE *file;
struct rate_hist *rate_hist;
struct EbmlGlobal ebml;
- uint32_t hash;
uint64_t psnr_sse_total;
uint64_t psnr_samples_total;
double psnr_totals[4];
@@ -841,7 +791,9 @@
stream->config.stereo_fmt = STEREO_FORMAT_MONO;
stream->config.write_webm = 1;
#if CONFIG_WEBM_IO
- stream->ebml.last_pts_ms = -1;
+ stream->ebml.last_pts_ns = -1;
+ stream->ebml.writer = NULL;
+ stream->ebml.segment = NULL;
#endif
/* Allows removal of the application version from the EBML tags */
@@ -1176,9 +1128,7 @@
#if CONFIG_WEBM_IO
if (stream->config.write_webm) {
- write_webm_file_footer(&stream->ebml, stream->hash);
- free(stream->ebml.cue_list);
- stream->ebml.cue_list = NULL;
+ write_webm_file_footer(&stream->ebml);
}
#endif
@@ -1334,12 +1284,6 @@
update_rate_histogram(stream->rate_hist, cfg, pkt);
#if CONFIG_WEBM_IO
if (stream->config.write_webm) {
- /* Update the hash */
- if (!stream->ebml.debug)
- stream->hash = murmur(pkt->data.frame.buf,
- (int)pkt->data.frame.sz,
- stream->hash);
-
write_webm_block(&stream->ebml, cfg, pkt);
}
#endif
diff --git a/webmenc.c b/webmenc.c
deleted file mode 100644
index 17bbeec..0000000
--- a/webmenc.c
+++ /dev/null
@@ -1,331 +0,0 @@
-/*
- * Copyright (c) 2013 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 "webmenc.h"
-
-#include <limits.h>
-#include <string.h>
-
-#include "third_party/libmkv/EbmlWriter.h"
-#include "third_party/libmkv/EbmlIDs.h"
-
-void Ebml_Write(struct EbmlGlobal *glob,
- const void *buffer_in,
- unsigned long len) {
- (void) fwrite(buffer_in, 1, len, glob->stream);
-}
-
-#define WRITE_BUFFER(s) \
-for (i = len - 1; i >= 0; i--) { \
- x = (char)(*(const s *)buffer_in >> (i * CHAR_BIT)); \
- Ebml_Write(glob, &x, 1); \
-}
-
-void Ebml_Serialize(struct EbmlGlobal *glob,
- const void *buffer_in,
- int buffer_size,
- unsigned long len) {
- char x;
- int i;
-
- /* buffer_size:
- * 1 - int8_t;
- * 2 - int16_t;
- * 3 - int32_t;
- * 4 - int64_t;
- */
- switch (buffer_size) {
- case 1:
- WRITE_BUFFER(int8_t)
- break;
- case 2:
- WRITE_BUFFER(int16_t)
- break;
- case 4:
- WRITE_BUFFER(int32_t)
- break;
- case 8:
- WRITE_BUFFER(int64_t)
- break;
- default:
- break;
- }
-}
-#undef WRITE_BUFFER
-
-/* Need a fixed size serializer for the track ID. libmkv provides a 64 bit
- * one, but not a 32 bit one.
- */
-static void Ebml_SerializeUnsigned32(struct EbmlGlobal *glob,
- unsigned int class_id,
- uint64_t ui) {
- const unsigned char sizeSerialized = 4 | 0x80;
- Ebml_WriteID(glob, class_id);
- Ebml_Serialize(glob, &sizeSerialized, sizeof(sizeSerialized), 1);
- Ebml_Serialize(glob, &ui, sizeof(ui), 4);
-}
-
-static void Ebml_StartSubElement(struct EbmlGlobal *glob,
- EbmlLoc *ebmlLoc,
- unsigned int class_id) {
- const uint64_t kEbmlUnknownLength = LITERALU64(0x01FFFFFF, 0xFFFFFFFF);
- Ebml_WriteID(glob, class_id);
- *ebmlLoc = ftello(glob->stream);
- Ebml_Serialize(glob, &kEbmlUnknownLength, sizeof(kEbmlUnknownLength), 8);
-}
-
-static void Ebml_EndSubElement(struct EbmlGlobal *glob, EbmlLoc *ebmlLoc) {
- off_t pos;
- uint64_t size;
-
- /* Save the current stream pointer. */
- pos = ftello(glob->stream);
-
- /* Calculate the size of this element. */
- size = pos - *ebmlLoc - 8;
- size |= LITERALU64(0x01000000, 0x00000000);
-
- /* Seek back to the beginning of the element and write the new size. */
- fseeko(glob->stream, *ebmlLoc, SEEK_SET);
- Ebml_Serialize(glob, &size, sizeof(size), 8);
-
- /* Reset the stream pointer. */
- fseeko(glob->stream, pos, SEEK_SET);
-}
-
-void write_webm_seek_element(struct EbmlGlobal *ebml,
- unsigned int id,
- off_t pos) {
- uint64_t offset = pos - ebml->position_reference;
- EbmlLoc start;
- Ebml_StartSubElement(ebml, &start, Seek);
- Ebml_SerializeBinary(ebml, SeekID, id);
- Ebml_SerializeUnsigned64(ebml, SeekPosition, offset);
- Ebml_EndSubElement(ebml, &start);
-}
-
-void write_webm_seek_info(struct EbmlGlobal *ebml) {
- off_t pos;
- EbmlLoc start;
- EbmlLoc startInfo;
- uint64_t frame_time;
- char version_string[64];
-
- /* Save the current stream pointer. */
- pos = ftello(ebml->stream);
-
- if (ebml->seek_info_pos)
- fseeko(ebml->stream, ebml->seek_info_pos, SEEK_SET);
- else
- ebml->seek_info_pos = pos;
-
- Ebml_StartSubElement(ebml, &start, SeekHead);
- write_webm_seek_element(ebml, Tracks, ebml->track_pos);
- write_webm_seek_element(ebml, Cues, ebml->cue_pos);
- write_webm_seek_element(ebml, Info, ebml->segment_info_pos);
- Ebml_EndSubElement(ebml, &start);
-
- /* Create and write the Segment Info. */
- if (ebml->debug) {
- strcpy(version_string, "vpxenc");
- } else {
- strcpy(version_string, "vpxenc ");
- strncat(version_string,
- vpx_codec_version_str(),
- sizeof(version_string) - 1 - strlen(version_string));
- }
-
- frame_time = (uint64_t)1000 * ebml->framerate.den
- / ebml->framerate.num;
- ebml->segment_info_pos = ftello(ebml->stream);
- Ebml_StartSubElement(ebml, &startInfo, Info);
- Ebml_SerializeUnsigned(ebml, TimecodeScale, 1000000);
- Ebml_SerializeFloat(ebml, Segment_Duration,
- (double)(ebml->last_pts_ms + frame_time));
- Ebml_SerializeString(ebml, 0x4D80, version_string);
- Ebml_SerializeString(ebml, 0x5741, version_string);
- Ebml_EndSubElement(ebml, &startInfo);
-}
-
-void write_webm_file_header(struct EbmlGlobal *glob,
- const vpx_codec_enc_cfg_t *cfg,
- const struct vpx_rational *fps,
- stereo_format_t stereo_fmt,
- unsigned int fourcc) {
- EbmlLoc start;
- EbmlLoc trackStart;
- EbmlLoc videoStart;
- unsigned int trackNumber = 1;
- uint64_t trackID = 0;
- unsigned int pixelWidth = cfg->g_w;
- unsigned int pixelHeight = cfg->g_h;
-
- /* Write the EBML header. */
- Ebml_StartSubElement(glob, &start, EBML);
- Ebml_SerializeUnsigned(glob, EBMLVersion, 1);
- Ebml_SerializeUnsigned(glob, EBMLReadVersion, 1);
- Ebml_SerializeUnsigned(glob, EBMLMaxIDLength, 4);
- Ebml_SerializeUnsigned(glob, EBMLMaxSizeLength, 8);
- Ebml_SerializeString(glob, DocType, "webm");
- Ebml_SerializeUnsigned(glob, DocTypeVersion, 2);
- Ebml_SerializeUnsigned(glob, DocTypeReadVersion, 2);
- Ebml_EndSubElement(glob, &start);
-
- /* Open and begin writing the segment element. */
- Ebml_StartSubElement(glob, &glob->startSegment, Segment);
- glob->position_reference = ftello(glob->stream);
- glob->framerate = *fps;
- write_webm_seek_info(glob);
-
- /* Open and write the Tracks element. */
- glob->track_pos = ftello(glob->stream);
- Ebml_StartSubElement(glob, &trackStart, Tracks);
-
- /* Open and write the Track entry. */
- Ebml_StartSubElement(glob, &start, TrackEntry);
- Ebml_SerializeUnsigned(glob, TrackNumber, trackNumber);
- glob->track_id_pos = ftello(glob->stream);
- Ebml_SerializeUnsigned32(glob, TrackUID, trackID);
- Ebml_SerializeUnsigned(glob, TrackType, 1);
- Ebml_SerializeString(glob, CodecID,
- fourcc == VP8_FOURCC ? "V_VP8" : "V_VP9");
- Ebml_StartSubElement(glob, &videoStart, Video);
- Ebml_SerializeUnsigned(glob, PixelWidth, pixelWidth);
- Ebml_SerializeUnsigned(glob, PixelHeight, pixelHeight);
- Ebml_SerializeUnsigned(glob, StereoMode, stereo_fmt);
- Ebml_EndSubElement(glob, &videoStart);
-
- /* Close Track entry. */
- Ebml_EndSubElement(glob, &start);
-
- /* Close Tracks element. */
- Ebml_EndSubElement(glob, &trackStart);
-
- /* Segment element remains open. */
-}
-
-void write_webm_block(struct EbmlGlobal *glob,
- const vpx_codec_enc_cfg_t *cfg,
- const vpx_codec_cx_pkt_t *pkt) {
- unsigned int block_length;
- unsigned char track_number;
- uint16_t block_timecode = 0;
- unsigned char flags;
- int64_t pts_ms;
- int start_cluster = 0, is_keyframe;
-
- /* Calculate the PTS of this frame in milliseconds. */
- pts_ms = pkt->data.frame.pts * 1000
- * (uint64_t)cfg->g_timebase.num / (uint64_t)cfg->g_timebase.den;
-
- if (pts_ms <= glob->last_pts_ms)
- pts_ms = glob->last_pts_ms + 1;
-
- glob->last_pts_ms = pts_ms;
-
- /* Calculate the relative time of this block. */
- if (pts_ms - glob->cluster_timecode > SHRT_MAX)
- start_cluster = 1;
- else
- block_timecode = (uint16_t)pts_ms - glob->cluster_timecode;
-
- is_keyframe = (pkt->data.frame.flags & VPX_FRAME_IS_KEY);
- if (start_cluster || is_keyframe) {
- if (glob->cluster_open)
- Ebml_EndSubElement(glob, &glob->startCluster);
-
- /* Open the new cluster. */
- block_timecode = 0;
- glob->cluster_open = 1;
- glob->cluster_timecode = (uint32_t)pts_ms;
- glob->cluster_pos = ftello(glob->stream);
- Ebml_StartSubElement(glob, &glob->startCluster, Cluster);
- Ebml_SerializeUnsigned(glob, Timecode, glob->cluster_timecode);
-
- /* Save a cue point if this is a keyframe. */
- if (is_keyframe) {
- struct cue_entry *cue, *new_cue_list;
-
- new_cue_list = realloc(glob->cue_list,
- (glob->cues + 1) * sizeof(struct cue_entry));
- if (new_cue_list)
- glob->cue_list = new_cue_list;
- else
- fatal("Failed to realloc cue list.");
-
- cue = &glob->cue_list[glob->cues];
- cue->time = glob->cluster_timecode;
- cue->loc = glob->cluster_pos;
- glob->cues++;
- }
- }
-
- /* Write the Simple Block. */
- Ebml_WriteID(glob, SimpleBlock);
-
- block_length = (unsigned int)pkt->data.frame.sz + 4;
- block_length |= 0x10000000;
- Ebml_Serialize(glob, &block_length, sizeof(block_length), 4);
-
- track_number = 1;
- track_number |= 0x80;
- Ebml_Write(glob, &track_number, 1);
-
- Ebml_Serialize(glob, &block_timecode, sizeof(block_timecode), 2);
-
- flags = 0;
- if (is_keyframe)
- flags |= 0x80;
- if (pkt->data.frame.flags & VPX_FRAME_IS_INVISIBLE)
- flags |= 0x08;
- Ebml_Write(glob, &flags, 1);
-
- Ebml_Write(glob, pkt->data.frame.buf, (unsigned int)pkt->data.frame.sz);
-}
-
-void write_webm_file_footer(struct EbmlGlobal *glob, int hash) {
- EbmlLoc start_cues;
- EbmlLoc start_cue_point;
- EbmlLoc start_cue_tracks;
- unsigned int i;
-
- if (glob->cluster_open)
- Ebml_EndSubElement(glob, &glob->startCluster);
-
- glob->cue_pos = ftello(glob->stream);
- Ebml_StartSubElement(glob, &start_cues, Cues);
-
- for (i = 0; i < glob->cues; i++) {
- struct cue_entry *cue = &glob->cue_list[i];
- Ebml_StartSubElement(glob, &start_cue_point, CuePoint);
- Ebml_SerializeUnsigned(glob, CueTime, cue->time);
-
- Ebml_StartSubElement(glob, &start_cue_tracks, CueTrackPositions);
- Ebml_SerializeUnsigned(glob, CueTrack, 1);
- Ebml_SerializeUnsigned64(glob, CueClusterPosition,
- cue->loc - glob->position_reference);
- Ebml_EndSubElement(glob, &start_cue_tracks);
-
- Ebml_EndSubElement(glob, &start_cue_point);
- }
-
- Ebml_EndSubElement(glob, &start_cues);
-
- /* Close the Segment. */
- Ebml_EndSubElement(glob, &glob->startSegment);
-
- /* Patch up the seek info block. */
- write_webm_seek_info(glob);
-
- /* Patch up the track id. */
- fseeko(glob->stream, glob->track_id_pos, SEEK_SET);
- Ebml_SerializeUnsigned32(glob, TrackUID, glob->debug ? 0xDEADBEEF : hash);
-
- fseeko(glob->stream, 0, SEEK_END);
-}
diff --git a/webmenc.cc b/webmenc.cc
new file mode 100644
index 0000000..a0e542b
--- /dev/null
+++ b/webmenc.cc
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2014 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 "./webmenc.h"
+
+#include <string>
+
+#include "third_party/libwebm/mkvmuxer.hpp"
+#include "third_party/libwebm/mkvmuxerutil.hpp"
+#include "third_party/libwebm/mkvwriter.hpp"
+
+namespace {
+const uint64_t kDebugTrackUid = 0xDEADBEEF;
+const int kVideoTrackNumber = 1;
+} // namespace
+
+void write_webm_file_header(struct EbmlGlobal *glob,
+ const vpx_codec_enc_cfg_t *cfg,
+ const struct vpx_rational *fps,
+ stereo_format_t stereo_fmt,
+ unsigned int fourcc) {
+ mkvmuxer::MkvWriter *const writer = new mkvmuxer::MkvWriter(glob->stream);
+ mkvmuxer::Segment *const segment = new mkvmuxer::Segment();
+ segment->Init(writer);
+ segment->set_mode(mkvmuxer::Segment::kFile);
+ segment->OutputCues(true);
+
+ mkvmuxer::SegmentInfo *const info = segment->GetSegmentInfo();
+ const uint64_t kTimecodeScale = 1000000;
+ info->set_timecode_scale(kTimecodeScale);
+ std::string version = "vpxenc";
+ if (!glob->debug) {
+ version.append(std::string(" ") + vpx_codec_version_str());
+ }
+ info->set_writing_app(version.c_str());
+
+ const uint64_t video_track_id =
+ segment->AddVideoTrack(static_cast<int>(cfg->g_w),
+ static_cast<int>(cfg->g_h),
+ kVideoTrackNumber);
+ mkvmuxer::VideoTrack* const video_track =
+ static_cast<mkvmuxer::VideoTrack*>(
+ segment->GetTrackByNumber(video_track_id));
+ video_track->SetStereoMode(stereo_fmt);
+ video_track->set_codec_id(fourcc == VP8_FOURCC ? "V_VP8" : "V_VP9");
+ if (glob->debug) {
+ video_track->set_uid(kDebugTrackUid);
+ }
+ glob->writer = writer;
+ glob->segment = segment;
+}
+
+void write_webm_block(struct EbmlGlobal *glob,
+ const vpx_codec_enc_cfg_t *cfg,
+ const vpx_codec_cx_pkt_t *pkt) {
+ mkvmuxer::Segment *const segment =
+ reinterpret_cast<mkvmuxer::Segment*>(glob->segment);
+ int64_t pts_ns = pkt->data.frame.pts * 1000000000ll *
+ cfg->g_timebase.num / cfg->g_timebase.den;
+ if (pts_ns <= glob->last_pts_ns)
+ pts_ns = glob->last_pts_ns + 1000000;
+ glob->last_pts_ns = pts_ns;
+
+ segment->AddFrame(static_cast<uint8_t*>(pkt->data.frame.buf),
+ pkt->data.frame.sz,
+ kVideoTrackNumber,
+ pts_ns,
+ pkt->data.frame.flags & VPX_FRAME_IS_KEY);
+}
+
+void write_webm_file_footer(struct EbmlGlobal *glob) {
+ mkvmuxer::MkvWriter *const writer =
+ reinterpret_cast<mkvmuxer::MkvWriter*>(glob->writer);
+ mkvmuxer::Segment *const segment =
+ reinterpret_cast<mkvmuxer::Segment*>(glob->segment);
+ segment->Finalize();
+ delete segment;
+ delete writer;
+ glob->writer = NULL;
+ glob->segment = NULL;
+}
diff --git a/webmenc.h b/webmenc.h
index 362aa89..0ac606b 100644
--- a/webmenc.h
+++ b/webmenc.h
@@ -13,13 +13,6 @@
#include <stdio.h>
#include <stdlib.h>
-#if defined(_MSC_VER)
-/* MSVS doesn't define off_t */
-typedef __int64 off_t;
-#else
-#include <stdint.h>
-#endif
-
#include "tools_common.h"
#include "vpx/vpx_encoder.h"
@@ -27,40 +20,13 @@
extern "C" {
#endif
-typedef off_t EbmlLoc;
-
-struct cue_entry {
- unsigned int time;
- uint64_t loc;
-};
-
+/* TODO(vigneshv): Rename this struct */
struct EbmlGlobal {
int debug;
-
FILE *stream;
- int64_t last_pts_ms;
- vpx_rational_t framerate;
-
- /* These pointers are to the start of an element */
- off_t position_reference;
- off_t seek_info_pos;
- off_t segment_info_pos;
- off_t track_pos;
- off_t cue_pos;
- off_t cluster_pos;
-
- /* This pointer is to a specific element to be serialized */
- off_t track_id_pos;
-
- /* These pointers are to the size field of the element */
- EbmlLoc startSegment;
- EbmlLoc startCluster;
-
- uint32_t cluster_timecode;
- int cluster_open;
-
- struct cue_entry *cue_list;
- unsigned int cues;
+ int64_t last_pts_ns;
+ void *writer;
+ void *segment;
};
/* Stereo 3D packed frame format */
@@ -72,10 +38,6 @@
STEREO_FORMAT_RIGHT_LEFT = 11
} stereo_format_t;
-void write_webm_seek_element(struct EbmlGlobal *ebml,
- unsigned int id,
- off_t pos);
-
void write_webm_file_header(struct EbmlGlobal *glob,
const vpx_codec_enc_cfg_t *cfg,
const struct vpx_rational *fps,
@@ -86,7 +48,7 @@
const vpx_codec_enc_cfg_t *cfg,
const vpx_codec_cx_pkt_t *pkt);
-void write_webm_file_footer(struct EbmlGlobal *glob, int hash);
+void write_webm_file_footer(struct EbmlGlobal *glob);
#ifdef __cplusplus
} // extern "C"