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

Commit 66551748 authored by Insun Kang's avatar Insun Kang
Browse files

First step of refactoring 'timedtext' code.

Goal
1. Removed dependency of TimedTextPlayer on AwsomePlayer.
2. Generalized TimedTextParser to TimedTextSource and its subclasses.

Summary
1. Introduced TimedTextDriver, TimedTextPlayer (new implementation),
TimedTextSource (and its subclasses).
2. Removed TimedTextParser.

Remaining TODOs
1. Revise VideoVidew, Gallery3D app, AwesomePlayer to check if
'pause' and 'resume' works well.
2. Consider revising MediaPlayer APIs such as setParameter() ->
addTextSource(). Need more thoughts.

Change-Id: Ie0c4f15b9690102de755cef6940f8c31ccf78e27
parent e5954268
Loading
Loading
Loading
Loading
+17 −17
Original line number Diff line number Diff line
@@ -30,7 +30,7 @@
#include "include/MPEG2TSExtractor.h"
#include "include/WVMExtractor.h"

#include "timedtext/TimedTextPlayer.h"
#include "timedtext/TimedTextDriver.h"

#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
@@ -192,7 +192,7 @@ AwesomePlayer::AwesomePlayer()
      mVideoBuffer(NULL),
      mDecryptHandle(NULL),
      mLastVideoTimeUs(-1),
      mTextPlayer(NULL) {
      mTextDriver(NULL) {
    CHECK_EQ(mClient.connect(), (status_t)OK);

    DataSource::RegisterDefaultSniffers();
@@ -530,9 +530,9 @@ void AwesomePlayer::reset_l() {
    delete mAudioPlayer;
    mAudioPlayer = NULL;

    if (mTextPlayer != NULL) {
        delete mTextPlayer;
        mTextPlayer = NULL;
    if (mTextDriver != NULL) {
        delete mTextDriver;
        mTextDriver = NULL;
    }

    mVideoRenderer.clear();
@@ -1118,7 +1118,7 @@ status_t AwesomePlayer::pause_l(bool at_eos) {
    }

    if (mFlags & TEXTPLAYER_STARTED) {
        mTextPlayer->pause();
        mTextDriver->pause();
        modifyFlags(TEXT_RUNNING, CLEAR);
    }

@@ -1272,9 +1272,9 @@ status_t AwesomePlayer::seekTo(int64_t timeUs) {
}

status_t AwesomePlayer::setTimedTextTrackIndex(int32_t index) {
    if (mTextPlayer != NULL) {
    if (mTextDriver != NULL) {
        if (index >= 0) { // to turn on a text track
            status_t err = mTextPlayer->setTimedTextTrackIndex(index);
            status_t err = mTextDriver->setTimedTextTrackIndex(index);
            if (err != OK) {
                return err;
            }
@@ -1290,7 +1290,7 @@ status_t AwesomePlayer::setTimedTextTrackIndex(int32_t index) {
                modifyFlags(TEXTPLAYER_STARTED, CLEAR);
            }

            return mTextPlayer->setTimedTextTrackIndex(index);
            return mTextDriver->setTimedTextTrackIndex(index);
        }
    } else {
        return INVALID_OPERATION;
@@ -1319,7 +1319,7 @@ status_t AwesomePlayer::seekTo_l(int64_t timeUs) {
    seekAudioIfNecessary_l();

    if (mFlags & TEXTPLAYER_STARTED) {
        mTextPlayer->seekTo(mSeekTimeUs);
        mTextDriver->seekToAsync(mSeekTimeUs);
    }

    if (!(mFlags & PLAYING)) {
@@ -1364,11 +1364,11 @@ void AwesomePlayer::addTextSource(sp<MediaSource> source) {
    Mutex::Autolock autoLock(mTimedTextLock);
    CHECK(source != NULL);

    if (mTextPlayer == NULL) {
        mTextPlayer = new TimedTextPlayer(this, mListener, &mQueue);
    if (mTextDriver == NULL) {
        mTextDriver = new TimedTextDriver(mListener);
    }

    mTextPlayer->addTextSource(source);
    mTextDriver->addInBandTextSource(source);
}

status_t AwesomePlayer::initAudioDecoder() {
@@ -1695,7 +1695,7 @@ void AwesomePlayer::onVideoEvent() {
    }

    if ((mFlags & TEXTPLAYER_STARTED) && !(mFlags & (TEXT_RUNNING | SEEK_PREVIEW))) {
        mTextPlayer->resume();
        mTextDriver->resume();
        modifyFlags(TEXT_RUNNING, SET);
    }

@@ -2241,11 +2241,11 @@ status_t AwesomePlayer::setParameter(int key, const Parcel &request) {
        case KEY_PARAMETER_TIMED_TEXT_ADD_OUT_OF_BAND_SOURCE:
        {
            Mutex::Autolock autoLock(mTimedTextLock);
            if (mTextPlayer == NULL) {
                mTextPlayer = new TimedTextPlayer(this, mListener, &mQueue);
            if (mTextDriver == NULL) {
                mTextDriver = new TimedTextDriver(mListener);
            }

            return mTextPlayer->setParameter(key, request);
            return mTextDriver->addOutOfBandTextSource(request);
        }
        case KEY_PARAMETER_CACHE_STAT_COLLECT_FREQ_MS:
        {
+0 −2
Original line number Diff line number Diff line
@@ -20,7 +20,6 @@
#include "include/MPEG4Extractor.h"
#include "include/SampleTable.h"
#include "include/ESDS.h"
#include "timedtext/TimedTextPlayer.h"

#include <arpa/inet.h>

@@ -2430,4 +2429,3 @@ bool SniffMPEG4(
}

}  // namespace android
+2 −3
Original line number Diff line number Diff line
@@ -41,7 +41,7 @@ struct ISurfaceTexture;
class DrmManagerClinet;
class DecryptHandle;

class TimedTextPlayer;
class TimedTextDriver;
struct WVMExtractor;

struct AwesomeRenderer : public RefBase {
@@ -232,7 +232,7 @@ private:
    sp<DecryptHandle> mDecryptHandle;

    int64_t mLastVideoTimeUs;
    TimedTextPlayer *mTextPlayer;
    TimedTextDriver *mTextDriver;
    mutable Mutex mTimedTextLock;

    sp<WVMExtractor> mWVMExtractor;
@@ -326,4 +326,3 @@ private:
}  // namespace android

#endif  // AWESOME_PLAYER_H_
+4 −1
Original line number Diff line number Diff line
@@ -3,7 +3,10 @@ include $(CLEAR_VARS)

LOCAL_SRC_FILES:=                 \
        TextDescriptions.cpp      \
        TimedTextParser.cpp       \
        TimedTextDriver.cpp       \
        TimedTextInBandSource.cpp \
        TimedTextSource.cpp       \
        TimedTextSRTSource.cpp    \
        TimedTextPlayer.cpp

LOCAL_CFLAGS += -Wno-multichar
+223 −0
Original line number Diff line number Diff line
 /*
 * Copyright (C) 2012 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

//#define LOG_NDEBUG 0
#define LOG_TAG "TimedTextDriver"
#include <utils/Log.h>

#include <binder/IPCThreadState.h>

#include <media/MediaPlayerInterface.h>
#include <media/stagefright/MediaErrors.h>
#include <media/stagefright/MediaSource.h>
#include <media/stagefright/DataSource.h>
#include <media/stagefright/Utils.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/ALooper.h>

#include "TimedTextDriver.h"

#include "TextDescriptions.h"
#include "TimedTextPlayer.h"
#include "TimedTextSource.h"

namespace android {

TimedTextDriver::TimedTextDriver(
        const wp<MediaPlayerBase> &listener)
    : mLooper(new ALooper),
      mListener(listener),
      mState(UNINITIALIZED) {
    mLooper->setName("TimedTextDriver");
    mLooper->start();
    mPlayer = new TimedTextPlayer(listener);
    mLooper->registerHandler(mPlayer);
}

TimedTextDriver::~TimedTextDriver() {
    mTextInBandVector.clear();
    mTextOutOfBandVector.clear();
    mLooper->stop();
}

status_t TimedTextDriver::setTimedTextTrackIndex_l(int32_t index) {
    if (index >=
            (int)(mTextInBandVector.size() + mTextOutOfBandVector.size())) {
        return BAD_VALUE;
    }

    sp<TimedTextSource> source;
    if (index < mTextInBandVector.size()) {
        source = mTextInBandVector.itemAt(index);
    } else {
        source = mTextOutOfBandVector.itemAt(index - mTextInBandVector.size());
    }
    mPlayer->setDataSource(source);
    return OK;
}

status_t TimedTextDriver::start() {
    Mutex::Autolock autoLock(mLock);
    switch (mState) {
        case UNINITIALIZED:
            return INVALID_OPERATION;
        case STOPPED:
            mPlayer->start();
            break;
        case PLAYING:
            return OK;
        case PAUSED:
            mPlayer->resume();
            break;
        default:
            TRESPASS();
    }
    mState = PLAYING;
    return OK;
}

status_t TimedTextDriver::stop() {
    return pause();
}

// TODO: Test if pause() works properly.
// Scenario 1: start - pause - resume
// Scenario 2: start - seek
// Scenario 3: start - pause - seek - resume
status_t TimedTextDriver::pause() {
    Mutex::Autolock autoLock(mLock);
    switch (mState) {
        case UNINITIALIZED:
            return INVALID_OPERATION;
        case STOPPED:
            return OK;
        case PLAYING:
            mPlayer->pause();
            break;
        case PAUSED:
            return OK;
        default:
            TRESPASS();
    }
    mState = PAUSED;
    return OK;
}

status_t TimedTextDriver::resume() {
    return start();
}

status_t TimedTextDriver::seekToAsync(int64_t timeUs) {
    mPlayer->seekToAsync(timeUs);
    return OK;
}

status_t TimedTextDriver::setTimedTextTrackIndex(int32_t index) {
    // TODO: This is current implementation for MediaPlayer::disableTimedText().
    // Find better way for readability.
    if (index < 0) {
        mPlayer->pause();
        return OK;
    }

    status_t ret = OK;
    Mutex::Autolock autoLock(mLock);
    switch (mState) {
        case UNINITIALIZED:
            ret = INVALID_OPERATION;
            break;
        case PAUSED:
            ret = setTimedTextTrackIndex_l(index);
            break;
        case PLAYING:
            mPlayer->pause();
            ret = setTimedTextTrackIndex_l(index);
            if (ret != OK) {
                break;
            }
            mPlayer->start();
            break;
        case STOPPED:
            // TODO: The only difference between STOPPED and PAUSED is this
            // part. Revise the flow from "MediaPlayer::enableTimedText()" and
            // remove one of the status, PAUSED and STOPPED, if possible.
            ret = setTimedTextTrackIndex_l(index);
            if (ret != OK) {
                break;
            }
            mPlayer->start();
            break;
        defaut:
            TRESPASS();
    }
    return ret;
}

status_t TimedTextDriver::addInBandTextSource(
        const sp<MediaSource>& mediaSource) {
    sp<TimedTextSource> source =
            TimedTextSource::CreateTimedTextSource(mediaSource);
    if (source == NULL) {
        return ERROR_UNSUPPORTED;
    }
    Mutex::Autolock autoLock(mLock);
    mTextInBandVector.add(source);
    if (mState == UNINITIALIZED) {
        mState = STOPPED;
    }
    return OK;
}

status_t TimedTextDriver::addOutOfBandTextSource(
        const Parcel &request) {
    // TODO: Define "TimedTextSource::CreateFromURI(uri)"
    // and move below lines there..?

    // String values written in Parcel are UTF-16 values.
    const String16 uri16 = request.readString16();
    String8 uri = String8(request.readString16());

    uri.toLower();
    // To support local subtitle file only for now
    if (strncasecmp("file://", uri.string(), 7)) {
        return ERROR_UNSUPPORTED;
    }
    sp<DataSource> dataSource =
            DataSource::CreateFromURI(uri);
    if (dataSource == NULL) {
        return ERROR_UNSUPPORTED;
    }

    sp<TimedTextSource> source;
    if (uri.getPathExtension() == String8(".srt")) {
        source = TimedTextSource::CreateTimedTextSource(
                dataSource, TimedTextSource::OUT_OF_BAND_FILE_SRT);
    }

    if (source == NULL) {
        return ERROR_UNSUPPORTED;
    }

    Mutex::Autolock autoLock(mLock);

    mTextOutOfBandVector.add(source);
    if (mState == UNINITIALIZED) {
        mState = STOPPED;
    }
    return OK;
}

}  // namespace android
Loading