FileDocCategorySizeDatePackage
MediaPlayerPerformance.javaAPI DocAndroid 5.1 API20778Thu Mar 12 22:22:30 GMT 2015com.android.mediaframeworktest.performance

MediaPlayerPerformance

public class MediaPlayerPerformance extends android.test.ActivityInstrumentationTestCase2
Junit / Instrumentation - performance measurement for media player and recorder FIXME: Add tests on H264 video encoder

Fields Summary
private String
TAG
private android.view.SurfaceHolder
mSurfaceHolder
private static final int
NUM_STRESS_LOOP
private static final int
NUM_PLAYBACk_IN_EACH_LOOP
private static final int
SHORT_WAIT
private static final long
MEDIA_STRESS_WAIT_TIME
private static final String
MEDIA_MEMORY_OUTPUT
private static final String
MEDIA_PROCMEM_OUTPUT
private static final int
CAMERA_ID
private static int
mStartMemory
private static int
mEndMemory
private static int
mStartPid
private static int
mEndPid
private android.os.Looper
mLooper
private RawPreviewCallback
mRawPreviewCallback
private final android.os.ConditionVariable
mPreviewDone
private static int
WAIT_FOR_COMMAND_TO_COMPLETE
private static int
ENCODER_LIMIT
private static int
DECODER_LIMIT
private static int
CAMERA_LIMIT
private Writer
mProcMemWriter
private Writer
mMemWriter
private android.media.CamcorderProfile
mCamcorderProfile
private int
mVideoWidth
private int
mVideoHeight
android.hardware.Camera
mCamera
Constructors Summary
public MediaPlayerPerformance()


      
        super("com.android.mediaframeworktest", MediaFrameworkTest.class);
    
Methods Summary
public java.lang.StringcaptureMediaserverInfo()

        String cm = "ps mediaserver";
        String memoryUsage = null;

        int ch;
        try {
            Process p = Runtime.getRuntime().exec(cm);
            InputStream in = p.getInputStream();
            StringBuffer sb = new StringBuffer(512);
            while ((ch = in.read()) != -1) {
                sb.append((char) ch);
            }
            memoryUsage = sb.toString();
        } catch (IOException e) {
            Log.v(TAG, e.toString());
        }
        String[] poList = memoryUsage.split("\r|\n|\r\n");
        // A new media.log is enabled with ro.test_harness is set.
        // The output of "ps mediaserver" will include the
        // media.log process in the first line. Update the parsing
        // to only read the thrid line.
        // Smaple ps mediaserver output:
        // USER     PID   PPID  VSIZE  RSS     WCHAN    PC         NAME
        // media     131   1     13676  4796  ffffffff 400b1bd0 S media.log
        // media     219   131   37768  6892  ffffffff 400b236c S /system/bin/mediaserver
        String memusage = poList[poList.length-1].concat("\n");
        return memusage;
    
public intgetMediaserverPid()

        String memoryUsage = null;
        int pidvalue = 0;
        memoryUsage = captureMediaserverInfo();
        String[] poList2 = memoryUsage.split("\t|\\s+");
        String pid = poList2[1];
        pidvalue = Integer.parseInt(pid);
        Log.v(TAG, "PID = " + pidvalue);
        return pidvalue;
    
public intgetMediaserverVsize()

        String memoryUsage = captureMediaserverInfo();
        String[] poList2 = memoryUsage.split("\t|\\s+");
        String vsize = poList2[3];
        int vsizevalue = Integer.parseInt(vsize);
        Log.v(TAG, "VSIZE = " + vsizevalue);
        return vsizevalue;
    
public voidgetMemoryWriteToLog(int writeCount)

        String memusage = null;
        try {
            if (writeCount == 0) {
                mStartMemory = getMediaserverVsize();
                mMemWriter.write("Start memory : " + mStartMemory + "\n");
            }
            memusage = captureMediaserverInfo();
            mMemWriter.write(memusage);
            if (writeCount == NUM_STRESS_LOOP - 1) {
                mEndMemory = getMediaserverVsize();
                mMemWriter.write("End Memory :" + mEndMemory + "\n");
            }
        } catch (Exception e) {
            e.toString();
        }
    
