/** * 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; } }
/** * 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(); }
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()); }
/** * 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; } }
/** * 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; } }
static void trigFinished() { if(itsDoneCallback) itsDoneCallback(0); resetDecoder(); }
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; }
/** * 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; } }
/** * 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; } }
void SoftHEVC::onReset() { ALOGV("onReset called"); SoftVideoDecoderOMXComponent::onReset(); mSignalledError = false; resetDecoder(); resetPlugin(); }
static void errorAndResetDecoder(byte value) { resetDecoder(); signalError(value); state = inactive; }
void SoftMPEG2::onReset() { SoftVideoDecoderOMXComponent::onReset(); mWaitForI = true; resetDecoder(); resetPlugin(); }
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; }
/** 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); }
/** * 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; } }
/** * 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; }
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; }
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; }
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; } } }