TimedTextDriver.cpp revision 3254b25e8b0f674ccc2226609e01dd86a600802e
16655174826330afe66ef766258181ae8c11f3f6cInsun Kang /*
26655174826330afe66ef766258181ae8c11f3f6cInsun Kang * Copyright (C) 2012 The Android Open Source Project
36655174826330afe66ef766258181ae8c11f3f6cInsun Kang *
46655174826330afe66ef766258181ae8c11f3f6cInsun Kang * Licensed under the Apache License, Version 2.0 (the "License");
56655174826330afe66ef766258181ae8c11f3f6cInsun Kang * you may not use this file except in compliance with the License.
66655174826330afe66ef766258181ae8c11f3f6cInsun Kang * You may obtain a copy of the License at
76655174826330afe66ef766258181ae8c11f3f6cInsun Kang *
86655174826330afe66ef766258181ae8c11f3f6cInsun Kang *      http://www.apache.org/licenses/LICENSE-2.0
96655174826330afe66ef766258181ae8c11f3f6cInsun Kang *
106655174826330afe66ef766258181ae8c11f3f6cInsun Kang * Unless required by applicable law or agreed to in writing, software
116655174826330afe66ef766258181ae8c11f3f6cInsun Kang * distributed under the License is distributed on an "AS IS" BASIS,
126655174826330afe66ef766258181ae8c11f3f6cInsun Kang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136655174826330afe66ef766258181ae8c11f3f6cInsun Kang * See the License for the specific language governing permissions and
146655174826330afe66ef766258181ae8c11f3f6cInsun Kang * limitations under the License.
156655174826330afe66ef766258181ae8c11f3f6cInsun Kang */
166655174826330afe66ef766258181ae8c11f3f6cInsun Kang
176655174826330afe66ef766258181ae8c11f3f6cInsun Kang//#define LOG_NDEBUG 0
186655174826330afe66ef766258181ae8c11f3f6cInsun Kang#define LOG_TAG "TimedTextDriver"
196655174826330afe66ef766258181ae8c11f3f6cInsun Kang#include <utils/Log.h>
206655174826330afe66ef766258181ae8c11f3f6cInsun Kang
216655174826330afe66ef766258181ae8c11f3f6cInsun Kang#include <binder/IPCThreadState.h>
226655174826330afe66ef766258181ae8c11f3f6cInsun Kang
236655174826330afe66ef766258181ae8c11f3f6cInsun Kang#include <media/MediaPlayerInterface.h>
246655174826330afe66ef766258181ae8c11f3f6cInsun Kang#include <media/stagefright/MediaErrors.h>
256655174826330afe66ef766258181ae8c11f3f6cInsun Kang#include <media/stagefright/MediaSource.h>
266655174826330afe66ef766258181ae8c11f3f6cInsun Kang#include <media/stagefright/DataSource.h>
276655174826330afe66ef766258181ae8c11f3f6cInsun Kang#include <media/stagefright/Utils.h>
286655174826330afe66ef766258181ae8c11f3f6cInsun Kang#include <media/stagefright/foundation/ADebug.h>
296655174826330afe66ef766258181ae8c11f3f6cInsun Kang#include <media/stagefright/foundation/ALooper.h>
303254b25e8b0f674ccc2226609e01dd86a600802eInsun Kang#include <media/stagefright/timedtext/TimedTextDriver.h>
316655174826330afe66ef766258181ae8c11f3f6cInsun Kang
326655174826330afe66ef766258181ae8c11f3f6cInsun Kang#include "TextDescriptions.h"
336655174826330afe66ef766258181ae8c11f3f6cInsun Kang#include "TimedTextPlayer.h"
346655174826330afe66ef766258181ae8c11f3f6cInsun Kang#include "TimedTextSource.h"
356655174826330afe66ef766258181ae8c11f3f6cInsun Kang
366655174826330afe66ef766258181ae8c11f3f6cInsun Kangnamespace android {
376655174826330afe66ef766258181ae8c11f3f6cInsun Kang
386655174826330afe66ef766258181ae8c11f3f6cInsun KangTimedTextDriver::TimedTextDriver(
396655174826330afe66ef766258181ae8c11f3f6cInsun Kang        const wp<MediaPlayerBase> &listener)
406655174826330afe66ef766258181ae8c11f3f6cInsun Kang    : mLooper(new ALooper),
416655174826330afe66ef766258181ae8c11f3f6cInsun Kang      mListener(listener),
426655174826330afe66ef766258181ae8c11f3f6cInsun Kang      mState(UNINITIALIZED) {
436655174826330afe66ef766258181ae8c11f3f6cInsun Kang    mLooper->setName("TimedTextDriver");
446655174826330afe66ef766258181ae8c11f3f6cInsun Kang    mLooper->start();
456655174826330afe66ef766258181ae8c11f3f6cInsun Kang    mPlayer = new TimedTextPlayer(listener);
466655174826330afe66ef766258181ae8c11f3f6cInsun Kang    mLooper->registerHandler(mPlayer);
476655174826330afe66ef766258181ae8c11f3f6cInsun Kang}
486655174826330afe66ef766258181ae8c11f3f6cInsun Kang
496655174826330afe66ef766258181ae8c11f3f6cInsun KangTimedTextDriver::~TimedTextDriver() {
506655174826330afe66ef766258181ae8c11f3f6cInsun Kang    mTextInBandVector.clear();
516655174826330afe66ef766258181ae8c11f3f6cInsun Kang    mTextOutOfBandVector.clear();
526655174826330afe66ef766258181ae8c11f3f6cInsun Kang    mLooper->stop();
536655174826330afe66ef766258181ae8c11f3f6cInsun Kang}
546655174826330afe66ef766258181ae8c11f3f6cInsun Kang
556655174826330afe66ef766258181ae8c11f3f6cInsun Kangstatus_t TimedTextDriver::setTimedTextTrackIndex_l(int32_t index) {
566655174826330afe66ef766258181ae8c11f3f6cInsun Kang    if (index >=
576655174826330afe66ef766258181ae8c11f3f6cInsun Kang            (int)(mTextInBandVector.size() + mTextOutOfBandVector.size())) {
586655174826330afe66ef766258181ae8c11f3f6cInsun Kang        return BAD_VALUE;
596655174826330afe66ef766258181ae8c11f3f6cInsun Kang    }
606655174826330afe66ef766258181ae8c11f3f6cInsun Kang
616655174826330afe66ef766258181ae8c11f3f6cInsun Kang    sp<TimedTextSource> source;
626655174826330afe66ef766258181ae8c11f3f6cInsun Kang    if (index < mTextInBandVector.size()) {
636655174826330afe66ef766258181ae8c11f3f6cInsun Kang        source = mTextInBandVector.itemAt(index);
646655174826330afe66ef766258181ae8c11f3f6cInsun Kang    } else {
656655174826330afe66ef766258181ae8c11f3f6cInsun Kang        source = mTextOutOfBandVector.itemAt(index - mTextInBandVector.size());
666655174826330afe66ef766258181ae8c11f3f6cInsun Kang    }
676655174826330afe66ef766258181ae8c11f3f6cInsun Kang    mPlayer->setDataSource(source);
686655174826330afe66ef766258181ae8c11f3f6cInsun Kang    return OK;
696655174826330afe66ef766258181ae8c11f3f6cInsun Kang}
706655174826330afe66ef766258181ae8c11f3f6cInsun Kang
716655174826330afe66ef766258181ae8c11f3f6cInsun Kangstatus_t TimedTextDriver::start() {
726655174826330afe66ef766258181ae8c11f3f6cInsun Kang    Mutex::Autolock autoLock(mLock);
736655174826330afe66ef766258181ae8c11f3f6cInsun Kang    switch (mState) {
746655174826330afe66ef766258181ae8c11f3f6cInsun Kang        case UNINITIALIZED:
756655174826330afe66ef766258181ae8c11f3f6cInsun Kang            return INVALID_OPERATION;
766655174826330afe66ef766258181ae8c11f3f6cInsun Kang        case STOPPED:
776655174826330afe66ef766258181ae8c11f3f6cInsun Kang            mPlayer->start();
786655174826330afe66ef766258181ae8c11f3f6cInsun Kang            break;
796655174826330afe66ef766258181ae8c11f3f6cInsun Kang        case PLAYING:
806655174826330afe66ef766258181ae8c11f3f6cInsun Kang            return OK;
816655174826330afe66ef766258181ae8c11f3f6cInsun Kang        case PAUSED:
826655174826330afe66ef766258181ae8c11f3f6cInsun Kang            mPlayer->resume();
836655174826330afe66ef766258181ae8c11f3f6cInsun Kang            break;
846655174826330afe66ef766258181ae8c11f3f6cInsun Kang        default:
856655174826330afe66ef766258181ae8c11f3f6cInsun Kang            TRESPASS();
866655174826330afe66ef766258181ae8c11f3f6cInsun Kang    }
876655174826330afe66ef766258181ae8c11f3f6cInsun Kang    mState = PLAYING;
886655174826330afe66ef766258181ae8c11f3f6cInsun Kang    return OK;
896655174826330afe66ef766258181ae8c11f3f6cInsun Kang}
906655174826330afe66ef766258181ae8c11f3f6cInsun Kang
916655174826330afe66ef766258181ae8c11f3f6cInsun Kangstatus_t TimedTextDriver::stop() {
926655174826330afe66ef766258181ae8c11f3f6cInsun Kang    return pause();
936655174826330afe66ef766258181ae8c11f3f6cInsun Kang}
946655174826330afe66ef766258181ae8c11f3f6cInsun Kang
956655174826330afe66ef766258181ae8c11f3f6cInsun Kang// TODO: Test if pause() works properly.
966655174826330afe66ef766258181ae8c11f3f6cInsun Kang// Scenario 1: start - pause - resume
976655174826330afe66ef766258181ae8c11f3f6cInsun Kang// Scenario 2: start - seek
986655174826330afe66ef766258181ae8c11f3f6cInsun Kang// Scenario 3: start - pause - seek - resume
996655174826330afe66ef766258181ae8c11f3f6cInsun Kangstatus_t TimedTextDriver::pause() {
1006655174826330afe66ef766258181ae8c11f3f6cInsun Kang    Mutex::Autolock autoLock(mLock);
1016655174826330afe66ef766258181ae8c11f3f6cInsun Kang    switch (mState) {
1026655174826330afe66ef766258181ae8c11f3f6cInsun Kang        case UNINITIALIZED:
1036655174826330afe66ef766258181ae8c11f3f6cInsun Kang            return INVALID_OPERATION;
1046655174826330afe66ef766258181ae8c11f3f6cInsun Kang        case STOPPED:
1056655174826330afe66ef766258181ae8c11f3f6cInsun Kang            return OK;
1066655174826330afe66ef766258181ae8c11f3f6cInsun Kang        case PLAYING:
1076655174826330afe66ef766258181ae8c11f3f6cInsun Kang            mPlayer->pause();
1086655174826330afe66ef766258181ae8c11f3f6cInsun Kang            break;
1096655174826330afe66ef766258181ae8c11f3f6cInsun Kang        case PAUSED:
1106655174826330afe66ef766258181ae8c11f3f6cInsun Kang            return OK;
1116655174826330afe66ef766258181ae8c11f3f6cInsun Kang        default:
1126655174826330afe66ef766258181ae8c11f3f6cInsun Kang            TRESPASS();
1136655174826330afe66ef766258181ae8c11f3f6cInsun Kang    }
1146655174826330afe66ef766258181ae8c11f3f6cInsun Kang    mState = PAUSED;
1156655174826330afe66ef766258181ae8c11f3f6cInsun Kang    return OK;
1166655174826330afe66ef766258181ae8c11f3f6cInsun Kang}
1176655174826330afe66ef766258181ae8c11f3f6cInsun Kang
1186655174826330afe66ef766258181ae8c11f3f6cInsun Kangstatus_t TimedTextDriver::resume() {
1196655174826330afe66ef766258181ae8c11f3f6cInsun Kang    return start();
1206655174826330afe66ef766258181ae8c11f3f6cInsun Kang}
1216655174826330afe66ef766258181ae8c11f3f6cInsun Kang
1226655174826330afe66ef766258181ae8c11f3f6cInsun Kangstatus_t TimedTextDriver::seekToAsync(int64_t timeUs) {
1236655174826330afe66ef766258181ae8c11f3f6cInsun Kang    mPlayer->seekToAsync(timeUs);
1246655174826330afe66ef766258181ae8c11f3f6cInsun Kang    return OK;
1256655174826330afe66ef766258181ae8c11f3f6cInsun Kang}
1266655174826330afe66ef766258181ae8c11f3f6cInsun Kang
1276655174826330afe66ef766258181ae8c11f3f6cInsun Kangstatus_t TimedTextDriver::setTimedTextTrackIndex(int32_t index) {
1286655174826330afe66ef766258181ae8c11f3f6cInsun Kang    // TODO: This is current implementation for MediaPlayer::disableTimedText().
1296655174826330afe66ef766258181ae8c11f3f6cInsun Kang    // Find better way for readability.
1306655174826330afe66ef766258181ae8c11f3f6cInsun Kang    if (index < 0) {
1316655174826330afe66ef766258181ae8c11f3f6cInsun Kang        mPlayer->pause();
1326655174826330afe66ef766258181ae8c11f3f6cInsun Kang        return OK;
1336655174826330afe66ef766258181ae8c11f3f6cInsun Kang    }
1346655174826330afe66ef766258181ae8c11f3f6cInsun Kang
1356655174826330afe66ef766258181ae8c11f3f6cInsun Kang    status_t ret = OK;
1366655174826330afe66ef766258181ae8c11f3f6cInsun Kang    Mutex::Autolock autoLock(mLock);
1376655174826330afe66ef766258181ae8c11f3f6cInsun Kang    switch (mState) {
1386655174826330afe66ef766258181ae8c11f3f6cInsun Kang        case UNINITIALIZED:
1396655174826330afe66ef766258181ae8c11f3f6cInsun Kang            ret = INVALID_OPERATION;
1406655174826330afe66ef766258181ae8c11f3f6cInsun Kang            break;
1416655174826330afe66ef766258181ae8c11f3f6cInsun Kang        case PAUSED:
1426655174826330afe66ef766258181ae8c11f3f6cInsun Kang            ret = setTimedTextTrackIndex_l(index);
1436655174826330afe66ef766258181ae8c11f3f6cInsun Kang            break;
1446655174826330afe66ef766258181ae8c11f3f6cInsun Kang        case PLAYING:
1456655174826330afe66ef766258181ae8c11f3f6cInsun Kang            mPlayer->pause();
1466655174826330afe66ef766258181ae8c11f3f6cInsun Kang            ret = setTimedTextTrackIndex_l(index);
1476655174826330afe66ef766258181ae8c11f3f6cInsun Kang            if (ret != OK) {
1486655174826330afe66ef766258181ae8c11f3f6cInsun Kang                break;
1496655174826330afe66ef766258181ae8c11f3f6cInsun Kang            }
1506655174826330afe66ef766258181ae8c11f3f6cInsun Kang            mPlayer->start();
1516655174826330afe66ef766258181ae8c11f3f6cInsun Kang            break;
1526655174826330afe66ef766258181ae8c11f3f6cInsun Kang        case STOPPED:
1536655174826330afe66ef766258181ae8c11f3f6cInsun Kang            // TODO: The only difference between STOPPED and PAUSED is this
1546655174826330afe66ef766258181ae8c11f3f6cInsun Kang            // part. Revise the flow from "MediaPlayer::enableTimedText()" and
1556655174826330afe66ef766258181ae8c11f3f6cInsun Kang            // remove one of the status, PAUSED and STOPPED, if possible.
1566655174826330afe66ef766258181ae8c11f3f6cInsun Kang            ret = setTimedTextTrackIndex_l(index);
1576655174826330afe66ef766258181ae8c11f3f6cInsun Kang            if (ret != OK) {
1586655174826330afe66ef766258181ae8c11f3f6cInsun Kang                break;
1596655174826330afe66ef766258181ae8c11f3f6cInsun Kang            }
1606655174826330afe66ef766258181ae8c11f3f6cInsun Kang            mPlayer->start();
1616655174826330afe66ef766258181ae8c11f3f6cInsun Kang            break;
1626655174826330afe66ef766258181ae8c11f3f6cInsun Kang        defaut:
1636655174826330afe66ef766258181ae8c11f3f6cInsun Kang            TRESPASS();
1646655174826330afe66ef766258181ae8c11f3f6cInsun Kang    }
1656655174826330afe66ef766258181ae8c11f3f6cInsun Kang    return ret;
1666655174826330afe66ef766258181ae8c11f3f6cInsun Kang}
1676655174826330afe66ef766258181ae8c11f3f6cInsun Kang
1686655174826330afe66ef766258181ae8c11f3f6cInsun Kangstatus_t TimedTextDriver::addInBandTextSource(
1696655174826330afe66ef766258181ae8c11f3f6cInsun Kang        const sp<MediaSource>& mediaSource) {
1706655174826330afe66ef766258181ae8c11f3f6cInsun Kang    sp<TimedTextSource> source =
1716655174826330afe66ef766258181ae8c11f3f6cInsun Kang            TimedTextSource::CreateTimedTextSource(mediaSource);
1726655174826330afe66ef766258181ae8c11f3f6cInsun Kang    if (source == NULL) {
1736655174826330afe66ef766258181ae8c11f3f6cInsun Kang        return ERROR_UNSUPPORTED;
1746655174826330afe66ef766258181ae8c11f3f6cInsun Kang    }
1756655174826330afe66ef766258181ae8c11f3f6cInsun Kang    Mutex::Autolock autoLock(mLock);
1766655174826330afe66ef766258181ae8c11f3f6cInsun Kang    mTextInBandVector.add(source);
1776655174826330afe66ef766258181ae8c11f3f6cInsun Kang    if (mState == UNINITIALIZED) {
1786655174826330afe66ef766258181ae8c11f3f6cInsun Kang        mState = STOPPED;
1796655174826330afe66ef766258181ae8c11f3f6cInsun Kang    }
1806655174826330afe66ef766258181ae8c11f3f6cInsun Kang    return OK;
1816655174826330afe66ef766258181ae8c11f3f6cInsun Kang}
1826655174826330afe66ef766258181ae8c11f3f6cInsun Kang
1836655174826330afe66ef766258181ae8c11f3f6cInsun Kangstatus_t TimedTextDriver::addOutOfBandTextSource(
1846655174826330afe66ef766258181ae8c11f3f6cInsun Kang        const Parcel &request) {
1856655174826330afe66ef766258181ae8c11f3f6cInsun Kang    // TODO: Define "TimedTextSource::CreateFromURI(uri)"
1866655174826330afe66ef766258181ae8c11f3f6cInsun Kang    // and move below lines there..?
1876655174826330afe66ef766258181ae8c11f3f6cInsun Kang
1886655174826330afe66ef766258181ae8c11f3f6cInsun Kang    // String values written in Parcel are UTF-16 values.
1896655174826330afe66ef766258181ae8c11f3f6cInsun Kang    const String16 uri16 = request.readString16();
1906655174826330afe66ef766258181ae8c11f3f6cInsun Kang    String8 uri = String8(request.readString16());
1916655174826330afe66ef766258181ae8c11f3f6cInsun Kang
1926655174826330afe66ef766258181ae8c11f3f6cInsun Kang    uri.toLower();
1936655174826330afe66ef766258181ae8c11f3f6cInsun Kang    // To support local subtitle file only for now
1946655174826330afe66ef766258181ae8c11f3f6cInsun Kang    if (strncasecmp("file://", uri.string(), 7)) {
1956655174826330afe66ef766258181ae8c11f3f6cInsun Kang        return ERROR_UNSUPPORTED;
1966655174826330afe66ef766258181ae8c11f3f6cInsun Kang    }
1976655174826330afe66ef766258181ae8c11f3f6cInsun Kang    sp<DataSource> dataSource =
1986655174826330afe66ef766258181ae8c11f3f6cInsun Kang            DataSource::CreateFromURI(uri);
1996655174826330afe66ef766258181ae8c11f3f6cInsun Kang    if (dataSource == NULL) {
2006655174826330afe66ef766258181ae8c11f3f6cInsun Kang        return ERROR_UNSUPPORTED;
2016655174826330afe66ef766258181ae8c11f3f6cInsun Kang    }
2026655174826330afe66ef766258181ae8c11f3f6cInsun Kang
2036655174826330afe66ef766258181ae8c11f3f6cInsun Kang    sp<TimedTextSource> source;
2046655174826330afe66ef766258181ae8c11f3f6cInsun Kang    if (uri.getPathExtension() == String8(".srt")) {
2056655174826330afe66ef766258181ae8c11f3f6cInsun Kang        source = TimedTextSource::CreateTimedTextSource(
2066655174826330afe66ef766258181ae8c11f3f6cInsun Kang                dataSource, TimedTextSource::OUT_OF_BAND_FILE_SRT);
2076655174826330afe66ef766258181ae8c11f3f6cInsun Kang    }
2086655174826330afe66ef766258181ae8c11f3f6cInsun Kang
2096655174826330afe66ef766258181ae8c11f3f6cInsun Kang    if (source == NULL) {
2106655174826330afe66ef766258181ae8c11f3f6cInsun Kang        return ERROR_UNSUPPORTED;
2116655174826330afe66ef766258181ae8c11f3f6cInsun Kang    }
2126655174826330afe66ef766258181ae8c11f3f6cInsun Kang
2136655174826330afe66ef766258181ae8c11f3f6cInsun Kang    Mutex::Autolock autoLock(mLock);
2146655174826330afe66ef766258181ae8c11f3f6cInsun Kang
2156655174826330afe66ef766258181ae8c11f3f6cInsun Kang    mTextOutOfBandVector.add(source);
2166655174826330afe66ef766258181ae8c11f3f6cInsun Kang    if (mState == UNINITIALIZED) {
2176655174826330afe66ef766258181ae8c11f3f6cInsun Kang        mState = STOPPED;
2186655174826330afe66ef766258181ae8c11f3f6cInsun Kang    }
2196655174826330afe66ef766258181ae8c11f3f6cInsun Kang    return OK;
2206655174826330afe66ef766258181ae8c11f3f6cInsun Kang}
2216655174826330afe66ef766258181ae8c11f3f6cInsun Kang
2226655174826330afe66ef766258181ae8c11f3f6cInsun Kang}  // namespace android
223