NuMediaExtractor API to unselect tracks and finer control over seeking.

Change-Id: I44d5a2b01d34b771bb0ff48b12829e33314c2374
related-to-bug: 6276111
diff --git a/include/media/stagefright/NuMediaExtractor.h b/include/media/stagefright/NuMediaExtractor.h
index e197134..c9c709c 100644
--- a/include/media/stagefright/NuMediaExtractor.h
+++ b/include/media/stagefright/NuMediaExtractor.h
@@ -18,6 +18,7 @@
 #define NU_MEDIA_EXTRACTOR_H_
 
 #include <media/stagefright/foundation/ABase.h>
+#include <media/stagefright/MediaSource.h>
 #include <utils/Errors.h>
 #include <utils/KeyedVector.h>
 #include <utils/RefBase.h>
@@ -53,8 +54,12 @@
     status_t getTrackFormat(size_t index, sp<AMessage> *format) const;
 
     status_t selectTrack(size_t index);
+    status_t unselectTrack(size_t index);
 
-    status_t seekTo(int64_t timeUs);
+    status_t seekTo(
+            int64_t timeUs,
+            MediaSource::ReadOptions::SeekMode mode =
+                MediaSource::ReadOptions::SEEK_CLOSEST_SYNC);
 
     status_t advance();
     status_t readSampleData(const sp<ABuffer> &buffer);
@@ -93,7 +98,11 @@
     int64_t mTotalBitrate;  // in bits/sec
     int64_t mDurationUs;
 
-    ssize_t fetchTrackSamples(int64_t seekTimeUs = -1ll);
+    ssize_t fetchTrackSamples(
+            int64_t seekTimeUs = -1ll,
+            MediaSource::ReadOptions::SeekMode mode =
+                MediaSource::ReadOptions::SEEK_CLOSEST_SYNC);
+
     void releaseTrackSamples();
 
     bool getTotalBitrate(int64_t *bitRate) const;
diff --git a/media/libstagefright/NuMediaExtractor.cpp b/media/libstagefright/NuMediaExtractor.cpp
index 7cfb8ea..5f3f63f 100644
--- a/media/libstagefright/NuMediaExtractor.cpp
+++ b/media/libstagefright/NuMediaExtractor.cpp
@@ -384,6 +384,47 @@
     return OK;
 }
 
+status_t NuMediaExtractor::unselectTrack(size_t index) {
+    Mutex::Autolock autoLock(mLock);
+
+    if (mImpl == NULL) {
+        return -EINVAL;
+    }
+
+    if (index >= mImpl->countTracks()) {
+        return -ERANGE;
+    }
+
+    size_t i;
+    for (i = 0; i < mSelectedTracks.size(); ++i) {
+        TrackInfo *info = &mSelectedTracks.editItemAt(i);
+
+        if (info->mTrackIndex == index) {
+            break;
+        }
+    }
+
+    if (i == mSelectedTracks.size()) {
+        // Not selected.
+        return OK;
+    }
+
+    TrackInfo *info = &mSelectedTracks.editItemAt(i);
+
+    if (info->mSample != NULL) {
+        info->mSample->release();
+        info->mSample = NULL;
+
+        info->mSampleTimeUs = -1ll;
+    }
+
+    CHECK_EQ((status_t)OK, info->mSource->stop());
+
+    mSelectedTracks.removeAt(i);
+
+    return OK;
+}
+
 void NuMediaExtractor::releaseTrackSamples() {
     for (size_t i = 0; i < mSelectedTracks.size(); ++i) {
         TrackInfo *info = &mSelectedTracks.editItemAt(i);
@@ -397,7 +438,8 @@
     }
 }
 
-ssize_t NuMediaExtractor::fetchTrackSamples(int64_t seekTimeUs) {
+ssize_t NuMediaExtractor::fetchTrackSamples(
+        int64_t seekTimeUs, MediaSource::ReadOptions::SeekMode mode) {
     TrackInfo *minInfo = NULL;
     ssize_t minIndex = -1;
 
@@ -419,7 +461,7 @@
         if (info->mSample == NULL) {
             MediaSource::ReadOptions options;
             if (seekTimeUs >= 0ll) {
-                options.setSeekTo(seekTimeUs);
+                options.setSeekTo(seekTimeUs, mode);
             }
             status_t err = info->mSource->read(&info->mSample, &options);
 
@@ -445,10 +487,11 @@
     return minIndex;
 }
 
-status_t NuMediaExtractor::seekTo(int64_t timeUs) {
+status_t NuMediaExtractor::seekTo(
+        int64_t timeUs, MediaSource::ReadOptions::SeekMode mode) {
     Mutex::Autolock autoLock(mLock);
 
-    ssize_t minIndex = fetchTrackSamples(timeUs);
+    ssize_t minIndex = fetchTrackSamples(timeUs, mode);
 
     if (minIndex < 0) {
         return ERROR_END_OF_STREAM;