Compare commits
10 Commits
sandbox/wa
...
sandbox/jk
Author | SHA1 | Date | |
---|---|---|---|
![]() |
b76c4c6ba7 | ||
![]() |
7f6a695771 | ||
![]() |
a764f61f70 | ||
![]() |
50c5e81c7c | ||
![]() |
6463c7cf72 | ||
![]() |
7070dab445 | ||
![]() |
0a9b65ba1c | ||
![]() |
0a50a29121 | ||
![]() |
118b445bab | ||
![]() |
3e78b5f2b8 |
32
examples.mk
32
examples.mk
@@ -8,6 +8,20 @@
|
||||
## be found in the AUTHORS file in the root of the source tree.
|
||||
##
|
||||
|
||||
LIBYUV_SRCS += third_party/libyuv/include/libyuv/basic_types.h \
|
||||
third_party/libyuv/include/libyuv/cpu_id.h \
|
||||
third_party/libyuv/include/libyuv/scale.h \
|
||||
third_party/libyuv/source/row.h \
|
||||
third_party/libyuv/source/scale.c \
|
||||
third_party/libyuv/source/cpu_id.c
|
||||
|
||||
NESTEGG_SRCS += nestegg/halloc/halloc.h \
|
||||
nestegg/halloc/src/align.h \
|
||||
nestegg/halloc/src/halloc.c \
|
||||
nestegg/halloc/src/hlist.h \
|
||||
nestegg/halloc/src/macros.h \
|
||||
nestegg/include/nestegg/nestegg.h \
|
||||
nestegg/src/nestegg.c
|
||||
|
||||
# List of examples to build. UTILS are files that are taken from the source
|
||||
# tree directly, and GEN_EXAMPLES are files that are created from the
|
||||
@@ -18,13 +32,7 @@ vpxdec.SRCS += vpx_ports/vpx_timer.h
|
||||
vpxdec.SRCS += vpx/vpx_integer.h
|
||||
vpxdec.SRCS += args.c args.h
|
||||
vpxdec.SRCS += tools_common.c tools_common.h
|
||||
vpxdec.SRCS += nestegg/halloc/halloc.h
|
||||
vpxdec.SRCS += nestegg/halloc/src/align.h
|
||||
vpxdec.SRCS += nestegg/halloc/src/halloc.c
|
||||
vpxdec.SRCS += nestegg/halloc/src/hlist.h
|
||||
vpxdec.SRCS += nestegg/halloc/src/macros.h
|
||||
vpxdec.SRCS += nestegg/include/nestegg/nestegg.h
|
||||
vpxdec.SRCS += nestegg/src/nestegg.c
|
||||
vpxdec.SRCS += $(NESTEGG_SRCS)
|
||||
vpxdec.GUID = BA5FE66F-38DD-E034-F542-B1578C5FB950
|
||||
vpxdec.DESCRIPTION = Full featured decoder
|
||||
UTILS-$(CONFIG_ENCODERS) += vpxenc.c
|
||||
@@ -35,6 +43,8 @@ vpxenc.SRCS += vpx_ports/mem_ops_aligned.h
|
||||
vpxenc.SRCS += libmkv/EbmlIDs.h
|
||||
vpxenc.SRCS += libmkv/EbmlWriter.c
|
||||
vpxenc.SRCS += libmkv/EbmlWriter.h
|
||||
vpxenc.SRCS += $(LIBYUV_SRCS)
|
||||
vpxenc.SRCS += $(NESTEGG_SRCS)
|
||||
vpxenc.GUID = 548DEC74-7A15-4B2B-AFC3-AA102E7C25C1
|
||||
vpxenc.DESCRIPTION = Full featured encoder
|
||||
UTILS-$(CONFIG_ENCODERS) += vp8_scalable_patterns.c
|
||||
@@ -98,13 +108,7 @@ vp8cx_set_ref.DESCRIPTION = VP8 set encoder reference frame
|
||||
|
||||
# C file is provided, not generated automatically.
|
||||
GEN_EXAMPLES-$(CONFIG_MULTI_RES_ENCODING) += vp8_multi_resolution_encoder.c
|
||||
vp8_multi_resolution_encoder.SRCS \
|
||||
+= third_party/libyuv/include/libyuv/basic_types.h \
|
||||
third_party/libyuv/include/libyuv/cpu_id.h \
|
||||
third_party/libyuv/include/libyuv/scale.h \
|
||||
third_party/libyuv/source/row.h \
|
||||
third_party/libyuv/source/scale.c \
|
||||
third_party/libyuv/source/cpu_id.c
|
||||
vp8_multi_resolution_encoder.SRCS += $(LIBYUV_SRCS)
|
||||
vp8_multi_resolution_encoder.GUID = 04f8738e-63c8-423b-90fa-7c2703a374de
|
||||
vp8_multi_resolution_encoder.DESCRIPTION = VP8 Multiple-resolution Encoding
|
||||
|
||||
|
8
third_party/libyuv/source/scale.c
vendored
8
third_party/libyuv/source/scale.c
vendored
@@ -60,7 +60,7 @@ void SetUseReferenceImpl(int use) {
|
||||
|
||||
#if defined(__ARM_NEON__) && !defined(YUV_DISABLE_ASM)
|
||||
#define HAS_SCALEROWDOWN2_NEON
|
||||
void ScaleRowDown2_NEON(const uint8* src_ptr, int /* src_stride */,
|
||||
void ScaleRowDown2_NEON(const uint8* src_ptr, int src_stride,
|
||||
uint8* dst, int dst_width) {
|
||||
asm volatile (
|
||||
"1: \n"
|
||||
@@ -102,7 +102,7 @@ void ScaleRowDown2Int_NEON(const uint8* src_ptr, int src_stride,
|
||||
}
|
||||
|
||||
#define HAS_SCALEROWDOWN4_NEON
|
||||
static void ScaleRowDown4_NEON(const uint8* src_ptr, int /* src_stride */,
|
||||
static void ScaleRowDown4_NEON(const uint8* src_ptr, int src_stride,
|
||||
uint8* dst_ptr, int dst_width) {
|
||||
asm volatile (
|
||||
"1: \n"
|
||||
@@ -160,7 +160,7 @@ static void ScaleRowDown4Int_NEON(const uint8* src_ptr, int src_stride,
|
||||
// Down scale from 4 to 3 pixels. Use the neon multilane read/write
|
||||
// to load up the every 4th pixel into a 4 different registers.
|
||||
// Point samples 32 pixels to 24 pixels.
|
||||
static void ScaleRowDown34_NEON(const uint8* src_ptr, int /* src_stride */,
|
||||
static void ScaleRowDown34_NEON(const uint8* src_ptr, int src_stride,
|
||||
uint8* dst_ptr, int dst_width) {
|
||||
asm volatile (
|
||||
"1: \n"
|
||||
@@ -284,7 +284,7 @@ const unsigned short mult38_div9[8] __attribute__ ((aligned(16))) =
|
||||
65536 / 18, 65536 / 18, 65536 / 18, 65536 / 18 };
|
||||
|
||||
// 32 -> 12
|
||||
static void ScaleRowDown38_NEON(const uint8* src_ptr, int,
|
||||
static void ScaleRowDown38_NEON(const uint8* src_ptr, int src_stride,
|
||||
uint8* dst_ptr, int dst_width) {
|
||||
asm volatile (
|
||||
"vld1.u8 {q3}, [%3] \n"
|
||||
|
@@ -205,6 +205,11 @@ typedef struct macroblockd
|
||||
DECLARE_ALIGNED(16, short, dequant_y2[16]);
|
||||
DECLARE_ALIGNED(16, short, dequant_uv[16]);
|
||||
|
||||
/* position of this macroblock */
|
||||
int mbr;
|
||||
int mbc;
|
||||
int mbrc;
|
||||
|
||||
/* 16 Y blocks, 4 U, 4 V, 1 DC 2nd order block, each with 16 entries. */
|
||||
BLOCKD block[25];
|
||||
int fullpixel_mask;
|
||||
|
@@ -411,6 +411,10 @@ void encode_mb_row(VP8_COMP *cpi,
|
||||
// for each macroblock col in image
|
||||
for (mb_col = 0; mb_col < cm->mb_cols; mb_col++)
|
||||
{
|
||||
xd->mbr = mb_row;
|
||||
xd->mbc = mb_col;
|
||||
xd->mbrc = mb_row * cm->mb_cols + mb_col;
|
||||
|
||||
// Distance of Mb to the left & right edges, specified in
|
||||
// 1/8th pel units as they are always compared to values
|
||||
// that are in 1/8th pel units
|
||||
@@ -1111,6 +1115,8 @@ extern int cnt_pm;
|
||||
|
||||
extern void vp8_fix_contexts(MACROBLOCKD *x);
|
||||
|
||||
#include "valgrind/memcheck.h"
|
||||
|
||||
int vp8cx_encode_inter_macroblock
|
||||
(
|
||||
VP8_COMP *cpi, MACROBLOCK *x, TOKENEXTRA **t,
|
||||
@@ -1130,6 +1136,15 @@ int vp8cx_encode_inter_macroblock
|
||||
else
|
||||
x->encode_breakout = cpi->oxcf.encode_breakout;
|
||||
|
||||
if (cpi->external_modeinfo)
|
||||
{
|
||||
vp8_rd_use_external_mode(cpi, x, recon_yoffset, recon_uvoffset, &rate,
|
||||
&distortion, &intra_error);
|
||||
VALGRIND_CHECK_VALUE_IS_DEFINED(rate);
|
||||
VALGRIND_CHECK_VALUE_IS_DEFINED(distortion);
|
||||
VALGRIND_CHECK_VALUE_IS_DEFINED(intra_error);
|
||||
}
|
||||
else
|
||||
if (cpi->sf.RD)
|
||||
{
|
||||
int zbin_mode_boost_enabled = cpi->zbin_mode_boost_enabled;
|
||||
|
@@ -859,7 +859,7 @@ void vp8_set_speed_features(VP8_COMP *cpi)
|
||||
{
|
||||
sf->auto_filter = 0; // Faster selection of loop filter
|
||||
sf->search_method = HEX;
|
||||
sf->iterative_sub_pixel = 0;
|
||||
//sf->iterative_sub_pixel = 0;
|
||||
}
|
||||
|
||||
if (Speed > 6)
|
||||
@@ -2449,7 +2449,7 @@ int vp8_use_as_reference(VP8_COMP *cpi, int ref_frame_flags)
|
||||
}
|
||||
int vp8_update_reference(VP8_COMP *cpi, int ref_frame_flags)
|
||||
{
|
||||
if (ref_frame_flags > 7)
|
||||
if (ref_frame_flags > 127)
|
||||
return -1 ;
|
||||
|
||||
cpi->common.refresh_golden_frame = 0;
|
||||
@@ -2465,6 +2465,8 @@ int vp8_update_reference(VP8_COMP *cpi, int ref_frame_flags)
|
||||
if (ref_frame_flags & VP8_ALT_FLAG)
|
||||
cpi->common.refresh_alt_ref_frame = 1;
|
||||
|
||||
cpi->common.copy_buffer_to_gf = (ref_frame_flags >> 3) & 3;
|
||||
cpi->common.copy_buffer_to_arf = (ref_frame_flags >> 5) & 3;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -3187,8 +3189,11 @@ static void encode_frame_to_data_rate
|
||||
cpi->per_frame_bandwidth = (int)(cpi->target_bandwidth / cpi->output_frame_rate);
|
||||
|
||||
// Default turn off buffer to buffer copying
|
||||
if(!cpi->external_modeinfo)
|
||||
{
|
||||
cm->copy_buffer_to_gf = 0;
|
||||
cm->copy_buffer_to_arf = 0;
|
||||
}
|
||||
|
||||
// Clear zbin over-quant value and mode boost values.
|
||||
cpi->zbin_over_quant = 0;
|
||||
@@ -4063,10 +4068,14 @@ static void encode_frame_to_data_rate
|
||||
// For inter frames the current default behavior is that when
|
||||
// cm->refresh_golden_frame is set we copy the old GF over to the ARF buffer
|
||||
// This is purely an encoder decision at present.
|
||||
if (!cpi->oxcf.error_resilient_mode && cm->refresh_golden_frame)
|
||||
if(!cpi->external_modeinfo)
|
||||
{
|
||||
if (!cpi->oxcf.error_resilient_mode && cm->refresh_golden_frame
|
||||
&& !cm->refresh_alt_ref_frame)
|
||||
cm->copy_buffer_to_arf = 2;
|
||||
else
|
||||
cm->copy_buffer_to_arf = 0;
|
||||
}
|
||||
|
||||
cm->frame_to_show = &cm->yv12_fb[cm->new_fb_idx];
|
||||
|
||||
@@ -4620,7 +4629,12 @@ int vp8_get_compressed_data(VP8_COMP *cpi, unsigned int *frame_flags, unsigned l
|
||||
return -1;
|
||||
|
||||
cm = &cpi->common;
|
||||
|
||||
if(cm->refresh_last_frame && cm->refresh_golden_frame && cm->refresh_alt_ref_frame)
|
||||
{
|
||||
cm->refresh_golden_frame = 0;
|
||||
cm->refresh_alt_ref_frame = 0;
|
||||
*frame_flags |= 1;
|
||||
}
|
||||
if (setjmp(cpi->common.error.jmp))
|
||||
{
|
||||
cpi->common.error.setjmp = 0;
|
||||
|
@@ -678,7 +678,7 @@ typedef struct VP8_COMP
|
||||
/* Number of MBs per row at lower-resolution level */
|
||||
int mr_low_res_mb_cols;
|
||||
#endif
|
||||
|
||||
MODE_INFO *external_modeinfo;
|
||||
} VP8_COMP;
|
||||
|
||||
void control_data_rate(VP8_COMP *cpi);
|
||||
|
@@ -33,6 +33,7 @@
|
||||
#include "rdopt.h"
|
||||
#include "vpx_mem/vpx_mem.h"
|
||||
#include "vp8/common/systemdependent.h"
|
||||
#include "valgrind/memcheck.h"
|
||||
|
||||
extern void vp8_update_zbin_extra(VP8_COMP *cpi, MACROBLOCK *x);
|
||||
|
||||
@@ -735,11 +736,12 @@ static int rd_pick_intra4x4mby_modes(VP8_COMP *cpi, MACROBLOCK *mb, int *Rate,
|
||||
break;
|
||||
}
|
||||
|
||||
VALGRIND_CHECK_VALUE_IS_DEFINED(tot_rate_y);
|
||||
VALGRIND_CHECK_VALUE_IS_DEFINED(total_rd);
|
||||
if(total_rd >= (int64_t)best_rd)
|
||||
return INT_MAX;
|
||||
|
||||
*Rate = cost;
|
||||
*rate_y += tot_rate_y;
|
||||
*rate_y = tot_rate_y;
|
||||
*Distortion = distortion;
|
||||
|
||||
return RDCOST(mb->rdmult, mb->rddiv, cost, distortion);
|
||||
@@ -1477,6 +1479,246 @@ static int vp8_rd_pick_best_mbsegmentation(VP8_COMP *cpi, MACROBLOCK *x,
|
||||
return bsi.segment_rd;
|
||||
}
|
||||
|
||||
|
||||
static void rd_reuse_segment(VP8_COMP *cpi, MACROBLOCK *x,
|
||||
BEST_SEG_INFO *bsi, unsigned int segmentation)
|
||||
{
|
||||
int i;
|
||||
int const *labels;
|
||||
int br = 0;
|
||||
int bd = 0;
|
||||
B_PREDICTION_MODE this_mode;
|
||||
int_mv reused_mv[16];
|
||||
|
||||
|
||||
int label_count;
|
||||
int this_segment_rd = 0;
|
||||
int label_mv_thresh;
|
||||
int rate = 0;
|
||||
int sbr = 0;
|
||||
int sbd = 0;
|
||||
int segmentyrate = 0;
|
||||
|
||||
vp8_variance_fn_ptr_t *v_fn_ptr;
|
||||
|
||||
ENTROPY_CONTEXT_PLANES t_above, t_left;
|
||||
ENTROPY_CONTEXT *ta;
|
||||
ENTROPY_CONTEXT *tl;
|
||||
ENTROPY_CONTEXT_PLANES t_above_b, t_left_b;
|
||||
ENTROPY_CONTEXT *ta_b;
|
||||
ENTROPY_CONTEXT *tl_b;
|
||||
|
||||
vpx_memcpy(&t_above, x->e_mbd.above_context, sizeof(ENTROPY_CONTEXT_PLANES));
|
||||
vpx_memcpy(&t_left, x->e_mbd.left_context, sizeof(ENTROPY_CONTEXT_PLANES));
|
||||
|
||||
ta = (ENTROPY_CONTEXT *)&t_above;
|
||||
tl = (ENTROPY_CONTEXT *)&t_left;
|
||||
ta_b = (ENTROPY_CONTEXT *)&t_above_b;
|
||||
tl_b = (ENTROPY_CONTEXT *)&t_left_b;
|
||||
|
||||
br = 0;
|
||||
bd = 0;
|
||||
|
||||
v_fn_ptr = &cpi->fn_ptr[segmentation];
|
||||
labels = vp8_mbsplits[segmentation];
|
||||
label_count = vp8_mbsplit_count[segmentation];
|
||||
|
||||
// 64 makes this threshold really big effectively
|
||||
// making it so that we very rarely check mvs on
|
||||
// segments. setting this to 1 would make mv thresh
|
||||
// roughly equal to what it is for macroblocks
|
||||
label_mv_thresh = 1 * bsi->mvthresh / label_count ;
|
||||
|
||||
// Segmentation method overheads
|
||||
rate = vp8_cost_token(vp8_mbsplit_tree, vp8_mbsplit_probs, vp8_mbsplit_encodings + segmentation);
|
||||
rate += vp8_cost_mv_ref(SPLITMV, bsi->mdcounts);
|
||||
this_segment_rd += RDCOST(x->rdmult, x->rddiv, rate, 0);
|
||||
br += rate;
|
||||
|
||||
for (i = 0; i < 16; i++)
|
||||
reused_mv[i].as_int = x->e_mbd.block[i].bmi.mv.as_int;
|
||||
|
||||
for (i = 0; i < label_count; i++)
|
||||
{
|
||||
int_mv mode_mv[B_MODE_COUNT];
|
||||
int best_label_rd = INT_MAX;
|
||||
B_PREDICTION_MODE mode_selected = ZERO4X4;
|
||||
int bestlabelyrate = 0;
|
||||
|
||||
// search for the best motion vector on this segment
|
||||
for (this_mode = LEFT4X4; this_mode <= NEW4X4 ; this_mode ++)
|
||||
{
|
||||
int this_rd;
|
||||
int distortion;
|
||||
int labelyrate;
|
||||
ENTROPY_CONTEXT_PLANES t_above_s, t_left_s;
|
||||
ENTROPY_CONTEXT *ta_s;
|
||||
ENTROPY_CONTEXT *tl_s;
|
||||
|
||||
vpx_memcpy(&t_above_s, &t_above, sizeof(ENTROPY_CONTEXT_PLANES));
|
||||
vpx_memcpy(&t_left_s, &t_left, sizeof(ENTROPY_CONTEXT_PLANES));
|
||||
|
||||
ta_s = (ENTROPY_CONTEXT *)&t_above_s;
|
||||
tl_s = (ENTROPY_CONTEXT *)&t_left_s;
|
||||
|
||||
/* find the first block for this label */
|
||||
if (this_mode == NEW4X4)
|
||||
{
|
||||
int b;
|
||||
for(b=0; b<16; b++)
|
||||
if(labels[b] == i) break;
|
||||
mode_mv[NEW4X4].as_int = reused_mv[b].as_int;
|
||||
}
|
||||
|
||||
|
||||
rate = labels2mode(x, labels, i, this_mode, &mode_mv[this_mode],
|
||||
bsi->ref_mv, x->mvcost);
|
||||
|
||||
// Trap vectors that reach beyond the UMV borders
|
||||
if (((mode_mv[this_mode].as_mv.row >> 3) < x->mv_row_min) || ((mode_mv[this_mode].as_mv.row >> 3) > x->mv_row_max) ||
|
||||
((mode_mv[this_mode].as_mv.col >> 3) < x->mv_col_min) || ((mode_mv[this_mode].as_mv.col >> 3) > x->mv_col_max))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
distortion = vp8_encode_inter_mb_segment(x, labels, i) / 4;
|
||||
|
||||
labelyrate = rdcost_mbsegment_y(x, labels, i, ta_s, tl_s);
|
||||
rate += labelyrate;
|
||||
|
||||
this_rd = RDCOST(x->rdmult, x->rddiv, rate, distortion);
|
||||
|
||||
if (this_rd < best_label_rd)
|
||||
{
|
||||
sbr = rate;
|
||||
sbd = distortion;
|
||||
bestlabelyrate = labelyrate;
|
||||
mode_selected = this_mode;
|
||||
best_label_rd = this_rd;
|
||||
|
||||
vpx_memcpy(ta_b, ta_s, sizeof(ENTROPY_CONTEXT_PLANES));
|
||||
vpx_memcpy(tl_b, tl_s, sizeof(ENTROPY_CONTEXT_PLANES));
|
||||
|
||||
}
|
||||
} /*for each 4x4 mode*/
|
||||
|
||||
vpx_memcpy(ta, ta_b, sizeof(ENTROPY_CONTEXT_PLANES));
|
||||
vpx_memcpy(tl, tl_b, sizeof(ENTROPY_CONTEXT_PLANES));
|
||||
|
||||
labels2mode(x, labels, i, mode_selected, &mode_mv[mode_selected],
|
||||
bsi->ref_mv, x->mvcost);
|
||||
|
||||
br += sbr;
|
||||
bd += sbd;
|
||||
segmentyrate += bestlabelyrate;
|
||||
this_segment_rd += best_label_rd;
|
||||
|
||||
if (this_segment_rd >= bsi->segment_rd)
|
||||
break;
|
||||
|
||||
} /* for each label */
|
||||
|
||||
if (this_segment_rd < bsi->segment_rd)
|
||||
{
|
||||
bsi->r = br;
|
||||
bsi->d = bd;
|
||||
bsi->segment_yrate = segmentyrate;
|
||||
bsi->segment_rd = this_segment_rd;
|
||||
bsi->segment_num = segmentation;
|
||||
|
||||
// store everything needed to come back to this!!
|
||||
for (i = 0; i < 16; i++)
|
||||
{
|
||||
bsi->mvs[i].as_mv = x->partition_info->bmi[i].mv.as_mv;
|
||||
bsi->modes[i] = x->partition_info->bmi[i].mode;
|
||||
bsi->eobs[i] = x->e_mbd.eobs[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int vp8_rd_reuse_mbsegmentation(VP8_COMP *cpi, MACROBLOCK *x,
|
||||
int_mv *best_ref_mv, int best_rd,
|
||||
int *mdcounts, int *returntotrate,
|
||||
int *returnyrate, int *returndistortion,
|
||||
int mvthresh)
|
||||
{
|
||||
int i;
|
||||
BEST_SEG_INFO bsi;
|
||||
|
||||
vpx_memset(&bsi, 0, sizeof(bsi));
|
||||
|
||||
bsi.segment_rd = best_rd;
|
||||
bsi.ref_mv = best_ref_mv;
|
||||
bsi.mvp.as_int = best_ref_mv->as_int;
|
||||
bsi.mvthresh = mvthresh;
|
||||
bsi.mdcounts = mdcounts;
|
||||
|
||||
for(i = 0; i < 16; i++)
|
||||
{
|
||||
bsi.modes[i] = ZERO4X4;
|
||||
}
|
||||
|
||||
{
|
||||
int s;
|
||||
|
||||
for(s = 0; s < BLOCK_4X4; s++)
|
||||
{
|
||||
char set[16] = {0};
|
||||
int smv[16];
|
||||
|
||||
for (i=0; i<16; i++)
|
||||
{
|
||||
int p = vp8_mbsplits[s][i];
|
||||
|
||||
if(!set[p])
|
||||
{
|
||||
set[p] = 1;
|
||||
smv[p] = x->e_mbd.block[i].bmi.mv.as_int;
|
||||
}
|
||||
if(smv[p] != x->e_mbd.block[i].bmi.mv.as_int)
|
||||
break;
|
||||
}
|
||||
if(i==16)
|
||||
break;
|
||||
}
|
||||
rd_check_segment(cpi, x, &bsi, s);
|
||||
}
|
||||
|
||||
/* set it to the best */
|
||||
for (i = 0; i < 16; i++)
|
||||
{
|
||||
BLOCKD *bd = &x->e_mbd.block[i];
|
||||
|
||||
bd->bmi.mv.as_int = bsi.mvs[i].as_int;
|
||||
*bd->eob = bsi.eobs[i];
|
||||
}
|
||||
|
||||
*returntotrate = bsi.r;
|
||||
*returndistortion = bsi.d;
|
||||
*returnyrate = bsi.segment_yrate;
|
||||
|
||||
/* save partitions */
|
||||
x->e_mbd.mode_info_context->mbmi.partitioning = bsi.segment_num;
|
||||
x->partition_info->count = vp8_mbsplit_count[bsi.segment_num];
|
||||
|
||||
for (i = 0; i < x->partition_info->count; i++)
|
||||
{
|
||||
int j;
|
||||
|
||||
j = vp8_mbsplit_offset[bsi.segment_num][i];
|
||||
|
||||
x->partition_info->bmi[i].mode = bsi.modes[j];
|
||||
x->partition_info->bmi[i].mv.as_mv = bsi.mvs[j].as_mv;
|
||||
}
|
||||
/*
|
||||
* used to set x->e_mbd.mode_info_context->mbmi.mv.as_int
|
||||
*/
|
||||
x->partition_info->bmi[15].mv.as_int = bsi.mvs[15].as_int;
|
||||
|
||||
return bsi.segment_rd;
|
||||
}
|
||||
|
||||
//The improved MV prediction
|
||||
void vp8_mv_pred
|
||||
(
|
||||
@@ -1709,6 +1951,591 @@ static void rd_update_mvcount(VP8_COMP *cpi, MACROBLOCK *x, int_mv *best_ref_mv)
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
void vp8_rd_use_external_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset,
|
||||
int recon_uvoffset, int *returnrate,
|
||||
int *returndistortion, int *returnintra)
|
||||
{
|
||||
unsigned char *plane[4][3];
|
||||
MODE_INFO *mi;
|
||||
int rate, rate_y, rate_uv;
|
||||
int distortion, distortion_y, distortion_uv;
|
||||
|
||||
|
||||
mi = cpi->external_modeinfo + x->e_mbd.mbrc;
|
||||
*x->e_mbd.mode_info_context = *mi;
|
||||
|
||||
/* Map partitioning info */
|
||||
if(mi->mbmi.mode == SPLITMV)
|
||||
{
|
||||
int i;
|
||||
|
||||
x->partition_info->count = vp8_mbsplit_count[mi->mbmi.partitioning];
|
||||
|
||||
for (i = 0; i < x->partition_info->count; i++)
|
||||
{
|
||||
int j;
|
||||
|
||||
j = vp8_mbsplit_offset[mi->mbmi.partitioning][i];
|
||||
|
||||
/* TODO: this is mapping a union onto a struct, assume the
|
||||
* data will never be looked at from the wrong context.
|
||||
*/
|
||||
x->partition_info->bmi[i].mode = NEW4X4; //mi->bmi[j].as_mode;
|
||||
x->partition_info->bmi[i].mv.as_int = mi->bmi[j].mv.as_int;
|
||||
}
|
||||
/*
|
||||
* used to set x->e_mbd.mode_info_context->mbmi.mv.as_int
|
||||
*/
|
||||
x->partition_info->bmi[15].mv.as_int = mi->bmi[15].mv.as_int;
|
||||
}
|
||||
|
||||
rate = x->mbmode_cost[x->e_mbd.frame_type][mi->mbmi.mode];
|
||||
rate += x->ref_frame_cost[mi->mbmi.ref_frame];
|
||||
if(mi->mbmi.ref_frame == INTRA_FRAME)
|
||||
{
|
||||
vp8_build_intra_predictors_mby(&x->e_mbd);
|
||||
macro_block_yrd(x, &rate_y, &distortion);
|
||||
//hack
|
||||
rate_uv = rate_y/4;
|
||||
distortion_uv = distortion_y/4;
|
||||
}
|
||||
else
|
||||
{
|
||||
int sign_bias;
|
||||
int_mv best_ref_mv_sb[2];
|
||||
int_mv mode_mv_sb[2][MB_MODE_COUNT];
|
||||
int_mv best_ref_mv;
|
||||
int mdcounts[4];
|
||||
|
||||
get_predictor_pointers(cpi, plane, recon_yoffset, recon_uvoffset);
|
||||
x->e_mbd.pre.y_buffer = plane[mi->mbmi.ref_frame][0];
|
||||
x->e_mbd.pre.u_buffer = plane[mi->mbmi.ref_frame][1];
|
||||
x->e_mbd.pre.v_buffer = plane[mi->mbmi.ref_frame][2];
|
||||
|
||||
/* Get nearby MV info */
|
||||
sign_bias = vp8_find_near_mvs_bias(&x->e_mbd,
|
||||
x->e_mbd.mode_info_context,
|
||||
mode_mv_sb,
|
||||
best_ref_mv_sb,
|
||||
mdcounts,
|
||||
mi->mbmi.ref_frame,
|
||||
cpi->common.ref_frame_sign_bias);
|
||||
best_ref_mv.as_int = best_ref_mv_sb[sign_bias].as_int;
|
||||
|
||||
if(mi->mbmi.mode != ZEROMV)
|
||||
rate += vp8_mv_bit_cost(&mi->mbmi.mv, &best_ref_mv, x->mvcost, 96);
|
||||
rate += vp8_cost_mv_ref(mi->mbmi.mode, mdcounts);
|
||||
|
||||
vp8_build_inter16x16_predictors_mby(&x->e_mbd, x->e_mbd.predictor, 16);
|
||||
//rate += vp8_cost_mv_ref(mi->mbmi.mode, mdcounts);
|
||||
|
||||
// Y cost and distortion
|
||||
macro_block_yrd(x, &rate_y, &distortion_y);
|
||||
|
||||
// UV cost and distortion
|
||||
rd_inter16x16_uv(cpi, x, &rate_uv, &distortion_uv,
|
||||
cpi->common.full_pixel);
|
||||
}
|
||||
|
||||
/* Test for skip blocks */
|
||||
if (cpi->common.mb_no_coeff_skip)
|
||||
{
|
||||
int i, bit=1;
|
||||
|
||||
for(i=0; i<24; i++)
|
||||
if(x->e_mbd.eobs[i])
|
||||
{
|
||||
bit = 0;
|
||||
break;
|
||||
}
|
||||
if(bit)
|
||||
{
|
||||
rate_y = 0;
|
||||
rate_uv = 0;
|
||||
}
|
||||
rate += vp8_cost_bit(cpi->prob_skip_false, bit);
|
||||
}
|
||||
|
||||
*returnrate = rate + rate_y + rate_uv;
|
||||
*returndistortion = distortion + distortion_y + distortion_uv;
|
||||
*returnintra = (mi->mbmi.ref_frame == INTRA_FRAME)
|
||||
? *returndistortion : INT_MAX;
|
||||
}
|
||||
#else
|
||||
void vp8_rd_use_external_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset,
|
||||
int recon_uvoffset, int *returnrate,
|
||||
int *returndistortion, int *returnintra)
|
||||
{
|
||||
MODE_INFO *mi = cpi->external_modeinfo + x->e_mbd.mbrc;
|
||||
BLOCK *b = &x->block[0];
|
||||
BLOCKD *d = &x->e_mbd.block[0];
|
||||
MACROBLOCKD *xd = &x->e_mbd;
|
||||
union b_mode_info best_bmodes[16];
|
||||
MB_MODE_INFO best_mbmode;
|
||||
PARTITION_INFO best_partition;
|
||||
int_mv best_ref_mv_sb[2];
|
||||
int_mv mode_mv_sb[2][MB_MODE_COUNT];
|
||||
int_mv best_ref_mv;
|
||||
int_mv *mode_mv;
|
||||
MB_PREDICTION_MODE this_mode;
|
||||
int num00;
|
||||
|
||||
int i;
|
||||
int mdcounts[4];
|
||||
int rate=0;
|
||||
int distortion=0;
|
||||
int best_rd = INT_MAX;
|
||||
int rate2, distortion2;
|
||||
int uv_intra_rate, uv_intra_distortion, uv_intra_rate_tokenonly;
|
||||
int rate_y, UNINITIALIZED_IS_SAFE(rate_uv);
|
||||
int distortion_uv;
|
||||
int best_yrd = INT_MAX;
|
||||
|
||||
MB_PREDICTION_MODE uv_intra_mode;
|
||||
int_mv mvp;
|
||||
int near_sadidx[8] = {0, 1, 2, 3, 4, 5, 6, 7};
|
||||
int saddone=0;
|
||||
int sr=0; //search range got from mv_pred(). It uses step_param levels. (0-7)
|
||||
|
||||
unsigned char *plane[4][3];
|
||||
int sign_bias = 0;
|
||||
|
||||
mode_mv = mode_mv_sb[sign_bias];
|
||||
best_ref_mv.as_int = 0;
|
||||
vpx_memset(mode_mv_sb, 0, sizeof(mode_mv_sb));
|
||||
vpx_memset(&best_mbmode, 0, sizeof(best_mbmode));
|
||||
vpx_memset(&best_bmodes, 0, sizeof(best_bmodes));
|
||||
|
||||
{
|
||||
sign_bias = vp8_find_near_mvs_bias(&x->e_mbd,
|
||||
x->e_mbd.mode_info_context,
|
||||
mode_mv_sb,
|
||||
best_ref_mv_sb,
|
||||
mdcounts,
|
||||
LAST_FRAME,
|
||||
cpi->common.ref_frame_sign_bias);
|
||||
|
||||
mode_mv = mode_mv_sb[sign_bias];
|
||||
best_ref_mv.as_int = best_ref_mv_sb[sign_bias].as_int;
|
||||
}
|
||||
|
||||
cpi->ref_frame_flags|=0x7;
|
||||
get_predictor_pointers(cpi, plane, recon_yoffset, recon_uvoffset);
|
||||
|
||||
*returnintra = INT_MAX;
|
||||
cpi->mbs_tested_so_far++; // Count of the number of MBs tested so far this frame
|
||||
|
||||
x->skip = 0;
|
||||
|
||||
x->e_mbd.mode_info_context->mbmi.ref_frame = INTRA_FRAME;
|
||||
rd_pick_intra_mbuv_mode(cpi, x, &uv_intra_rate, &uv_intra_rate_tokenonly, &uv_intra_distortion);
|
||||
uv_intra_mode = x->e_mbd.mode_info_context->mbmi.uv_mode;
|
||||
|
||||
{
|
||||
int this_rd = INT_MAX;
|
||||
int disable_skip = 0;
|
||||
int other_cost = 0;
|
||||
int this_ref_frame;
|
||||
|
||||
// These variables hold are rolling total cost and distortion for this mode
|
||||
rate2 = 0;
|
||||
distortion2 = 0;
|
||||
|
||||
this_mode = mi->mbmi.mode; //JRK
|
||||
this_ref_frame = mi->mbmi.ref_frame;
|
||||
|
||||
#if 1
|
||||
memcpy(x->e_mbd.mode_info_context, mi, sizeof(*mi));
|
||||
#else
|
||||
x->e_mbd.mode_info_context->mbmi.mode = this_mode;
|
||||
x->e_mbd.mode_info_context->mbmi.uv_mode = DC_PRED;
|
||||
x->e_mbd.mode_info_context->mbmi.ref_frame = this_ref_frame;
|
||||
#endif
|
||||
//if(this_mode == SPLITMV) this_mode=NEWMV;
|
||||
/* everything but intra */
|
||||
if (x->e_mbd.mode_info_context->mbmi.ref_frame)
|
||||
{
|
||||
x->e_mbd.pre.y_buffer = plane[this_ref_frame][0];
|
||||
x->e_mbd.pre.u_buffer = plane[this_ref_frame][1];
|
||||
x->e_mbd.pre.v_buffer = plane[this_ref_frame][2];
|
||||
|
||||
if (sign_bias != cpi->common.ref_frame_sign_bias[this_ref_frame])
|
||||
{
|
||||
sign_bias = cpi->common.ref_frame_sign_bias[this_ref_frame];
|
||||
mode_mv = mode_mv_sb[sign_bias];
|
||||
best_ref_mv.as_int = best_ref_mv_sb[sign_bias].as_int;
|
||||
}
|
||||
}
|
||||
|
||||
// Experimental code. Special case for gf and arf zeromv modes. Increase zbin size to supress noise
|
||||
if (cpi->zbin_mode_boost_enabled)
|
||||
{
|
||||
if ( this_ref_frame == INTRA_FRAME )
|
||||
cpi->zbin_mode_boost = 0;
|
||||
else
|
||||
{
|
||||
if (this_mode == ZEROMV)
|
||||
{
|
||||
if (this_ref_frame != LAST_FRAME)
|
||||
cpi->zbin_mode_boost = GF_ZEROMV_ZBIN_BOOST;
|
||||
else
|
||||
cpi->zbin_mode_boost = LF_ZEROMV_ZBIN_BOOST;
|
||||
}
|
||||
else if (this_mode == SPLITMV)
|
||||
cpi->zbin_mode_boost = 0;
|
||||
else
|
||||
cpi->zbin_mode_boost = MV_ZBIN_BOOST;
|
||||
}
|
||||
|
||||
vp8_update_zbin_extra(cpi, x);
|
||||
}
|
||||
|
||||
VALGRIND_CHECK_VALUE_IS_DEFINED(rate2);
|
||||
switch (this_mode)
|
||||
{
|
||||
case B_PRED:
|
||||
{
|
||||
int tmp_rd;
|
||||
|
||||
// Note the rate value returned here includes the cost of coding the BPRED mode : x->mbmode_cost[x->e_mbd.frame_type][BPRED];
|
||||
tmp_rd = rd_pick_intra4x4mby_modes(cpi, x, &rate, &rate_y, &distortion, INT_MAX);
|
||||
VALGRIND_CHECK_VALUE_IS_DEFINED(rate);
|
||||
VALGRIND_CHECK_VALUE_IS_DEFINED(rate_y);
|
||||
VALGRIND_CHECK_VALUE_IS_DEFINED(distortion);
|
||||
rate2 += rate;
|
||||
distortion2 += distortion;
|
||||
|
||||
if(tmp_rd < best_yrd)
|
||||
{
|
||||
rate2 += uv_intra_rate;
|
||||
rate_uv = uv_intra_rate_tokenonly;
|
||||
distortion2 += uv_intra_distortion;
|
||||
distortion_uv = uv_intra_distortion;
|
||||
}
|
||||
else
|
||||
{
|
||||
this_rd = INT_MAX;
|
||||
disable_skip = 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SPLITMV:
|
||||
{
|
||||
#if 1
|
||||
int tmp_rd;
|
||||
int this_rd_thresh;
|
||||
|
||||
//this_rd_thresh = (this_ref_frame == 1) ? cpi->rd_threshes[THR_NEW1] : cpi->rd_threshes[THR_NEW3];
|
||||
//this_rd_thresh = (this_ref_frame == 2) ? cpi->rd_threshes[THR_NEW2] : this_rd_thresh;
|
||||
this_rd_thresh = 0;
|
||||
|
||||
#if 0
|
||||
tmp_rd = vp8_rd_pick_best_mbsegmentation(cpi, x, &best_ref_mv,
|
||||
best_yrd, mdcounts,
|
||||
&rate, &rate_y, &distortion, this_rd_thresh) ;
|
||||
#else
|
||||
tmp_rd = vp8_rd_reuse_mbsegmentation(cpi, x, &best_ref_mv,
|
||||
best_yrd, mdcounts,
|
||||
&rate, &rate_y, &distortion, this_rd_thresh) ;
|
||||
#endif
|
||||
|
||||
VALGRIND_CHECK_VALUE_IS_DEFINED(rate);
|
||||
VALGRIND_CHECK_VALUE_IS_DEFINED(distortion);
|
||||
rate2 += rate;
|
||||
distortion2 += distortion;
|
||||
|
||||
// If even the 'Y' rd value of split is higher than best so far then dont bother looking at UV
|
||||
if (tmp_rd < best_yrd)
|
||||
{
|
||||
// Now work out UV cost and add it in
|
||||
rd_inter4x4_uv(cpi, x, &rate_uv, &distortion_uv, cpi->common.full_pixel);
|
||||
rate2 += rate_uv;
|
||||
distortion2 += distortion_uv;
|
||||
}
|
||||
else
|
||||
{
|
||||
this_rd = INT_MAX;
|
||||
disable_skip = 1;
|
||||
}
|
||||
#else
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 16; i++)
|
||||
{
|
||||
x->e_mbd.block[i].bmi = mi->bmi[i];
|
||||
x->e_mbd.block[i].eob = 15;
|
||||
}
|
||||
x->e_mbd.mode_info_context->mbmi.partitioning = mi->mbmi.partitioning;
|
||||
x->partition_info->count = vp8_mbsplit_count[mi->mbmi.partitioning];
|
||||
for (i = 0; i < x->partition_info->count; i++)
|
||||
{
|
||||
int j;
|
||||
|
||||
j = vp8_mbsplit_offset[mi->mbmi.partitioning][i];
|
||||
|
||||
x->partition_info->bmi[i].mode =
|
||||
mi->bmi[j].mv.as_int ? NEW4X4 : ZERO4X4;
|
||||
x->partition_info->bmi[i].mv.as_mv = mi->bmi[j].mv.as_mv;
|
||||
distortion2 = vp8_encode_inter_mb_segment(x, vp8_mbsplits[segmentation], i);
|
||||
rate2 = 0;
|
||||
}
|
||||
// rate = labels2mode(x, labels, i, this_mode, &mode_mv[this_mode], bsi->ref_mv, x->mvcost);
|
||||
|
||||
#endif
|
||||
}
|
||||
VALGRIND_CHECK_VALUE_IS_DEFINED(rate_y);
|
||||
break;
|
||||
case DC_PRED:
|
||||
case V_PRED:
|
||||
case H_PRED:
|
||||
case TM_PRED:
|
||||
x->e_mbd.mode_info_context->mbmi.ref_frame = INTRA_FRAME;
|
||||
vp8_build_intra_predictors_mby
|
||||
(&x->e_mbd);
|
||||
macro_block_yrd(x, &rate_y, &distortion) ;
|
||||
rate2 += rate_y;
|
||||
distortion2 += distortion;
|
||||
rate2 += x->mbmode_cost[x->e_mbd.frame_type][x->e_mbd.mode_info_context->mbmi.mode];
|
||||
rate2 += uv_intra_rate;
|
||||
rate_uv = uv_intra_rate_tokenonly;
|
||||
distortion2 += uv_intra_distortion;
|
||||
distortion_uv = uv_intra_distortion;
|
||||
VALGRIND_CHECK_VALUE_IS_DEFINED(rate_y);
|
||||
break;
|
||||
|
||||
case NEWMV:
|
||||
mode_mv[NEWMV].as_int = mi->mbmi.mv.as_int;
|
||||
case NEARESTMV:
|
||||
case NEARMV:
|
||||
// Clip "next_nearest" so that it does not extend to far out of image
|
||||
vp8_clamp_mv2(&mode_mv[this_mode], xd);
|
||||
|
||||
// Do not bother proceeding if the vector (from newmv,nearest or near) is 0,0 as this should then be coded using the zeromv mode.
|
||||
if (((this_mode == NEARMV) || (this_mode == NEARESTMV)) && (mode_mv[this_mode].as_int == 0))
|
||||
this_mode = ZEROMV;
|
||||
|
||||
case ZEROMV:
|
||||
|
||||
// Trap vectors that reach beyond the UMV borders
|
||||
// Note that ALL New MV, Nearest MV Near MV and Zero MV code drops through to this point
|
||||
// because of the lack of break statements in the previous two cases.
|
||||
if (((mode_mv[this_mode].as_mv.row >> 3) < x->mv_row_min) || ((mode_mv[this_mode].as_mv.row >> 3) > x->mv_row_max) ||
|
||||
((mode_mv[this_mode].as_mv.col >> 3) < x->mv_col_min) || ((mode_mv[this_mode].as_mv.col >> 3) > x->mv_col_max))
|
||||
assert(0);
|
||||
|
||||
vp8_set_mbmode_and_mvs(x, this_mode, &mode_mv[this_mode]);
|
||||
vp8_build_inter16x16_predictors_mby(&x->e_mbd, x->e_mbd.predictor, 16);
|
||||
|
||||
if (cpi->active_map_enabled && x->active_ptr[0] == 0) {
|
||||
x->skip = 1;
|
||||
}
|
||||
else if (x->encode_breakout)
|
||||
{
|
||||
unsigned int sse;
|
||||
unsigned int var;
|
||||
int threshold = (xd->block[0].dequant[1]
|
||||
* xd->block[0].dequant[1] >>4);
|
||||
|
||||
if(threshold < x->encode_breakout)
|
||||
threshold = x->encode_breakout;
|
||||
|
||||
var = vp8_variance16x16
|
||||
(*(b->base_src), b->src_stride,
|
||||
x->e_mbd.predictor, 16, &sse);
|
||||
|
||||
if (sse < threshold)
|
||||
{
|
||||
unsigned int q2dc = xd->block[24].dequant[0];
|
||||
/* If theres is no codeable 2nd order dc
|
||||
or a very small uniform pixel change change */
|
||||
if ((sse - var < q2dc * q2dc >>4) ||
|
||||
(sse /2 > var && sse-var < 64))
|
||||
{
|
||||
// Check u and v to make sure skip is ok
|
||||
int sse2= VP8_UVSSE(x);
|
||||
if (sse2 * 2 < threshold)
|
||||
{
|
||||
x->skip = 1;
|
||||
distortion2 = sse + sse2;
|
||||
rate2 = 500;
|
||||
|
||||
/* for best_yrd calculation */
|
||||
rate_uv = 0;
|
||||
distortion_uv = sse2;
|
||||
|
||||
disable_skip = 1;
|
||||
this_rd = RDCOST(x->rdmult, x->rddiv, rate2, distortion2);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//intermodecost[mode_index] = vp8_cost_mv_ref(this_mode, mdcounts); // Experimental debug code
|
||||
|
||||
// Add in the Mv/mode cost
|
||||
rate2 += vp8_cost_mv_ref(this_mode, mdcounts);
|
||||
|
||||
// Y cost and distortion
|
||||
macro_block_yrd(x, &rate_y, &distortion);
|
||||
rate2 += rate_y;
|
||||
distortion2 += distortion;
|
||||
|
||||
// UV cost and distortion
|
||||
rd_inter16x16_uv(cpi, x, &rate_uv, &distortion_uv, cpi->common.full_pixel);
|
||||
rate2 += rate_uv;
|
||||
distortion2 += distortion_uv;
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
VALGRIND_CHECK_VALUE_IS_DEFINED(rate_y);
|
||||
|
||||
VALGRIND_CHECK_VALUE_IS_DEFINED(rate2);
|
||||
// Where skip is allowable add in the default per mb cost for the no skip case.
|
||||
// where we then decide to skip we have to delete this and replace it with the
|
||||
// cost of signallying a skip
|
||||
if (cpi->common.mb_no_coeff_skip)
|
||||
{
|
||||
other_cost += vp8_cost_bit(cpi->prob_skip_false, 0);
|
||||
rate2 += other_cost;
|
||||
}
|
||||
|
||||
/* Estimate the reference frame signaling cost and add it
|
||||
* to the rolling cost variable.
|
||||
*/
|
||||
rate2 +=
|
||||
x->ref_frame_cost[x->e_mbd.mode_info_context->mbmi.ref_frame];
|
||||
|
||||
VALGRIND_CHECK_VALUE_IS_DEFINED(rate2);
|
||||
VALGRIND_CHECK_VALUE_IS_DEFINED(rate_y);
|
||||
VALGRIND_CHECK_VALUE_IS_DEFINED(rate_uv);
|
||||
if (!disable_skip)
|
||||
{
|
||||
// Test for the condition where skip block will be activated because there are no non zero coefficients and make any necessary adjustment for rate
|
||||
if (cpi->common.mb_no_coeff_skip)
|
||||
{
|
||||
int tteob;
|
||||
|
||||
tteob = 0;
|
||||
|
||||
for (i = 0; i <= 24; i++)
|
||||
{
|
||||
tteob += x->e_mbd.eobs[i];
|
||||
}
|
||||
|
||||
if (tteob == 0)
|
||||
{
|
||||
rate2 -= (rate_y + rate_uv);
|
||||
//for best_yrd calculation
|
||||
rate_uv = 0;
|
||||
|
||||
// Back out no skip flag costing and add in skip flag costing
|
||||
if (cpi->prob_skip_false)
|
||||
{
|
||||
int prob_skip_cost;
|
||||
|
||||
prob_skip_cost = vp8_cost_bit(cpi->prob_skip_false, 1);
|
||||
prob_skip_cost -= vp8_cost_bit(cpi->prob_skip_false, 0);
|
||||
rate2 += prob_skip_cost;
|
||||
other_cost += prob_skip_cost;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Calculate the final RD estimate for this mode
|
||||
this_rd = RDCOST(x->rdmult, x->rddiv, rate2, distortion2);
|
||||
}
|
||||
|
||||
VALGRIND_CHECK_VALUE_IS_DEFINED(rate2);
|
||||
// Keep record of best intra distortion
|
||||
if (x->e_mbd.mode_info_context->mbmi.ref_frame == INTRA_FRAME)
|
||||
{
|
||||
*returnintra = distortion2 ;
|
||||
}
|
||||
|
||||
// Did this mode help.. i.i is it the new best mode
|
||||
{
|
||||
if (this_mode <= B_PRED)
|
||||
{
|
||||
x->e_mbd.mode_info_context->mbmi.uv_mode = uv_intra_mode;
|
||||
/* required for left and above block mv */
|
||||
x->e_mbd.mode_info_context->mbmi.mv.as_int = 0;
|
||||
}
|
||||
|
||||
other_cost +=
|
||||
x->ref_frame_cost[x->e_mbd.mode_info_context->mbmi.ref_frame];
|
||||
|
||||
/* Calculate the final y RD estimate for this mode */
|
||||
best_yrd = RDCOST(x->rdmult, x->rddiv, (rate2-rate_uv-other_cost),
|
||||
(distortion2-distortion_uv));
|
||||
|
||||
VALGRIND_CHECK_VALUE_IS_DEFINED(rate2);
|
||||
*returnrate = rate2;
|
||||
*returndistortion = distortion2;
|
||||
best_rd = this_rd;
|
||||
vpx_memcpy(&best_mbmode, &x->e_mbd.mode_info_context->mbmi, sizeof(MB_MODE_INFO));
|
||||
vpx_memcpy(&best_partition, x->partition_info, sizeof(PARTITION_INFO));
|
||||
|
||||
if ((this_mode == B_PRED) || (this_mode == SPLITMV))
|
||||
for (i = 0; i < 16; i++)
|
||||
{
|
||||
best_bmodes[i] = x->e_mbd.block[i].bmi;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VALGRIND_CHECK_VALUE_IS_DEFINED(*returnrate);
|
||||
VALGRIND_CHECK_VALUE_IS_DEFINED(*returndistortion);
|
||||
VALGRIND_CHECK_VALUE_IS_DEFINED(*returnintra);
|
||||
|
||||
if (cpi->is_src_frame_alt_ref &&
|
||||
(best_mbmode.mode != ZEROMV || best_mbmode.ref_frame != ALTREF_FRAME))
|
||||
{
|
||||
x->e_mbd.mode_info_context->mbmi.mode = ZEROMV;
|
||||
x->e_mbd.mode_info_context->mbmi.ref_frame = ALTREF_FRAME;
|
||||
x->e_mbd.mode_info_context->mbmi.mv.as_int = 0;
|
||||
x->e_mbd.mode_info_context->mbmi.uv_mode = DC_PRED;
|
||||
x->e_mbd.mode_info_context->mbmi.mb_skip_coeff =
|
||||
(cpi->common.mb_no_coeff_skip);
|
||||
x->e_mbd.mode_info_context->mbmi.partitioning = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// macroblock modes
|
||||
vpx_memcpy(&x->e_mbd.mode_info_context->mbmi, &best_mbmode, sizeof(MB_MODE_INFO));
|
||||
|
||||
if (best_mbmode.mode == B_PRED)
|
||||
{
|
||||
for (i = 0; i < 16; i++)
|
||||
xd->mode_info_context->bmi[i].as_mode = best_bmodes[i].as_mode;
|
||||
}
|
||||
|
||||
if (best_mbmode.mode == SPLITMV)
|
||||
{
|
||||
for (i = 0; i < 16; i++)
|
||||
xd->mode_info_context->bmi[i].mv.as_int = best_bmodes[i].mv.as_int;
|
||||
|
||||
vpx_memcpy(x->partition_info, &best_partition, sizeof(PARTITION_INFO));
|
||||
|
||||
x->e_mbd.mode_info_context->mbmi.mv.as_int =
|
||||
x->partition_info->bmi[15].mv.as_int;
|
||||
}
|
||||
|
||||
if (sign_bias
|
||||
!= cpi->common.ref_frame_sign_bias[xd->mode_info_context->mbmi.ref_frame])
|
||||
best_ref_mv.as_int = best_ref_mv_sb[!sign_bias].as_int;
|
||||
|
||||
rd_update_mvcount(cpi, x, &best_ref_mv);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset,
|
||||
int recon_uvoffset, int *returnrate,
|
||||
|
@@ -77,6 +77,18 @@ static const struct extraconfig_map extracfg_map[] =
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct cx_data_iter
|
||||
{
|
||||
struct vpx_codec_cx_pkt pkt;
|
||||
int frame_out;
|
||||
int pkt_list_done;
|
||||
vpx_codec_iter_t pkt_list_iter;
|
||||
int mode_info_done;
|
||||
int mode_info_row;
|
||||
};
|
||||
|
||||
|
||||
struct vpx_codec_alg_priv
|
||||
{
|
||||
vpx_codec_priv_t base;
|
||||
@@ -92,6 +104,7 @@ struct vpx_codec_alg_priv
|
||||
vpx_codec_pkt_list_decl(64) pkt_list; // changed to accomendate the maximum number of lagged frames allowed
|
||||
int deprecated_mode;
|
||||
unsigned int fixed_kf_cntr;
|
||||
struct cx_data_iter cx_data_iter;
|
||||
};
|
||||
|
||||
|
||||
@@ -952,7 +965,45 @@ static vpx_codec_err_t vp8e_encode(vpx_codec_alg_priv_t *ctx,
|
||||
static const vpx_codec_cx_pkt_t *vp8e_get_cxdata(vpx_codec_alg_priv_t *ctx,
|
||||
vpx_codec_iter_t *iter)
|
||||
{
|
||||
return vpx_codec_pkt_list_get(&ctx->pkt_list.head, iter);
|
||||
if(!*iter)
|
||||
{
|
||||
memset(&ctx->cx_data_iter, 0, sizeof(ctx->cx_data_iter));
|
||||
*iter = &ctx->cx_data_iter;
|
||||
}
|
||||
if(!ctx->cx_data_iter.pkt_list_done)
|
||||
{
|
||||
const vpx_codec_cx_pkt_t *pkt;
|
||||
|
||||
pkt = vpx_codec_pkt_list_get(&ctx->pkt_list.head,
|
||||
&ctx->cx_data_iter.pkt_list_iter);
|
||||
if(pkt)
|
||||
{
|
||||
ctx->cx_data_iter.frame_out = 1;
|
||||
return pkt;
|
||||
}
|
||||
ctx->cx_data_iter.pkt_list_done = 1;
|
||||
}
|
||||
if(!ctx->cx_data_iter.frame_out)
|
||||
return NULL;
|
||||
if(!ctx->cx_data_iter.mode_info_done)
|
||||
{
|
||||
vpx_codec_cx_pkt_t *pkt = &ctx->cx_data_iter.pkt;
|
||||
|
||||
if(ctx->cx_data_iter.mode_info_row < ctx->cpi->common.mb_rows)
|
||||
{
|
||||
pkt->kind = VPX_CODEC_CUSTOM_PKT;
|
||||
pkt->data.raw.buf = ctx->cpi->common.mi
|
||||
+ ctx->cpi->common.mode_info_stride
|
||||
* ctx->cx_data_iter.mode_info_row;
|
||||
pkt->data.raw.sz = sizeof(MODE_INFO) * ctx->cpi->common.mb_cols;
|
||||
|
||||
ctx->cx_data_iter.mode_info_row++;
|
||||
return pkt;
|
||||
}
|
||||
else
|
||||
ctx->cx_data_iter.mode_info_done = 1;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static vpx_codec_err_t vp8e_set_reference(vpx_codec_alg_priv_t *ctx,
|
||||
@@ -1168,6 +1219,38 @@ static vpx_codec_err_t vp8e_set_scalemode(vpx_codec_alg_priv_t *ctx,
|
||||
}
|
||||
|
||||
|
||||
static vpx_codec_err_t set_modeinfo(vpx_codec_alg_priv_t *ctx,
|
||||
int ctr_id,
|
||||
va_list args)
|
||||
{
|
||||
vpx_fixed_buf_t *data = va_arg(args, vpx_fixed_buf_t *);
|
||||
|
||||
ctx->cpi->external_modeinfo = data ? data->buf : NULL;
|
||||
return VPX_CODEC_OK;
|
||||
}
|
||||
|
||||
|
||||
static vpx_codec_err_t vp8_get_last_ref_updates(vpx_codec_alg_priv_t *ctx,
|
||||
int ctrl_id,
|
||||
va_list args)
|
||||
{
|
||||
int *update_info = va_arg(args, int *);
|
||||
VP8_COMP *pbi = ctx->cpi;
|
||||
|
||||
if (update_info)
|
||||
{
|
||||
*update_info = pbi->common.refresh_alt_ref_frame * (int) VP8_ALTR_FRAME
|
||||
+ pbi->common.refresh_golden_frame * (int) VP8_GOLD_FRAME
|
||||
+ pbi->common.refresh_last_frame * (int) VP8_LAST_FRAME
|
||||
+ (pbi->common.copy_buffer_to_gf << 3)
|
||||
+ (pbi->common.copy_buffer_to_arf << 5);
|
||||
|
||||
return VPX_CODEC_OK;
|
||||
}
|
||||
else
|
||||
return VPX_CODEC_INVALID_PARAM;
|
||||
}
|
||||
|
||||
static vpx_codec_ctrl_fn_map_t vp8e_ctf_maps[] =
|
||||
{
|
||||
{VP8_SET_REFERENCE, vp8e_set_reference},
|
||||
@@ -1194,6 +1277,8 @@ static vpx_codec_ctrl_fn_map_t vp8e_ctf_maps[] =
|
||||
{VP8E_SET_TUNING, set_param},
|
||||
{VP8E_SET_CQ_LEVEL, set_param},
|
||||
{VP8E_SET_MAX_INTRA_BITRATE_PCT, set_param},
|
||||
{VP8E_SET_MODEINFO, set_modeinfo},
|
||||
{VP8E_GET_LAST_REF_UPDATES, vp8_get_last_ref_updates},
|
||||
{ -1, NULL},
|
||||
};
|
||||
|
||||
|
@@ -70,6 +70,7 @@ struct vpx_codec_alg_priv
|
||||
vpx_image_t img;
|
||||
int img_setup;
|
||||
int img_avail;
|
||||
vpx_fixed_buf_t mode_info;
|
||||
};
|
||||
|
||||
static unsigned long vp8_priv_sz(const vpx_codec_dec_cfg_t *si, vpx_codec_flags_t flags)
|
||||
@@ -692,7 +693,9 @@ static vpx_codec_err_t vp8_get_last_ref_updates(vpx_codec_alg_priv_t *ctx,
|
||||
{
|
||||
*update_info = pbi->common.refresh_alt_ref_frame * (int) VP8_ALTR_FRAME
|
||||
+ pbi->common.refresh_golden_frame * (int) VP8_GOLD_FRAME
|
||||
+ pbi->common.refresh_last_frame * (int) VP8_LAST_FRAME;
|
||||
+ pbi->common.refresh_last_frame * (int) VP8_LAST_FRAME
|
||||
+ (pbi->common.copy_buffer_to_gf << 3)
|
||||
+ (pbi->common.copy_buffer_to_arf << 5);
|
||||
|
||||
return VPX_CODEC_OK;
|
||||
}
|
||||
@@ -741,6 +744,43 @@ static vpx_codec_err_t vp8_get_frame_corrupted(vpx_codec_alg_priv_t *ctx,
|
||||
|
||||
}
|
||||
|
||||
static vpx_codec_err_t get_mode_info(vpx_codec_alg_priv_t *ctx,
|
||||
int ctrl_id,
|
||||
va_list args)
|
||||
{
|
||||
vpx_fixed_buf_t **data = va_arg(args, vpx_fixed_buf_t **);
|
||||
VP8D_COMP *pbi = (VP8D_COMP *)ctx->pbi;
|
||||
size_t mi_sz = sizeof(MODE_INFO)*pbi->common.mb_rows * pbi->common.mb_cols;
|
||||
char *buf;
|
||||
size_t buf_stride;
|
||||
int i;
|
||||
MODE_INFO *mi;
|
||||
|
||||
if(data)
|
||||
{
|
||||
if(ctx->mode_info.sz != mi_sz)
|
||||
{
|
||||
free(ctx->mode_info.buf);
|
||||
ctx->mode_info.buf = malloc(mi_sz);
|
||||
ctx->mode_info.sz = mi_sz;
|
||||
}
|
||||
|
||||
mi = pbi->common.mi;
|
||||
buf = ctx->mode_info.buf;
|
||||
buf_stride = pbi->common.mb_cols * sizeof(MODE_INFO);
|
||||
for(i=0; i<pbi->common.mb_rows; i++)
|
||||
{
|
||||
memcpy(buf, mi, buf_stride);
|
||||
buf += buf_stride;
|
||||
mi += pbi->common.mode_info_stride;
|
||||
}
|
||||
*data = &ctx->mode_info;
|
||||
return VPX_CODEC_OK;
|
||||
}
|
||||
else
|
||||
return VPX_CODEC_INVALID_PARAM;
|
||||
}
|
||||
|
||||
vpx_codec_ctrl_fn_map_t vp8_ctf_maps[] =
|
||||
{
|
||||
{VP8_SET_REFERENCE, vp8_set_reference},
|
||||
@@ -753,6 +793,7 @@ vpx_codec_ctrl_fn_map_t vp8_ctf_maps[] =
|
||||
{VP8D_GET_LAST_REF_UPDATES, vp8_get_last_ref_updates},
|
||||
{VP8D_GET_FRAME_CORRUPTED, vp8_get_frame_corrupted},
|
||||
{VP8D_GET_LAST_REF_USED, vp8_get_last_ref_frame},
|
||||
{VP8D_GET_MODE_INFO, get_mode_info},
|
||||
{ -1, NULL},
|
||||
};
|
||||
|
||||
|
@@ -178,6 +178,10 @@ enum vp8e_enc_control_id
|
||||
*
|
||||
*/
|
||||
VP8E_SET_MAX_INTRA_BITRATE_PCT,
|
||||
|
||||
/*!\brief Mode/mv data */
|
||||
VP8E_SET_MODEINFO,
|
||||
VP8E_GET_LAST_REF_UPDATES
|
||||
};
|
||||
|
||||
/*!\brief vpx 1-D scaling mode
|
||||
@@ -311,6 +315,8 @@ VPX_CTRL_USE_TYPE(VP8E_GET_LAST_QUANTIZER_64, int *)
|
||||
|
||||
VPX_CTRL_USE_TYPE(VP8E_SET_MAX_INTRA_BITRATE_PCT, unsigned int)
|
||||
|
||||
VPX_CTRL_USE_TYPE(VP8E_SET_MODEINFO, vpx_fixed_buf_t *)
|
||||
VPX_CTRL_USE_TYPE(VP8E_GET_LAST_REF_UPDATES, int *)
|
||||
|
||||
/*! @} - end defgroup vp8_encoder */
|
||||
#include "vpx_codec_impl_bottom.h"
|
||||
|
@@ -60,6 +60,8 @@ enum vp8_dec_control_id
|
||||
*/
|
||||
VP8D_GET_LAST_REF_USED,
|
||||
|
||||
VP8D_GET_MODE_INFO,
|
||||
|
||||
VP8_DECODER_CTRL_ID_MAX
|
||||
} ;
|
||||
|
||||
@@ -75,6 +77,7 @@ enum vp8_dec_control_id
|
||||
VPX_CTRL_USE_TYPE(VP8D_GET_LAST_REF_UPDATES, int *)
|
||||
VPX_CTRL_USE_TYPE(VP8D_GET_FRAME_CORRUPTED, int *)
|
||||
VPX_CTRL_USE_TYPE(VP8D_GET_LAST_REF_USED, int *)
|
||||
VPX_CTRL_USE_TYPE(VP8D_GET_MODE_INFO, vpx_fixed_buf_t **)
|
||||
|
||||
/*! @} - end defgroup vp8_decoder */
|
||||
|
||||
|
@@ -134,6 +134,17 @@ extern "C" {
|
||||
vpx_codec_err_t;
|
||||
|
||||
|
||||
/*!\brief Generic fixed size buffer structure
|
||||
*
|
||||
* This structure is able to hold a reference to any fixed size buffer.
|
||||
*/
|
||||
typedef struct vpx_fixed_buf
|
||||
{
|
||||
void *buf; /**< Pointer to the data */
|
||||
size_t sz; /**< Length of the buffer, in chars */
|
||||
} vpx_fixed_buf_t; /**< alias for struct vpx_fixed_buf */
|
||||
|
||||
|
||||
/*! \brief Codec capabilities bitfield
|
||||
*
|
||||
* Each codec advertises the capabilities it supports as part of its
|
||||
|
@@ -77,17 +77,6 @@ extern "C" {
|
||||
partition at a time. */
|
||||
|
||||
|
||||
/*!\brief Generic fixed size buffer structure
|
||||
*
|
||||
* This structure is able to hold a reference to any fixed size buffer.
|
||||
*/
|
||||
typedef struct vpx_fixed_buf
|
||||
{
|
||||
void *buf; /**< Pointer to the data */
|
||||
size_t sz; /**< Length of the buffer, in chars */
|
||||
} vpx_fixed_buf_t; /**< alias for struct vpx_fixed_buf */
|
||||
|
||||
|
||||
/*!\brief Time Stamp Type
|
||||
*
|
||||
* An integer, which when multiplied by the stream's time base, provides
|
||||
|
474
vpxenc.c
474
vpxenc.c
@@ -39,6 +39,10 @@
|
||||
#include "y4minput.h"
|
||||
#include "libmkv/EbmlWriter.h"
|
||||
#include "libmkv/EbmlIDs.h"
|
||||
#include "third_party/libyuv/include/libyuv/scale.h"
|
||||
#include "nestegg/include/nestegg/nestegg.h"
|
||||
#include "vpx/vpx_decoder.h"
|
||||
#include "vpx/vp8dx.h"
|
||||
|
||||
/* Need special handling of these functions on Windows */
|
||||
#if defined(_MSC_VER)
|
||||
@@ -289,7 +293,8 @@ enum video_file_type
|
||||
{
|
||||
FILE_TYPE_RAW,
|
||||
FILE_TYPE_IVF,
|
||||
FILE_TYPE_Y4M
|
||||
FILE_TYPE_Y4M,
|
||||
FILE_TYPE_WEBM
|
||||
};
|
||||
|
||||
struct detect_buffer {
|
||||
@@ -299,6 +304,151 @@ struct detect_buffer {
|
||||
};
|
||||
|
||||
|
||||
struct webm_ctx
|
||||
{
|
||||
FILE *infile;
|
||||
nestegg *nestegg_ctx;
|
||||
nestegg_packet *pkt;
|
||||
unsigned int chunk;
|
||||
unsigned int chunks;
|
||||
unsigned int video_track;
|
||||
vpx_codec_ctx_t decoder;
|
||||
unsigned char *buf;
|
||||
size_t buf_sz;
|
||||
};
|
||||
|
||||
static int
|
||||
nestegg_read_cb(void *buffer, size_t length, void *userdata)
|
||||
{
|
||||
FILE *f = userdata;
|
||||
|
||||
if(fread(buffer, 1, length, f) < length)
|
||||
{
|
||||
if (ferror(f))
|
||||
return -1;
|
||||
if (feof(f))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
nestegg_seek_cb(int64_t offset, int whence, void * userdata)
|
||||
{
|
||||
switch(whence) {
|
||||
case NESTEGG_SEEK_SET: whence = SEEK_SET; break;
|
||||
case NESTEGG_SEEK_CUR: whence = SEEK_CUR; break;
|
||||
case NESTEGG_SEEK_END: whence = SEEK_END; break;
|
||||
};
|
||||
return fseek(userdata, offset, whence)? -1 : 0;
|
||||
}
|
||||
|
||||
|
||||
static int64_t
|
||||
nestegg_tell_cb(void * userdata)
|
||||
{
|
||||
return ftell(userdata);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
webm_guess_framerate(struct webm_ctx *input,
|
||||
unsigned int *fps_den,
|
||||
unsigned int *fps_num)
|
||||
{
|
||||
unsigned int i;
|
||||
uint64_t tstamp=0;
|
||||
|
||||
/* Guess the framerate. Read up to 1 second, or 50 video packets,
|
||||
* whichever comes first.
|
||||
*/
|
||||
for(i=0; tstamp < 1000000000 && i < 50;)
|
||||
{
|
||||
nestegg_packet * pkt;
|
||||
unsigned int track;
|
||||
|
||||
if(nestegg_read_packet(input->nestegg_ctx, &pkt) <= 0)
|
||||
break;
|
||||
|
||||
nestegg_packet_track(pkt, &track);
|
||||
if(track == input->video_track)
|
||||
{
|
||||
nestegg_packet_tstamp(pkt, &tstamp);
|
||||
i++;
|
||||
}
|
||||
|
||||
nestegg_free_packet(pkt);
|
||||
}
|
||||
|
||||
if(nestegg_track_seek(input->nestegg_ctx, input->video_track, 0))
|
||||
goto fail;
|
||||
|
||||
*fps_num = (i - 1) * 1000000;
|
||||
*fps_den = tstamp / 1000;
|
||||
return 0;
|
||||
fail:
|
||||
nestegg_destroy(input->nestegg_ctx);
|
||||
input->nestegg_ctx = NULL;
|
||||
rewind(input->infile);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
file_is_webm(struct webm_ctx *input,
|
||||
unsigned int *width,
|
||||
unsigned int *height,
|
||||
unsigned int *fps_den,
|
||||
unsigned int *fps_num)
|
||||
{
|
||||
unsigned int i, n;
|
||||
int track_type = -1;
|
||||
|
||||
nestegg_io io = {nestegg_read_cb, nestegg_seek_cb, nestegg_tell_cb,
|
||||
input->infile};
|
||||
nestegg_video_params params;
|
||||
|
||||
if(nestegg_init(&input->nestegg_ctx, io, NULL))
|
||||
goto fail;
|
||||
|
||||
if(nestegg_track_count(input->nestegg_ctx, &n))
|
||||
goto fail;
|
||||
|
||||
for(i=0; i<n; i++)
|
||||
{
|
||||
track_type = nestegg_track_type(input->nestegg_ctx, i);
|
||||
|
||||
if(track_type == NESTEGG_TRACK_VIDEO)
|
||||
break;
|
||||
else if(track_type < 0)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if(nestegg_track_codec_id(input->nestegg_ctx, i) != NESTEGG_CODEC_VP8)
|
||||
{
|
||||
fprintf(stderr, "Not VP8 video, quitting.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
input->video_track = i;
|
||||
|
||||
if(nestegg_track_video_params(input->nestegg_ctx, i, ¶ms))
|
||||
goto fail;
|
||||
|
||||
if(webm_guess_framerate(input, fps_den, fps_num))
|
||||
goto fail;
|
||||
|
||||
*width = params.width;
|
||||
*height = params.height;
|
||||
return 1;
|
||||
fail:
|
||||
input->nestegg_ctx = NULL;
|
||||
rewind(input->infile);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
struct input_state
|
||||
{
|
||||
char *fn;
|
||||
@@ -310,6 +460,7 @@ struct input_state
|
||||
unsigned int h;
|
||||
struct vpx_rational framerate;
|
||||
int use_i420;
|
||||
struct webm_ctx webm;
|
||||
};
|
||||
|
||||
|
||||
@@ -323,6 +474,53 @@ static int read_frame(struct input_state *input, vpx_image_t *img)
|
||||
int plane = 0;
|
||||
int shortread = 0;
|
||||
|
||||
if (file_type == FILE_TYPE_WEBM)
|
||||
{
|
||||
struct webm_ctx *webm = &input->webm;
|
||||
unsigned int p,r;
|
||||
vpx_image_t *src;
|
||||
vpx_codec_iter_t iter = NULL;
|
||||
|
||||
if(webm->chunk >= webm->chunks)
|
||||
{
|
||||
unsigned int track;
|
||||
|
||||
do
|
||||
{
|
||||
/* End of this packet, get another. */
|
||||
if(webm->pkt)
|
||||
nestegg_free_packet(webm->pkt);
|
||||
|
||||
if(nestegg_read_packet(webm->nestegg_ctx, &webm->pkt) <= 0
|
||||
|| nestegg_packet_track(webm->pkt, &track))
|
||||
return 0;
|
||||
|
||||
} while(track != webm->video_track);
|
||||
|
||||
if(nestegg_packet_count(webm->pkt, &webm->chunks))
|
||||
return 0;
|
||||
webm->chunk = 0;
|
||||
}
|
||||
|
||||
if(nestegg_packet_data(webm->pkt, webm->chunk,
|
||||
&webm->buf, &webm->buf_sz))
|
||||
return 0;
|
||||
|
||||
webm->chunk++;
|
||||
|
||||
if (vpx_codec_decode(&webm->decoder, webm->buf, webm->buf_sz, NULL, 0))
|
||||
fatal("decode failed");
|
||||
|
||||
if ((src = vpx_codec_get_frame(&webm->decoder, &iter)))
|
||||
for(p=0; p<3; p++)
|
||||
for(r=0; r<img->d_h >> (p>0); r++)
|
||||
memcpy(img->planes[p] + r * img->stride[p],
|
||||
src->planes[p] + r * src->stride[p],
|
||||
img->d_w >> (p>0));
|
||||
|
||||
return !!src;
|
||||
}
|
||||
else
|
||||
if (file_type == FILE_TYPE_Y4M)
|
||||
{
|
||||
if (y4m_input_fetch_frame(y4m, f, img) < 1)
|
||||
@@ -984,12 +1182,17 @@ 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 read_modemv_arg = ARG_DEF(NULL, "read-modemv", 1,
|
||||
"Read modes/mvs");
|
||||
static const arg_def_t write_modemv_arg = ARG_DEF(NULL, "write-modemv", 0,
|
||||
"Write modes/mvs");
|
||||
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, &q_hist_n, &rate_hist_n,
|
||||
&read_modemv_arg, &write_modemv_arg,
|
||||
NULL
|
||||
};
|
||||
|
||||
@@ -1495,6 +1698,9 @@ struct global_config
|
||||
int debug;
|
||||
int show_q_hist_buckets;
|
||||
int show_rate_hist_buckets;
|
||||
int read_modemv;
|
||||
int write_modemv;
|
||||
const char *modemv_file;
|
||||
};
|
||||
|
||||
|
||||
@@ -1530,6 +1736,7 @@ struct stream_state
|
||||
uint64_t cx_time;
|
||||
size_t nbytes;
|
||||
stats_io_t stats;
|
||||
struct vpx_image *img;
|
||||
};
|
||||
|
||||
|
||||
@@ -1609,6 +1816,13 @@ static void parse_global_config(struct global_config *global, char **argv)
|
||||
global->show_q_hist_buckets = arg_parse_uint(&arg);
|
||||
else if (arg_match(&arg, &rate_hist_n, argi))
|
||||
global->show_rate_hist_buckets = arg_parse_uint(&arg);
|
||||
else if (arg_match(&arg, &read_modemv_arg, argi))
|
||||
{
|
||||
global->read_modemv = 1;
|
||||
global->modemv_file = arg.val;
|
||||
}
|
||||
else if (arg_match(&arg, &write_modemv_arg, argi))
|
||||
global->write_modemv = 1;
|
||||
else
|
||||
argj++;
|
||||
}
|
||||
@@ -1639,6 +1853,21 @@ void open_input_file(struct input_state *input)
|
||||
if (!input->file)
|
||||
fatal("Failed to open input file");
|
||||
|
||||
if(strstr(input->fn, ".webm"))
|
||||
{
|
||||
input->webm.infile = input->file;
|
||||
input->file_type = FILE_TYPE_WEBM;
|
||||
if(!file_is_webm(&input->webm,
|
||||
&input->w, &input->h,
|
||||
&input->framerate.den,
|
||||
&input->framerate.num))
|
||||
fatal("Couldn't open webm file");
|
||||
if (vpx_codec_dec_init(&input->webm.decoder,
|
||||
&vpx_codec_vp8_dx_algo, NULL, 0))
|
||||
fatal("Couldn't init decoder");
|
||||
return;
|
||||
}
|
||||
|
||||
/* For RAW input sources, these bytes will applied on the first frame
|
||||
* in read_frame().
|
||||
*/
|
||||
@@ -1943,11 +2172,17 @@ static void set_stream_dimensions(struct stream_state *stream,
|
||||
unsigned int w,
|
||||
unsigned int h)
|
||||
{
|
||||
if ((stream->config.cfg.g_w && stream->config.cfg.g_w != w)
|
||||
||(stream->config.cfg.g_h && stream->config.cfg.g_h != h))
|
||||
fatal("Stream %d: Resizing not yet supported", stream->index);
|
||||
stream->config.cfg.g_w = w;
|
||||
stream->config.cfg.g_h = h;
|
||||
if(!stream->config.cfg.g_w)
|
||||
{
|
||||
if(!stream->config.cfg.g_h)
|
||||
stream->config.cfg.g_w = w;
|
||||
else
|
||||
stream->config.cfg.g_w = w * stream->config.cfg.g_h / h;
|
||||
}
|
||||
if(!stream->config.cfg.g_h)
|
||||
{
|
||||
stream->config.cfg.g_h = h * stream->config.cfg.g_w / w;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2117,6 +2352,26 @@ static void encode_frame(struct stream_state *stream,
|
||||
next_frame_start = (cfg->g_timebase.den * (int64_t)(frames_in)
|
||||
* global->framerate.den)
|
||||
/ cfg->g_timebase.num / global->framerate.num;
|
||||
|
||||
/* Scale if necessary */
|
||||
if(img && (img->d_w != cfg->g_w || img->d_h != cfg->g_h))
|
||||
{
|
||||
if(!stream->img)
|
||||
stream->img = vpx_img_alloc(NULL, VPX_IMG_FMT_I420,
|
||||
cfg->g_w, cfg->g_h, 16);
|
||||
I420Scale(img->planes[PLANE_Y], img->stride[PLANE_Y],
|
||||
img->planes[PLANE_U], img->stride[PLANE_U],
|
||||
img->planes[PLANE_V], img->stride[PLANE_V],
|
||||
img->d_w, img->d_h,
|
||||
stream->img->planes[PLANE_Y], stream->img->stride[PLANE_Y],
|
||||
stream->img->planes[PLANE_U], stream->img->stride[PLANE_U],
|
||||
stream->img->planes[PLANE_V], stream->img->stride[PLANE_V],
|
||||
stream->img->d_w, stream->img->d_h,
|
||||
kFilterBox);
|
||||
|
||||
img = stream->img;
|
||||
}
|
||||
|
||||
vpx_usec_timer_start(&timer);
|
||||
vpx_codec_encode(&stream->encoder, img, frame_start,
|
||||
next_frame_start - frame_start,
|
||||
@@ -2211,6 +2466,128 @@ static void get_cx_data(struct stream_state *stream,
|
||||
}
|
||||
|
||||
|
||||
struct link_record
|
||||
{
|
||||
uint32_t sz;
|
||||
uint16_t w;
|
||||
uint16_t h;
|
||||
int refs_updated;
|
||||
};
|
||||
|
||||
static void
|
||||
write_multistream_file(struct stream_state *streams,
|
||||
struct global_config *global,
|
||||
int *got_data)
|
||||
{
|
||||
const vpx_codec_cx_pkt_t *pkt;
|
||||
vpx_codec_cx_pkt_t outpkt = {0};
|
||||
int newsz;
|
||||
|
||||
FOREACH_STREAM({
|
||||
vpx_codec_iter_t iter = NULL;
|
||||
const struct vpx_codec_enc_cfg *cfg = &stream->config.cfg;
|
||||
struct link_record link = {0};
|
||||
|
||||
vpx_codec_control(&stream->encoder, VP8E_GET_LAST_REF_UPDATES, &link.refs_updated);
|
||||
ctx_exit_on_error(&stream->encoder, "Failed to get refs");
|
||||
|
||||
while ((pkt = vpx_codec_get_cx_data(&stream->encoder, &iter)))
|
||||
{
|
||||
*got_data = 1;
|
||||
|
||||
switch (pkt->kind)
|
||||
{
|
||||
case VPX_CODEC_CX_FRAME_PKT:
|
||||
stream->frames_out++;
|
||||
fprintf(stderr, " %6luF",
|
||||
(unsigned long)pkt->data.frame.sz);
|
||||
|
||||
update_rate_histogram(&stream->rate_hist, cfg, pkt);
|
||||
stream->nbytes += pkt->data.raw.sz;
|
||||
|
||||
if(stream == streams)
|
||||
{
|
||||
outpkt = *pkt;
|
||||
outpkt.data.raw.buf = malloc(outpkt.data.raw.sz);
|
||||
memcpy(outpkt.data.raw.buf, pkt->data.raw.buf, pkt->data.raw.sz);
|
||||
}
|
||||
break;
|
||||
case VPX_CODEC_STATS_PKT:
|
||||
stream->frames_out++;
|
||||
fprintf(stderr, " %6luS",
|
||||
(unsigned long)pkt->data.twopass_stats.sz);
|
||||
stats_write(&stream->stats,
|
||||
pkt->data.twopass_stats.buf,
|
||||
pkt->data.twopass_stats.sz);
|
||||
stream->nbytes += pkt->data.raw.sz;
|
||||
break;
|
||||
case VPX_CODEC_PSNR_PKT:
|
||||
|
||||
if (global->show_psnr)
|
||||
{
|
||||
int i;
|
||||
|
||||
stream->psnr_sse_total += pkt->data.psnr.sse[0];
|
||||
stream->psnr_samples_total += pkt->data.psnr.samples[0];
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
fprintf(stderr, "%.3lf ", pkt->data.psnr.psnr[i]);
|
||||
stream->psnr_totals[i] += pkt->data.psnr.psnr[i];
|
||||
}
|
||||
stream->psnr_count++;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
/* Append other data packets to outpkt */
|
||||
newsz = outpkt.data.raw.sz + pkt->data.raw.sz;
|
||||
outpkt.data.raw.buf = realloc(outpkt.data.raw.buf, newsz);
|
||||
memcpy((char*)outpkt.data.raw.buf + outpkt.data.raw.sz,
|
||||
pkt->data.raw.buf, pkt->data.raw.sz);
|
||||
outpkt.data.raw.sz = newsz;
|
||||
link.sz += pkt->data.raw.sz;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(link.sz)
|
||||
{
|
||||
link.w = cfg->g_w;
|
||||
link.h = cfg->g_h;
|
||||
link.sz |= (stream == streams)?0:(1<<31);
|
||||
newsz = outpkt.data.raw.sz + sizeof(link);
|
||||
outpkt.data.raw.buf = realloc(outpkt.data.raw.buf, newsz);
|
||||
memcpy((char*)outpkt.data.raw.buf + outpkt.data.raw.sz,
|
||||
&link, sizeof(link));
|
||||
outpkt.data.raw.sz = newsz;
|
||||
}
|
||||
|
||||
});
|
||||
if(outpkt.data.raw.sz)
|
||||
{
|
||||
const struct vpx_codec_enc_cfg *cfg = &streams->config.cfg;
|
||||
struct stream_state *stream = streams;
|
||||
const vpx_codec_cx_pkt_t *pkt = &outpkt;
|
||||
|
||||
if(stream->config.write_webm)
|
||||
{
|
||||
/* Update the hash */
|
||||
if(!stream->ebml.debug)
|
||||
stream->hash = murmur(pkt->data.frame.buf,
|
||||
pkt->data.frame.sz, stream->hash);
|
||||
|
||||
write_webm_block(&streams->ebml, cfg, pkt);
|
||||
}
|
||||
else
|
||||
{
|
||||
write_ivf_frame_header(stream->file, pkt);
|
||||
if(fwrite(pkt->data.frame.buf, 1,
|
||||
pkt->data.frame.sz, stream->file));
|
||||
}
|
||||
free(outpkt.data.raw.buf);
|
||||
}
|
||||
}
|
||||
|
||||
static void show_psnr(struct stream_state *stream)
|
||||
{
|
||||
int i;
|
||||
@@ -2238,13 +2615,71 @@ float usec_to_fps(uint64_t usec, unsigned int frames)
|
||||
}
|
||||
|
||||
|
||||
static void set_modeinfo(struct stream_state *stream,
|
||||
struct input_state *input)
|
||||
{
|
||||
struct webm_ctx *webm = &input->webm;
|
||||
unsigned char *ptr;
|
||||
struct link_record link;
|
||||
int again;
|
||||
int refs=0;
|
||||
int mi_set = 0;
|
||||
|
||||
vpx_codec_control(&stream->encoder, VP8E_SET_MODEINFO, NULL);
|
||||
ptr = webm->buf + webm->buf_sz;
|
||||
do
|
||||
{
|
||||
ptr -= sizeof(link);
|
||||
memcpy(&link, ptr, sizeof(link));
|
||||
again = link.sz >> 31;
|
||||
link.sz &= ~(1<<31);
|
||||
ptr -= link.sz;
|
||||
if(link.w == stream->config.cfg.g_w
|
||||
&& link.h == stream->config.cfg.g_h)
|
||||
{
|
||||
vpx_fixed_buf_t modeinfo;
|
||||
|
||||
modeinfo.buf = ptr;
|
||||
modeinfo.sz = link.sz;
|
||||
vpx_codec_control(&stream->encoder, VP8E_SET_MODEINFO, &modeinfo);
|
||||
vpx_codec_control(&stream->encoder, VP8E_UPD_REFERENCE, link.refs_updated);
|
||||
ctx_exit_on_error(&stream->encoder, "Failed to set refs");
|
||||
mi_set = 1;
|
||||
break;
|
||||
}
|
||||
if((link.w|link.sz)&0xF)
|
||||
break;
|
||||
if(link.w > 16383 || link.h > 16383)
|
||||
break;
|
||||
} while(again);
|
||||
|
||||
if(!mi_set
|
||||
&& stream->config.cfg.g_w == input->w
|
||||
&& stream->config.cfg.g_h == input->h)
|
||||
{
|
||||
vpx_fixed_buf_t *modeinfo;
|
||||
int refs_updated;
|
||||
|
||||
vpx_codec_control(&webm->decoder, VP8D_GET_MODE_INFO, &modeinfo);
|
||||
ctx_exit_on_error(&webm->decoder, "Failed to get mode info");
|
||||
vpx_codec_control(&stream->encoder, VP8E_SET_MODEINFO, modeinfo);
|
||||
ctx_exit_on_error(&webm->decoder, "Failed to set mode info");
|
||||
|
||||
vpx_codec_control(&webm->decoder, VP8D_GET_LAST_REF_UPDATES, &refs_updated);
|
||||
ctx_exit_on_error(&webm->decoder, "Failed to get ref updates");
|
||||
vpx_codec_control(&stream->encoder, VP8E_UPD_REFERENCE, refs_updated);
|
||||
ctx_exit_on_error(&stream->encoder, "Failed to set ref updates");
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, const char **argv_)
|
||||
{
|
||||
int pass;
|
||||
vpx_image_t raw;
|
||||
vpx_image_t raw, junk;
|
||||
int frame_avail, got_data;
|
||||
|
||||
struct input_state input = {0};
|
||||
struct input_state modemv_input = {0};
|
||||
struct global_config global;
|
||||
struct stream_state *streams = NULL;
|
||||
char **argv, **argi;
|
||||
@@ -2300,6 +2735,12 @@ int main(int argc, const char **argv_)
|
||||
int frames_in = 0;
|
||||
|
||||
open_input_file(&input);
|
||||
if(global.read_modemv)
|
||||
{
|
||||
modemv_input = input;
|
||||
modemv_input.fn = global.modemv_file;
|
||||
open_input_file(&modemv_input);
|
||||
}
|
||||
|
||||
/* If the input file doesn't specify its w/h (raw files), try to get
|
||||
* the data from the first stream's configuration.
|
||||
@@ -2315,6 +2756,9 @@ int main(int argc, const char **argv_)
|
||||
});
|
||||
|
||||
/* Update stream configurations from the input file's parameters */
|
||||
if(!input.w || !input.h)
|
||||
fatal("Specify stream dimensions with --width (-w) "
|
||||
" and --height (-h)");
|
||||
FOREACH_STREAM(set_stream_dimensions(stream, input.w, input.h));
|
||||
FOREACH_STREAM(validate_stream_config(stream));
|
||||
|
||||
@@ -2356,6 +2800,11 @@ int main(int argc, const char **argv_)
|
||||
&global.framerate));
|
||||
}
|
||||
|
||||
if(global.read_modemv)
|
||||
vpx_img_alloc(&junk,
|
||||
input.use_i420 ? VPX_IMG_FMT_I420
|
||||
: VPX_IMG_FMT_YV12,
|
||||
input.w, input.h, 1);
|
||||
FOREACH_STREAM(open_output_file(stream, &global));
|
||||
FOREACH_STREAM(setup_pass(stream, &global, pass));
|
||||
FOREACH_STREAM(initialize_encoder(stream, &global));
|
||||
@@ -2370,6 +2819,8 @@ int main(int argc, const char **argv_)
|
||||
if (!global.limit || frames_in < global.limit)
|
||||
{
|
||||
frame_avail = read_frame(&input, &raw);
|
||||
if(global.read_modemv)
|
||||
read_frame(&modemv_input, &junk);
|
||||
|
||||
if (frame_avail)
|
||||
frames_in++;
|
||||
@@ -2391,6 +2842,10 @@ int main(int argc, const char **argv_)
|
||||
else
|
||||
frame_avail = 0;
|
||||
|
||||
/* Update mode/mv info if available */
|
||||
if(modemv_input.file_type == FILE_TYPE_WEBM && global.read_modemv)
|
||||
FOREACH_STREAM(set_modeinfo(stream, &modemv_input));
|
||||
|
||||
vpx_usec_timer_start(&timer);
|
||||
FOREACH_STREAM(encode_frame(stream, &global,
|
||||
frame_avail ? &raw : NULL,
|
||||
@@ -2401,7 +2856,10 @@ int main(int argc, const char **argv_)
|
||||
FOREACH_STREAM(update_quantizer_histogram(stream));
|
||||
|
||||
got_data = 0;
|
||||
FOREACH_STREAM(get_cx_data(stream, &global, &got_data));
|
||||
if(global.write_modemv)
|
||||
write_multistream_file(streams, &global, &got_data);
|
||||
else
|
||||
FOREACH_STREAM(get_cx_data(stream, &global, &got_data));
|
||||
|
||||
fflush(stdout);
|
||||
}
|
||||
|
Reference in New Issue
Block a user