Merge "stagefright: return encrypted input buffer for secure codecs" into lmp-dev
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index 2ea12ae..ceedb40 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -64,16 +64,18 @@
};
struct NuPlayer::SeekAction : public Action {
- SeekAction(int64_t seekTimeUs)
- : mSeekTimeUs(seekTimeUs) {
+ SeekAction(int64_t seekTimeUs, bool needNotify)
+ : mSeekTimeUs(seekTimeUs),
+ mNeedNotify(needNotify) {
}
virtual void execute(NuPlayer *player) {
- player->performSeek(mSeekTimeUs);
+ player->performSeek(mSeekTimeUs, mNeedNotify);
}
private:
int64_t mSeekTimeUs;
+ bool mNeedNotify;
DISALLOW_EVIL_CONSTRUCTORS(SeekAction);
};
@@ -324,9 +326,10 @@
(new AMessage(kWhatReset, id()))->post();
}
-void NuPlayer::seekToAsync(int64_t seekTimeUs) {
+void NuPlayer::seekToAsync(int64_t seekTimeUs, bool needNotify) {
sp<AMessage> msg = new AMessage(kWhatSeek, id());
msg->setInt64("seekTimeUs", seekTimeUs);
+ msg->setInt32("needNotify", needNotify);
msg->post();
}
@@ -561,7 +564,8 @@
// the extractor may not yet be started and will assert.
// If the video decoder is not set (perhaps audio only in this case)
// do not perform a seek as it is not needed.
- mDeferredActions.push_back(new SeekAction(mCurrentPositionUs));
+ mDeferredActions.push_back(
+ new SeekAction(mCurrentPositionUs, false /* needNotify */));
}
// If there is a new surface texture, instantiate decoders
@@ -940,7 +944,7 @@
mRenderer->signalDisableOffloadAudio();
mOffloadAudio = false;
- performSeek(positionUs);
+ performSeek(positionUs, false /* needNotify */);
instantiateDecoder(true /* audio */, &mAudioDecoder);
}
break;
@@ -969,14 +973,18 @@
case kWhatSeek:
{
int64_t seekTimeUs;
+ int32_t needNotify;
CHECK(msg->findInt64("seekTimeUs", &seekTimeUs));
+ CHECK(msg->findInt32("needNotify", &needNotify));
- ALOGV("kWhatSeek seekTimeUs=%lld us", seekTimeUs);
+ ALOGV("kWhatSeek seekTimeUs=%lld us, needNotify=%d",
+ seekTimeUs, needNotify);
mDeferredActions.push_back(
new SimpleAction(&NuPlayer::performDecoderFlush));
- mDeferredActions.push_back(new SeekAction(seekTimeUs));
+ mDeferredActions.push_back(
+ new SeekAction(seekTimeUs, needNotify));
processDeferredActions();
break;
@@ -1802,10 +1810,11 @@
}
}
-void NuPlayer::performSeek(int64_t seekTimeUs) {
- ALOGV("performSeek seekTimeUs=%lld us (%.2f secs)",
+void NuPlayer::performSeek(int64_t seekTimeUs, bool needNotify) {
+ ALOGV("performSeek seekTimeUs=%lld us (%.2f secs), needNotify(%d)",
seekTimeUs,
- seekTimeUs / 1E6);
+ seekTimeUs / 1E6,
+ needNotify);
if (mSource == NULL) {
// This happens when reset occurs right before the loop mode
@@ -1822,7 +1831,9 @@
sp<NuPlayerDriver> driver = mDriver.promote();
if (driver != NULL) {
driver->notifyPosition(seekTimeUs);
- driver->notifySeekComplete();
+ if (needNotify) {
+ driver->notifySeekComplete();
+ }
}
}
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.h b/media/libmediaplayerservice/nuplayer/NuPlayer.h
index eee96ca..8fa7269 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.h
@@ -59,8 +59,9 @@
// Will notify the driver through "notifyResetComplete" once finished.
void resetAsync();
- // Will notify the driver through "notifySeekComplete" once finished.
- void seekToAsync(int64_t seekTimeUs);
+ // Will notify the driver through "notifySeekComplete" once finished
+ // and needNotify is true.
+ void seekToAsync(int64_t seekTimeUs, bool needNotify = false);
status_t setVideoScalingMode(int32_t mode);
status_t getTrackInfo(Parcel* reply) const;
@@ -215,7 +216,7 @@
void processDeferredActions();
- void performSeek(int64_t seekTimeUs);
+ void performSeek(int64_t seekTimeUs, bool needNotify);
void performDecoderFlush();
void performDecoderShutdown(bool audio, bool video);
void performReset();
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
index 7ec9876..a9bca49 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
@@ -240,9 +240,7 @@
mPlayer->start();
if (mStartupSeekTimeUs >= 0) {
- if (mStartupSeekTimeUs == 0) {
- notifySeekComplete_l();
- } else {
+ if (mStartupSeekTimeUs > 0) {
mPlayer->seekToAsync(mStartupSeekTimeUs);
}
@@ -369,7 +367,7 @@
mAtEOS = false;
// seeks can take a while, so we essentially paused
notifyListener_l(MEDIA_PAUSED);
- mPlayer->seekToAsync(seekTimeUs);
+ mPlayer->seekToAsync(seekTimeUs, true /* needNotify */);
break;
}
diff --git a/media/libstagefright/NuCachedSource2.cpp b/media/libstagefright/NuCachedSource2.cpp
index be2a873..f469d4d 100644
--- a/media/libstagefright/NuCachedSource2.cpp
+++ b/media/libstagefright/NuCachedSource2.cpp
@@ -254,6 +254,10 @@
// set mDisconnecting to true, if a fetch returns after
// this, the source will be marked as EOS.
mDisconnecting = true;
+
+ // explicitly signal mCondition so that the pending readAt()
+ // will immediately return
+ mCondition.signal();
}
// explicitly disconnect from the source, to allow any
@@ -325,7 +329,11 @@
Mutex::Autolock autoLock(mLock);
- if (err == ERROR_UNSUPPORTED || err == -EPIPE) {
+ if (mDisconnecting) {
+ mNumRetriesLeft = 0;
+ mFinalStatus = ERROR_END_OF_STREAM;
+ return;
+ } else if (err == ERROR_UNSUPPORTED || err == -EPIPE) {
// These are errors that are not likely to go away even if we
// retry, i.e. the server doesn't support range requests or similar.
mNumRetriesLeft = 0;
@@ -515,10 +523,14 @@
CHECK(mAsyncResult == NULL);
msg->post();
- while (mAsyncResult == NULL) {
+ while (mAsyncResult == NULL && !mDisconnecting) {
mCondition.wait(mLock);
}
+ if (mDisconnecting) {
+ return ERROR_END_OF_STREAM;
+ }
+
int32_t result;
CHECK(mAsyncResult->findInt32("result", &result));
diff --git a/media/libstagefright/codecs/hevcdec/SoftHEVC.cpp b/media/libstagefright/codecs/hevcdec/SoftHEVC.cpp
index b0d0827..f4cba54 100644
--- a/media/libstagefright/codecs/hevcdec/SoftHEVC.cpp
+++ b/media/libstagefright/codecs/hevcdec/SoftHEVC.cpp
@@ -67,22 +67,16 @@
: SoftVideoDecoderOMXComponent(name, componentName, codingType,
kProfileLevels, ARRAY_SIZE(kProfileLevels),
320 /* width */, 240 /* height */, callbacks,
- appData, component) {
+ appData, component),
+ mMemRecords(NULL),
+ mFlushOutBuffer(NULL),
+ mOmxColorFormat(OMX_COLOR_FormatYUV420Planar),
+ mIvColorFormat(IV_YUV_420P),
+ mNewWidth(mWidth),
+ mNewHeight(mHeight),
+ mChangingResolution(false) {
initPorts(kNumBuffers, INPUT_BUF_SIZE, kNumBuffers,
CODEC_MIME_TYPE);
-
- mOmxColorFormat = OMX_COLOR_FormatYUV420Planar;
- mStride = mWidth;
-
- if (OMX_COLOR_FormatYUV420Planar == mOmxColorFormat) {
- mIvColorFormat = IV_YUV_420P;
- } else if (OMX_COLOR_FormatYUV420SemiPlanar == mOmxColorFormat) {
- mIvColorFormat = IV_YUV_420SP_UV;
- }
-
- mInitWidth = mWidth;
- mInitHeight = mHeight;
-
CHECK_EQ(initDecoder(), (status_t)OK);
}
@@ -144,7 +138,7 @@
s_ctl_ip.u4_size = sizeof(ivd_ctl_set_config_ip_t);
s_ctl_op.u4_size = sizeof(ivd_ctl_set_config_op_t);
- ALOGD("Set the run-time (dynamic) parameters");
+ ALOGV("Set the run-time (dynamic) parameters stride = %u", stride);
status = ivdec_api_function(mCodecCtx, (void *)&s_ctl_ip,
(void *)&s_ctl_op);
@@ -188,7 +182,7 @@
}
/* Set the run-time (dynamic) parameters */
- setParams(0);
+ setParams(outputBufferWidth());
/* Set number of cores/threads to be used by the codec */
setNumCores();
@@ -250,23 +244,25 @@
WORD32 i4_level;
mNumCores = GetCPUCoreCount();
- mMemRecords = NULL;
- mFlushOutBuffer = NULL;
/* Initialize number of ref and reorder modes (for HEVC) */
u4_num_reorder_frames = 16;
u4_num_ref_frames = 16;
u4_share_disp_buf = 0;
- if ((mWidth * mHeight) > (1920 * 1088)) {
+ uint32_t displayStride = outputBufferWidth();
+ uint32_t displayHeight = outputBufferHeight();
+ uint32_t displaySizeY = displayStride * displayHeight;
+
+ if (displaySizeY > (1920 * 1088)) {
i4_level = 50;
- } else if ((mWidth * mHeight) > (1280 * 720)) {
+ } else if (displaySizeY > (1280 * 720)) {
i4_level = 40;
- } else if ((mWidth * mHeight) > (960 * 540)) {
+ } else if (displaySizeY > (960 * 540)) {
i4_level = 31;
- } else if ((mWidth * mHeight) > (640 * 360)) {
+ } else if (displaySizeY > (640 * 360)) {
i4_level = 30;
- } else if ((mWidth * mHeight) > (352 * 288)) {
+ } else if (displaySizeY > (352 * 288)) {
i4_level = 21;
} else {
i4_level = 20;
@@ -317,8 +313,8 @@
s_fill_mem_ip.s_ivd_fill_mem_rec_ip_t.e_cmd = IV_CMD_FILL_NUM_MEM_REC;
s_fill_mem_ip.s_ivd_fill_mem_rec_ip_t.pv_mem_rec_location = mMemRecords;
- s_fill_mem_ip.s_ivd_fill_mem_rec_ip_t.u4_max_frm_wd = mWidth;
- s_fill_mem_ip.s_ivd_fill_mem_rec_ip_t.u4_max_frm_ht = mHeight;
+ s_fill_mem_ip.s_ivd_fill_mem_rec_ip_t.u4_max_frm_wd = displayStride;
+ s_fill_mem_ip.s_ivd_fill_mem_rec_ip_t.u4_max_frm_ht = displayHeight;
s_fill_mem_op.s_ivd_fill_mem_rec_op_t.u4_size =
sizeof(ivdext_fill_mem_rec_op_t);
@@ -363,8 +359,8 @@
s_init_ip.s_ivd_init_ip_t.u4_size = sizeof(ivdext_init_ip_t);
s_init_ip.s_ivd_init_ip_t.e_cmd = (IVD_API_COMMAND_TYPE_T)IV_CMD_INIT;
s_init_ip.s_ivd_init_ip_t.pv_mem_rec_location = mMemRecords;
- s_init_ip.s_ivd_init_ip_t.u4_frm_max_wd = mWidth;
- s_init_ip.s_ivd_init_ip_t.u4_frm_max_ht = mHeight;
+ s_init_ip.s_ivd_init_ip_t.u4_frm_max_wd = displayStride;
+ s_init_ip.s_ivd_init_ip_t.u4_frm_max_ht = displayHeight;
s_init_ip.i4_level = i4_level;
s_init_ip.u4_num_reorder_frames = u4_num_reorder_frames;
@@ -395,7 +391,7 @@
resetPlugin();
/* Set the run time (dynamic) parameters */
- setParams(0);
+ setParams(displayStride);
/* Set number of cores/threads to be used by the codec */
setNumCores();
@@ -404,12 +400,15 @@
logVersion();
/* Allocate internal picture buffer */
- mFlushOutBuffer = (uint8_t *)ivd_aligned_malloc(128, mStride * mHeight * 3 / 2);
+ uint32_t bufferSize = displaySizeY * 3 / 2;
+ mFlushOutBuffer = (uint8_t *)ivd_aligned_malloc(128, bufferSize);
if (NULL == mFlushOutBuffer) {
- ALOGE("Could not allocate flushOutputBuffer of size %zu", mStride * mHeight * 3 / 2);
+ ALOGE("Could not allocate flushOutputBuffer of size %zu", bufferSize);
return NO_MEMORY;
}
+ mInitNeeded = false;
+ mFlushNeeded = false;
return OK;
}
@@ -428,11 +427,17 @@
ps_mem_rec++;
}
ivd_aligned_free(mMemRecords);
+ mMemRecords = NULL;
}
if(mFlushOutBuffer) {
ivd_aligned_free(mFlushOutBuffer);
+ mFlushOutBuffer = NULL;
}
+
+ mInitNeeded = true;
+ mChangingResolution = false;
+
return OK;
}
@@ -449,6 +454,7 @@
}
return OK;
}
+
void SoftHEVC::onReset() {
ALOGD("onReset called");
SoftVideoDecoderOMXComponent::onReset();
@@ -457,12 +463,22 @@
resetPlugin();
}
+OMX_ERRORTYPE SoftHEVC::internalSetParameter(OMX_INDEXTYPE index, const OMX_PTR params) {
+ const uint32_t oldWidth = mWidth;
+ const uint32_t oldHeight = mHeight;
+ OMX_ERRORTYPE ret = SoftVideoDecoderOMXComponent::internalSetParameter(index, params);
+ if (mWidth != oldWidth || mHeight != oldHeight) {
+ reInitDecoder();
+ }
+ return ret;
+}
+
void SoftHEVC::setDecodeArgs(ivd_video_decode_ip_t *ps_dec_ip,
ivd_video_decode_op_t *ps_dec_op,
OMX_BUFFERHEADERTYPE *inHeader,
OMX_BUFFERHEADERTYPE *outHeader,
- size_t sizeY,
size_t timeStampIx) {
+ size_t sizeY = outputBufferWidth() * outputBufferHeight();
size_t sizeUV;
uint8_t *pBuf;
@@ -502,8 +518,6 @@
return;
}
void SoftHEVC::onPortFlushCompleted(OMX_U32 portIndex) {
- ALOGD("onPortFlushCompleted on port %d", portIndex);
-
/* Once the output buffers are flushed, ignore any buffers that are held in decoder */
if (kOutputPortIndex == portIndex) {
setFlushMode();
@@ -514,7 +528,7 @@
IV_API_CALL_STATUS_T status;
size_t sizeY, sizeUV;
- setDecodeArgs(&s_dec_ip, &s_dec_op, NULL, NULL, mStride * mHeight, 0);
+ setDecodeArgs(&s_dec_ip, &s_dec_op, NULL, NULL, 0);
status = ivdec_api_function(mCodecCtx, (void *)&s_dec_ip,
(void *)&s_dec_op);
@@ -527,8 +541,6 @@
}
void SoftHEVC::onQueueFilled(OMX_U32 portIndex) {
- IV_API_CALL_STATUS_T status;
-
UNUSED(portIndex);
if (mOutputPortSettingsChange != NONE) {
@@ -548,7 +560,7 @@
setFlushMode();
}
- while (outQueue.size() == kNumBuffers) {
+ while (!outQueue.empty()) {
BufferInfo *inInfo;
OMX_BUFFERHEADERTYPE *inHeader;
@@ -586,6 +598,16 @@
}
}
+ // 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;
@@ -608,68 +630,91 @@
WORD32 timeDelay, timeTaken;
size_t sizeY, sizeUV;
- setDecodeArgs(&s_dec_ip, &s_dec_op, inHeader, outHeader,
- mStride * mHeight, timeStampIx);
+ 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);
- status = ivdec_api_function(mCodecCtx, (void *)&s_dec_ip,
- (void *)&s_dec_op);
+ IV_API_CALL_STATUS_T status;
+ status = ivdec_api_function(mCodecCtx, (void *)&s_dec_ip, (void *)&s_dec_op);
+ // 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);
- ALOGD("timeTaken=%6d delay=%6d numBytes=%6d", timeTaken, timeDelay,
- s_dec_op.u4_num_bytes_consumed);
-
- /* If width and height are greater than the
- * the dimensions used during codec create, then
- * delete the current instance and recreate an instance with
- * new dimensions */
-
- if(IHEVCD_UNSUPPORTED_DIMENSIONS == s_dec_op.u4_error_code) {
- mInitWidth = s_dec_op.u4_pic_wd;
- mInitHeight = s_dec_op.u4_pic_ht;
- mStride = mInitWidth;
- CHECK_EQ(reInitDecoder(), (status_t)OK);
-
- setDecodeArgs(&s_dec_ip, &s_dec_op, inHeader, outHeader,
- mStride * mHeight, timeStampIx);
-
- status = ivdec_api_function(mCodecCtx, (void *)&s_dec_ip,
- (void *)&s_dec_op);
+ 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 valid height and width are decoded,
- * then look at change in resolution */
+ // 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 ((width != mWidth) || (height != mHeight)) {
- mWidth = width;
- mHeight = height;
- mStride = mWidth;
-
- updatePortDefinitions();
-
- notify(OMX_EventPortSettingsChanged, 1, 0, NULL);
- mOutputPortSettingsChange = AWAITING_DISABLED;
+ if (portWillReset) {
+ resetDecoder();
return;
}
}
if (s_dec_op.u4_output_present) {
- outHeader->nFilledLen = (mStride * mHeight * 3) / 2;
+ outHeader->nFilledLen = (mWidth * mHeight * 3) / 2;
outHeader->nTimeStamp = mTimeStamps[s_dec_op.u4_ts];
mTimeStampsValid[s_dec_op.u4_ts] = false;
@@ -711,7 +756,7 @@
}
}
-} // namespace android
+} // namespace android
android::SoftOMXComponent *createSoftOMXComponent(const char *name,
const OMX_CALLBACKTYPE *callbacks, OMX_PTR appData,
diff --git a/media/libstagefright/codecs/hevcdec/SoftHEVC.h b/media/libstagefright/codecs/hevcdec/SoftHEVC.h
index 233db0c..a91f528 100644
--- a/media/libstagefright/codecs/hevcdec/SoftHEVC.h
+++ b/media/libstagefright/codecs/hevcdec/SoftHEVC.h
@@ -62,6 +62,7 @@
virtual void onQueueFilled(OMX_U32 portIndex);
virtual void onPortFlushCompleted(OMX_U32 portIndex);
virtual void onReset();
+ virtual OMX_ERRORTYPE internalSetParameter(OMX_INDEXTYPE index, const OMX_PTR params);
private:
// Number of input and output buffers
enum {
@@ -72,12 +73,6 @@
iv_mem_rec_t *mMemRecords; // Memory records requested by the codec
size_t mNumMemRecords; // Number of memory records requested by the codec
- uint32_t mNewWidth; // New width after change in resolution
- uint32_t mNewHeight; // New height after change in resolution
- uint32_t mInitWidth; // Width used during codec creation
- uint32_t mInitHeight; // Height used during codec creation
- size_t mStride; // Stride to be used for display buffers
-
size_t mNumCores; // Number of cores to be uesd by the codec
struct timeval mTimeStart; // Time at the start of decode()
@@ -98,7 +93,13 @@
bool mIsInFlush; // codec is flush mode
bool mReceivedEOS; // EOS is receieved on input port
- bool mIsAdapting; // plugin in middle of change in resolution
+ bool mInitNeeded;
+ uint32_t mNewWidth;
+ uint32_t mNewHeight;
+ // The input stream has changed to a different resolution, which is still supported by the
+ // codec. So the codec is switching to decode the new resolution.
+ bool mChangingResolution;
+ bool mFlushNeeded;
status_t initDecoder();
status_t deInitDecoder();
@@ -114,7 +115,6 @@
ivd_video_decode_op_t *ps_dec_op,
OMX_BUFFERHEADERTYPE *inHeader,
OMX_BUFFERHEADERTYPE *outHeader,
- size_t sizeY,
size_t timeStampIx);
DISALLOW_EVIL_CONSTRUCTORS (SoftHEVC);
diff --git a/media/libstagefright/include/SoftVideoDecoderOMXComponent.h b/media/libstagefright/include/SoftVideoDecoderOMXComponent.h
index 8cb8ed7..37b1fe1 100644
--- a/media/libstagefright/include/SoftVideoDecoderOMXComponent.h
+++ b/media/libstagefright/include/SoftVideoDecoderOMXComponent.h
@@ -65,6 +65,9 @@
virtual void updatePortDefinitions(bool updateCrop = true);
+ uint32_t outputBufferWidth();
+ uint32_t outputBufferHeight();
+
void handlePortSettingsChange(
bool *portWillReset, uint32_t width, uint32_t height,
bool cropChanged = false, bool fakeStride = false);
diff --git a/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp b/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp
index 1cb1859..5853469 100644
--- a/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp
+++ b/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp
@@ -133,8 +133,8 @@
def->nBufferSize = def->format.video.nFrameWidth * def->format.video.nFrameHeight * 3 / 2;
def = &editPortInfo(kOutputPortIndex)->mDef;
- def->format.video.nFrameWidth = mIsAdaptive ? mAdaptiveMaxWidth : mWidth;
- def->format.video.nFrameHeight = mIsAdaptive ? mAdaptiveMaxHeight : mHeight;
+ def->format.video.nFrameWidth = outputBufferWidth();
+ def->format.video.nFrameHeight = outputBufferHeight();
def->format.video.nStride = def->format.video.nFrameWidth;
def->format.video.nSliceHeight = def->format.video.nFrameHeight;
@@ -150,6 +150,15 @@
}
}
+
+uint32_t SoftVideoDecoderOMXComponent::outputBufferWidth() {
+ return mIsAdaptive ? mAdaptiveMaxWidth : mWidth;
+}
+
+uint32_t SoftVideoDecoderOMXComponent::outputBufferHeight() {
+ return mIsAdaptive ? mAdaptiveMaxHeight : mHeight;
+}
+
void SoftVideoDecoderOMXComponent::handlePortSettingsChange(
bool *portWillReset, uint32_t width, uint32_t height, bool cropChanged, bool fakeStride) {
*portWillReset = false;
@@ -199,9 +208,9 @@
void SoftVideoDecoderOMXComponent::copyYV12FrameToOutputBuffer(
uint8_t *dst, const uint8_t *srcY, const uint8_t *srcU, const uint8_t *srcV,
size_t srcYStride, size_t srcUStride, size_t srcVStride) {
- size_t dstYStride = mIsAdaptive ? mAdaptiveMaxWidth : mWidth;
+ size_t dstYStride = outputBufferWidth();
size_t dstUVStride = dstYStride / 2;
- size_t dstHeight = mIsAdaptive ? mAdaptiveMaxHeight : mHeight;
+ size_t dstHeight = outputBufferHeight();
uint8_t *dstStart = dst;
for (size_t i = 0; i < mHeight; ++i) {
diff --git a/services/audiopolicy/AudioPolicyManager.cpp b/services/audiopolicy/AudioPolicyManager.cpp
index 95ac070..d51ee8e 100644
--- a/services/audiopolicy/AudioPolicyManager.cpp
+++ b/services/audiopolicy/AudioPolicyManager.cpp
@@ -112,7 +112,7 @@
STRING_TO_ENUM(AUDIO_DEVICE_IN_LOOPBACK),
};
-const StringToEnum sFlagNameToEnumTable[] = {
+const StringToEnum sOutputFlagNameToEnumTable[] = {
STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_DIRECT),
STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_PRIMARY),
STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_FAST),
@@ -122,6 +122,11 @@
STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_HW_AV_SYNC),
};
+const StringToEnum sInputFlagNameToEnumTable[] = {
+ STRING_TO_ENUM(AUDIO_INPUT_FLAG_FAST),
+ STRING_TO_ENUM(AUDIO_INPUT_FLAG_HW_HOTWORD),
+};
+
const StringToEnum sFormatNameToEnumTable[] = {
STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
STRING_TO_ENUM(AUDIO_FORMAT_PCM_8_BIT),
@@ -1292,16 +1297,41 @@
break;
}
+ audio_io_handle_t input = AUDIO_IO_HANDLE_NONE;
+ bool isSoundTrigger = false;
+ audio_source_t halInputSource = inputSource;
+ if (inputSource == AUDIO_SOURCE_HOTWORD) {
+ ssize_t index = mSoundTriggerSessions.indexOfKey(session);
+ if (index >= 0) {
+ input = mSoundTriggerSessions.valueFor(session);
+ isSoundTrigger = true;
+ flags = (audio_input_flags_t)(flags | AUDIO_INPUT_FLAG_HW_HOTWORD);
+ ALOGV("SoundTrigger capture on session %d input %d", session, input);
+ } else {
+ halInputSource = AUDIO_SOURCE_VOICE_RECOGNITION;
+ }
+ }
+
sp<IOProfile> profile = getInputProfile(device,
samplingRate,
format,
channelMask,
flags);
if (profile == 0) {
- ALOGW("getInput() could not find profile for device 0x%X, samplingRate %u, format %#x, "
- "channelMask 0x%X, flags %#x",
- device, samplingRate, format, channelMask, flags);
- return AUDIO_IO_HANDLE_NONE;
+ //retry without flags
+ audio_input_flags_t log_flags = flags;
+ flags = AUDIO_INPUT_FLAG_NONE;
+ profile = getInputProfile(device,
+ samplingRate,
+ format,
+ channelMask,
+ flags);
+ if (profile == 0) {
+ ALOGW("getInput() could not find profile for device 0x%X, samplingRate %u, format %#x, "
+ "channelMask 0x%X, flags %#x",
+ device, samplingRate, format, channelMask, log_flags);
+ return AUDIO_IO_HANDLE_NONE;
+ }
}
if (profile->mModule->mHandle == 0) {
@@ -1313,20 +1343,7 @@
config.sample_rate = samplingRate;
config.channel_mask = channelMask;
config.format = format;
- audio_io_handle_t input = AUDIO_IO_HANDLE_NONE;
- bool isSoundTrigger = false;
- audio_source_t halInputSource = inputSource;
- if (inputSource == AUDIO_SOURCE_HOTWORD) {
- ssize_t index = mSoundTriggerSessions.indexOfKey(session);
- if (index >= 0) {
- input = mSoundTriggerSessions.valueFor(session);
- isSoundTrigger = true;
- ALOGV("SoundTrigger capture on session %d input %d", session, input);
- } else {
- halInputSource = AUDIO_SOURCE_VOICE_RECOGNITION;
- }
- }
status_t status = mpClientInterface->openInput(profile->mModule->mHandle,
&input,
&config,
@@ -5220,7 +5237,7 @@
mStrategyMutedByDevice[i] = false;
}
if (profile != NULL) {
- mFlags = profile->mFlags;
+ mFlags = (audio_output_flags_t)profile->mFlags;
mSamplingRate = profile->pickSamplingRate();
mFormat = profile->pickFormat();
mChannelMask = profile->pickChannelMask();
@@ -5568,6 +5585,8 @@
} else if (strcmp(node->name, DEVICES_TAG) == 0) {
profile->mSupportedDevices.loadDevicesFromName((char *)node->value,
mDeclaredDevices);
+ } else if (strcmp(node->name, FLAGS_TAG) == 0) {
+ profile->mFlags = parseInputFlagNames((char *)node->value);
} else if (strcmp(node->name, GAINS_TAG) == 0) {
profile->loadGains(node);
}
@@ -5613,7 +5632,7 @@
profile->mSupportedDevices.loadDevicesFromName((char *)node->value,
mDeclaredDevices);
} else if (strcmp(node->name, FLAGS_TAG) == 0) {
- profile->mFlags = parseFlagNames((char *)node->value);
+ profile->mFlags = parseOutputFlagNames((char *)node->value);
} else if (strcmp(node->name, GAINS_TAG) == 0) {
profile->loadGains(node);
}
@@ -5728,7 +5747,7 @@
AudioPolicyManager::AudioPort::AudioPort(const String8& name, audio_port_type_t type,
audio_port_role_t role, const sp<HwModule>& module) :
- mName(name), mType(type), mRole(role), mModule(module), mFlags((audio_output_flags_t)0)
+ mName(name), mType(type), mRole(role), mModule(module), mFlags(0)
{
mUseInChannelMask = ((type == AUDIO_PORT_TYPE_DEVICE) && (role == AUDIO_PORT_ROLE_SOURCE)) ||
((type == AUDIO_PORT_TYPE_MIX) && (role == AUDIO_PORT_ROLE_SINK));
@@ -6560,7 +6579,7 @@
uint32_t *updatedSamplingRate,
audio_format_t format,
audio_channel_mask_t channelMask,
- audio_output_flags_t flags) const
+ uint32_t flags) const
{
const bool isPlaybackThread = mType == AUDIO_PORT_TYPE_MIX && mRole == AUDIO_PORT_ROLE_SOURCE;
const bool isRecordThread = mType == AUDIO_PORT_TYPE_MIX && mRole == AUDIO_PORT_ROLE_SINK;
@@ -6602,7 +6621,7 @@
// An existing fast stream is compatible with a normal track request.
// An existing normal stream is compatible with a fast track request,
// but the fast request will be denied by AudioFlinger and converted to normal track.
- if (isRecordThread && (((audio_input_flags_t) mFlags ^ (audio_input_flags_t) flags) &
+ if (isRecordThread && ((mFlags ^ flags) &
~AUDIO_INPUT_FLAG_FAST)) {
return false;
}
@@ -6958,7 +6977,7 @@
// --- audio_policy.conf file parsing
-audio_output_flags_t AudioPolicyManager::parseFlagNames(char *name)
+uint32_t AudioPolicyManager::parseOutputFlagNames(char *name)
{
uint32_t flag = 0;
@@ -6967,8 +6986,8 @@
char *flagName = strtok(name, "|");
while (flagName != NULL) {
if (strlen(flagName) != 0) {
- flag |= stringToEnum(sFlagNameToEnumTable,
- ARRAY_SIZE(sFlagNameToEnumTable),
+ flag |= stringToEnum(sOutputFlagNameToEnumTable,
+ ARRAY_SIZE(sOutputFlagNameToEnumTable),
flagName);
}
flagName = strtok(NULL, "|");
@@ -6980,7 +6999,25 @@
flag |= AUDIO_OUTPUT_FLAG_DIRECT;
}
- return (audio_output_flags_t)flag;
+ return flag;
+}
+
+uint32_t AudioPolicyManager::parseInputFlagNames(char *name)
+{
+ uint32_t flag = 0;
+
+ // it is OK to cast name to non const here as we are not going to use it after
+ // strtok() modifies it
+ char *flagName = strtok(name, "|");
+ while (flagName != NULL) {
+ if (strlen(flagName) != 0) {
+ flag |= stringToEnum(sInputFlagNameToEnumTable,
+ ARRAY_SIZE(sInputFlagNameToEnumTable),
+ flagName);
+ }
+ flagName = strtok(NULL, "|");
+ }
+ return flag;
}
audio_devices_t AudioPolicyManager::parseDeviceNames(char *name)
diff --git a/services/audiopolicy/AudioPolicyManager.h b/services/audiopolicy/AudioPolicyManager.h
index da0d95d..0ea7b97 100644
--- a/services/audiopolicy/AudioPolicyManager.h
+++ b/services/audiopolicy/AudioPolicyManager.h
@@ -283,8 +283,8 @@
Vector <audio_format_t> mFormats; // supported audio formats
Vector < sp<AudioGain> > mGains; // gain controllers
sp<HwModule> mModule; // audio HW module exposing this I/O stream
- audio_output_flags_t mFlags; // attribute flags (e.g primary output,
- // direct output...). For outputs only.
+ uint32_t mFlags; // attribute flags (e.g primary output,
+ // direct output...).
};
class AudioPortConfig: public virtual RefBase
@@ -387,7 +387,7 @@
uint32_t *updatedSamplingRate,
audio_format_t format,
audio_channel_mask_t channelMask,
- audio_output_flags_t flags) const;
+ uint32_t flags) const;
void dump(int fd);
void log();
@@ -754,7 +754,8 @@
size_t size,
uint32_t value);
static bool stringToBool(const char *value);
- static audio_output_flags_t parseFlagNames(char *name);
+ static uint32_t parseOutputFlagNames(char *name);
+ static uint32_t parseInputFlagNames(char *name);
static audio_devices_t parseDeviceNames(char *name);
void loadHwModule(cnode *root);
void loadHwModules(cnode *root);