Compare commits
	
		
			10 Commits
		
	
	
		
			v1.6.0
			...
			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