1 /* 2 * Copyright (C) 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.base.CharMatcher; 21 import com.google.common.base.Splitter; 22 import com.google.gson.JsonDeserializationContext; 23 import com.google.gson.JsonDeserializer; 24 import com.google.gson.JsonElement; 25 import com.google.gson.JsonObject; 26 import com.google.gson.JsonParseException; 27 28 import java.lang.reflect.Type; 29 import java.util.PrimitiveIterator; 30 31 @AutoValue 32 public abstract class ReferenceConfig { testId()33 public abstract String testId(); 34 referenceFile()35 public abstract String referenceFile(); 36 referenceCurve()37 public abstract RateDistortionCurve referenceCurve(); 38 referenceThreshold()39 public abstract double referenceThreshold(); 40 create( String testId, String referenceFile, RateDistortionCurve curve, double referenceThreshold)41 public static ReferenceConfig create( 42 String testId, 43 String referenceFile, 44 RateDistortionCurve curve, 45 double referenceThreshold) { 46 return new AutoValue_ReferenceConfig(testId, referenceFile, curve, referenceThreshold); 47 } 48 49 public static class Deserializer implements JsonDeserializer<ReferenceConfig> { 50 51 @Override deserialize( JsonElement json, Type typeOfT, JsonDeserializationContext context)52 public ReferenceConfig deserialize( 53 JsonElement json, Type typeOfT, JsonDeserializationContext context) 54 throws JsonParseException { 55 JsonObject referenceConfig = json.getAsJsonObject(); 56 57 String testId = referenceConfig.get("TestId").getAsString(); 58 59 // Trim the file extension off the reference filename. 60 String referenceFileName = referenceConfig.get("RefFileName").getAsString(); 61 if (referenceFileName.endsWith(".y4m")) { 62 referenceFileName = referenceFileName.substring(0, referenceFileName.length() - 4); 63 } 64 65 // These are stored as whitespace separated, so parse them, 66 // split them, and convert them into a RateDistortionCurve. 67 String refRates = referenceConfig.get("RefRate").getAsString(); 68 String refVmafs = referenceConfig.get("RefVmaf").getAsString(); 69 70 PrimitiveIterator.OfDouble rates = 71 Splitter.on(CharMatcher.whitespace()) 72 .splitToStream(refRates) 73 .mapToDouble(Double::parseDouble) 74 .iterator(); 75 PrimitiveIterator.OfDouble vmafs = 76 Splitter.on(CharMatcher.whitespace()) 77 .splitToStream(refVmafs) 78 .mapToDouble(Double::parseDouble) 79 .iterator(); 80 81 RateDistortionCurve.Builder curveBuilder = RateDistortionCurve.builder(); 82 while (rates.hasNext() && vmafs.hasNext()) { 83 curveBuilder.addPoint(RateDistortionPoint.create(rates.next(), vmafs.next())); 84 } 85 86 // If there was a misalignment of values, throw JsonParseException 87 if (rates.hasNext() || vmafs.hasNext()) { 88 throw new JsonParseException( 89 "Number of bitrates did not match number of VMAF scores."); 90 } 91 RateDistortionCurve curve = curveBuilder.build(); 92 93 double referenceThreshold = 94 Double.parseDouble(referenceConfig.get("RefThreshold").getAsString()); 95 96 return ReferenceConfig.create(testId, referenceFileName, curve, referenceThreshold); 97 } 98 } 99 } 100