Example #1
0
/**
 * Test the EUCJP decoder.
 */
nsresult testEUCJPDecoder()
{
  char * testName = "T103";
  printf("\n[%s] Unicode <- EUCJP\n", testName);

  // create converter
  CREATE_DECODER("euc-jp");

  // test data
  char src[] = {"\x45"};
  PRUnichar exp[] = {0x0045};

  // test converter - normal operation
  res = testDecoder(dec, src, ARRAY_SIZE(src)-1, exp, ARRAY_SIZE(exp), testName);

  // reset converter
  if (NS_SUCCEEDED(res)) res = resetDecoder(dec, testName);

  // test converter - stress test
  if (NS_SUCCEEDED(res)) 
    res = testStressDecoder(dec, src, ARRAY_SIZE(src)-1, exp, ARRAY_SIZE(exp), testName);

  // release converter
  NS_RELEASE(dec);

  if (NS_FAILED(res)) {
    return res;
  } else {
    printf("Test Passed.\n");
    return NS_OK;
  }
}
Example #2
0
/**
 * A standard decoder test.
 */
nsresult standardDecoderTest(char * aTestName, char * aCharset, char * aSrc, 
  PRInt32 aSrcLen, PRUnichar * aRes, PRInt32 aResLen)
{
  printf("\n[%s] Unicode <- %s\n", aTestName, aCharset);

  // create converter
  CREATE_DECODER(aCharset);

  // test converter - easy test
  res = testDecoder(dec, aSrc, aSrcLen, aRes, aResLen, aTestName);

  // reset converter
  if (NS_SUCCEEDED(res)) res = resetDecoder(dec, aTestName);

  // test converter - stress test
  if (NS_SUCCEEDED(res)) 
    res = testStressDecoder(dec, aSrc, aSrcLen, aRes, aResLen, aTestName);

  // release converter
  NS_RELEASE(dec);

  if (NS_FAILED(res)) {
    return res;
  } else {
    printf("Test Passed.\n");
    return NS_OK;
  }
}
void SoftAVC::onReset() {
    SoftVideoDecoderOMXComponent::onReset();

    mSignalledError = false;
    resetDecoder();
    resetPlugin();
}
Example #4
0
void SoftHEVC::onReset() {
    ALOGD("onReset called");
    SoftVideoDecoderOMXComponent::onReset();

    resetDecoder();
    resetPlugin();
}
// initialise on creation
void TrcPktDecodeEtmV3::initDecoder()
{
    m_CSID = 0;
    resetDecoder();
    m_code_follower.initInterfaces(getMemoryAccessAttachPt(),getInstrDecodeAttachPt());
    m_outputElemList.initSendIf(getTraceElemOutAttachPt());
}
Example #6
0
/**
 * Test the UTF8 decoder.
 */
nsresult testUTF8Decoder()
{
  char * testName = "T106";
  printf("\n[%s] Unicode <- UTF8\n", testName);

  // create converter
  CREATE_DECODER("utf-8");

#ifdef NOPE // XXX decomment this when I have test data
  // test data
  char src[] = {};
  PRUnichar exp[] = {};

  // test converter - normal operation
  res = testDecoder(dec, src, ARRAY_SIZE(src)-1, exp, ARRAY_SIZE(exp), testName);

  // reset converter
  if (NS_SUCCEEDED(res)) res = resetDecoder(dec, testName);

  // test converter - stress test
  if (NS_SUCCEEDED(res)) 
    res = testStressDecoder(dec, src, ARRAY_SIZE(src)-1, exp, ARRAY_SIZE(exp), testName);
#endif

  // release converter
  NS_RELEASE(dec);

  if (NS_FAILED(res)) {
    return res;
  } else {
    printf("Test Passed.\n");
    return NS_OK;
  }
}
Example #7
0
/**
 * Test the M-UTF-7 decoder.
 */
nsresult testMUTF7Decoder()
{
  char * testName = "T107";
  printf("\n[%s] Unicode <- MUTF7\n", testName);

  // create converter
  CREATE_DECODER("x-imap4-modified-utf7");

  // test data
  char src[] = {"\x50\x51\x52\x53&AAAAAAAA-&-&AAA-"};
  PRUnichar exp[] = {0x0050,0x0051,0x0052,0x0053,0x0000,0x0000,0x0000,'&',0x0000};

  // test converter - normal operation
  res = testDecoder(dec, src, ARRAY_SIZE(src)-1, exp, ARRAY_SIZE(exp), testName);

  // reset converter
  if (NS_SUCCEEDED(res)) res = resetDecoder(dec, testName);

  // test converter - stress test
  if (NS_SUCCEEDED(res)) 
    res = testStressDecoder(dec, src, ARRAY_SIZE(src)-1, exp, ARRAY_SIZE(exp), testName);

  // release converter
  NS_RELEASE(dec);

  if (NS_FAILED(res)) {
    return res;
  } else {
    printf("Test Passed.\n");
    return NS_OK;
  }
}
Example #8
0
	static void trigFinished()
	{
		if(itsDoneCallback)
			itsDoneCallback(0);

		resetDecoder();
	}
Example #9
0
int decode_out(Gzb64* gzb64, unsigned char* buf, const size_t length)
{
	int zret, ret;

	/* should be guaranteed at least length after inflate */
	int gz_in_bytes = evbuffer_get_contiguous_space(gzb64->decode_output_buffer);
	unsigned char* gzin_buf = evbuffer_pullup(gzb64->decode_output_buffer, gz_in_bytes );

	if(DEBUG) hex_debug(gzin_buf, gz_in_bytes);
	
	gzb64->gz_decode_strm.next_in = gzin_buf;
	gzb64->gz_decode_strm.avail_in = gz_in_bytes;
	gzb64->gz_decode_strm.next_out = buf;
    gzb64->gz_decode_strm.avail_out = length;
	zret = inflate (& gzb64->gz_decode_strm, Z_NO_FLUSH);
	if(zret < 0) zerr(zret);

	evbuffer_drain(gzb64->decode_output_buffer, gz_in_bytes - gzb64->gz_decode_strm.avail_in);

	ret = length - gzb64->gz_decode_strm.avail_out;
	
	if(gzb64->decoded_last_chunk && 0 == ret) {
		resetDecoder(gzb64);
	}

	return ret;
}
Example #10
0
/**
 * Test the ISO2022JP decoder.
 */
nsresult testISO2022JPDecoder()
{
  char * testName = "T102";
  printf("\n[%s] Unicode <- ISO2022JP\n", testName);

  // create converter
  CREATE_DECODER("iso-2022-jp");

  // test data
  char src[] = {"\x0d\x7f\xdd" "\x1b(J\xaa\xdc\x41" "\x1b$B\x21\x21" "\x1b$@\x32\x37" "\x1b(J\x1b(B\xcc"};
  PRUnichar exp[] = {0x000d,0x007f,0xfffd, 0xff6a,0xFF9C,0x0041, 0x3000, 0x5378, 0xfffd};

  // test converter - normal operation
  res = testDecoder(dec, src, ARRAY_SIZE(src)-1, exp, ARRAY_SIZE(exp), testName);

  // reset converter
  if (NS_SUCCEEDED(res)) res = resetDecoder(dec, testName);

  // test converter - stress test
  if (NS_SUCCEEDED(res)) 
    res = testStressDecoder(dec, src, ARRAY_SIZE(src)-1, exp, ARRAY_SIZE(exp), testName);

  // release converter
  NS_RELEASE(dec);

  if (NS_FAILED(res)) {
    return res;
  } else {
    printf("Test Passed.\n");
    return NS_OK;
  }
}
Example #11
0
/**
 * Test the UTF-7 decoder.
 */
