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

Commit 453f2ef1 authored by Nipun Kwatra's avatar Nipun Kwatra Committed by Android (Google) Code Review
Browse files

Merge "client_id->clientId, bugfix for signaling of read abort on stop."

parents 818c830c ea434daf
Loading
Loading
Loading
Loading
+9 −9
Original line number Original line Diff line number Diff line
@@ -115,23 +115,23 @@ private:
    // Functions used by Client to implement the MediaSource interface.
    // Functions used by Client to implement the MediaSource interface.


    // If the real source has not been started yet by any client, starts it.
    // If the real source has not been started yet by any client, starts it.
    status_t start(int client_id, MetaData *params);
    status_t start(int clientId, MetaData *params);


    // Stops the real source after all clients have called stop().
    // Stops the real source after all clients have called stop().
    status_t stop(int client_id);
    status_t stop(int clientId);


    // returns the real source's getFormat().
    // returns the real source's getFormat().
    sp<MetaData> getFormat(int client_id);
    sp<MetaData> getFormat(int clientId);


    // If the client's desired buffer has already been read into
    // If the client's desired buffer has already been read into
    // mLastReadMediaBuffer, points the buffer to that. Otherwise if it is the
    // mLastReadMediaBuffer, points the buffer to that. Otherwise if it is the
    // master client, reads the buffer from source or else waits for the master
    // master client, reads the buffer from source or else waits for the master
    // client to read the buffer and uses that.
    // client to read the buffer and uses that.
    status_t read(int client_id,
    status_t read(int clientId,
            MediaBuffer **buffer, const MediaSource::ReadOptions *options = NULL);
            MediaBuffer **buffer, const MediaSource::ReadOptions *options = NULL);


    // Not implemented right now.
    // Not implemented right now.
    status_t pause(int client_id);
    status_t pause(int clientId);


    // Function which reads a buffer from the real source into
    // Function which reads a buffer from the real source into
    // mLastReadMediaBuffer
    // mLastReadMediaBuffer
@@ -140,11 +140,11 @@ private:
    // Waits until read from the real source has been completed.
    // Waits until read from the real source has been completed.
    // _lock means that the function should be called when the thread has already
    // _lock means that the function should be called when the thread has already
    // obtained the lock for the mutex mLock.
    // obtained the lock for the mutex mLock.
    void waitForReadFromSource_lock(int32_t client_id);
    void waitForReadFromSource_lock(int32_t clientId);


    // Waits until all clients have read the current buffer in
    // Waits until all clients have read the current buffer in
    // mLastReadCompleted.
    // mLastReadCompleted.
    void waitForAllClientsLastRead_lock(int32_t client_id);
    void waitForAllClientsLastRead_lock(int32_t clientId);


    // Each client calls this after it completes its read(). Once all clients
    // Each client calls this after it completes its read(). Once all clients
    // have called this for the current buffer, the function calls
    // have called this for the current buffer, the function calls
@@ -163,7 +163,7 @@ private:
    public:
    public:
        // Constructor stores reference to the parent MediaSourceSplitter and it
        // Constructor stores reference to the parent MediaSourceSplitter and it
        // client id.
        // client id.
        Client(sp<MediaSourceSplitter> splitter, int32_t client_id);
        Client(sp<MediaSourceSplitter> splitter, int32_t clientId);


        // MediaSource interface
        // MediaSource interface
        virtual status_t start(MetaData *params = NULL);
        virtual status_t start(MetaData *params = NULL);
@@ -182,7 +182,7 @@ private:
        sp<MediaSourceSplitter> mSplitter;
        sp<MediaSourceSplitter> mSplitter;


        // Id of this client.
        // Id of this client.
        int32_t mClient_id;
        int32_t mClientId;
    };
    };


    friend class Client;
    friend class Client;
+48 −43
Original line number Original line Diff line number Diff line
@@ -48,113 +48,118 @@ sp<MediaSource> MediaSourceSplitter::createClient() {
    return client;
    return client;
}
}


