From 496238cc7551d414067dcbbb4fe3bd801f205f95 Mon Sep 17 00:00:00 2001 From: Andreas Huber Date: Thu, 13 Sep 2012 16:43:51 -0700 Subject: [PATCH] Support IDR requests in wifi display, MediaCodec and ACodec. Change-Id: I596cf8dd61b63465437f78413186fad2be287244 --- include/media/stagefright/ACodec.h | 5 +++ include/media/stagefright/MediaCodec.h | 3 ++ media/libstagefright/ACodec.cpp | 41 ++++++++++++++++++++++ media/libstagefright/MediaCodec.cpp | 12 +++++++ .../wifi-display/source/Converter.cpp | 21 +++++++++++ .../libstagefright/wifi-display/source/Converter.h | 6 +++- .../wifi-display/source/PlaybackSession.cpp | 8 +++++ .../wifi-display/source/PlaybackSession.h | 2 ++ .../wifi-display/source/WifiDisplaySource.cpp | 3 ++ 9 files changed, 100 insertions(+), 1 deletion(-) diff --git a/include/media/stagefright/ACodec.h b/include/media/stagefright/ACodec.h index 500dde6b2f..d27f463749 100644 --- a/include/media/stagefright/ACodec.h +++ b/include/media/stagefright/ACodec.h @@ -58,6 +58,8 @@ struct ACodec : public AHierarchicalStateMachine { void initiateConfigureComponent(const sp &msg); void initiateStart(); + void signalRequestIDRFrame(); + struct PortDescription : public RefBase { size_t countBuffers(); IOMX::buffer_id bufferIDAt(size_t index) const; @@ -102,6 +104,7 @@ private: kWhatAllocateComponent = 'allo', kWhatConfigureComponent = 'conf', kWhatStart = 'star', + kWhatRequestIDRFrame = 'ridr', }; enum { @@ -262,6 +265,8 @@ private: OMX_ERRORTYPE error = OMX_ErrorUndefined, status_t internalError = UNKNOWN_ERROR); + status_t requestIDRFrame(); + DISALLOW_EVIL_CONSTRUCTORS(ACodec); }; diff --git a/include/media/stagefright/MediaCodec.h b/include/media/stagefright/MediaCodec.h index e46e8e95c5..8c612d4a2f 100644 --- a/include/media/stagefright/MediaCodec.h +++ b/include/media/stagefright/MediaCodec.h @@ -106,6 +106,8 @@ struct MediaCodec : public AHandler { status_t getInputBuffers(Vector > *buffers) const; status_t getOutputBuffers(Vector > *buffers) const; + status_t requestIDRFrame(); + protected: virtual ~MediaCodec(); virtual void onMessageReceived(const sp &msg); @@ -145,6 +147,7 @@ private: kWhatDequeueInputTimedOut = 'dITO', kWhatDequeueOutputTimedOut = 'dOTO', kWhatCodecNotify = 'codc', + kWhatRequestIDRFrame = 'ridr', }; enum { diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp index 3dd5d60f06..8190498e3f 100644 --- a/media/libstagefright/ACodec.cpp +++ b/media/libstagefright/ACodec.cpp @@ -34,6 +34,8 @@ #include +#include "include/avc_utils.h" + namespace android { template @@ -401,6 +403,10 @@ void ACodec::initiateShutdown(bool keepComponentAllocated) { msg->post(); } +void ACodec::signalRequestIDRFrame() { + (new AMessage(kWhatRequestIDRFrame, id()))->post(); +} + status_t ACodec::allocateBuffersOnPort(OMX_U32 portIndex) { CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput); @@ -2284,6 +2290,24 @@ error: ACodec::PortDescription::PortDescription() { } +status_t ACodec::requestIDRFrame() { + if (!mIsEncoder) { + return ERROR_UNSUPPORTED; + } + + OMX_CONFIG_INTRAREFRESHVOPTYPE params; + InitOMXParams(¶ms); + + params.nPortIndex = kPortIndexOutput; + params.IntraRefreshVOP = OMX_TRUE; + + return mOMX->setConfig( + mNode, + OMX_IndexConfigVideoIntraVOPRefresh, + ¶ms, + sizeof(params)); +} + void ACodec::PortDescription::addBuffer( IOMX::buffer_id id, const sp &buffer) { mBufferIDs.push_back(id); @@ -2737,6 +2761,12 @@ bool ACodec::BaseState::onOMXFillBufferDone( if (mCodec->mNativeWindow == NULL) { info->mData->setRange(rangeOffset, rangeLength); + +#if 0 + if (IsIDR(info->mData)) { + ALOGI("IDR frame"); + } +#endif } if (mCodec->mSkipCutBuffer != NULL) { @@ -3400,6 +3430,17 @@ bool ACodec::ExecutingState::onMessageReceived(const sp &msg) { break; } + case kWhatRequestIDRFrame: + { + status_t err = mCodec->requestIDRFrame(); + if (err != OK) { + ALOGW("Requesting an IDR frame failed."); + } + + handled = true; + break; + } + default: handled = BaseState::onMessageReceived(msg); break; diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp index 2060699426..7f97430488 100644 --- a/media/libstagefright/MediaCodec.cpp +++ b/media/libstagefright/MediaCodec.cpp @@ -327,6 +327,12 @@ status_t MediaCodec::flush() { return PostAndAwaitResponse(msg, &response); } +status_t MediaCodec::requestIDRFrame() { + (new AMessage(kWhatRequestIDRFrame, id()))->post(); + + return OK; +} + //////////////////////////////////////////////////////////////////////////////// void MediaCodec::cancelPendingDequeueOperations() { @@ -1133,6 +1139,12 @@ void MediaCodec::onMessageReceived(const sp &msg) { break; } + case kWhatRequestIDRFrame: + { + mCodec->signalRequestIDRFrame(); + break; + } + default: TRESPASS(); } diff --git a/media/libstagefright/wifi-display/source/Converter.cpp b/media/libstagefright/wifi-display/source/Converter.cpp index c4845e3e1e..390b2e27fc 100644 --- a/media/libstagefright/wifi-display/source/Converter.cpp +++ b/media/libstagefright/wifi-display/source/Converter.cpp @@ -40,7 +40,15 @@ Converter::Converter( mNotify(notify), mCodecLooper(codecLooper), mInputFormat(format), + mIsVideo(false), mDoMoreWorkPending(false) { + AString mime; + CHECK(mInputFormat->findString("mime", &mime)); + + if (!strncasecmp("video/", mime.c_str(), 6)) { + mIsVideo = true; + } + mInitCheck = initEncoder(); } @@ -202,6 +210,15 @@ void Converter::onMessageReceived(const sp &msg) { break; } + case kWhatRequestIDRFrame: + { + if (mIsVideo) { + ALOGI("requesting IDR frame"); + mEncoder->requestIDRFrame(); + } + break; + } + default: TRESPASS(); } @@ -306,5 +323,9 @@ status_t Converter::doMoreWork() { return err; } +void Converter::requestIDRFrame() { + (new AMessage(kWhatRequestIDRFrame, id()))->post(); +} + } // namespace android diff --git a/media/libstagefright/wifi-display/source/Converter.h b/media/libstagefright/wifi-display/source/Converter.h index 67471c7fb8..901ae2e4f7 100644 --- a/media/libstagefright/wifi-display/source/Converter.h +++ b/media/libstagefright/wifi-display/source/Converter.h @@ -43,6 +43,8 @@ struct Converter : public AHandler { void feedAccessUnit(const sp &accessUnit); void signalEOS(); + void requestIDRFrame(); + enum { kWhatAccessUnit, kWhatEOS, @@ -57,13 +59,15 @@ private: enum { kWhatFeedAccessUnit, kWhatInputEOS, - kWhatDoMoreWork + kWhatDoMoreWork, + kWhatRequestIDRFrame, }; status_t mInitCheck; sp mNotify; sp mCodecLooper; sp mInputFormat; + bool mIsVideo; sp mOutputFormat; sp mEncoder; diff --git a/media/libstagefright/wifi-display/source/PlaybackSession.cpp b/media/libstagefright/wifi-display/source/PlaybackSession.cpp index c38a3009d2..f6f7030885 100644 --- a/media/libstagefright/wifi-display/source/PlaybackSession.cpp +++ b/media/libstagefright/wifi-display/source/PlaybackSession.cpp @@ -1164,5 +1164,13 @@ status_t WifiDisplaySource::PlaybackSession::parseTSFB( return OK; } +void WifiDisplaySource::PlaybackSession::requestIDRFrame() { + for (size_t i = 0; i < mTracks.size(); ++i) { + const sp &track = mTracks.valueAt(i); + + track->converter()->requestIDRFrame(); + } +} + } // namespace android diff --git a/media/libstagefright/wifi-display/source/PlaybackSession.h b/media/libstagefright/wifi-display/source/PlaybackSession.h index 88f6ea97a5..8b6ddeed87 100644 --- a/media/libstagefright/wifi-display/source/PlaybackSession.h +++ b/media/libstagefright/wifi-display/source/PlaybackSession.h @@ -58,6 +58,8 @@ struct WifiDisplaySource::PlaybackSession : public AHandler { int32_t width() const; int32_t height() const; + void requestIDRFrame(); + enum { kWhatSessionDead, kWhatBinaryData, diff --git a/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp b/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp index aeefcf3e3c..53adb875bf 100644 --- a/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp +++ b/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp @@ -984,6 +984,9 @@ void WifiDisplaySource::onSetParameterRequest( } #endif + // XXX check that the parameter is about that. + playbackSession->requestIDRFrame(); + playbackSession->updateLiveness(); AString response = "RTSP/1.0 200 OK\r\n"; -- 2.11.0