History

vp9: Allow for disabling loopfilter per spatial layer

For SVC: add parameter to the control SET_SVC_PARAMS to allow for disabling the loopfilter per spatial layer. Note this svc setting will override the setting via VP9E_SET_DISABLE_LOOPFILTER (which should only be used for non-SVC). Add unittest to handle both SVC (spatial or temporal layers) and non-SVC (single layer) case.

Marco Paniconi committed 6 years ago

Commit 7beafef1 parent 94384b56 files · +96 −7Browse files

Unified · Split

6 files
  1. test/svc_end_to_end_test.cc +84 −1
  2. test/svc_test.cc +7 −6
  3. vp9/encoder/vp9_svc_layercontext.c +2 −0
  4. vp9/encoder/vp9_svc_layercontext.h +1 −0
  5. vp9/vp9_cx_iface.c +1 −0
  6. vpx/vpx_encoder.h +1 −0
test/svc_end_to_end_test.cc+84−1
@@ -494,7 +494,31 @@ class LoopfilterOnePassCbrSvc : public OnePassCbrSvc, · 493 unmodified lines
494494 virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
495495 ::libvpx_test::Encoder *encoder) {
496496 PreEncodeFrameHookSetup(video, encoder);
497− encoder->Control(VP9E_SET_DISABLE_LOOPFILTER, loopfilter_off_);
497+ if (number_temporal_layers_ > 1 || number_spatial_layers_ > 1) {
498+ // Consider 3 cases:
499+ if (loopfilter_off_ == 0) {
500+ // loopfilter is on for all spatial layers on every superrframe.
501+ for (int i = 0; i < VPX_SS_MAX_LAYERS; ++i) {
502+ svc_params_.loopfilter_ctrl[i] = 0;
503+ }
504+ } else if (loopfilter_off_ == 1) {
505+ // loopfilter is off for non-reference frames for all spatial layers.
506+ for (int i = 0; i < VPX_SS_MAX_LAYERS; ++i) {
507+ svc_params_.loopfilter_ctrl[i] = 1;
508+ }
509+ } else {
510+ // loopfilter is off for all SL0 frames, and off only for non-reference
511+ // frames for SL > 0.
512+ svc_params_.loopfilter_ctrl[0] = 2;
513+ for (int i = 1; i < VPX_SS_MAX_LAYERS; ++i) {
514+ svc_params_.loopfilter_ctrl[i] = 1;
515+ }
516+ }
517+ encoder->Control(VP9E_SET_SVC_PARAMETERS, &svc_params_);
518+ } else if (number_temporal_layers_ == 1 && number_spatial_layers_ == 1) {
519+ // For non-SVC mode use the single layer control.
520+ encoder->Control(VP9E_SET_DISABLE_LOOPFILTER, loopfilter_off_);
521+ }
498522 }
499523
500524 virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) {
@@ -524,6 +548,35 @@ class LoopfilterOnePassCbrSvc : public OnePassCbrSvc, · 23 unmodified lines
524548 int num_nonref_frames_;
525549 };
526550
551+TEST_P(LoopfilterOnePassCbrSvc, OnePassCbrSvc1SL1TLLoopfilterOff) {
552+ SetSvcConfig(1, 1);
553+ cfg_.rc_buf_initial_sz = 500;
554+ cfg_.rc_buf_optimal_sz = 500;
555+ cfg_.rc_buf_sz = 1000;
556+ cfg_.rc_min_quantizer = 0;
557+ cfg_.rc_max_quantizer = 63;
558+ cfg_.g_threads = 1;
559+ cfg_.rc_dropframe_thresh = 0;
560+ cfg_.rc_target_bitrate = 800;
561+ cfg_.kf_max_dist = 9999;
562+ cfg_.rc_end_usage = VPX_CBR;
563+ cfg_.g_lag_in_frames = 0;
564+ cfg_.g_error_resilient = 1;
565+ cfg_.ts_rate_decimator[0] = 1;
566+ cfg_.temporal_layering_mode = 0;
567+ ::libvpx_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480, 30, 1,
568+ 0, 400);
569+ cfg_.rc_target_bitrate = 600;
570+ AssignLayerBitrates();
571+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
572+#if CONFIG_VP9_DECODER
573+ if (loopfilter_off_ == 0)
574+ EXPECT_EQ(GetNonRefFrames(), GetMismatchFrames());
575+ else
576+ EXPECT_EQ(GetMismatchFrames(), 0);
577+#endif
578+}
579+
527580 TEST_P(LoopfilterOnePassCbrSvc, OnePassCbrSvc1SL3TLLoopfilterOff) {
528581 SetSvcConfig(1, 3);
529582 cfg_.rc_buf_initial_sz = 500;
@@ -542,7 +595,37 @@ TEST_P(LoopfilterOnePassCbrSvc, OnePassCbrSvc1SL3TLLoopfilterOff) { · 12 unmodified lines
542595 cfg_.ts_rate_decimator[1] = 2;
543596 cfg_.ts_rate_decimator[2] = 1;
544597 cfg_.temporal_layering_mode = 3;
598+ ::libvpx_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480, 30, 1,
599+ 0, 400);
600+ cfg_.rc_target_bitrate = 600;
601+ AssignLayerBitrates();
602+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
603+#if CONFIG_VP9_DECODER
604+ if (loopfilter_off_ == 0)
605+ EXPECT_EQ(GetNonRefFrames(), GetMismatchFrames());
606+ else
607+ EXPECT_EQ(GetMismatchFrames(), 0);
608+#endif
609+}
545610
611+TEST_P(LoopfilterOnePassCbrSvc, OnePassCbrSvc3SL3TLLoopfilterOff) {
612+ SetSvcConfig(3, 3);
613+ cfg_.rc_buf_initial_sz = 500;
614+ cfg_.rc_buf_optimal_sz = 500;
615+ cfg_.rc_buf_sz = 1000;
616+ cfg_.rc_min_quantizer = 0;
617+ cfg_.rc_max_quantizer = 63;
618+ cfg_.g_threads = 1;
619+ cfg_.rc_dropframe_thresh = 0;
620+ cfg_.rc_target_bitrate = 800;
621+ cfg_.kf_max_dist = 9999;
622+ cfg_.rc_end_usage = VPX_CBR;
623+ cfg_.g_lag_in_frames = 0;
624+ cfg_.g_error_resilient = 1;
625+ cfg_.ts_rate_decimator[0] = 4;
626+ cfg_.ts_rate_decimator[1] = 2;
627+ cfg_.ts_rate_decimator[2] = 1;
628+ cfg_.temporal_layering_mode = 3;
546629 ::libvpx_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480, 30, 1,
547630 0, 400);
548631 cfg_.rc_target_bitrate = 600;
test/svc_test.cc+7−6
@@ -43,13 +43,14 @@ void OnePassCbrSvc::PreEncodeFrameHookSetup(::libvpx_test::VideoSource *video, · 42 unmodified lines
4343 svc_params_.max_quantizers[i] = 63;
4444 svc_params_.min_quantizers[i] = 0;
4545 }
46− svc_params_.speed_per_layer[0] = base_speed_setting_;
47− for (int i = 1; i < VPX_SS_MAX_LAYERS; ++i) {
48− svc_params_.speed_per_layer[i] = speed_setting_;
46+ if (number_temporal_layers_ > 1 || number_spatial_layers_ > 1) {
47+ svc_params_.speed_per_layer[0] = base_speed_setting_;
48+ for (int i = 1; i < VPX_SS_MAX_LAYERS; ++i) {
49+ svc_params_.speed_per_layer[i] = speed_setting_;
50+ }
51+ encoder->Control(VP9E_SET_SVC, 1);
52+ encoder->Control(VP9E_SET_SVC_PARAMETERS, &svc_params_);
4953 }
50−
51− encoder->Control(VP9E_SET_SVC, 1);
52− encoder->Control(VP9E_SET_SVC_PARAMETERS, &svc_params_);
5354 encoder->Control(VP8E_SET_CPUUSED, speed_setting_);
5455 encoder->Control(VP9E_SET_AQ_MODE, 3);
5556 encoder->Control(VP8E_SET_MAX_INTRA_BITRATE_PCT, 300);
vp9/encoder/vp9_svc_layercontext.c+2−0
@@ -357,6 +357,8 @@ void vp9_restore_layer_context(VP9_COMP *const cpi) { · 356 unmodified lines
357357 if (is_one_pass_cbr_svc(cpi) && lc->speed > 0) {
358358 cpi->oxcf.speed = lc->speed;
359359 }
360+ if (lc->loopfilter_ctrl >= 0 || lc->loopfilter_ctrl < 3)
361+ cpi->loopfilter_ctrl = lc->loopfilter_ctrl;
360362 // Reset the frames_since_key and frames_to_key counters to their values
361363 // before the layer restore. Keep these defined for the stream (not layer).
362364 if (cpi->svc.number_temporal_layers > 1 ||
vp9/encoder/vp9_svc_layercontext.h+1−0
@@ -71,6 +71,7 @@ typedef struct { · 70 unmodified lines
7171 int actual_num_seg2_blocks;
7272 int counter_encode_maxq_scene_change;
7373 uint8_t speed;
74+ int loopfilter_ctrl;
7475 } LAYER_CONTEXT;
7576
7677 typedef struct SVC {
vp9/vp9_cx_iface.c+1−0
@@ -1573,6 +1573,7 @@ static vpx_codec_err_t ctrl_set_svc_parameters(vpx_codec_alg_priv_t *ctx, · 1572 unmodified lines
15731573 lc->scaling_factor_num = params->scaling_factor_num[sl];
15741574 lc->scaling_factor_den = params->scaling_factor_den[sl];
15751575 lc->speed = params->speed_per_layer[sl];
1576+ lc->loopfilter_ctrl = params->loopfilter_ctrl[sl];
15761577 }
15771578 }
15781579
vpx/vpx_encoder.h+1−0
@@ -705,6 +705,7 @@ typedef struct vpx_svc_parameters { · 704 unmodified lines
705705 int scaling_factor_den[VPX_MAX_LAYERS]; /**< Scaling factor-denominator */
706706 int speed_per_layer[VPX_MAX_LAYERS]; /**< Speed setting for each sl */
707707 int temporal_layering_mode; /**< Temporal layering mode */
708+ int loopfilter_ctrl[VPX_MAX_LAYERS]; /**< Loopfilter ctrl for each sl */
708709 } vpx_svc_extra_cfg_t;
709710
710711 /*!\brief Initialize an encoder instance

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t