OSDN Git Service

stagefright: explicitly release extractor in StagefrightMetadataRetriever
authorChong Zhang <chz@google.com>
Fri, 8 Sep 2017 00:43:19 +0000 (17:43 -0700)
committerChong Zhang <chz@google.com>
Fri, 8 Sep 2017 01:32:09 +0000 (18:32 -0700)
Extractor dtor on media.extractor side happens asynchronously with the
dtor of StagefrightMetadataRetriever. If the extractor calls back into
the DataSource after mediaserver side released the reference to it, the
binder transaction could get stuck.

Adding an explicity release() and call it before StagefrightMetadataRetriever
continues to destruct the DataSource. Only implement it for MPEG4Extractor
to avoid impacting other extractors at this stage.

Also adding some code to aggressively release the extractor and data
source in HeifDecoderImpl to free up memory.

bug: 65463215

Change-Id: I84c442a1e010dd37a976af5453a353e43f672e22

media/libheif/HeifDecoderImpl.cpp
media/libmedia/IMediaExtractor.cpp
media/libmedia/include/media/IMediaExtractor.h
media/libstagefright/MPEG4Extractor.cpp
media/libstagefright/StagefrightMetadataRetriever.cpp
media/libstagefright/include/MPEG4Extractor.h
media/libstagefright/include/media/stagefright/MediaExtractor.h

index 115baff..4b131a7 100644 (file)
@@ -401,6 +401,10 @@ bool HeifDecoderImpl::decode(HeifFrameInfo* frameInfo) {
                 videoFrame->getFlattenedIccData());
     }
     mFrameDecoded = true;
+
+    // Aggressive clear to avoid holding on to resources
+    mRetriever.clear();
+    mDataSource.clear();
     return true;
 }
 
index 19b00f3..3c43a72 100644 (file)
@@ -38,7 +38,8 @@ enum {
     SETMEDIACAS,
     SETUID,
     NAME,
-    GETMETRICS
+    GETMETRICS,
+    RELEASE,
 };
 
 class BpMediaExtractor : public BpInterface<IMediaExtractor> {
@@ -138,6 +139,13 @@ public:
         ALOGV("name NOT IMPLEMENTED");
         return NULL;
     }
+
+    virtual void release() {
+        ALOGV("release");
+        Parcel data, reply;
+        data.writeInterfaceToken(BpMediaExtractor::getInterfaceDescriptor());
+        remote()->transact(RELEASE, data, &reply);
+    }
 };
 
 IMPLEMENT_META_INTERFACE(MediaExtractor, "android.media.IMediaExtractor");
@@ -215,6 +223,12 @@ status_t BnMediaExtractor::onTransact(
             reply->writeInt32(setMediaCas(casToken));
             return OK;
         }
+        case RELEASE: {
+            ALOGV("release");
+            CHECK_INTERFACE(IMediaExtractor, data, reply);
+            release();
+            return OK;
+        }
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
index 1e13b65..0ac7673 100644 (file)
@@ -68,6 +68,8 @@ public:
     virtual void setUID(uid_t uid)  = 0;
 
     virtual const char * name() = 0;
+
+    virtual void release() = 0;
 };
 
 
index 5ef0f56..eedb2f5 100644 (file)
@@ -354,6 +354,10 @@ MPEG4Extractor::MPEG4Extractor(const sp<DataSource> &source)
 }
 
 MPEG4Extractor::~MPEG4Extractor() {
+    release();
+}
+
+void MPEG4Extractor::release() {
     Track *track = mFirstTrack;
     while (track) {
         Track *next = track->next;
@@ -375,6 +379,12 @@ MPEG4Extractor::~MPEG4Extractor() {
     for (size_t i = 0; i < mPssh.size(); i++) {
         delete [] mPssh[i].data;
     }
+    mPssh.clear();
+
+    if (mDataSource != NULL) {
+        mDataSource->close();
+        mDataSource.clear();
+    }
 }
 
 uint32_t MPEG4Extractor::flags() const {
index a53897f..103da95 100644 (file)
@@ -60,6 +60,12 @@ StagefrightMetadataRetriever::StagefrightMetadataRetriever()
 StagefrightMetadataRetriever::~StagefrightMetadataRetriever() {
     ALOGV("~StagefrightMetadataRetriever()");
     clearMetadata();
+    // Explicitly release extractor before continuing with the destructor,
+    // some extractors might need to callback to close off the DataSource
+    // and we need to make sure it's still there.
+    if (mExtractor != NULL) {
+        mExtractor->release();
+    }
     if (mSource != NULL) {
         mSource->close();
     }
index 4a4c538..c9d7dde 100644 (file)
@@ -62,6 +62,7 @@ public:
     virtual sp<MetaData> getMetaData();
     virtual uint32_t flags() const;
     virtual const char * name() { return "MPEG4Extractor"; }
+    virtual void release();
 
     // for DRM
     virtual char* getDrmTrackInfo(size_t trackID, int *len);
index f12160b..6ec7eaf 100644 (file)
@@ -72,6 +72,8 @@ public:
 
     virtual const char * name() { return "<unspecified>"; }
 
+    virtual void release() {}
+
 protected:
     MediaExtractor();
     virtual ~MediaExtractor();