OSDN Git Service

Support IDR requests in wifi display, MediaCodec and ACodec.
authorAndreas Huber <andih@google.com>
Thu, 13 Sep 2012 23:43:51 +0000 (16:43 -0700)
committerAndreas Huber <andih@google.com>
Thu, 13 Sep 2012 23:43:51 +0000 (16:43 -0700)
Change-Id: I596cf8dd61b63465437f78413186fad2be287244

include/media/stagefright/ACodec.h
include/media/stagefright/MediaCodec.h
media/libstagefright/ACodec.cpp
media/libstagefright/MediaCodec.cpp
media/libstagefright/wifi-display/source/Converter.cpp
media/libstagefright/wifi-display/source/Converter.h
media/libstagefright/wifi-display/source/PlaybackSession.cpp
media/libstagefright/wifi-display/source/PlaybackSession.h
media/libstagefright/wifi-display/source/WifiDisplaySource.cpp

index 500dde6..d27f463 100644 (file)
@@ -58,6 +58,8 @@ struct ACodec : public AHierarchicalStateMachine {
     void initiateConfigureComponent(const sp<AMessage> &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);
 };
 
index e46e8e9..8c612d4 100644 (file)
@@ -106,6 +106,8 @@ struct MediaCodec : public AHandler {
     status_t getInputBuffers(Vector<sp<ABuffer> > *buffers) const;
     status_t getOutputBuffers(Vector<sp<ABuffer> > *buffers) const;
 
+    status_t requestIDRFrame();
+
 protected:
     virtual ~MediaCodec();
     virtual void onMessageReceived(const sp<AMessage> &msg);
@@ -145,6 +147,7 @@ private:
         kWhatDequeueInputTimedOut       = 'dITO',
         kWhatDequeueOutputTimedOut      = 'dOTO',
         kWhatCodecNotify                = 'codc',
+        kWhatRequestIDRFrame            = 'ridr',
     };
 
     enum {
index 3dd5d60..8190498 100644 (file)
@@ -34,6 +34,8 @@
 
 #include <OMX_Component.h>
 
+#include "include/avc_utils.h"
+
 namespace android {
 
 template<class T>
@@ -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(&params);
+
+    params.nPortIndex = kPortIndexOutput;
+    params.IntraRefreshVOP = OMX_TRUE;
+
+    return mOMX->setConfig(
+            mNode,
+            OMX_IndexConfigVideoIntraVOPRefresh,
+            &params,
+            sizeof(params));
+}
+
 void ACodec::PortDescription::addBuffer(
         IOMX::buffer_id id, const sp<ABuffer> &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<AMessage> &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;
index 2060699..7f97430 100644 (file)
@@ -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<AMessage> &msg) {
             break;
         }
 
+        case kWhatRequestIDRFrame:
+        {
+            mCodec->signalRequestIDRFrame();
+            break;
+        }
+
         default:
             TRESPASS();
     }
index c4845e3..390b2e2 100644 (file)
@@ -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<AMessage> &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
 
index 67471c7..901ae2e 100644 (file)
@@ -43,6 +43,8 @@ struct Converter : public AHandler {
     void feedAccessUnit(const sp<ABuffer> &accessUnit);
     void signalEOS();
 
+    void requestIDRFrame();
+
     enum {
         kWhatAccessUnit,
         kWhatEOS,
@@ -57,13 +59,15 @@ private:
     enum {
         kWhatFeedAccessUnit,
         kWhatInputEOS,
-        kWhatDoMoreWork
+        kWhatDoMoreWork,
+        kWhatRequestIDRFrame,
     };
 
     status_t mInitCheck;
     sp<AMessage> mNotify;
     sp<ALooper> mCodecLooper;
     sp<AMessage> mInputFormat;
+    bool mIsVideo;
     sp<AMessage> mOutputFormat;
 
     sp<MediaCodec> mEncoder;
index c38a300..f6f7030 100644 (file)
@@ -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> &track = mTracks.valueAt(i);
+
+        track->converter()->requestIDRFrame();
+    }
+}
+
 }  // namespace android
 
index 88f6ea9..8b6ddee 100644 (file)
@@ -58,6 +58,8 @@ struct WifiDisplaySource::PlaybackSession : public AHandler {
     int32_t width() const;
     int32_t height() const;
 
+    void requestIDRFrame();
+
     enum {
         kWhatSessionDead,
         kWhatBinaryData,
index aeefcf3..53adb87 100644 (file)
@@ -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";