nsresult testUTF7Decoder()
{
  char * testName = "T108";
  printf("\n[%s] Unicode <- UTF7\n", testName);

  // create converter
  CREATE_DECODER("utf-7");

  // test data
  char src[] = {"+ADwAIQ-DOC"};
  PRUnichar exp[] = {'<','!','D','O','C'};

  // test converter - normal operation
  res = testDecoder(dec, src, ARRAY_SIZE(src)-1, exp, ARRAY_SIZE(exp), testName);

  // reset converter
  if (NS_SUCCEEDED(res)) res = resetDecoder(dec, testName);

  // test converter - stress test
  if (NS_SUCCEEDED(res)) 
    res = testStressDecoder(dec, src, ARRAY_SIZE(src)-1, exp, ARRAY_SIZE(exp), testName);

  // release converter
  NS_RELEASE(dec);

  if (NS_FAILED(res)) {
    return res;
  } else {
    printf("Test Passed.\n");
    return NS_OK;
  }
}
Example #12
0
void SoftHEVC::onReset() {
    ALOGV("onReset called");
    SoftVideoDecoderOMXComponent::onReset();

    mSignalledError = false;
    resetDecoder();
    resetPlugin();
}
Example #13
0
	static void errorAndResetDecoder(byte value)
	{
		resetDecoder();

		signalError(value);

		state = inactive;
	}
void SoftMPEG2::onReset() {
    SoftVideoDecoderOMXComponent::onReset();

    mWaitForI = true;

    resetDecoder();
    resetPlugin();
}
Example #15
0
TEST_F(BitmapImageTest, webpHasColorProfile)
{
    loadImage("/LayoutTests/fast/images/resources/webp-color-profile-lossy.webp");
    EXPECT_EQ(1u, decodedFramesCount());
    EXPECT_EQ(2560000u, decodedSize());
    EXPECT_TRUE(m_image->hasColorProfile());

    destroyDecodedData(true);
    resetDecoder();

    loadImage("/LayoutTests/fast/images/resources/test.webp");
    EXPECT_EQ(1u, decodedFramesCount());
    EXPECT_EQ(65536u, decodedSize());
    EXPECT_FALSE(m_image->hasColorProfile());
}
TEST_F(BitmapImageTest, jpegHasColorProfile)
{
    loadImage("/tests/fast/images/resources/icc-v2-gbr.jpg");
    EXPECT_EQ(1u, decodedFramesCount());
    EXPECT_EQ(227700u, decodedSize());
    EXPECT_TRUE(m_image->hasColorProfile());

    resetDecoder();
    destroyDecodedData(true);

    loadImage("/tests/fast/images/resources/green.jpg");
    EXPECT_EQ(1u, decodedFramesCount());
    EXPECT_EQ(1024u, decodedSize());
    EXPECT_FALSE(m_image->hasColorProfile());
}
TEST_F(BitmapImageTest, pngHasColorProfile)
{
    loadImage("/tests/fast/images/resources/palatted-color-png-gamma-one-color-profile.png");
    EXPECT_EQ(1u, decodedFramesCount());
    EXPECT_EQ(65536u, decodedSize());
    EXPECT_TRUE(m_image->hasColorProfile());

    resetDecoder();
    destroyDecodedData(true);

    loadImage("/tests/fast/images/resources/green.jpg");
    EXPECT_EQ(1u, decodedFramesCount());
    EXPECT_EQ(1024u, decodedSize());
    EXPECT_FALSE(m_image->hasColorProfile());
}
ocsd_datapath_resp_t TrcPktDecodeEtmV3::sendUnsyncPacket()
{
    ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
    OcsdTraceElement *pElem = 0;
    try {
        pElem = GetNextOpElem(resp);
        pElem->setType(OCSD_GEN_TRC_ELEM_NO_SYNC);
        resp = m_outputElemList.sendElements();
    }
    catch(ocsdError &err)
    {
        LogError(err);
        resetDecoder(); // mark decoder as unsynced - dump any current state.
    }
    return resp;
}
Example #19
0
	/**
	 public entry point to initiate an ADB transaction on the bus
	*/
	void initiateAdbTransfer(AdbPacket* adbPacket, void (*done_callback)(uint8_t errorCode))
	{
		// reset
		resetDecoder();

		// keep reference to the packet
		itsAdbPacket = adbPacket;

		itsDoneCallback = done_callback;

		// keep the line idle for at least IDLE_TIME_US
		// TODO: remember how much time left since last packet
		// and adjust setTimeout accordingly
		state = idle;
		adb_highimpedance();
		setTimeout(IDLE_TIME_US);
	}
Example #20
0
/**
 * Test the SJIS decoder.
 */
nsresult testSJISDecoder()
{
  char * testName = "T105";
  printf("\n[%s] Unicode <- SJIS\n", testName);

  // create converter
  CREATE_DECODER("Shift_JIS");

  // test data
  char src[] = {
    "Japanese" /* English */
    "\x8a\xbf\x8e\x9a" /* Kanji */
    "\x83\x4a\x83\x5e\x83\x4a\x83\x69" /* Kantakana */
    "\x82\xd0\x82\xe7\x82\xaa\x82\xc8" /* Hiragana */
    "\x82\x50\x82\x51\x82\x52\x82\x60\x82\x61\x82\x62" /* full width 123ABC */
  };
  PRUnichar exp[] = {
    0x004A, 0x0061, 0x0070, 0x0061, 0x006E, 0x0065, 0x0073, 0x0065,
    0x6f22, 0x5b57,
    0x30ab, 0x30bf, 0x30ab, 0x30ca,
    0x3072, 0x3089, 0x304c, 0x306a,
    0xff11, 0xff12, 0xff13, 0xff21, 0xff22, 0xff23
  };

  // test converter - normal operation
  res = testDecoder(dec, src, ARRAY_SIZE(src)-1, exp, ARRAY_SIZE(exp), testName);

  // reset converter
  if (NS_SUCCEEDED(res)) res = resetDecoder(dec, testName);

  // test converter - stress test
  if (NS_SUCCEEDED(res)) 
    res = testStressDecoder(dec, src, ARRAY_SIZE(src)-1, exp, ARRAY_SIZE(exp), testName);

  // release converter
  NS_RELEASE(dec);

  if (NS_FAILED(res)) {
    return res;
  } else {
    printf("Test Passed.\n");
    return NS_OK;
  }
}
Example #21
0
/**
 * Test the ISO88597 decoder.
 */
