`

junit.framework.AssertionFailedError: Failed to get achievable frame rates for O

阅读更多
之前对于CTS测试的失败case接触不多,组长突然转了这样一个bug给我。
1027 I TestRunner: failed: testAvcGoog0Perf0320x0240(android.media.cts.VideoDecoderPerfTest)
05-23 01:24:17.675  1007  1027 I TestRunner: ----- begin exception -----
05-23 01:24:17.676  1007  1027 I TestRunner: junit.framework.AssertionFailedError: Failed to get achievable frame rates for OMX.google.h264.decoder video/avc 320x240
05-23 01:24:17.676  1007  1027 I TestRunner: 	at junit.framework.Assert.fail(Assert.java:50)
05-23 01:24:17.676  1007  1027 I TestRunner: 	at junit.framework.Assert.assertTrue(Assert.java:20)
05-23 01:24:17.676  1007  1027 I TestRunner: 	at junit.framework.Assert.assertNull(Assert.java:237)
05-23 01:24:17.676  1007  1027 I TestRunner: 	at android.media.cts.VideoDecoderPerfTest.decode(VideoDecoderPerfTest.java:107)
05-23 01:24:17.676  1007  1027 I TestRunner: 	at android.media.cts.VideoDecoderPerfTest.perf(VideoDecoderPerfTest.java:317)
05-23 01:24:17.676  1007  1027 I TestRunner: 	at android.media.cts.VideoDecoderPerfTest.testAvcGoog0Perf0320x0240(VideoDecoderPerfTest.java:335)
05-23 01:24:17.676  1007  1027 I TestRunner: 	at java.lang.reflect.Method.invoke(Native Method)
05-23 01:24:17.676  1007  1027 I TestRunner: 	at android.test.InstrumentationTestCase.runMethod(InstrumentationTestCase.java:220)
05-23 01:24:17.676  1007  1027 I TestRunner: 	at android.test.InstrumentationTestCase.runTest(InstrumentationTestCase.java:205)
05-23 01:24:17.676  1007  1027 I TestRunner: 	at android.test.ActivityInstrumentationTestCase2.runTest(ActivityInstrumentationTestCase2.java:192)
05-23 01:24:17.676  1007  1027 I TestRunner: 	at junit.framework.TestCase.runBare(TestCase.java:134)
05-23 01:24:17.676  1007  1027 I TestRunner: 	at junit.framework.TestResult$1.protect(TestResult.java:115)
05-23 01:24:17.676  1007  1027 I TestRunner: 	at android.support.test.internal.runner.junit3.AndroidTestResult.runProtected(AndroidTestResult.java:77)
05-23 01:24:17.676  1007  1027 I TestRunner: 	at junit.framework.TestResult.run(TestResult.java:118)
05-23 01:24:17.676  1007  1027 I TestRunner: 	at android.support.test.internal.runner.junit3.AndroidTestResult.run(AndroidTestResult.java:55)
05-23 01:24:17.676  1007  1027 I TestRunner: 	at junit.framework.TestCase.run(TestCase.java:124)
05-23 01:24:17.676  1007  1027 I TestRunner: 	at android.support.test.internal.runner.junit3.NonLeakyTestSuite$NonLeakyTest.run(NonLeakyTestSuite.java:63)
05-23 01:24:17.676  1007  1027 I TestRunner: 	at android.support.test.internal.runner.junit3.AndroidTestSuite$2.run(AndroidTestSuite.java:111)
05-23 01:24:17.676  1007  1027 I TestRunner: 	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:457)
05-23 01:24:17.676  1007  1027 I TestRunner: 	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
05-23 01:24:17.676  1007  1027 I TestRunner: 	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
05-23 01:24:17.676  1007  1027 I TestRunner: 	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
05-23 01:24:17.676  1007  1027 I TestRunner: 	at java.lang.Thread.run(Thread.java:764)
05-23 01:24:17.676  1007  1027 I TestRunner: ----- end exception -----
05-23 01:24:17.679  1007  1027 I TestRunner: finished: testAvcGoog0Perf0320x0240(android.media.cts.VideoDecoderPerfTest)
05-23 01:24:17.693  1007  1007 I MonitoringInstr: Activities that are still in CREATED to STOPPED: 1

我根据相关信息找了对应的测试case
http://androidxref.com/8.0.0_r4/xref/cts/tests/tests/media/src/android/media/cts/VideoDecoderPerfTest.java

log失败的地方:
http://androidxref.com/8.0.0_r4/xref/cts/common/device-side/util/src/com/android/compatibility/common/util/MediaPerfUtils.java
    /** Verifies |measuredFps| against reported achievable rates. Returns null if at least
     *  one measurement falls within the margins of the reported range. Otherwise, returns
     *  an error message to display.*/
    public static String verifyAchievableFrameRates(
            String name, String mime, int w, int h, double... measuredFps) {
        Range<Double> reported =
            MediaUtils.getVideoCapabilities(name, mime).getAchievableFrameRatesFor(w, h);
        String kind = "achievable frame rates for " + name + " " + mime + " " + w + "x" + h;
        if (reported == null) {
            return "Failed to get " + kind;
        }
        double lowerBoundary1 = reported.getLower() / FRAMERATE_TOLERANCE;
        double upperBoundary1 = reported.getUpper() * FRAMERATE_TOLERANCE;
        double lowerBoundary2 = reported.getUpper() / Math.pow(FRAMERATE_TOLERANCE, 2);
        double upperBoundary2 = reported.getLower() * Math.pow(FRAMERATE_TOLERANCE, 2);
        Log.d(TAG, name + " " + mime + " " + w + "x" + h +
                " lowerBoundary1 " + lowerBoundary1 + " upperBoundary1 " + upperBoundary1 +
                " lowerBoundary2 " + lowerBoundary2 + " upperBoundary2 " + upperBoundary2 +
                " measured " + Arrays.toString(measuredFps));

        for (double measured : measuredFps) {
            if (measured >= lowerBoundary1 && measured <= upperBoundary1
                    && measured >= lowerBoundary2 && measured <= upperBoundary2) {
                return null;
            }
        }

        return "Expected " + kind + ": " + reported + ".\n"
                + "Measured frame rate: " + Arrays.toString(measuredFps) + ".\n";
    }

找到对应测试里面的视频文件,该视频可以正常播放。这个视频解码相关的,因为是做高通的平台,高通扩展了自己的解码。优先会使用高通的解码器,所以我先做了这样的测试,优先高通的解码去掉,使用google原生解码的,发现同样失败了,所以继续分析。

再继续跟踪是定位到:
http://androidxref.com/8.0.0_r4/xref/frameworks/base/media/java/android/media/MediaCodecInfo.java
        @Nullable
        public Range<Double> getAchievableFrameRatesFor(int width, int height) {
            if (!supports(width, height, null)) {
                throw new IllegalArgumentException("unsupported size");
            }

            if (mMeasuredFrameRates == null || mMeasuredFrameRates.size() <= 0) {
                Log.w(TAG, "Codec did not publish any measurement data.");
                return null;
            }

            return estimateFrameRatesFor(width, height);
        }

这个返回了size等于0,再接着分析mMeasuredFrameRates 是在getMeasuredFrameRates这个方法赋值的
        private Map<Size, Range<Long>> getMeasuredFrameRates(Map<String, Object> map) {
            Map<Size, Range<Long>> ret = new HashMap<Size, Range<Long>>();
            final String prefix = "measured-frame-rate-";
            Set<String> keys = map.keySet();
            for (String key : keys) {
                // looking for: measured-frame-rate-WIDTHxHEIGHT-range
                if (!key.startsWith(prefix)) {
                    continue;
                }
                String subKey = key.substring(prefix.length());
                String[] temp = key.split("-");
                 Log.w(TAG, key+ " : " + map.get(key));
                if (temp.length != 5) {
                    continue;
                }
                String sizeStr = temp[3];
                Size size = Utils.parseSize(sizeStr, null);					
                if (size == null || size.getWidth() * size.getHeight() <= 0) {
                    continue;
                }
                Range<Long> range = Utils.parseLongRange(map.get(key), null);
				if(range !=null){
				 Log.w(TAG, "range== " + range.toString());
				}
                if (range == null || range.getLower() < 0 || range.getUpper() < 0) {
                    continue;
                }
				Log.w(TAG, "put  " +size.toString()+" : "+ range.toString());
                ret.put(size, range);
            }
			Log.w(TAG, "getMeasuredFrameRates : "+ ret.size()+" "+mParent.getMimeType());
            return ret;
        }

这里注释写了是对measured-frame-rate-WIDTHxHEIGHT-range的解析。搜索一下measured-frame-rate-发现在/device/qcom/msm8909/media_codecs_performance.xml有这些
<Decoders>
       <MediaCodec name="OMX.qcom.video.decoder.avc" type="video/avc" update="true">
            <Limit name="measured-frame-rate-320x240" range="457-457" />
            <Limit name="measured-frame-rate-720x480" range="274-274" />
            <Limit name="measured-frame-rate-1280x720" range="168-168" />
            <Limit name="measured-frame-rate-1920x1088" range="54-54" />
        </MediaCodec>
....
</Decoders>

从测试机器里pull /vendor/etc/media_codecs_performance.xml。发现也是有OMX.qcom.video.decoder.avc。getMeasuredFrameRates的数据来源于media_codecs_performance.xml,该文件也提供了OMX.qcom.video.decoder.avc对应的配置,为何得到的mMeasuredFrameRates 未空呢?继续在MediaCodeInfo和MediaCodeList加debug信息发现,MediaCodeList会加载所有的media code信息(其来源于media_cocdes.xml和media_codecs_performance.xml),而一个media codec对应一个MediaCodeInfo,MediaCodeInfo又会包含多个CodecCapabilities,其他包含AudioCapabilities、VideoCapabilities、EncoderCapabilities。

将parseFromInfo中的要解析的MediaFormat打印出来发现其中确实没有包含"measured-frame-rate-"的信息。

01-02 08:10:44.007   910   910 E CodecCapabilities: mDefaultFormat: {mime=video/avc}

01-02 08:10:44.007   910   910 W VideoCapabilities: parseFromInfo:{size-range=64x64-1920x1088, feature-adaptive-playback=0, bitrate-range=1-20000000, blocks-per-second-range=1-244800, alignment=2x2, max-concurrent-instances=8, feature-can-swap-width-height=0, block-size=16x16}
01-02 08:10:44.014   910   910 W VideoCapabilities: getMeasuredFrameRates : 0 video/avc
01-02 08:10:44.

并且发现了media_codecs_performance.xml中measured-frame-rate-320x240是以-分隔后长度是4,但在getMeasuredFrameRates的size是5,并且注释写measured-frame-rate-WIDTHxHEIGHT-range格式与xml文件不一致,所以推断是解析的时候进行了转换。最后找到了对xml解析的地方
http://androidxref.com/8.0.0_r4/xref/frameworks/av/media/vndk/xmlparser/1.0/MediaCodecsXmlParser.cpp

针对这个解析才发现log提示了:
01-02 09:15:42.310   479   479 E MediaCodecsXmlParser: addMediaCodecFromAttributes: updating non-existing codec
01-02 09:15:42.310   479   479 W MediaCodecsXmlParser: parseTopLevelXMLFile(/vendor/etc/media_codecs_performance.xml) failed

解析media_codecs_performance.xml解析失败了,是由于updating non-existing codec。
继续加log定位解析到哪行失败了,最后发现是解析到:
        <MediaCodec name="OMX.google.vp9.encoder" type="video/x-vnd.on2.vp9" update="true">
            <Limit name="measured-frame-rate-320x180" range="35-35" />
            <Limit name="measured-frame-rate-640x360" range="10-10" />
            <Limit name="measured-frame-rate-1280x720" range="5-5" />
        </MediaCodec>


将"OMX.google.vp9.encoder"在media_codecs.xml和其include的media_codecs_google_video_le.xml查找,确实没有定义该encoder,所以会报updating non-existing codec。

http://androidxref.com/8.0.0_r4/xref/frameworks/av/media/libstagefright/data/media_codecs_google_video_le.xml

最终解决方法是将:media_codecs_performance.xml中的OMX.google.vp9.encoder移除。

MediaCodecsXmlParser将media_codecs.xml和其include的media_codecs_google_video_le.xml和media_codecs_performance.xml的信息组合成MediaFormat信息供MediaCodecInfo使用。其结构类似这样
{size-range=64x64-1920x1088, feature-adaptive-playback=0, bitrate-range=1-20000000, blocks-per-second-range=1-244800, alignment=2x2, max-concurrent-instances=8, feature-can-swap-width-height=0, block-size=16x16}

MediaCodecsXmlParser中的addLimit通过如下代码
            mCurrentType->second[std::string(a_name) + "-range"] = range;
将measured-frame-rate-WIDTHxHEIGHT拼接了-range,所以代码和前面的分析疑点对应起来了。

此外由于搭建CTS环境比较麻烦,需要跑测试部门找人帮忙验证该问题,这样debug起来非常困难和浪费时间,看了一下fail这部分的代码和其他牵扯比较少,所以我把相关代码抽出来写了单独的demo进行测试debug.


总结:1.由于以前没有接触过相关内容,所以靠从问题最终fail log一直反推分析定位问题及相关代码。如果有此相关经验早从其他log看到关键问题所在01-01 07:53:20.230   489   489 E MediaCodecsXmlParser: addMediaCodecFromAttributes: updating non-existing codec
01-01 07:53:20.231   489   489 W MediaCodecsXmlParser: parseTopLevelXMLFile(/vendor/etc/media_codecs_performance.xml) failed

反过来也是有好处的,通过问题能让你快速地理解某些知识点。




分享到:
评论

相关推荐

    junit的jar包

    junit.framework.AssertionFailedError.class junit.framework.ComparisonCompactor.class junit.framework.ComparisonFailure.class junit.framework.JUnit4TestAdapter.class junit.framework.JUnit4...

    jenkins所需的插件等

    4. **Junit 插件**:解析 JUnit 格式的测试结果,提供测试报告和失败测试的可视化。 5. **Email-Ext 插件**:发送构建结果通知,包括成功、失败或异常情况,支持自定义邮件模板。 6. **Blue Ocean 插件**:提供...

    junit-vintage-engine-5.6.2.jar_junit testng

    junit-vintage-engine-5.6.2.jarjunit-vintage-engine-5.6.2.jarjunit-vintage-engine-5.6.2.jar

    junit-jupiter-api-5.4.2-API文档-中英对照版.zip

    Maven坐标:org.junit.jupiter:junit-jupiter-api:5.4.2; 标签:junit、jupiter、api、中英对照文档、jar包、java; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化...

    jaxen.jar和dom4j.jar

    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15) at org.junit.runners....

    junit-jupiter-api-5.8.2-API文档-中文版.zip

    Maven坐标:org.junit.jupiter:junit-jupiter-api:5.8.2; 标签:junit、jupiter、api、jar包、java、中文文档; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译,...

    junit-platform-launcher-1.8.0-M1-API文档-中文版.zip

    Maven坐标:org.junit.platform:junit-platform-launcher:1.8.0-M1; 标签:junit、platform、launcher、中文文档、jar包、java; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档...

    junit-jupiter-engine-5.8.2-API文档-中文版.zip

    Maven坐标:org.junit.jupiter:junit-jupiter-engine:5.8.2; 标签:junit、engine、jupiter、jar包、java、中文文档; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化...

    junit-jupiter-params-5.7.2-API文档-中文版.zip

    Maven坐标:org.junit.jupiter:junit-jupiter-params:5.7.2; 标签:junit、jupiter、params、中文文档、jar包、java; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化...

    org.eclipse.jdt.core_3.5.2.v_981_R35x

    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15) at org.junit.runners....

    HIbernate4.3.6整合c3p0所需jar

    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15) at org.junit.runners....

    junit-jupiter-api-5.8.0-M1-API文档-中英对照版.zip

    Maven坐标:org.junit.jupiter:junit-jupiter-api:5.8.0-M1; 标签:junit、jupiter、api、中英对照文档、jar包、java; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性...

    初试android studio 创建project时报错:Could not download junit.jar(junit:junit:4.12)

    本人小白,开始学习Android,记录自己的错误瞬间,大神不要喷我,哈哈! 安装好android studio后,测试...如果不在意的话,可以不下载它,在module的build.gradle中dependencies模块把加载junit的testCompile ‘junit:j

    junit-jupiter-engine-5.8.0-M1-API文档-中文版.zip

    Maven坐标:org.junit.jupiter:junit-jupiter-engine:5.8.0-M1; 标签:junit、jupiter、engine、中文文档、jar包、java; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 ...

    junit-4.12.jar

    在Android Studio中,有时可能会遇到"Could not download junit.jar (junit:junit:4.12)"这样的错误提示,这通常意味着在构建过程中无法自动下载并集成所需的Junit库。 Junit,全称JUnit,是一个用于Java语言的单元...

    junit.jar包

    org.junit4.nl_zh_3.6.0.v20100814043401 android studio 报错缺少junit.jar包问题 放到D:\Program Files\Android\Android Studio\gradle\gradle-4.1\lib\plugins(路径要与自己的对应)

    spring 常用的26个包

    17. `org.springframework.test`:提供了Spring框架的测试支持,包括JUnit集成、Mock对象等。 18. `org.springframework.transaction`:事务管理相关的包,提供了PlatformTransactionManager接口和各种事务策略。 ...

    JUnit.in.Action中文版.pdf

    JUnit.in.Action中文版.pdf是一个面向Java开发者的指导性文档,主要针对那些希望学习如何使用JUnit来搭建测试框架的初学者,以及那些希望更深入了解单元测试的开发者。 文档标题“JUnit.in.Action中文版.pdf”表明...

Global site tag (gtag.js) - Google Analytics