private voidinitializeMessageLooper()

        final ConditionVariable startDone = new ConditionVariable();
        new Thread() {
            @Override
            public void run() {
                Looper.prepare();
                Log.v(TAG, "start loopRun");
                mLooper = Looper.myLooper();
                mCamera = Camera.open(CAMERA_ID);
                startDone.open();
                Looper.loop();
                Log.v(TAG, "initializeMessageLooper: quit.");
            }
        }.start();

        if (!startDone.block(WAIT_FOR_COMMAND_TO_COMPLETE)) {
            fail("initializeMessageLooper: start timeout");
        }
    
public voidmediaStressPlayback(java.lang.String testFilePath)

        for (int i = 0; i < NUM_PLAYBACk_IN_EACH_LOOP; i++) {
            MediaPlayer mp = new MediaPlayer();
            try {
                mp.setDataSource(testFilePath);
                mp.setDisplay(MediaFrameworkTest.mSurfaceView.getHolder());
                mp.prepare();
                mp.start();
                Thread.sleep(MEDIA_STRESS_WAIT_TIME);
                mp.release();
            } catch (Exception e) {
                mp.release();
                Log.v(TAG, e.toString());
            }
        }
    
protected voidsetUp()

        super.setUp();
        //Insert a 2 second before launching the test activity. This is
        //the workaround for the race condition of requesting the updated surface.
        Thread.sleep(SHORT_WAIT);
        getActivity();
        //Check if the device support the camcorder
        mCamcorderProfile = CamcorderProfile.get(CAMERA_ID);
        if (mCamcorderProfile != null) {
            mVideoWidth = mCamcorderProfile.videoFrameWidth;
            mVideoHeight = mCamcorderProfile.videoFrameHeight;
            Log.v(TAG, "height = " + mVideoHeight + " width= " + mVideoWidth);
        }
        if (MediaFrameworkPerfTestRunner.mGetNativeHeapDump)
            MediaTestUtil.getNativeHeapDump(this.getName() + "_before");

        if (MediaFrameworkPerfTestRunner.mGetProcmem) {
            mProcMemWriter = new BufferedWriter(new FileWriter
                    (new File(MEDIA_PROCMEM_OUTPUT), true));
            mProcMemWriter.write(this.getName() + "\n");
        }
        mMemWriter = new BufferedWriter(new FileWriter
                (new File(MEDIA_MEMORY_OUTPUT), true));
        mMemWriter.write(this.getName() + "\n");
    
public voidstressAudioRecord(java.lang.String filePath)

        // This test is only for the short media file
        for (int i = 0; i < NUM_PLAYBACk_IN_EACH_LOOP; i++) {
            MediaRecorder mRecorder = new MediaRecorder();
            try {
                mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
                mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
                mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
                mRecorder.setOutputFile(filePath);
                mRecorder.prepare();
                mRecorder.start();
                Thread.sleep(MEDIA_STRESS_WAIT_TIME);
                mRecorder.stop();
                mRecorder.release();
            } catch (Exception e) {
                Log.v(TAG, e.toString());
                mRecorder.release();
            }
        }
    
public voidstressCameraPreview()

        for (int i = 0; i < NUM_PLAYBACk_IN_EACH_LOOP; i++) {
            try {
                initializeMessageLooper();
                mCamera.setPreviewCallback(mRawPreviewCallback);
                mSurfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
                mCamera.setPreviewDisplay(mSurfaceHolder);
                mCamera.startPreview();
                waitForPreviewDone();
                Thread.sleep(1000);
                mCamera.stopPreview();
                terminateMessageLooper();
            } catch (Exception e) {
                Log.v(TAG, e.toString());
            }
        }
    
private booleanstressVideoRecord(int frameRate, int width, int height, int videoFormat, int outFormat, java.lang.String outFile, boolean videoOnly)

        // Video recording
        boolean doesTestFail = false;
        for (int i = 0; i < NUM_PLAYBACk_IN_EACH_LOOP; i++) {
            MediaRecorder mRecorder = new MediaRecorder();
            try {
                if (!videoOnly) {
                    Log.v(TAG, "setAudioSource");
                    mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
                }
                mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
                mRecorder.setOutputFormat(outFormat);
                Log.v(TAG, "output format " + outFormat);
                mRecorder.setOutputFile(outFile);
                mRecorder.setVideoFrameRate(frameRate);
                mRecorder.setVideoSize(width, height);
                Log.v(TAG, "setEncoder");
                mRecorder.setVideoEncoder(videoFormat);
                if (!videoOnly) {
                    mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
                }
                mSurfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
                mRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());
                mRecorder.prepare();
                mRecorder.start();
                Thread.sleep(MEDIA_STRESS_WAIT_TIME);
                mRecorder.stop();
                mRecorder.release();
                //Insert 2 seconds to make sure the camera released.
                Thread.sleep(SHORT_WAIT);
            } catch (Exception e) {
                Log.v("record video failed ", e.toString());
                mRecorder.release();
                doesTestFail = true;
                break;
            }
        }
        return !doesTestFail;
    
