Merge "move audio sink open/close to NuPlayerRenderer" into lmp-dev
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index 1729f93..d922dc0 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -48,7 +48,8 @@
 class MPEG4Source : public MediaSource {
 public:
     // Caller retains ownership of both "dataSource" and "sampleTable".
-    MPEG4Source(const sp<MetaData> &format,
+    MPEG4Source(const sp<MPEG4Extractor> &owner,
+                const sp<MetaData> &format,
                 const sp<DataSource> &dataSource,
                 int32_t timeScale,
                 const sp<SampleTable> &sampleTable,
@@ -70,6 +71,8 @@
 private:
     Mutex mLock;
 
+    // keep the MPEG4Extractor around, since we're referencing its data
+    sp<MPEG4Extractor> mOwner;
     sp<MetaData> mFormat;
     sp<DataSource> mDataSource;
     int32_t mTimescale;
@@ -2593,7 +2596,7 @@
 
     ALOGV("getTrack called, pssh: %zu", mPssh.size());
 
-    return new MPEG4Source(
+    return new MPEG4Source(this,
             track->meta, mDataSource, track->timescale, track->sampleTable,
             mSidxEntries, trex, mMoofOffset);
 }
@@ -2940,6 +2943,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 
 MPEG4Source::MPEG4Source(
+        const sp<MPEG4Extractor> &owner,
         const sp<MetaData> &format,
         const sp<DataSource> &dataSource,
         int32_t timeScale,
@@ -2947,7 +2951,8 @@
         Vector<SidxEntry> &sidx,
         const Trex *trex,
         off64_t firstMoofOffset)
-    : mFormat(format),
+    : mOwner(owner),
+      mFormat(format),
       mDataSource(dataSource),
       mTimescale(timeScale),
       mSampleTable(sampleTable),
diff --git a/services/audiopolicy/AudioPolicyService.cpp b/services/audiopolicy/AudioPolicyService.cpp
index 06a7e84..dd4067f 100644
--- a/services/audiopolicy/AudioPolicyService.cpp
+++ b/services/audiopolicy/AudioPolicyService.cpp
@@ -839,18 +839,38 @@
         case CREATE_AUDIO_PATCH:
         case RELEASE_AUDIO_PATCH: {
             audio_patch_handle_t handle;
+            struct audio_patch patch;
             if (command->mCommand == CREATE_AUDIO_PATCH) {
                 handle = ((CreateAudioPatchData *)command->mParam.get())->mHandle;
+                patch = ((CreateAudioPatchData *)command->mParam.get())->mPatch;
             } else {
                 handle = ((ReleaseAudioPatchData *)command->mParam.get())->mHandle;
             }
             audio_patch_handle_t handle2;
+            struct audio_patch patch2;
             if (command2->mCommand == CREATE_AUDIO_PATCH) {
                 handle2 = ((CreateAudioPatchData *)command2->mParam.get())->mHandle;
+                patch2 = ((CreateAudioPatchData *)command2->mParam.get())->mPatch;
             } else {
                 handle2 = ((ReleaseAudioPatchData *)command2->mParam.get())->mHandle;
             }
             if (handle != handle2) break;
+            /* Filter CREATE_AUDIO_PATCH commands only when they are issued for
+               same output. */
+            if( (command->mCommand == CREATE_AUDIO_PATCH) &&
+                (command2->mCommand == CREATE_AUDIO_PATCH) ) {
+                bool isOutputDiff = false;
+                if (patch.num_sources == patch2.num_sources) {
+                    for (unsigned count = 0; count < patch.num_sources; count++) {
+                        if (patch.sources[count].id != patch2.sources[count].id) {
+                            isOutputDiff = true;
+                            break;
+                        }
+                    }
+                    if (isOutputDiff)
+                       break;
+                }
+            }
             ALOGV("Filtering out %s audio patch command for handle %d",
                   (command->mCommand == CREATE_AUDIO_PATCH) ? "create" : "release", handle);
             removedCommands.add(command2);