status_t MediaSourceSplitter::start(int client_id, MetaData *params) {
status_t MediaSourceSplitter::start(int clientId, MetaData *params) {
    Mutex::Autolock autoLock(mLock);
    Mutex::Autolock autoLock(mLock);


    LOGV("start client (%d)", client_id);
    LOGV("start client (%d)", clientId);
    if (mClientsStarted[client_id]) {
    if (mClientsStarted[clientId]) {
        return OK;
        return OK;
    }
    }


    mNumberOfClientsStarted++;
    mNumberOfClientsStarted++;


    if (!mSourceStarted) {
    if (!mSourceStarted) {
        LOGV("Starting real source from client (%d)", client_id);
        LOGV("Starting real source from client (%d)", clientId);
        status_t err = mSource->start(params);
        status_t err = mSource->start(params);


        if (err == OK) {
        if (err == OK) {
            mSourceStarted = true;
            mSourceStarted = true;
            mClientsStarted.editItemAt(client_id) = true;
            mClientsStarted.editItemAt(clientId) = true;
            mClientsDesiredReadBit.editItemAt(client_id) = !mCurrentReadBit;
            mClientsDesiredReadBit.editItemAt(clientId) = !mCurrentReadBit;
        }
        }


        return err;
        return err;
    } else {
    } else {
        mClientsStarted.editItemAt(client_id) = true;
        mClientsStarted.editItemAt(clientId) = true;
        if (mLastReadCompleted) {
        if (mLastReadCompleted) {
            // Last read was completed. So join in the threads for the next read.
            // Last read was completed. So join in the threads for the next read.
            mClientsDesiredReadBit.editItemAt(client_id) = !mCurrentReadBit;
            mClientsDesiredReadBit.editItemAt(clientId) = !mCurrentReadBit;
        } else {
        } else {
            // Last read is ongoing. So join in the threads for the current read.
            // Last read is ongoing. So join in the threads for the current read.
            mClientsDesiredReadBit.editItemAt(client_id) = mCurrentReadBit;
            mClientsDesiredReadBit.editItemAt(clientId) = mCurrentReadBit;
        }
        }
        return OK;
        return OK;
    }
    }
}
}


status_t MediaSourceSplitter::stop(int client_id) {
status_t MediaSourceSplitter::stop(int clientId) {
    Mutex::Autolock autoLock(mLock);
    Mutex::Autolock autoLock(mLock);


    LOGV("stop client (%d)", client_id);
    LOGV("stop client (%d)", clientId);
    CHECK(client_id >= 0 && client_id < mNumberOfClients);
    CHECK(clientId >= 0 && clientId < mNumberOfClients);
    CHECK(mClientsStarted[client_id]);
    CHECK(mClientsStarted[clientId]);


    if (--mNumberOfClientsStarted == 0) {
    if (--mNumberOfClientsStarted == 0) {
        LOGV("Stopping real source from client (%d)", client_id);
        LOGV("Stopping real source from client (%d)", clientId);
        status_t err = mSource->stop();
        status_t err = mSource->stop();
        mSourceStarted = false;
        mSourceStarted = false;
        mClientsStarted.editItemAt(client_id) = false;
        mClientsStarted.editItemAt(clientId) = false;
        return err;
        return err;
    } else {
    } else {
        mClientsStarted.editItemAt(client_id) = false;
        mClientsStarted.editItemAt(clientId) = false;
        if (!mLastReadCompleted) {
        if (!mLastReadCompleted && (mClientsDesiredReadBit[clientId] == mCurrentReadBit)) {
            // Other threads may be waiting for all the reads to complete.
            // !mLastReadCompleted implies that buffer has been read from source, but all
            // Signal that the read has been aborted.
            // clients haven't read it.
            // mClientsDesiredReadBit[clientId] == mCurrentReadBit implies that this
            // client would have wanted to read from this buffer. (i.e. it has not yet
            // called read() for the current read buffer.)
            // Since other threads may be waiting for all the clients' reads to complete,
            // signal that this read has been aborted.
            signalReadComplete_lock(true);
            signalReadComplete_lock(true);
        }
        }
        return OK;
        return OK;
    }
    }
}
}


sp<MetaData> MediaSourceSplitter::getFormat(int client_id) {
sp<MetaData> MediaSourceSplitter::getFormat(int clientId) {
    Mutex::Autolock autoLock(mLock);
    Mutex::Autolock autoLock(mLock);


    LOGV("getFormat client (%d)", client_id);
    LOGV("getFormat client (%d)", clientId);
    return mSource->getFormat();
    return mSource->getFormat();
}
}