protected voidtearDown()

        if (MediaFrameworkPerfTestRunner.mGetNativeHeapDump)
            MediaTestUtil.getNativeHeapDump(this.getName() + "_after");

        if (MediaFrameworkPerfTestRunner.mGetProcmem) {
            mProcMemWriter.close();
        }
        mMemWriter.write("\n");
        mMemWriter.close();
        super.tearDown();
    
private voidterminateMessageLooper()

        mLooper.quit();
        // Looper.quit() is asynchronous. The looper may still has some
        // preview callbacks in the queue after quit is called. The preview
        // callback still uses the camera object (setHasPreviewCallback).
        // After camera is released, RuntimeException will be thrown from
        // the method. So we need to join the looper thread here.
        mLooper.getThread().join();
        mCamera.release();
    
public voidtestCameraPreviewMemoryUsage()

        boolean memoryResult = false;

        mStartPid = getMediaserverPid();
        for (int i = 0; i < NUM_STRESS_LOOP; i++) {
            stressCameraPreview();
            getMemoryWriteToLog(i);
            writeProcmemInfo();
        }
        memoryResult = validateMemoryResult(mStartPid, mStartMemory, CAMERA_LIMIT);
        assertTrue("camera preview memory test", memoryResult);
    
public voidtestH263RecordVideoOnlyMemoryUsage()

        if (mCamcorderProfile != null) {
            boolean memoryResult = false;
            mStartPid = getMediaserverPid();
            int frameRate = MediaProfileReader
                    .getMaxFrameRateForCodec(MediaRecorder.VideoEncoder.H263);
            assertTrue("H263 video recording frame rate", frameRate != -1);
            for (int i = 0; i < NUM_STRESS_LOOP; i++) {
                assertTrue(stressVideoRecord(frameRate, mVideoWidth, mVideoHeight,
                        MediaRecorder.VideoEncoder.H263, MediaRecorder.OutputFormat.MPEG_4,
                        MediaNames.RECORDED_VIDEO_3GP, true));
                getMemoryWriteToLog(i);
                writeProcmemInfo();
            }
            memoryResult = validateMemoryResult(mStartPid, mStartMemory, ENCODER_LIMIT);
            assertTrue("H263 record only memory test", memoryResult);
        }
    
public voidtestH263VideoPlaybackMemoryUsage()

        boolean memoryResult = false;

        mStartPid = getMediaserverPid();
        for (int i = 0; i < NUM_STRESS_LOOP; i++) {
            mediaStressPlayback(MediaNames.VIDEO_HIGHRES_H263);
            getMemoryWriteToLog(i);
            writeProcmemInfo();
        }
        memoryResult = validateMemoryResult(mStartPid, mStartMemory, DECODER_LIMIT);
        assertTrue("H263 playback memory test", memoryResult);
    
public voidtestH264VideoPlaybackMemoryUsage()

        boolean memoryResult = false;

        mStartPid = getMediaserverPid();
        for (int i = 0; i < NUM_STRESS_LOOP; i++) {
            mediaStressPlayback(MediaNames.VIDEO_H264_AMR);
            getMemoryWriteToLog(i);
            writeProcmemInfo();
        }
        memoryResult = validateMemoryResult(mStartPid, mStartMemory, DECODER_LIMIT);
        assertTrue("H264 playback memory test", memoryResult);
    
public voidtestHEVCVideoPlaybackMemoryUsage()

        boolean memoryResult = false;

        mStartPid = getMediaserverPid();
        for (int i = 0; i < NUM_STRESS_LOOP; i++) {
            mediaStressPlayback(MediaNames.VIDEO_HEVC_AAC);
            getMemoryWriteToLog(i);
            writeProcmemInfo();
        }
        memoryResult = validateMemoryResult(mStartPid, mStartMemory, DECODER_LIMIT);
        assertTrue("HEVC playback memory test", memoryResult);
    
