1 /*
2  * Copyright 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.media.videoquality.bdrate;
18 
19 import com.google.auto.value.AutoValue;
20 import com.google.common.collect.ImmutableSortedSet;
21 
22 import java.util.Comparator;
23 
24 /**
25  * Collection of {@link RateDistortionPoint}s that represent a rate-distorion curve for a given
26  * encoder configuration for calculating Bjontegaard-Delta (BD).
27  *
28  * <p>{@link RateDistortionPoint}s are maintained in ascending bitrate order, which allows for easy
29  * precondition checks (such as monotonicity).
30  */
31 @AutoValue
32 public abstract class RateDistortionCurve {
33 
builder()34     public static RateDistortionCurve.Builder builder() {
35         return new AutoValue_RateDistortionCurve.Builder();
36     }
37 
38     /** Returns the points that describe this curve, ordered by bitrate. */
points()39     public abstract ImmutableSortedSet<RateDistortionPoint> points();
40 
41     @AutoValue.Builder
42     public abstract static class Builder {
43         private final ImmutableSortedSet.Builder<RateDistortionPoint> mPointsBuilder =
44                 new ImmutableSortedSet.Builder<>(Comparator.comparing(RateDistortionPoint::rate));
45 
addPoint(RateDistortionPoint point)46         public Builder addPoint(RateDistortionPoint point) {
47             // Points are stored in weight order for easier precondition checks later on.
48             mPointsBuilder.add(point);
49             return this;
50         }
51 
setPoints(ImmutableSortedSet<RateDistortionPoint> points)52         abstract Builder setPoints(ImmutableSortedSet<RateDistortionPoint> points);
53 
autoBuild()54         abstract RateDistortionCurve autoBuild();
55 
build()56         public RateDistortionCurve build() {
57             setPoints(mPointsBuilder.build());
58             return autoBuild();
59         }
60     }
61 
getLog10RatesArray()62     public double[] getLog10RatesArray() {
63         return points().stream().mapToDouble(p -> Math.log10(p.rate())).toArray();
64     }
65 
getDistortionsArray()66     public double[] getDistortionsArray() {
67         return points().stream().mapToDouble(RateDistortionPoint::distortion).toArray();
68     }
69 
getMinDistortion()70     public double getMinDistortion() {
71         return points().first().distortion();
72     }
73 
getMaxDistortion()74     public double getMaxDistortion() {
75         return points().last().distortion();
76     }
77 
getMinLog10Bitrate()78     public double getMinLog10Bitrate() {
79         return Math.log10(points().first().rate());
80     }
81 
getMaxLog10Bitrate()82     public double getMaxLog10Bitrate() {
83         return Math.log10(points().last().rate());
84     }
85 }
86