status_t MediaSourceSplitter::read(int client_id,
status_t MediaSourceSplitter::read(int clientId,
        MediaBuffer **buffer, const MediaSource::ReadOptions *options) {
        MediaBuffer **buffer, const MediaSource::ReadOptions *options) {
    Mutex::Autolock autoLock(mLock);
    Mutex::Autolock autoLock(mLock);


    CHECK(client_id >= 0 && client_id < mNumberOfClients);
    CHECK(clientId >= 0 && clientId < mNumberOfClients);


    LOGV("read client (%d)", client_id);
    LOGV("read client (%d)", clientId);
    *buffer = NULL;
    *buffer = NULL;


    if (!mClientsStarted[client_id]) {
    if (!mClientsStarted[clientId]) {
        return OK;
        return OK;
    }
    }


    if (mCurrentReadBit != mClientsDesiredReadBit[client_id]) {
    if (mCurrentReadBit != mClientsDesiredReadBit[clientId]) {
        // Desired buffer has not been read from source yet.
        // Desired buffer has not been read from source yet.


        // If the current client is the special client with client_id = 0
        // If the current client is the special client with clientId = 0
        // then read from source, else wait until the client 0 has finished
        // then read from source, else wait until the client 0 has finished
        // reading from source.
        // reading from source.
        if (client_id == 0) {
        if (clientId == 0) {
            // Wait for all client's last read to complete first so as to not
            // Wait for all client's last read to complete first so as to not
            // corrupt the buffer at mLastReadMediaBuffer.
            // corrupt the buffer at mLastReadMediaBuffer.
            waitForAllClientsLastRead_lock(client_id);
            waitForAllClientsLastRead_lock(clientId);


            readFromSource_lock(options);
            readFromSource_lock(options);
            *buffer = mLastReadMediaBuffer;
            *buffer = mLastReadMediaBuffer;
        } else {
        } else {
            waitForReadFromSource_lock(client_id);
            waitForReadFromSource_lock(clientId);


            *buffer = mLastReadMediaBuffer;
            *buffer = mLastReadMediaBuffer;
            (*buffer)->add_ref();
            (*buffer)->add_ref();
        }
        }
        CHECK(mCurrentReadBit == mClientsDesiredReadBit[client_id]);
        CHECK(mCurrentReadBit == mClientsDesiredReadBit[clientId]);
    } else {
    } else {
        // Desired buffer has already been read from source. Use the cached data.
        // Desired buffer has already been read from source. Use the cached data.
        CHECK(client_id != 0);
        CHECK(clientId != 0);


        *buffer = mLastReadMediaBuffer;
        *buffer = mLastReadMediaBuffer;
        (*buffer)->add_ref();
        (*buffer)->add_ref();
    }
    }


    mClientsDesiredReadBit.editItemAt(client_id) = !mClientsDesiredReadBit[client_id];
    mClientsDesiredReadBit.editItemAt(clientId) = !mClientsDesiredReadBit[clientId];
    signalReadComplete_lock(false);
    signalReadComplete_lock(false);


    return mLastReadStatus;
    return mLastReadStatus;
@@ -168,11 +173,11 @@ void MediaSourceSplitter::readFromSource_lock(const MediaSource::ReadOptions *op
    mReadFromSourceCondition.broadcast();
    mReadFromSourceCondition.broadcast();
}
}


void MediaSourceSplitter::waitForReadFromSource_lock(int32_t client_id) {
void MediaSourceSplitter::waitForReadFromSource_lock(int32_t clientId) {
    mReadFromSourceCondition.wait(mLock);
    mReadFromSourceCondition.wait(mLock);
}
}


void MediaSourceSplitter::waitForAllClientsLastRead_lock(int32_t client_id) {
void MediaSourceSplitter::waitForAllClientsLastRead_lock(int32_t clientId) {
    if (mLastReadCompleted) {
    if (mLastReadCompleted) {
        return;
        return;
    }
    }
@@ -192,7 +197,7 @@ void MediaSourceSplitter::signalReadComplete_lock(bool readAborted) {
    }
    }
}
}


status_t MediaSourceSplitter::pause(int client_id) {
status_t MediaSourceSplitter::pause(int clientId) {
    return ERROR_UNSUPPORTED;
    return ERROR_UNSUPPORTED;
}
}


@@ -200,30 +205,30 @@ status_t MediaSourceSplitter::pause(int client_id) {


MediaSourceSplitter::Client::Client(
MediaSourceSplitter::Client::Client(
        sp<MediaSourceSplitter> splitter,
        sp<MediaSourceSplitter> splitter,
        int32_t client_id) {
        int32_t clientId) {
    mSplitter = splitter;
    mSplitter = splitter;
    mClient_id = client_id;
    mClientId = clientId;
}
}


status_t MediaSourceSplitter::Client::start(MetaData *params) {
status_t MediaSourceSplitter::Client::start(MetaData *params) {
    return mSplitter->start(mClient_id, params);
    return mSplitter->start(mClientId, params);
}
}


status_t MediaSourceSplitter::Client::stop() {
status_t MediaSourceSplitter::Client::stop() {
    return mSplitter->stop(mClient_id);
    return mSplitter->stop(mClientId);
}
}


sp<MetaData> MediaSourceSplitter::Client::getFormat() {
sp<MetaData> MediaSourceSplitter::Client::getFormat() {
    return mSplitter->getFormat(mClient_id);
    return mSplitter->getFormat(mClientId);
}
}


status_t MediaSourceSplitter::Client::read(
status_t MediaSourceSplitter::Client::read(
        MediaBuffer **buffer, const ReadOptions *options) {
        MediaBuffer **buffer, const ReadOptions *options) {
    return mSplitter->read(mClient_id, buffer, options);
    return mSplitter->read(mClientId, buffer, options);
}
}


status_t MediaSourceSplitter::Client::pause() {
status_t MediaSourceSplitter::Client::pause() {
    return mSplitter->pause(mClient_id);
    return mSplitter->pause(mClientId);
}
}


}  // namespace android
}  // namespace android