public voidtestMpeg4RecordVideoOnlyMemoryUsage()

        if (mCamcorderProfile != null) {
            boolean memoryResult = false;
            mStartPid = getMediaserverPid();
            int frameRate = MediaProfileReader.getMaxFrameRateForCodec
                    (MediaRecorder.VideoEncoder.MPEG_4_SP);
            assertTrue("MPEG4 video recording frame rate", frameRate != -1);
            for (int i = 0; i < NUM_STRESS_LOOP; i++) {
                assertTrue(stressVideoRecord(frameRate, mVideoWidth, mVideoHeight,
                        MediaRecorder.VideoEncoder.MPEG_4_SP, MediaRecorder.OutputFormat.MPEG_4,
                        MediaNames.RECORDED_VIDEO_3GP, true));
                getMemoryWriteToLog(i);
                writeProcmemInfo();
            }
            memoryResult = validateMemoryResult(mStartPid, mStartMemory, ENCODER_LIMIT);
            assertTrue("mpeg4 record only memory test", memoryResult);
        }
    
public voidtestRecordAudioOnlyMemoryUsage()

        boolean memoryResult = false;

        mStartPid = getMediaserverPid();
        for (int i = 0; i < NUM_STRESS_LOOP; i++) {
            stressAudioRecord(MediaNames.RECORDER_OUTPUT);
            getMemoryWriteToLog(i);
            writeProcmemInfo();
        }
        memoryResult = validateMemoryResult(mStartPid, mStartMemory, ENCODER_LIMIT);
        assertTrue("audio record only memory test", memoryResult);
    
public voidtestRecordVideoAudioMemoryUsage()

        if (mCamcorderProfile != null) {
            boolean memoryResult = false;
            mStartPid = getMediaserverPid();
            int frameRate = MediaProfileReader
                    .getMaxFrameRateForCodec(MediaRecorder.VideoEncoder.H263);
            assertTrue("H263 video recording frame rate", frameRate != -1);
            for (int i = 0; i < NUM_STRESS_LOOP; i++) {
                assertTrue(stressVideoRecord(frameRate, mVideoWidth, mVideoHeight,
                        MediaRecorder.VideoEncoder.H263, MediaRecorder.OutputFormat.MPEG_4,
                        MediaNames.RECORDED_VIDEO_3GP, false));
                getMemoryWriteToLog(i);
                writeProcmemInfo();
            }
            memoryResult = validateMemoryResult(mStartPid, mStartMemory, ENCODER_LIMIT);
            assertTrue("H263 audio video record memory test", memoryResult);
        }
    
public booleanvalidateMemoryResult(int startPid, int startMemory, int limit)

        // Wait for 10 seconds to make sure the memory settle.
        Thread.sleep(10000);
        mEndPid = getMediaserverPid();
        int memDiff = mEndMemory - startMemory;
        if (memDiff < 0) {
            memDiff = 0;
        }
        mMemWriter.write("The total diff = " + memDiff);
        mMemWriter.write("\n\n");
        // mediaserver crash
        if (startPid != mEndPid) {
            mMemWriter.write("mediaserver died. Test failed\n");
            return false;
        }
        // memory leak greter than the tolerant
        if (memDiff > limit) return false;
        return true;
    
private voidwaitForPreviewDone()

        if (!mPreviewDone.block(WAIT_FOR_COMMAND_TO_COMPLETE)) {
            Log.v(TAG, "waitForPreviewDone: timeout");
        }
        mPreviewDone.close();
    
public voidwriteProcmemInfo()

        if (MediaFrameworkPerfTestRunner.mGetProcmem) {
            String cmd = "procmem " + getMediaserverPid();
            Process p = Runtime.getRuntime().exec(cmd);

            InputStream inStream = p.getInputStream();
            InputStreamReader inReader = new InputStreamReader(inStream);
            BufferedReader inBuffer = new BufferedReader(inReader);
            String s;
            while ((s = inBuffer.readLine()) != null) {
                mProcMemWriter.write(s);
                mProcMemWriter.write("\n");
            }
            mProcMemWriter.write("\n\n");
        }