Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 52bef17f authored by James Dong's avatar James Dong Committed by Android (Google) Code Review
Browse files

Merge "Fix for multiple audio/timed track feature implementation - part one"

parents f7ffb8bf eec46abb
Loading
Loading
Loading
Loading
+20 −10
Original line number Diff line number Diff line
@@ -40,18 +40,24 @@ public:

    status_t start();
    status_t pause();
    status_t selectTrack(int32_t index);
    status_t unselectTrack(int32_t index);
    status_t selectTrack(size_t index);
    status_t unselectTrack(size_t index);

    status_t seekToAsync(int64_t timeUs);

    status_t addInBandTextSource(const sp<MediaSource>& source);
    status_t addOutOfBandTextSource(const char *uri, const char *mimeType);
    status_t addInBandTextSource(
            size_t trackIndex, const sp<MediaSource>& source);

    status_t addOutOfBandTextSource(
            size_t trackIndex, const char *uri, const char *mimeType);

    // Caller owns the file desriptor and caller is responsible for closing it.
    status_t addOutOfBandTextSource(
            int fd, off64_t offset, off64_t length, const char *mimeType);
            size_t trackIndex, int fd, off64_t offset,
            off64_t length, const char *mimeType);

    void getTrackInfo(Parcel *parcel);
    void getExternalTrackInfo(Parcel *parcel);
    size_t countExternalTracks() const;

private:
    Mutex mLock;
@@ -68,13 +74,17 @@ private:

    // Variables to be guarded by mLock.
    State mState;
    int32_t mCurrentTrackIndex;
    Vector<sp<TimedTextSource> > mTextSourceVector;
    size_t mCurrentTrackIndex;
    KeyedVector<size_t, sp<TimedTextSource> > mTextSourceVector;
    Vector<bool> mTextSourceTypeVector;

    // -- End of variables to be guarded by mLock

    status_t selectTrack_l(int32_t index);
    status_t selectTrack_l(size_t index);

    status_t createOutOfBandTextSource(
            const char *mimeType, const sp<DataSource>& dataSource);
            size_t trackIndex, const char* mimeType,
            const sp<DataSource>& dataSource);

    DISALLOW_EVIL_CONSTRUCTORS(TimedTextDriver);
};
+102 −37
Original line number Diff line number Diff line
@@ -356,6 +356,7 @@ status_t AwesomePlayer::setDataSource_l(const sp<MediaExtractor> &extractor) {

    int64_t totalBitRate = 0;

    mExtractor = extractor;
    for (size_t i = 0; i < extractor->countTracks(); ++i) {
        sp<MetaData> meta = extractor->getTrackMetaData(i);

@@ -443,7 +444,7 @@ status_t AwesomePlayer::setDataSource_l(const sp<MediaExtractor> &extractor) {
                }
            }
        } else if (!strcasecmp(mime.string(), MEDIA_MIMETYPE_TEXT_3GPP)) {
            addTextSource(extractor->getTrack(i));
            addTextSource(i, extractor->getTrack(i));
        }
    }

