Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 18f8459a authored by Sashwath Sundher's avatar Sashwath Sundher
Browse files

Enable decode looping for specified duration

Bug: 253529226

Change-Id: I273b4ba2e3e5c7abe4d55f87b43bf4811b26b534
parent 68d01b5e
Loading
Loading
Loading
Loading
+27 −4
Original line number Diff line number Diff line
@@ -48,6 +48,9 @@ public class Decoder implements IBufferXfer.IReceiveBuffer {
    private boolean mSawOutputEOS;
    private boolean mSignalledError;

    private int mNumInFramesProvided;
    private int mNumInFramesRequired;

    private int mNumOutputFrame;
    private int mIndex;

@@ -87,6 +90,10 @@ public class Decoder implements IBufferXfer.IReceiveBuffer {
    }
    public void setupDecoder(Surface surface, boolean render,
            boolean useFrameReleaseQueue, int frameRate) {
        setupDecoder(surface, render, useFrameReleaseQueue, frameRate, -1);
    }
    public void setupDecoder(Surface surface, boolean render,
            boolean useFrameReleaseQueue, int frameRate, int numInFramesRequired) {
        mSignalledError = false;
        mOutputStream = null;
        mSurface = surface;
@@ -95,6 +102,8 @@ public class Decoder implements IBufferXfer.IReceiveBuffer {
            Log.i(TAG, "Using FrameReleaseQueue with frameRate " + frameRate);
            mFrameReleaseQueue = new FrameReleaseQueue(mRender, frameRate);
        }
        mNumInFramesRequired = numInFramesRequired;
        Log.i(TAG, "Decoding " + mNumInFramesRequired + " frames");
    }

    private MediaCodec createCodec(String codecName, MediaFormat format) throws IOException {
@@ -147,6 +156,10 @@ public class Decoder implements IBufferXfer.IReceiveBuffer {
        mSawOutputEOS = false;
        mNumOutputFrame = 0;
        mIndex = 0;
        mNumInFramesProvided = 0;
        if (mNumInFramesRequired < 0) {
            mNumInFramesRequired = mInputBuffer.size();
        }
        long sTime = mStats.getCurTime();
        mCodec = createCodec(codecName, format);
        if (mCodec == null) {
@@ -305,12 +318,22 @@ public class Decoder implements IBufferXfer.IReceiveBuffer {
    }

    private void onInputAvailable(int inputBufferId, MediaCodec mediaCodec) {
        if ((inputBufferId >= 0) && !mSawInputEOS) {
        if (inputBufferId >= 0) {
            ByteBuffer inputCodecBuffer = mediaCodec.getInputBuffer(inputBufferId);
            BufferInfo bufInfo = mInputBufferInfo.get(mIndex);
            inputCodecBuffer.put(mInputBuffer.get(mIndex).array());
            mIndex++;
            BufferInfo bufInfo;
            if (mNumInFramesProvided >= mNumInFramesRequired) {
                Log.i(TAG, "Input frame limit reached");
                mIndex = mInputBufferInfo.size() - 1;
                bufInfo = mInputBufferInfo.get(mIndex);
                if ((bufInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) == 0) {
                    Log.e(TAG, "Error in EOS flag for Decoder");
                }
            }
            bufInfo = mInputBufferInfo.get(mIndex);
            mSawInputEOS = (bufInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0;
            inputCodecBuffer.put(mInputBuffer.get(mIndex).array());
            mNumInFramesProvided++;
            mIndex = mNumInFramesProvided % (mInputBufferInfo.size() - 1);
            if (mSawInputEOS) {
                Log.i(TAG, "Saw input EOS");
            }
+35 −9
Original line number Diff line number Diff line
@@ -31,6 +31,8 @@ public class FrameReleaseQueue {
    private boolean doFrameRelease = false;
    private boolean mRender = false;
    private int mWaitTime = 40; // milliseconds per frame
    private int mWaitTimeCorrection = 0;
    private int mCorrectionLoopCount;
    private int firstReleaseTime = -1;
    private int THRESHOLD_TIME = 5;

@@ -48,29 +50,40 @@ public class FrameReleaseQueue {
    private class ReleaseThread extends Thread {
        public void run() {
            int nextReleaseTime = 0;
            int loopCount = 0;
            while (doFrameRelease || mFrameInfoQueue.size() > 0) {
                FrameInfo curFrameInfo = mFrameInfoQueue.peek();
                if (curFrameInfo == null) {
                    nextReleaseTime += mWaitTime;
                } else {
                    if (firstReleaseTime == -1) {
                    if (curFrameInfo.displayTime == 0) {
                        // first frame of loop
                        firstReleaseTime = getCurSysTime();
                        nextReleaseTime = firstReleaseTime + mWaitTime;
                        popAndRelease(curFrameInfo);
                        popAndRelease(curFrameInfo, true);
                    } else if (!doFrameRelease && mFrameInfoQueue.size() == 1) {
                        // EOS
                        Log.i(TAG, "EOS");
                        popAndRelease(curFrameInfo, false);
                    } else {
                        nextReleaseTime += mWaitTime;
                        int curSysTime = getCurSysTime();
                        int curMediaTime = curSysTime - firstReleaseTime;
                        while (curFrameInfo != null && curFrameInfo.displayTime <= curMediaTime) {
                        while (curFrameInfo != null && curFrameInfo.displayTime > 0 &&
                                curFrameInfo.displayTime <= curMediaTime) {
                            if (!((curMediaTime - curFrameInfo.displayTime) < THRESHOLD_TIME)) {
                                Log.d(TAG, "Dropping expired frame " + curFrameInfo.number);
                                Log.d(TAG, "Dropping expired frame " + curFrameInfo.number +
                                    " display time " + curFrameInfo.displayTime +
                                    " current time " + curMediaTime);
                                popAndRelease(curFrameInfo, false);
                            } else {
                                popAndRelease(curFrameInfo, true);
                            }
                            popAndRelease(curFrameInfo);
                            curFrameInfo = mFrameInfoQueue.peek();
                        }
                        if (curFrameInfo != null && curFrameInfo.displayTime > curMediaTime) {
                            if ((curFrameInfo.displayTime - curMediaTime) < THRESHOLD_TIME) {
                                popAndRelease(curFrameInfo);
                                popAndRelease(curFrameInfo, true);
                            }
                        }
                    }
@@ -85,6 +98,10 @@ public class FrameReleaseQueue {
                } else {
                    Log.d(TAG, "Thread sleep time less than 1");
                }
                if (loopCount % mCorrectionLoopCount == 0) {
                    nextReleaseTime += mWaitTimeCorrection;
                }
                loopCount += 1;
            }
        }
    }
@@ -94,10 +111,18 @@ public class FrameReleaseQueue {
        this.mReleaseThread = new ReleaseThread();
        this.doFrameRelease = true;
        this.mRender = render;
        this.mWaitTime = (int)(1.0f/frameRate * 1000); // wait time in milliseconds per frame
        this.mWaitTime = 1000 / frameRate; // wait time in milliseconds per frame
        int waitTimeRemainder = 1000 % frameRate;
        int gcd = gcd(frameRate, waitTimeRemainder);
        this.mCorrectionLoopCount = frameRate / gcd;
        this.mWaitTimeCorrection = waitTimeRemainder / gcd;
        Log.i(TAG, "Constructed FrameReleaseQueue with wait time " + this.mWaitTime + " ms");
    }

    private static int gcd(int a, int b) {
        return b == 0 ? a : gcd(b, a % b);
    }

    public void setMediaCodec(MediaCodec mediaCodec) {
        this.mCodec = mediaCodec;
    }
@@ -121,14 +146,15 @@ public class FrameReleaseQueue {
        return (int)(System.nanoTime()/1000000);
    }

    private void popAndRelease(FrameInfo curFrameInfo) {
    private void popAndRelease(FrameInfo curFrameInfo, boolean renderThisFrame) {
        try {
            curFrameInfo = mFrameInfoQueue.take();
        } catch (InterruptedException e) {
            Log.e(TAG, "Threw InterruptedException on take");
        }
        boolean actualRender = (renderThisFrame && mRender);
        try {
            mCodec.releaseOutputBuffer(curFrameInfo.bufferId, mRender);
            mCodec.releaseOutputBuffer(curFrameInfo.bufferId, actualRender);
        } catch (IllegalStateException e) {
            Log.e(TAG,
                    "Threw IllegalStateException on releaseOutputBuffer for frame "