nsresult testISO88597Decoder()
{
  char * testName = "T104";
  printf("\n[%s] Unicode <- ISO88597\n", testName);

  // create converter
  CREATE_DECODER("iso-8859-7");

  // test data
  char src[] = {
    "\x09\x0d\x20\x40"
    "\x80\x98\xa3\xaf"
    "\xa7\xb1\xb3\xc9"
    "\xd9\xe3\xf4\xff"
  };
  PRUnichar exp[] = {
    0x0009, 0x000d, 0x0020, 0x0040, 
    0xfffd, 0xfffd, 0x00a3, 0x2015,
    0x00a7, 0x00b1, 0x00b3, 0x0399,
    0x03a9, 0x03b3, 0x03c4, 0xfffd
  };

  // test converter - normal operation
  res = testDecoder(dec, src, ARRAY_SIZE(src)-1, exp, ARRAY_SIZE(exp), testName);

  // reset converter
  if (NS_SUCCEEDED(res)) res = resetDecoder(dec, testName);

  // test converter - stress test
  if (NS_SUCCEEDED(res)) 
    res = testStressDecoder(dec, src, ARRAY_SIZE(src)-1, exp, ARRAY_SIZE(exp), testName);

  // release converter
  NS_RELEASE(dec);

  if (NS_FAILED(res)) {
    return res;
  } else {
    printf("Test Passed.\n");
    return NS_OK;
  }
}
ocsd_datapath_resp_t TrcPktDecodeEtmV3::onEOT()
{
    ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
    OcsdTraceElement *pElem = 0;
    try {
        pElem = GetNextOpElem(resp);
        pElem->setType(OCSD_GEN_TRC_ELEM_EO_TRACE);
        m_outputElemList.commitAllPendElem();
        m_curr_state = SEND_PKTS;
        resp = m_outputElemList.sendElements();
        if(OCSD_DATA_RESP_IS_CONT(resp))
            m_curr_state = DECODE_PKTS;
    }
    catch(ocsdError &err)
    {
        LogError(err);
        resetDecoder(); // mark decoder as unsynced - dump any current state.
    }    
    return resp;
}
Example #23
0
int decode_out_ev(Gzb64* gzb64, struct evbuffer* output)
{
	struct evbuffer_iovec v[2];
	int n, i, written;
	size_t n_to_add = BUFF_SIZE;

	/* Reserve BUFF_SIZE bytes.*/
	n = evbuffer_reserve_space(output, n_to_add, v, 2);
	if (n<=0)
	   return -1; /* Unable to reserve the space for some reason. */

	for (i=0; i<n && n_to_add > 0; ++i) {
	   size_t len = v[i].iov_len;
	   if (len > n_to_add) /* Don't write more than n_to_add bytes. */
		  len = n_to_add;
	   if ( (written = decode_out(gzb64, v[i].iov_base, len)) < 0) {
		  /* If there was a problem during data generation, we can just stop
		     here; no data will be committed to the buffer. */
		  return -1;
	   }
	   /* Set iov_len to the number of bytes we actually wrote, so we
		  don't commit too much. */
	   v[i].iov_len = written;
	}

	/* We commit the space here.  Note that we give it 'i' (the number of
	   vectors we actually used) rather than 'n' (the number of vectors we
	   had available. */
	if (evbuffer_commit_space(output, v, i) < 0)
	   return -1; /* Error committing */
	
	/* recurse if some data was recieved */
	if( written > 0 )
		return decode_out_ev(gzb64, output);

	resetDecoder(gzb64);

	return 0;
}
Example #24
0
void SoftHEVC::onQueueFilled(OMX_U32 portIndex) {
    UNUSED(portIndex);

    if (mSignalledError) {
        return;
    }
    if (mOutputPortSettingsChange != NONE) {
        return;
    }

    if (NULL == mCodecCtx) {
        if (OK != initDecoder()) {
            ALOGE("Failed to initialize decoder");
            notify(OMX_EventError, OMX_ErrorUnsupportedSetting, 0, NULL);
            mSignalledError = true;
            return;
        }
    }
    if (outputBufferWidth() != mStride) {
        /* Set the run-time (dynamic) parameters */
        mStride = outputBufferWidth();
        setParams(mStride);
    }

    List<BufferInfo *> &inQueue = getPortQueue(kInputPortIndex);
    List<BufferInfo *> &outQueue = getPortQueue(kOutputPortIndex);

    while (!outQueue.empty()) {
        BufferInfo *inInfo;
        OMX_BUFFERHEADERTYPE *inHeader;

        BufferInfo *outInfo;
        OMX_BUFFERHEADERTYPE *outHeader;
        size_t timeStampIx;

        inInfo = NULL;
        inHeader = NULL;

        if (!mIsInFlush) {
            if (!inQueue.empty()) {
                inInfo = *inQueue.begin();
                inHeader = inInfo->mHeader;
            } else {
                break;
            }
        }

        outInfo = *outQueue.begin();
        outHeader = outInfo->mHeader;
        outHeader->nFlags = 0;
        outHeader->nTimeStamp = 0;
        outHeader->nOffset = 0;

        if (inHeader != NULL && (inHeader->nFlags & OMX_BUFFERFLAG_EOS)) {
            mReceivedEOS = true;
            if (inHeader->nFilledLen == 0) {
                inQueue.erase(inQueue.begin());
                inInfo->mOwnedByUs = false;
                notifyEmptyBufferDone(inHeader);
                inHeader = NULL;
                setFlushMode();
            }
        }

        /* Get a free slot in timestamp array to hold input timestamp */
        {
            size_t i;
            timeStampIx = 0;
            for (i = 0; i < MAX_TIME_STAMPS; i++) {
                if (!mTimeStampsValid[i]) {
                    timeStampIx = i;
                    break;
                }
            }
            if (inHeader != NULL) {
                mTimeStampsValid[timeStampIx] = true;
                mTimeStamps[timeStampIx] = inHeader->nTimeStamp;
            }
        }

        {
            ivd_video_decode_ip_t s_dec_ip;
            ivd_video_decode_op_t s_dec_op;
            WORD32 timeDelay, timeTaken;
            size_t sizeY, sizeUV;

            if (!setDecodeArgs(&s_dec_ip, &s_dec_op, inHeader, outHeader, timeStampIx)) {
                ALOGE("Decoder arg setup failed");
                notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
                mSignalledError = true;
                return;
            }

            GETTIME(&mTimeStart, NULL);
            /* Compute time elapsed between end of previous decode()
             * to start of current decode() */
            TIME_DIFF(mTimeEnd, mTimeStart, timeDelay);

            IV_API_CALL_STATUS_T status;
            status = ivdec_api_function(mCodecCtx, (void *)&s_dec_ip, (void *)&s_dec_op);

            bool unsupportedResolution =
                (IVD_STREAM_WIDTH_HEIGHT_NOT_SUPPORTED == (s_dec_op.u4_error_code & 0xFF));

            /* Check for unsupported dimensions */
            if (unsupportedResolution) {
                ALOGE("Unsupported resolution : %dx%d", mWidth, mHeight);
                notify(OMX_EventError, OMX_ErrorUnsupportedSetting, 0, NULL);
                mSignalledError = true;
                return;
            }

            bool allocationFailed = (IVD_MEM_ALLOC_FAILED == (s_dec_op.u4_error_code & 0xFF));
            if (allocationFailed) {
                ALOGE("Allocation failure in decoder");
                notify(OMX_EventError, OMX_ErrorUnsupportedSetting, 0, NULL);
                mSignalledError = true;
                return;
            }

            bool resChanged = (IVD_RES_CHANGED == (s_dec_op.u4_error_code & 0xFF));

            getVUIParams();

            GETTIME(&mTimeEnd, NULL);
            /* Compute time taken for decode() */
            TIME_DIFF(mTimeStart, mTimeEnd, timeTaken);

            ALOGV("timeTaken=%6d delay=%6d numBytes=%6d", timeTaken, timeDelay,
                   s_dec_op.u4_num_bytes_consumed);
            if (s_dec_op.u4_frame_decoded_flag && !mFlushNeeded) {
                mFlushNeeded = true;
            }

            if ((inHeader != NULL) && (1 != s_dec_op.u4_frame_decoded_flag)) {
                /* If the input did not contain picture data, then ignore
                 * the associated timestamp */
                mTimeStampsValid[timeStampIx] = false;
            }

            // If the decoder is in the changing resolution mode and there is no output present,
            // that means the switching is done and it's ready to reset the decoder and the plugin.
            if (mChangingResolution && !s_dec_op.u4_output_present) {
                mChangingResolution = false;
                resetDecoder();
                resetPlugin();
                mStride = outputBufferWidth();
                setParams(mStride);
                continue;
            }

            if (resChanged) {
                mChangingResolution = true;
                if (mFlushNeeded) {
                    setFlushMode();
                }
                continue;
            }

            // Combine the resolution change and coloraspects change in one PortSettingChange event
            // if necessary.
            if ((0 < s_dec_op.u4_pic_wd) && (0 < s_dec_op.u4_pic_ht)) {
                uint32_t width = s_dec_op.u4_pic_wd;
                uint32_t height = s_dec_op.u4_pic_ht;
                bool portWillReset = false;
                handlePortSettingsChange(&portWillReset, width, height);

                if (portWillReset) {
                    resetDecoder();
                    resetPlugin();
                    return;
                }
            } else if (mUpdateColorAspects) {
                notify(OMX_EventPortSettingsChanged, kOutputPortIndex,
                    kDescribeColorAspectsIndex, NULL);
                mUpdateColorAspects = false;
                return;
            }

            if (s_dec_op.u4_output_present) {
                outHeader->nFilledLen = (outputBufferWidth() * outputBufferHeight() * 3) / 2;

                outHeader->nTimeStamp = mTimeStamps[s_dec_op.u4_ts];
                mTimeStampsValid[s_dec_op.u4_ts] = false;

                outInfo->mOwnedByUs = false;
                outQueue.erase(outQueue.begin());
                outInfo = NULL;
                notifyFillBufferDone(outHeader);
                outHeader = NULL;
            } else if (mIsInFlush) {
                /* If in flush mode and no output is returned by the codec,
                 * then come out of flush mode */
                mIsInFlush = false;

                /* If EOS was recieved on input port and there is no output
                 * from the codec, then signal EOS on output port */
                if (mReceivedEOS) {
                    outHeader->nFilledLen = 0;
                    outHeader->nFlags |= OMX_BUFFERFLAG_EOS;

                    outInfo->mOwnedByUs = false;
                    outQueue.erase(outQueue.begin());
                    outInfo = NULL;
                    notifyFillBufferDone(outHeader);
                    outHeader = NULL;
                    resetPlugin();
                }
            }
        }

        /* If input EOS is seen and decoder is not in flush mode,
         * set the decoder in flush mode.
         * There can be a case where EOS is sent along with last picture data
         * In that case, only after decoding that input data, decoder has to be
         * put in flush. This case is handled here  */

        if (mReceivedEOS && !mIsInFlush) {
            setFlushMode();
        }

        // TODO: Handle more than one picture data
        if (inHeader != NULL) {
            inInfo->mOwnedByUs = false;
            inQueue.erase(inQueue.begin());
            inInfo = NULL;
            notifyEmptyBufferDone(inHeader);
            inHeader = NULL;
        }
    }
}
void SoftAVC::onQueueFilled(OMX_U32 portIndex) {
    UNUSED(portIndex);

    if (mSignalledError) {
        return;
    }
    if (mOutputPortSettingsChange != NONE) {
        return;
    }

    List<BufferInfo *> &inQueue = getPortQueue(kInputPortIndex);
    List<BufferInfo *> &outQueue = getPortQueue(kOutputPortIndex);

    /* If input EOS is seen and decoder is not in flush mode,
     * set the decoder in flush mode.
     * There can be a case where EOS is sent along with last picture data
     * In that case, only after decoding that input data, decoder has to be
     * put in flush. This case is handled here  */

    if (mReceivedEOS && !mIsInFlush) {
        setFlushMode();
    }

    while (!outQueue.empty()) {
        BufferInfo *inInfo;
        OMX_BUFFERHEADERTYPE *inHeader;

        BufferInfo *outInfo;
        OMX_BUFFERHEADERTYPE *outHeader;
        size_t timeStampIx;

        inInfo = NULL;
        inHeader = NULL;

        if (!mIsInFlush) {
            if (!inQueue.empty()) {
                inInfo = *inQueue.begin();
                inHeader = inInfo->mHeader;
                if (inHeader == NULL) {
                    inQueue.erase(inQueue.begin());
                    inInfo->mOwnedByUs = false;
                    continue;
                }
            } else {
                break;
            }
        }

        outInfo = *outQueue.begin();
        outHeader = outInfo->mHeader;
        outHeader->nFlags = 0;
        outHeader->nTimeStamp = 0;
        outHeader->nOffset = 0;

        if (inHeader != NULL) {
            if (inHeader->nFilledLen == 0) {
                inQueue.erase(inQueue.begin());
                inInfo->mOwnedByUs = false;
                notifyEmptyBufferDone(inHeader);

                if (!(inHeader->nFlags & OMX_BUFFERFLAG_EOS)) {
                    continue;
                }

                mReceivedEOS = true;
                inHeader = NULL;
                setFlushMode();
            } else if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
                mReceivedEOS = true;
            }
        }

        // When there is an init required and the decoder is not in flush mode,
        // update output port's definition and reinitialize decoder.
        if (mInitNeeded && !mIsInFlush) {
            bool portWillReset = false;

            status_t err = reInitDecoder(mNewWidth, mNewHeight);
            if (err != OK) {
                notify(OMX_EventError, OMX_ErrorUnsupportedSetting, err, NULL);
                mSignalledError = true;
                return;
            }

            handlePortSettingsChange(&portWillReset, mNewWidth, mNewHeight);
            return;
        }

        /* Get a free slot in timestamp array to hold input timestamp */
        {
            size_t i;
            timeStampIx = 0;
            for (i = 0; i < MAX_TIME_STAMPS; i++) {
                if (!mTimeStampsValid[i]) {
                    timeStampIx = i;
                    break;
                }
            }
            if (inHeader != NULL) {
                mTimeStampsValid[timeStampIx] = true;
                mTimeStamps[timeStampIx] = inHeader->nTimeStamp;
            }
        }

        {
            ivd_video_decode_ip_t s_dec_ip;
            ivd_video_decode_op_t s_dec_op;
            WORD32 timeDelay, timeTaken;
            size_t sizeY, sizeUV;

            setDecodeArgs(&s_dec_ip, &s_dec_op, inHeader, outHeader, timeStampIx);
            // If input dump is enabled, then write to file
            DUMP_TO_FILE(mInFile, s_dec_ip.pv_stream_buffer, s_dec_ip.u4_num_Bytes);

            GETTIME(&mTimeStart, NULL);
            /* Compute time elapsed between end of previous decode()
             * to start of current decode() */
            TIME_DIFF(mTimeEnd, mTimeStart, timeDelay);

            IV_API_CALL_STATUS_T status;
            status = ivdec_api_function(mCodecCtx, (void *)&s_dec_ip, (void *)&s_dec_op);

            bool unsupportedDimensions =
                (IVD_STREAM_WIDTH_HEIGHT_NOT_SUPPORTED == (s_dec_op.u4_error_code & 0xFF));
            bool resChanged = (IVD_RES_CHANGED == (s_dec_op.u4_error_code & 0xFF));
            bool unsupportedLevel = (IH264D_UNSUPPORTED_LEVEL == (s_dec_op.u4_error_code & 0xFF));

            GETTIME(&mTimeEnd, NULL);
            /* Compute time taken for decode() */
            TIME_DIFF(mTimeStart, mTimeEnd, timeTaken);

            PRINT_TIME("timeTaken=%6d delay=%6d numBytes=%6d", timeTaken, timeDelay,
                   s_dec_op.u4_num_bytes_consumed);
            if (s_dec_op.u4_frame_decoded_flag && !mFlushNeeded) {
                mFlushNeeded = true;
            }

            if ((inHeader != NULL) && (1 != s_dec_op.u4_frame_decoded_flag)) {
                /* If the input did not contain picture data, then ignore
                 * the associated timestamp */
                mTimeStampsValid[timeStampIx] = false;
            }


            // This is needed to handle CTS DecoderTest testCodecResetsH264WithoutSurface,
            // which is not sending SPS/PPS after port reconfiguration and flush to the codec.
            if (unsupportedDimensions && !mFlushNeeded) {
                bool portWillReset = false;
                mNewWidth = s_dec_op.u4_pic_wd;
                mNewHeight = s_dec_op.u4_pic_ht;

                status_t err = reInitDecoder(mNewWidth, mNewHeight);
                if (err != OK) {
                    notify(OMX_EventError, OMX_ErrorUnsupportedSetting, err, NULL);
                    mSignalledError = true;
                    return;
                }

                handlePortSettingsChange(&portWillReset, mNewWidth, mNewHeight);

                setDecodeArgs(&s_dec_ip, &s_dec_op, inHeader, outHeader, timeStampIx);

                ivdec_api_function(mCodecCtx, (void *)&s_dec_ip, (void *)&s_dec_op);
                return;
            }

            if (unsupportedLevel && !mFlushNeeded) {

                mNewLevel = 51;

                status_t err = reInitDecoder(mNewWidth, mNewHeight);
                if (err != OK) {
                    notify(OMX_EventError, OMX_ErrorUnsupportedSetting, err, NULL);
                    mSignalledError = true;
                    return;
                }

                setDecodeArgs(&s_dec_ip, &s_dec_op, inHeader, outHeader, timeStampIx);

                ivdec_api_function(mCodecCtx, (void *)&s_dec_ip, (void *)&s_dec_op);
                return;
            }

            // If the decoder is in the changing resolution mode and there is no output present,
            // that means the switching is done and it's ready to reset the decoder and the plugin.
            if (mChangingResolution && !s_dec_op.u4_output_present) {
                mChangingResolution = false;
                resetDecoder();
                resetPlugin();
                continue;
            }

            if (unsupportedDimensions || resChanged) {
                mChangingResolution = true;
                if (mFlushNeeded) {
                    setFlushMode();
                }

                if (unsupportedDimensions) {
                    mNewWidth = s_dec_op.u4_pic_wd;
                    mNewHeight = s_dec_op.u4_pic_ht;
                    mInitNeeded = true;
                }
                continue;
            }

            if (unsupportedLevel) {

                if (mFlushNeeded) {
                    setFlushMode();
                }

                mNewLevel = 51;
                mInitNeeded = true;
                continue;
            }

            if ((0 < s_dec_op.u4_pic_wd) && (0 < s_dec_op.u4_pic_ht)) {
                uint32_t width = s_dec_op.u4_pic_wd;
                uint32_t height = s_dec_op.u4_pic_ht;
                bool portWillReset = false;
                handlePortSettingsChange(&portWillReset, width, height);

                if (portWillReset) {
                    resetDecoder();
                    return;
                }
            }

            if (s_dec_op.u4_output_present) {
                outHeader->nFilledLen = (outputBufferWidth() * outputBufferHeight() * 3) / 2;

                outHeader->nTimeStamp = mTimeStamps[s_dec_op.u4_ts];
                mTimeStampsValid[s_dec_op.u4_ts] = false;

                outInfo->mOwnedByUs = false;
                outQueue.erase(outQueue.begin());
                outInfo = NULL;
                notifyFillBufferDone(outHeader);
                outHeader = NULL;
            } else {
                /* If in flush mode and no output is returned by the codec,
                 * then come out of flush mode */
                mIsInFlush = false;

                /* If EOS was recieved on input port and there is no output
                 * from the codec, then signal EOS on output port */
                if (mReceivedEOS) {
                    outHeader->nFilledLen = 0;
                    outHeader->nFlags |= OMX_BUFFERFLAG_EOS;

                    outInfo->mOwnedByUs = false;
                    outQueue.erase(outQueue.begin());
                    outInfo = NULL;
                    notifyFillBufferDone(outHeader);
                    outHeader = NULL;
                    resetPlugin();
                }
            }
        }

        if (inHeader != NULL) {
            inInfo->mOwnedByUs = false;
            inQueue.erase(inQueue.begin());
            inInfo = NULL;
            notifyEmptyBufferDone(inHeader);
            inHeader = NULL;
        }
    }
}
ocsd_datapath_resp_t TrcPktDecodeEtmV3::processBranchAddr()
{
    ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
    OcsdTraceElement *pElem = 0;
    bool bUpdatePEContext = false;

    // might need to cancel something ... if the last output was an instruction range or excep return
    if(m_curr_packet_in->isExcepCancel())
        m_outputElemList.cancelPendElem();
    else         
        m_outputElemList.commitAllPendElem(); // otherwise commit any pending elements.

    // record the address
    m_IAddr = m_curr_packet_in->getAddr();
    setNeedAddr(false);    // no longer need an address.
   
    // exception packet - may need additional output
    if(m_curr_packet_in->isExcepPkt())
    {
        // exeception packet may have exception, context change, or both.
        // check for context change
        if(m_curr_packet_in->isCtxtUpdated())
        {
            
            ocsd_sec_level sec = m_curr_packet_in->isNS() ? ocsd_sec_nonsecure : ocsd_sec_secure;
            if(sec != m_PeContext.getSecLevel())
            {
                m_PeContext.setSecLevel(sec);
                bUpdatePEContext = true;
            }
            ocsd_ex_level pkt_el = m_curr_packet_in->isHyp() ?  ocsd_EL2 : ocsd_EL_unknown;
            if(pkt_el != m_PeContext.getEL())
            {
                m_PeContext.setEL(pkt_el);
                bUpdatePEContext = true;
            }
        }

        // now decide if we need to send any packets out.
        try {

            if(bUpdatePEContext)
            {
                pElem = GetNextOpElem(resp);
                pElem->setType(OCSD_GEN_TRC_ELEM_PE_CONTEXT);
                pElem->setContext(m_PeContext);
            }

            // check for exception
            if(m_curr_packet_in->excepNum() != 0)
            {
                pElem = GetNextOpElem(resp);
                pElem->setType(OCSD_GEN_TRC_ELEM_EXCEPTION);
                pElem->setExceptionNum(m_curr_packet_in->excepNum());                        
            }

            // finally - do we have anything to send yet?
            m_curr_state = m_outputElemList.elemToSend() ? SEND_PKTS : DECODE_PKTS;
        }
        catch(ocsdError &err)
        {
            LogError(err);
            resetDecoder(); // mark decoder as unsynced - dump any current state.
        }
    }       
    return resp;
}
void SoftMPEG2::onQueueFilled(OMX_U32 portIndex) {
    UNUSED(portIndex);

    if (mOutputPortSettingsChange != NONE) {
        return;
    }

    List<BufferInfo *> &inQueue = getPortQueue(kInputPortIndex);
    List<BufferInfo *> &outQueue = getPortQueue(kOutputPortIndex);

    /* If input EOS is seen and decoder is not in flush mode,
     * set the decoder in flush mode.
     * There can be a case where EOS is sent along with last picture data
     * In that case, only after decoding that input data, decoder has to be
     * put in flush. This case is handled here  */

    if (mReceivedEOS && !mIsInFlush) {
        setFlushMode();
    }

    while (!outQueue.empty()) {
        BufferInfo *inInfo;
        OMX_BUFFERHEADERTYPE *inHeader;

        BufferInfo *outInfo;
        OMX_BUFFERHEADERTYPE *outHeader;
        size_t timeStampIx;

        inInfo = NULL;
        inHeader = NULL;

        if (!mIsInFlush) {
            if (!inQueue.empty()) {
                inInfo = *inQueue.begin();
                inHeader = inInfo->mHeader;
            } else {
                break;
            }
        }

        outInfo = *outQueue.begin();
        outHeader = outInfo->mHeader;
        outHeader->nFlags = 0;
        outHeader->nTimeStamp = 0;
        outHeader->nOffset = 0;

        if (inHeader != NULL && (inHeader->nFlags & OMX_BUFFERFLAG_EOS)) {
            mReceivedEOS = true;
            if (inHeader->nFilledLen == 0) {
                inQueue.erase(inQueue.begin());
                inInfo->mOwnedByUs = false;
                notifyEmptyBufferDone(inHeader);
                inHeader = NULL;
                setFlushMode();
            }
        }

        // When there is an init required and the decoder is not in flush mode,
        // update output port's definition and reinitialize decoder.
        if (mInitNeeded && !mIsInFlush) {
            bool portWillReset = false;
            handlePortSettingsChange(&portWillReset, mNewWidth, mNewHeight);

            CHECK_EQ(reInitDecoder(), (status_t)OK);
            return;
        }

        /* Get a free slot in timestamp array to hold input timestamp */
        {
            size_t i;
            timeStampIx = 0;
            for (i = 0; i < MAX_TIME_STAMPS; i++) {
                if (!mTimeStampsValid[i]) {
                    timeStampIx = i;
                    break;
                }
            }
            if (inHeader != NULL) {
                mTimeStampsValid[timeStampIx] = true;
                mTimeStamps[timeStampIx] = inHeader->nTimeStamp;
            }
        }

        {
            ivd_video_decode_ip_t s_dec_ip;
            ivd_video_decode_op_t s_dec_op;
            WORD32 timeDelay, timeTaken;
            size_t sizeY, sizeUV;

            setDecodeArgs(&s_dec_ip, &s_dec_op, inHeader, outHeader, timeStampIx);
            // If input dump is enabled, then write to file
            DUMP_TO_FILE(mInFile, s_dec_ip.pv_stream_buffer, s_dec_ip.u4_num_Bytes);

            if (s_dec_ip.u4_num_Bytes > 0) {
                char *ptr = (char *)s_dec_ip.pv_stream_buffer;
            }

            GETTIME(&mTimeStart, NULL);
            /* Compute time elapsed between end of previous decode()
             * to start of current decode() */
            TIME_DIFF(mTimeEnd, mTimeStart, timeDelay);

            IV_API_CALL_STATUS_T status;
            status = ivdec_api_function(mCodecCtx, (void *)&s_dec_ip, (void *)&s_dec_op);

            bool unsupportedDimensions = (IMPEG2D_UNSUPPORTED_DIMENSIONS == s_dec_op.u4_error_code);
            bool resChanged = (IVD_RES_CHANGED == (s_dec_op.u4_error_code & 0xFF));

            GETTIME(&mTimeEnd, NULL);
            /* Compute time taken for decode() */
            TIME_DIFF(mTimeStart, mTimeEnd, timeTaken);

            ALOGV("timeTaken=%6d delay=%6d numBytes=%6d", timeTaken, timeDelay,
                   s_dec_op.u4_num_bytes_consumed);
            if (s_dec_op.u4_frame_decoded_flag && !mFlushNeeded) {
                mFlushNeeded = true;
            }

            if ((inHeader != NULL) && (1 != s_dec_op.u4_frame_decoded_flag)) {
                /* If the input did not contain picture data, then ignore
                 * the associated timestamp */
                mTimeStampsValid[timeStampIx] = false;
            }

            // This is needed to handle CTS DecoderTest testCodecResetsMPEG2WithoutSurface,
            // which is not sending SPS/PPS after port reconfiguration and flush to the codec.
            if (unsupportedDimensions && !mFlushNeeded) {
                bool portWillReset = false;
                handlePortSettingsChange(&portWillReset, s_dec_op.u4_pic_wd, s_dec_op.u4_pic_ht);

                CHECK_EQ(reInitDecoder(), (status_t)OK);

                setDecodeArgs(&s_dec_ip, &s_dec_op, inHeader, outHeader, timeStampIx);

                ivdec_api_function(mCodecCtx, (void *)&s_dec_ip, (void *)&s_dec_op);
                return;
            }

            // If the decoder is in the changing resolution mode and there is no output present,
            // that means the switching is done and it's ready to reset the decoder and the plugin.
            if (mChangingResolution && !s_dec_op.u4_output_present) {
                mChangingResolution = false;
                resetDecoder();
                resetPlugin();
                continue;
            }

            if (unsupportedDimensions || resChanged) {
                mChangingResolution = true;
                if (mFlushNeeded) {
                    setFlushMode();
                }

                if (unsupportedDimensions) {
                    mNewWidth = s_dec_op.u4_pic_wd;
                    mNewHeight = s_dec_op.u4_pic_ht;
                    mInitNeeded = true;
                }
                continue;
            }

            if ((0 < s_dec_op.u4_pic_wd) && (0 < s_dec_op.u4_pic_ht)) {
                uint32_t width = s_dec_op.u4_pic_wd;
                uint32_t height = s_dec_op.u4_pic_ht;
                bool portWillReset = false;
                handlePortSettingsChange(&portWillReset, width, height);

                if (portWillReset) {
                    resetDecoder();
                    return;
                }
            }

            if (s_dec_op.u4_output_present) {
                size_t timeStampIdx;
                outHeader->nFilledLen = (mWidth * mHeight * 3) / 2;

                timeStampIdx = getMinTimestampIdx(mTimeStamps, mTimeStampsValid);
                outHeader->nTimeStamp = mTimeStamps[timeStampIdx];
                mTimeStampsValid[timeStampIdx] = false;

                /* mWaitForI waits for the first I picture. Once made FALSE, it
                   has to remain false till explicitly set to TRUE. */
                mWaitForI = mWaitForI && !(IV_I_FRAME == s_dec_op.e_pic_type);

                if (mWaitForI) {
                    s_dec_op.u4_output_present = false;
                } else {
                    ALOGV("Output timestamp: %lld, res: %ux%u",
                            (long long)outHeader->nTimeStamp, mWidth, mHeight);
                    DUMP_TO_FILE(mOutFile, outHeader->pBuffer, outHeader->nFilledLen);
                    outInfo->mOwnedByUs = false;
                    outQueue.erase(outQueue.begin());
                    outInfo = NULL;
                    notifyFillBufferDone(outHeader);
                    outHeader = NULL;
                }
            } else {
                /* If in flush mode and no output is returned by the codec,
                 * then come out of flush mode */
                mIsInFlush = false;

                /* If EOS was recieved on input port and there is no output
                 * from the codec, then signal EOS on output port */
                if (mReceivedEOS) {
                    outHeader->nFilledLen = 0;
                    outHeader->nFlags |= OMX_BUFFERFLAG_EOS;

                    outInfo->mOwnedByUs = false;
                    outQueue.erase(outQueue.begin());
                    outInfo = NULL;
                    notifyFillBufferDone(outHeader);
                    outHeader = NULL;
                    resetPlugin();
                }
            }
        }

        // TODO: Handle more than one picture data
        if (inHeader != NULL) {
            inInfo->mOwnedByUs = false;
            inQueue.erase(inQueue.begin());
            inInfo = NULL;
            notifyEmptyBufferDone(inHeader);
            inHeader = NULL;
        }
    }
}
ocsd_datapath_resp_t TrcPktDecodeEtmV3::processPHdr()
{
    ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
    OcsdTraceElement *pElem = 0;
    ocsd_isa isa;
    Etmv3Atoms atoms(m_config->isCycleAcc());

    atoms.initAtomPkt(m_curr_packet_in,m_index_curr_pkt);
    isa = m_curr_packet_in->ISA();
    m_code_follower.setMemSpaceAccess((m_PeContext.getSecLevel() ==  ocsd_sec_secure) ? OCSD_MEM_SPACE_S : OCSD_MEM_SPACE_N);

    try
    {
        do 
        {
            // if we do not have a valid address then send any cycle count elements 
            // and stop processing
            if(m_bNeedAddr)
            {
                // output unknown address packet or a cycle count packet
                if(!m_bSentUnknown || m_config->isCycleAcc())
                {
                    pElem = GetNextOpElem(resp);
                    if(m_bSentUnknown || !atoms.numAtoms())
                        pElem->setType(OCSD_GEN_TRC_ELEM_CYCLE_COUNT);
                    else
                        pElem->setType(OCSD_GEN_TRC_ELEM_ADDR_UNKNOWN);
                    if(m_config->isCycleAcc())
                        pElem->setCycleCount(atoms.getRemainCC());
                    m_bSentUnknown = true;
                }
                atoms.clearAll();   // skip remaining atoms
            }
            else    // have an address, can process atoms
            {
                pElem = GetNextOpElem(resp);
                pElem->setType(OCSD_GEN_TRC_ELEM_INSTR_RANGE);
    
                // cycle accurate may have a cycle count to use
                if(m_config->isCycleAcc())
                {
                    // note: it is possible to have a CC only atom packet.
                    if(!atoms.numAtoms())   // override type if CC only
                         pElem->setType(OCSD_GEN_TRC_ELEM_CYCLE_COUNT);
                    // set cycle count
                    pElem->setCycleCount(atoms.getAtomCC());
                }

                // now process the atom 
                if(atoms.numAtoms())
                {
                    m_code_follower.setISA(isa);
                    m_code_follower.followSingleAtom(m_IAddr,atoms.getCurrAtomVal());

                    // valid code range
                    if(m_code_follower.hasRange())
                    {
                        pElem->setAddrRange(m_IAddr,m_code_follower.getRangeEn());
                        pElem->setLastInstrInfo(atoms.getCurrAtomVal() == ATOM_E, 
                                    m_code_follower.getInstrType(),
                                    m_code_follower.getInstrSubType());
                        pElem->setISA(isa);
                        if(m_code_follower.hasNextAddr())
                            m_IAddr = m_code_follower.getNextAddr();
                        else
                            setNeedAddr(true);
                    }

                    // next address has new ISA?
                    if(m_code_follower.ISAChanged())
                        isa = m_code_follower.nextISA();
                    
                    // there is a nacc
                    if(m_code_follower.isNacc())
                    {
                        if(m_code_follower.hasRange())
                        {
                            pElem = GetNextOpElem(resp);
                            pElem->setType(OCSD_GEN_TRC_ELEM_ADDR_NACC);
                        }
                        else
                            pElem->updateType(OCSD_GEN_TRC_ELEM_ADDR_NACC);
                        pElem->setAddrStart(m_code_follower.getNaccAddr());
                        setNeedAddr(true);
                        m_code_follower.clearNacc(); // we have generated some code for the nacc.
                    }
                }

                atoms.clearAtom();  // next atom
            }
        }
        while(atoms.numAtoms());

        // is tha last element an atom?
        int numElem = m_outputElemList.getNumElem();
        if(numElem >= 1)
        {
            // if the last thing is an instruction range, pend it - could be cancelled later.
            if(m_outputElemList.getElemType(numElem-1) == OCSD_GEN_TRC_ELEM_INSTR_RANGE)
                m_outputElemList.pendLastNElem(1);
        }

        // finally - do we have anything to send yet?
        m_curr_state = m_outputElemList.elemToSend() ? SEND_PKTS : DECODE_PKTS;
    }
    catch(ocsdError &err)
    {
        LogError(err);
        resetDecoder(); // mark decoder as unsynced - dump any current state.
    }
    return resp;
}
/* implementation packet decoding interface */
ocsd_datapath_resp_t TrcPktDecodeEtmV3::processPacket()
{
    ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
    bool bPktDone = false;

    if(!m_config)
        return OCSD_RESP_FATAL_NOT_INIT;

    // iterate round the state machine, waiting for sync, then decoding packets.
    while(!bPktDone)
    {
        switch(m_curr_state)
        {
        case NO_SYNC:
            // output the initial not synced packet to the sink
            resp = sendUnsyncPacket();  
            m_curr_state = WAIT_ASYNC;  // immediate wait for ASync and actually check out the packet
            break;

        case WAIT_ASYNC:
            // if async, wait for ISync, but this packet done.
            if(m_curr_packet_in->getType() == ETM3_PKT_A_SYNC)
                m_curr_state = WAIT_ISYNC;
            bPktDone = true;
            break;

        case WAIT_ISYNC:
            m_bWaitISync = true;    // we are waiting for ISync
            if((m_curr_packet_in->getType() == ETM3_PKT_I_SYNC) || 
                (m_curr_packet_in->getType() == ETM3_PKT_I_SYNC_CYCLE))
            {
                // process the ISync immediately as the first ISync seen.
                resp = processISync((m_curr_packet_in->getType() == ETM3_PKT_I_SYNC_CYCLE),true);
                m_curr_state = SEND_PKTS;
                m_bWaitISync = false;
            }
            // something like TS, CC, PHDR+CC, which after ASYNC may be valid prior to ISync
            else if(preISyncValid(m_curr_packet_in->getType()))
            {
                // decode anything that might be valid - send will be set automatically 
                resp = decodePacket(bPktDone);
            }
            else
                bPktDone = true; 
            break;

        case DECODE_PKTS:
            resp = decodePacket(bPktDone);
            break;

        case SEND_PKTS:
            resp = m_outputElemList.sendElements();
            if(OCSD_DATA_RESP_IS_CONT(resp))
                m_curr_state = m_bWaitISync ? WAIT_ISYNC : DECODE_PKTS;
            bPktDone = true;
            break;  

        default:
            bPktDone = true;
            LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_FAIL,m_index_curr_pkt,"Unknown Decoder State"));
            resetDecoder(); // mark decoder as unsynced - dump any current state.
            resp = OCSD_RESP_FATAL_SYS_ERR;
            break;
        }
    }

    return resp;
}
Example #30
0
void SoftHEVC::onQueueFilled(OMX_U32 portIndex) {
    UNUSED(portIndex);

    if (mOutputPortSettingsChange != NONE) {
        return;
    }

    List<BufferInfo *> &inQueue = getPortQueue(kInputPortIndex);
    List<BufferInfo *> &outQueue = getPortQueue(kOutputPortIndex);

    /* If input EOS is seen and decoder is not in flush mode,
     * set the decoder in flush mode.
     * There can be a case where EOS is sent along with last picture data
     * In that case, only after decoding that input data, decoder has to be
     * put in flush. This case is handled here  */

    if (mReceivedEOS && !mIsInFlush) {
        setFlushMode();
    }

    while (!outQueue.empty()) {
        BufferInfo *inInfo;
        OMX_BUFFERHEADERTYPE *inHeader;

        BufferInfo *outInfo;
        OMX_BUFFERHEADERTYPE *outHeader;
        size_t timeStampIx;

        inInfo = NULL;
        inHeader = NULL;

        if (!mIsInFlush) {
            if (!inQueue.empty()) {
                inInfo = *inQueue.begin();
                inHeader = inInfo->mHeader;
            } else {
                break;
            }
        }

        outInfo = *outQueue.begin();
        outHeader = outInfo->mHeader;
        outHeader->nFlags = 0;
        outHeader->nTimeStamp = 0;
        outHeader->nOffset = 0;

        if (inHeader != NULL && (inHeader->nFlags & OMX_BUFFERFLAG_EOS)) {
            ALOGD("EOS seen on input");
            mReceivedEOS = true;
            if (inHeader->nFilledLen == 0) {
                inQueue.erase(inQueue.begin());
                inInfo->mOwnedByUs = false;
                notifyEmptyBufferDone(inHeader);
                inHeader = NULL;
                setFlushMode();
            }
        }

        // When there is an init required and the decoder is not in flush mode,
        // update output port's definition and reinitialize decoder.
        if (mInitNeeded && !mIsInFlush) {
            bool portWillReset = false;
            handlePortSettingsChange(&portWillReset, mNewWidth, mNewHeight);

            CHECK_EQ(reInitDecoder(), (status_t)OK);
            return;
        }

        /* Get a free slot in timestamp array to hold input timestamp */
        {
            size_t i;
            timeStampIx = 0;
            for (i = 0; i < MAX_TIME_STAMPS; i++) {
                if (!mTimeStampsValid[i]) {
                    timeStampIx = i;
                    break;
                }
            }
            if (inHeader != NULL) {
                mTimeStampsValid[timeStampIx] = true;
                mTimeStamps[timeStampIx] = inHeader->nTimeStamp;
            }
        }

        {
            ivd_video_decode_ip_t s_dec_ip;
            ivd_video_decode_op_t s_dec_op;
            WORD32 timeDelay, timeTaken;
            size_t sizeY, sizeUV;

            setDecodeArgs(&s_dec_ip, &s_dec_op, inHeader, outHeader, timeStampIx);

            GETTIME(&mTimeStart, NULL);
            /* Compute time elapsed between end of previous decode()
             * to start of current decode() */
            TIME_DIFF(mTimeEnd, mTimeStart, timeDelay);

            IV_API_CALL_STATUS_T status;
            status = ivdec_api_function(mCodecCtx, (void *)&s_dec_ip, (void *)&s_dec_op);

            //Fixed 
            if ( mWidth != s_dec_op.u4_pic_wd || mHeight != s_dec_op.u4_pic_ht) {                 
                ALOGE("mWidth %d, mHeight %d -> mNewWidth %d, mNewHeight %d", mWidth, mHeight, mNewWidth, mNewHeight);
                if(mFlushOutBuffer) {
                    ivd_aligned_free(mFlushOutBuffer);
                    mFlushOutBuffer = NULL;
                }
                
                uint32_t bufferSize = s_dec_op.u4_pic_wd * s_dec_op.u4_pic_ht * 3 / 2;
                mFlushOutBuffer = (uint8_t *)ivd_aligned_malloc(128, bufferSize);
                if (NULL == mFlushOutBuffer) {
                    ALOGE("Could not allocate flushOutputBuffer of size %zu", bufferSize);
                    return;
                }
                ALOGE("re-alloc mFlushOutBuffer");
            }

            // FIXME: Compare |status| to IHEVCD_UNSUPPORTED_DIMENSIONS, which is not one of the
            // IV_API_CALL_STATUS_T, seems be wrong. But this is what the decoder returns right now.
            // The decoder should be fixed so that |u4_error_code| instead of |status| returns
            // IHEVCD_UNSUPPORTED_DIMENSIONS.
            bool unsupportedDimensions =
                ((IHEVCD_UNSUPPORTED_DIMENSIONS == status)
                    || (IHEVCD_UNSUPPORTED_DIMENSIONS == s_dec_op.u4_error_code));
            bool resChanged = (IVD_RES_CHANGED == (s_dec_op.u4_error_code & 0xFF));

            GETTIME(&mTimeEnd, NULL);
            /* Compute time taken for decode() */
            TIME_DIFF(mTimeStart, mTimeEnd, timeTaken);

            ALOGV("timeTaken=%6d delay=%6d numBytes=%6d", timeTaken, timeDelay,
                   s_dec_op.u4_num_bytes_consumed);
            if (s_dec_op.u4_frame_decoded_flag && !mFlushNeeded) {
                mFlushNeeded = true;
            }

            if ((inHeader != NULL) && (1 != s_dec_op.u4_frame_decoded_flag)) {
                /* If the input did not contain picture data, then ignore
                 * the associated timestamp */
                mTimeStampsValid[timeStampIx] = false;
            }

            // This is needed to handle CTS DecoderTest testCodecResetsHEVCWithoutSurface,
            // which is not sending SPS/PPS after port reconfiguration and flush to the codec.
            if (unsupportedDimensions && !mFlushNeeded) {
                bool portWillReset = false;
                handlePortSettingsChange(&portWillReset, s_dec_op.u4_pic_wd, s_dec_op.u4_pic_ht);

                CHECK_EQ(reInitDecoder(), (status_t)OK);

                setDecodeArgs(&s_dec_ip, &s_dec_op, inHeader, outHeader, timeStampIx);

                ivdec_api_function(mCodecCtx, (void *)&s_dec_ip, (void *)&s_dec_op);
                return;
            }

            // If the decoder is in the changing resolution mode and there is no output present,
            // that means the switching is done and it's ready to reset the decoder and the plugin.
            if (mChangingResolution && !s_dec_op.u4_output_present) {
                mChangingResolution = false;
                resetDecoder();
                resetPlugin();
                continue;
            }

            if (unsupportedDimensions || resChanged) {
                mChangingResolution = true;
                if (mFlushNeeded) {
                    setFlushMode();
                }

                if (unsupportedDimensions) {
                    mNewWidth = s_dec_op.u4_pic_wd;
                    mNewHeight = s_dec_op.u4_pic_ht;
                    mInitNeeded = true;
                }
                continue;
            }

            if ((0 < s_dec_op.u4_pic_wd) && (0 < s_dec_op.u4_pic_ht)) {
                uint32_t width = s_dec_op.u4_pic_wd;
                uint32_t height = s_dec_op.u4_pic_ht;
                bool portWillReset = false;
                handlePortSettingsChange(&portWillReset, width, height);

                if (portWillReset) {
                    resetDecoder();
                    return;
                }
            }

            if (s_dec_op.u4_output_present) {
                outHeader->nFilledLen = (mWidth * mHeight * 3) / 2;

                outHeader->nTimeStamp = mTimeStamps[s_dec_op.u4_ts];
                mTimeStampsValid[s_dec_op.u4_ts] = false;

                outInfo->mOwnedByUs = false;
                outQueue.erase(outQueue.begin());
                outInfo = NULL;
                notifyFillBufferDone(outHeader);
                outHeader = NULL;
            } else {
                /* If in flush mode and no output is returned by the codec,
                 * then come out of flush mode */
                mIsInFlush = false;

                /* If EOS was recieved on input port and there is no output
                 * from the codec, then signal EOS on output port */
                if (mReceivedEOS) {
                    outHeader->nFilledLen = 0;
                    outHeader->nFlags |= OMX_BUFFERFLAG_EOS;

                    outInfo->mOwnedByUs = false;
                    outQueue.erase(outQueue.begin());
                    outInfo = NULL;
                    notifyFillBufferDone(outHeader);
                    outHeader = NULL;
                    resetPlugin();
                }
            }
        }

        // TODO: Handle more than one picture data
        if (inHeader != NULL) {
            inInfo->mOwnedByUs = false;
            inQueue.erase(inQueue.begin());
            inInfo = NULL;
            notifyEmptyBufferDone(inHeader);
            inHeader = NULL;
        }
    }
}