@@ -507,6 +508,7 @@ void AwesomePlayer::reset_l() {
    mCachedSource.clear();
    mAudioTrack.clear();
    mVideoTrack.clear();
    mExtractor.clear();

    // Shutdown audio first, so that the respone to the reset request
    // appears to happen instantaneously as far as the user is concerned
@@ -1331,7 +1333,7 @@ void AwesomePlayer::setAudioSource(sp<MediaSource> source) {
    mAudioTrack = source;
}

void AwesomePlayer::addTextSource(const sp<MediaSource>& source) {
void AwesomePlayer::addTextSource(size_t trackIndex, const sp<MediaSource>& source) {
    Mutex::Autolock autoLock(mTimedTextLock);
    CHECK(source != NULL);

@@ -1339,7 +1341,7 @@ void AwesomePlayer::addTextSource(const sp<MediaSource>& source) {
        mTextDriver = new TimedTextDriver(mListener);
    }

    mTextDriver->addInBandTextSource(source);
    mTextDriver->addInBandTextSource(trackIndex, source);
}

status_t AwesomePlayer::initAudioDecoder() {
@@ -2254,6 +2256,94 @@ status_t AwesomePlayer::getParameter(int key, Parcel *reply) {
    }
}

status_t AwesomePlayer::getTrackInfo(Parcel *reply) const {
    Mutex::Autolock autoLock(mTimedTextLock);
    if (mTextDriver == NULL) {
        return INVALID_OPERATION;
    }

    reply->writeInt32(mTextDriver->countExternalTracks() +
                mExtractor->countTracks());
    for (size_t i = 0; i < mExtractor->countTracks(); ++i) {
        sp<MetaData> meta = mExtractor->getTrackMetaData(i);

        const char *_mime;
        CHECK(meta->findCString(kKeyMIMEType, &_mime));

        String8 mime = String8(_mime);

        reply->writeInt32(2); // 2 fields

        if (!strncasecmp(mime.string(), "video/", 6)) {
            reply->writeInt32(MEDIA_TRACK_TYPE_VIDEO);
        } else if (!strncasecmp(mime.string(), "audio/", 6)) {
            reply->writeInt32(MEDIA_TRACK_TYPE_AUDIO);
        } else if (!strcasecmp(mime.string(), MEDIA_MIMETYPE_TEXT_3GPP)) {
            reply->writeInt32(MEDIA_TRACK_TYPE_TIMEDTEXT);
        } else {
            reply->writeInt32(MEDIA_TRACK_TYPE_UNKNOWN);
        }

        const char *lang;
        if (meta->findCString(kKeyMediaLanguage, &lang)) {
            reply->writeString16(String16(lang));
        } else {
            reply->writeString16(String16(""));
        }
    }

    mTextDriver->getExternalTrackInfo(reply);
    return OK;
}

// FIXME:
// At present, only timed text track is able to be selected or unselected.
status_t AwesomePlayer::selectTrack(size_t trackIndex, bool select) {
    Mutex::Autolock autoLock(mTimedTextLock);
    if (mTextDriver == NULL) {
        return INVALID_OPERATION;
    }

    if (trackIndex >= mExtractor->countTracks()
                + mTextDriver->countExternalTracks()) {
        return BAD_VALUE;
    }

    if (trackIndex < mExtractor->countTracks()) {
        sp<MetaData> meta = mExtractor->getTrackMetaData(trackIndex);
        const char *_mime;
        CHECK(meta->findCString(kKeyMIMEType, &_mime));
        String8 mime = String8(_mime);

        if (strcasecmp(mime.string(), MEDIA_MIMETYPE_TEXT_3GPP)) {
            return ERROR_UNSUPPORTED;
        }
    }

    status_t err = OK;
    if (select) {
        err = mTextDriver->selectTrack(trackIndex);
        if (err == OK) {
            modifyFlags(TEXTPLAYER_INITIALIZED, SET);
            if (mFlags & PLAYING && !(mFlags & TEXT_RUNNING)) {
                mTextDriver->start();
                modifyFlags(TEXT_RUNNING, SET);
            }
        }
    } else {
        err = mTextDriver->unselectTrack(trackIndex);
        if (err == OK) {
            modifyFlags(TEXTPLAYER_INITIALIZED, CLEAR);
            modifyFlags(TEXT_RUNNING, CLEAR);
        }
    }
    return err;
}

size_t AwesomePlayer::countTracks() const {
    return mExtractor->countTracks() + mTextDriver->countExternalTracks();
}

status_t AwesomePlayer::invoke(const Parcel &request, Parcel *reply) {
    if (NULL == reply) {
        return android::BAD_VALUE;
@@ -2266,12 +2356,7 @@ status_t AwesomePlayer::invoke(const Parcel &request, Parcel *reply) {
    switch(methodId) {
        case INVOKE_ID_GET_TRACK_INFO:
        {
            Mutex::Autolock autoLock(mTimedTextLock);
            if (mTextDriver == NULL) {
                return INVALID_OPERATION;
            }
            mTextDriver->getTrackInfo(reply);
            return OK;
            return getTrackInfo(reply);
        }
        case INVOKE_ID_ADD_EXTERNAL_SOURCE:
        {
@@ -2282,7 +2367,8 @@ status_t AwesomePlayer::invoke(const Parcel &request, Parcel *reply) {
            // String values written in Parcel are UTF-16 values.
            String8 uri(request.readString16());
            String8 mimeType(request.readString16());
            return mTextDriver->addOutOfBandTextSource(uri, mimeType);
            size_t nTracks = countTracks();
            return mTextDriver->addOutOfBandTextSource(nTracks, uri, mimeType);
        }
        case INVOKE_ID_ADD_EXTERNAL_SOURCE_FD:
        {
@@ -2294,40 +2380,19 @@ status_t AwesomePlayer::invoke(const Parcel &request, Parcel *reply) {
            off64_t offset = request.readInt64();
            off64_t length  = request.readInt64();
            String8 mimeType(request.readString16());
            size_t nTracks = countTracks();
            return mTextDriver->addOutOfBandTextSource(
                    fd, offset, length, mimeType);
                    nTracks, fd, offset, length, mimeType);
        }
        case INVOKE_ID_SELECT_TRACK:
        {
            Mutex::Autolock autoLock(mTimedTextLock);
            if (mTextDriver == NULL) {
                return INVALID_OPERATION;
            }

            status_t err = mTextDriver->selectTrack(
                    request.readInt32());
            if (err == OK) {
                modifyFlags(TEXTPLAYER_INITIALIZED, SET);
                if (mFlags & PLAYING && !(mFlags & TEXT_RUNNING)) {
                    mTextDriver->start();
                    modifyFlags(TEXT_RUNNING, SET);
                }
            }
            return err;
            int trackIndex = request.readInt32();
            return selectTrack(trackIndex, true);
        }
        case INVOKE_ID_UNSELECT_TRACK:
        {
            Mutex::Autolock autoLock(mTimedTextLock);
            if (mTextDriver == NULL) {
                return INVALID_OPERATION;
            }
            status_t err = mTextDriver->unselectTrack(
                    request.readInt32());
            if (err == OK) {
                modifyFlags(TEXTPLAYER_INITIALIZED, CLEAR);
                modifyFlags(TEXT_RUNNING, CLEAR);
            }
            return err;
            int trackIndex = request.readInt32();
            return selectTrack(trackIndex, false);
        }
        default:
        {
+10 −1
Original line number Diff line number Diff line
@@ -235,6 +235,7 @@ private:
    mutable Mutex mTimedTextLock;

    sp<WVMExtractor> mWVMExtractor;
    sp<MediaExtractor> mExtractor;

    status_t setDataSource_l(
            const char *uri,
@@ -257,7 +258,7 @@ private:
    void setVideoSource(sp<MediaSource> source);
    status_t initVideoDecoder(uint32_t flags = 0);

    void addTextSource(const sp<MediaSource>& source);
    void addTextSource(size_t trackIndex, const sp<MediaSource>& source);

    void onStreamDone();

@@ -318,6 +319,14 @@ private:
        Vector<TrackStat> mTracks;
    } mStats;

    status_t getTrackInfo(Parcel* reply) const;

    // when select is true, the given track is selected.
    // otherwise, the given track is unselected.
    status_t selectTrack(size_t trackIndex, bool select);

    size_t countTracks() const;

    AwesomePlayer(const AwesomePlayer &);
    AwesomePlayer &operator=(const AwesomePlayer &);
};
+36 −23
Original line number Diff line number Diff line
@@ -52,16 +52,13 @@ TimedTextDriver::TimedTextDriver(

TimedTextDriver::~TimedTextDriver() {
    mTextSourceVector.clear();
    mTextSourceTypeVector.clear();
    mLooper->stop();
}

status_t TimedTextDriver::selectTrack_l(int32_t index) {
    if (index >= (int)(mTextSourceVector.size())) {
        return BAD_VALUE;
    }

status_t TimedTextDriver::selectTrack_l(size_t index) {
    sp<TimedTextSource> source;
    source = mTextSourceVector.itemAt(index);
    source = mTextSourceVector.valueFor(index);
    mPlayer->setDataSource(source);
    if (mState == UNINITIALIZED) {
        mState = PAUSED;
@@ -108,7 +105,7 @@ status_t TimedTextDriver::pause() {
    return OK;
}

status_t TimedTextDriver::selectTrack(int32_t index) {
status_t TimedTextDriver::selectTrack(size_t index) {
    status_t ret = OK;
    Mutex::Autolock autoLock(mLock);
    switch (mState) {
@@ -130,7 +127,7 @@ status_t TimedTextDriver::selectTrack(int32_t index) {
    return ret;
}

status_t TimedTextDriver::unselectTrack(int32_t index) {
status_t TimedTextDriver::unselectTrack(size_t index) {
    if (mCurrentTrackIndex != index) {
        return INVALID_OPERATION;
    }
@@ -149,19 +146,21 @@ status_t TimedTextDriver::seekToAsync(int64_t timeUs) {
}

status_t TimedTextDriver::addInBandTextSource(
        const sp<MediaSource>& mediaSource) {
        size_t trackIndex, const sp<MediaSource>& mediaSource) {
    sp<TimedTextSource> source =
            TimedTextSource::CreateTimedTextSource(mediaSource);
    if (source == NULL) {
        return ERROR_UNSUPPORTED;
    }
    Mutex::Autolock autoLock(mLock);
    mTextSourceVector.add(source);
    mTextSourceVector.add(trackIndex, source);
    mTextSourceTypeVector.add(true);
    return OK;
}

status_t TimedTextDriver::addOutOfBandTextSource(
        const char *uri, const char *mimeType) {
        size_t trackIndex, const char *uri, const char *mimeType) {

    // To support local subtitle file only for now
    if (strncasecmp("file://", uri, 7)) {
        ALOGE("uri('%s') is not a file", uri);
@@ -170,11 +169,11 @@ status_t TimedTextDriver::addOutOfBandTextSource(

    sp<DataSource> dataSource =
            DataSource::CreateFromURI(uri);
    return createOutOfBandTextSource(mimeType, dataSource);
    return createOutOfBandTextSource(trackIndex, mimeType, dataSource);
}

status_t TimedTextDriver::addOutOfBandTextSource(
        int fd, off64_t offset, off64_t length, const char *mimeType) {
        size_t trackIndex, int fd, off64_t offset, off64_t length, const char *mimeType) {

    if (fd < 0) {
        ALOGE("Invalid file descriptor: %d", fd);
@@ -182,11 +181,13 @@ status_t TimedTextDriver::addOutOfBandTextSource(
    }

    sp<DataSource> dataSource = new FileSource(dup(fd), offset, length);
    return createOutOfBandTextSource(mimeType, dataSource);
    return createOutOfBandTextSource(trackIndex, mimeType, dataSource);
}

status_t TimedTextDriver::createOutOfBandTextSource(
        const char *mimeType, const sp<DataSource>& dataSource) {
        size_t trackIndex,
        const char *mimeType,
        const sp<DataSource>& dataSource) {

    if (dataSource == NULL) {
        return ERROR_UNSUPPORTED;
@@ -199,28 +200,40 @@ status_t TimedTextDriver::createOutOfBandTextSource(
    }

    if (source == NULL) {
        ALOGE("Failed to create timed text source");
        return ERROR_UNSUPPORTED;
    }

    Mutex::Autolock autoLock(mLock);
    mTextSourceVector.add(source);
    mTextSourceVector.add(trackIndex, source);
    mTextSourceTypeVector.add(false);
    return OK;
}

void TimedTextDriver::getTrackInfo(Parcel *parcel) {
size_t TimedTextDriver::countExternalTracks() const {
    size_t nTracks = 0;
    for (size_t i = 0, n = mTextSourceTypeVector.size(); i < n; ++i) {
        if (!mTextSourceTypeVector[i]) {
            ++nTracks;
        }
    }
    return nTracks;
}

void TimedTextDriver::getExternalTrackInfo(Parcel *parcel) {
    Mutex::Autolock autoLock(mLock);
    Vector<sp<TimedTextSource> >::const_iterator iter;
    parcel->writeInt32(mTextSourceVector.size());
    for (iter = mTextSourceVector.begin();
         iter != mTextSourceVector.end(); ++iter) {
        sp<MetaData> meta = (*iter)->getFormat();
    for (size_t i = 0, n = mTextSourceTypeVector.size(); i < n; ++i) {
        if (mTextSourceTypeVector[i]) {
            continue;
        }

        sp<MetaData> meta = mTextSourceVector.valueAt(i)->getFormat();

        // There are two fields.
        parcel->writeInt32(2);

        // track type.
        parcel->writeInt32(MEDIA_TRACK_TYPE_TIMEDTEXT);

        const char *lang = "und";
        if (meta != NULL) {
            meta->findCString(kKeyMediaLanguage, &lang);