17a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang /* 26655174826330afe66ef766258181ae8c11f3f6cInsun Kang * Copyright (C) 2012 The Android Open Source Project 37a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang * 47a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang * Licensed under the Apache License, Version 2.0 (the "License"); 57a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang * you may not use this file except in compliance with the License. 67a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang * You may obtain a copy of the License at 77a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang * 87a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang * http://www.apache.org/licenses/LICENSE-2.0 97a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang * 107a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang * Unless required by applicable law or agreed to in writing, software 117a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang * distributed under the License is distributed on an "AS IS" BASIS, 127a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 137a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang * See the License for the specific language governing permissions and 147a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang * limitations under the License. 157a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang */ 167a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang 177a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang//#define LOG_NDEBUG 0 187a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang#define LOG_TAG "TimedTextPlayer" 197a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang#include <utils/Log.h> 207a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang 21b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross#include <inttypes.h> 222f0632f12cd02b0350918720443c888b48f4417bInsun Kang#include <limits.h> 23f1d5aa162c02a16b7195a43a9bcea4d592600ac4James Dong#include <media/stagefright/foundation/ADebug.h> 246655174826330afe66ef766258181ae8c11f3f6cInsun Kang#include <media/stagefright/foundation/AMessage.h> 253254b25e8b0f674ccc2226609e01dd86a600802eInsun Kang#include <media/stagefright/timedtext/TimedTextDriver.h> 267a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang#include <media/stagefright/MediaErrors.h> 276655174826330afe66ef766258181ae8c11f3f6cInsun Kang#include <media/MediaPlayerInterface.h> 283b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang 29965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang#include "TimedTextPlayer.h" 307a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang 316655174826330afe66ef766258181ae8c11f3f6cInsun Kang#include "TimedTextSource.h" 327a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang 336655174826330afe66ef766258181ae8c11f3f6cInsun Kangnamespace android { 347a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang 352f0632f12cd02b0350918720443c888b48f4417bInsun Kang// Event should be fired a bit earlier considering the processing time till 362f0632f12cd02b0350918720443c888b48f4417bInsun Kang// application actually gets the notification message. 376655174826330afe66ef766258181ae8c11f3f6cInsun Kangstatic const int64_t kAdjustmentProcessingTimeUs = 100000ll; 382f0632f12cd02b0350918720443c888b48f4417bInsun Kangstatic const int64_t kMaxDelayUs = 5000000ll; 39bae00e73c6d1d87cc5fd42b50f95d1d9572162eaInsun Kangstatic const int64_t kWaitTimeUsToRetryRead = 100000ll; 402f0632f12cd02b0350918720443c888b48f4417bInsun Kangstatic const int64_t kInvalidTimeUs = INT_MIN; 417a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang 426655174826330afe66ef766258181ae8c11f3f6cInsun KangTimedTextPlayer::TimedTextPlayer(const wp<MediaPlayerBase> &listener) 436655174826330afe66ef766258181ae8c11f3f6cInsun Kang : mListener(listener), 446655174826330afe66ef766258181ae8c11f3f6cInsun Kang mSource(NULL), 456472badc497a9e748411f8c8c9ed5d83ef335a85Insun Kang mPendingSeekTimeUs(kInvalidTimeUs), 466472badc497a9e748411f8c8c9ed5d83ef335a85Insun Kang mPaused(false), 476655174826330afe66ef766258181ae8c11f3f6cInsun Kang mSendSubtitleGeneration(0) { 487a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang} 497a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang 507a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria WangTimedTextPlayer::~TimedTextPlayer() { 516655174826330afe66ef766258181ae8c11f3f6cInsun Kang if (mSource != NULL) { 526655174826330afe66ef766258181ae8c11f3f6cInsun Kang mSource->stop(); 536655174826330afe66ef766258181ae8c11f3f6cInsun Kang mSource.clear(); 546655174826330afe66ef766258181ae8c11f3f6cInsun Kang mSource = NULL; 557a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang } 567a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang} 577a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang 586655174826330afe66ef766258181ae8c11f3f6cInsun Kangvoid TimedTextPlayer::start() { 596472badc497a9e748411f8c8c9ed5d83ef335a85Insun Kang (new AMessage(kWhatStart, id()))->post(); 607a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang} 617a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang 627a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wangvoid TimedTextPlayer::pause() { 636655174826330afe66ef766258181ae8c11f3f6cInsun Kang (new AMessage(kWhatPause, id()))->post(); 647a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang} 657a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang 66bb6bc8491fe819f96e1902e56694715cb110ce94Insun Kangvoid TimedTextPlayer::resume() { 67bb6bc8491fe819f96e1902e56694715cb110ce94Insun Kang (new AMessage(kWhatResume, id()))->post(); 68bb6bc8491fe819f96e1902e56694715cb110ce94Insun Kang} 69bb6bc8491fe819f96e1902e56694715cb110ce94Insun Kang 706655174826330afe66ef766258181ae8c11f3f6cInsun Kangvoid TimedTextPlayer::seekToAsync(int64_t timeUs) { 716655174826330afe66ef766258181ae8c11f3f6cInsun Kang sp<AMessage> msg = new AMessage(kWhatSeek, id()); 726655174826330afe66ef766258181ae8c11f3f6cInsun Kang msg->setInt64("seekTimeUs", timeUs); 736655174826330afe66ef766258181ae8c11f3f6cInsun Kang msg->post(); 747a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang} 757a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang 766655174826330afe66ef766258181ae8c11f3f6cInsun Kangvoid TimedTextPlayer::setDataSource(sp<TimedTextSource> source) { 776655174826330afe66ef766258181ae8c11f3f6cInsun Kang sp<AMessage> msg = new AMessage(kWhatSetSource, id()); 786655174826330afe66ef766258181ae8c11f3f6cInsun Kang msg->setObject("source", source); 796655174826330afe66ef766258181ae8c11f3f6cInsun Kang msg->post(); 807a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang} 817a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang 826655174826330afe66ef766258181ae8c11f3f6cInsun Kangvoid TimedTextPlayer::onMessageReceived(const sp<AMessage> &msg) { 836655174826330afe66ef766258181ae8c11f3f6cInsun Kang switch (msg->what()) { 846655174826330afe66ef766258181ae8c11f3f6cInsun Kang case kWhatPause: { 856472badc497a9e748411f8c8c9ed5d83ef335a85Insun Kang mPaused = true; 866655174826330afe66ef766258181ae8c11f3f6cInsun Kang break; 87965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang } 88bb6bc8491fe819f96e1902e56694715cb110ce94Insun Kang case kWhatResume: { 896472badc497a9e748411f8c8c9ed5d83ef335a85Insun Kang mPaused = false; 906472badc497a9e748411f8c8c9ed5d83ef335a85Insun Kang if (mPendingSeekTimeUs != kInvalidTimeUs) { 916472badc497a9e748411f8c8c9ed5d83ef335a85Insun Kang seekToAsync(mPendingSeekTimeUs); 926472badc497a9e748411f8c8c9ed5d83ef335a85Insun Kang mPendingSeekTimeUs = kInvalidTimeUs; 936472badc497a9e748411f8c8c9ed5d83ef335a85Insun Kang } else { 946472badc497a9e748411f8c8c9ed5d83ef335a85Insun Kang doRead(); 956472badc497a9e748411f8c8c9ed5d83ef335a85Insun Kang } 966472badc497a9e748411f8c8c9ed5d83ef335a85Insun Kang break; 976472badc497a9e748411f8c8c9ed5d83ef335a85Insun Kang } 986472badc497a9e748411f8c8c9ed5d83ef335a85Insun Kang case kWhatStart: { 996472badc497a9e748411f8c8c9ed5d83ef335a85Insun Kang sp<MediaPlayerBase> listener = mListener.promote(); 1006472badc497a9e748411f8c8c9ed5d83ef335a85Insun Kang if (listener == NULL) { 1016472badc497a9e748411f8c8c9ed5d83ef335a85Insun Kang ALOGE("Listener is NULL when kWhatStart is received."); 1026472badc497a9e748411f8c8c9ed5d83ef335a85Insun Kang break; 1036472badc497a9e748411f8c8c9ed5d83ef335a85Insun Kang } 1046472badc497a9e748411f8c8c9ed5d83ef335a85Insun Kang mPaused = false; 1056472badc497a9e748411f8c8c9ed5d83ef335a85Insun Kang mPendingSeekTimeUs = kInvalidTimeUs; 1066472badc497a9e748411f8c8c9ed5d83ef335a85Insun Kang int32_t positionMs = 0; 1076472badc497a9e748411f8c8c9ed5d83ef335a85Insun Kang listener->getCurrentPosition(&positionMs); 1086472badc497a9e748411f8c8c9ed5d83ef335a85Insun Kang int64_t seekTimeUs = positionMs * 1000ll; 1096472badc497a9e748411f8c8c9ed5d83ef335a85Insun Kang 1106472badc497a9e748411f8c8c9ed5d83ef335a85Insun Kang notifyListener(); 1116472badc497a9e748411f8c8c9ed5d83ef335a85Insun Kang mSendSubtitleGeneration++; 1126472badc497a9e748411f8c8c9ed5d83ef335a85Insun Kang doSeekAndRead(seekTimeUs); 113bb6bc8491fe819f96e1902e56694715cb110ce94Insun Kang break; 114bb6bc8491fe819f96e1902e56694715cb110ce94Insun Kang } 1154e1c91dd07fad96ee2387eda510c6da45e5dff0aInsun Kang case kWhatRetryRead: { 116bb6bc8491fe819f96e1902e56694715cb110ce94Insun Kang int32_t generation = -1; 117bb6bc8491fe819f96e1902e56694715cb110ce94Insun Kang CHECK(msg->findInt32("generation", &generation)); 118bb6bc8491fe819f96e1902e56694715cb110ce94Insun Kang if (generation != mSendSubtitleGeneration) { 119bb6bc8491fe819f96e1902e56694715cb110ce94Insun Kang // Drop obsolete msg. 120bb6bc8491fe819f96e1902e56694715cb110ce94Insun Kang break; 121bb6bc8491fe819f96e1902e56694715cb110ce94Insun Kang } 1224e1c91dd07fad96ee2387eda510c6da45e5dff0aInsun Kang int64_t seekTimeUs; 1234e1c91dd07fad96ee2387eda510c6da45e5dff0aInsun Kang int seekMode; 1244e1c91dd07fad96ee2387eda510c6da45e5dff0aInsun Kang if (msg->findInt64("seekTimeUs", &seekTimeUs) && 1254e1c91dd07fad96ee2387eda510c6da45e5dff0aInsun Kang msg->findInt32("seekMode", &seekMode)) { 1264e1c91dd07fad96ee2387eda510c6da45e5dff0aInsun Kang MediaSource::ReadOptions options; 1274e1c91dd07fad96ee2387eda510c6da45e5dff0aInsun Kang options.setSeekTo( 1284e1c91dd07fad96ee2387eda510c6da45e5dff0aInsun Kang seekTimeUs, 1294e1c91dd07fad96ee2387eda510c6da45e5dff0aInsun Kang static_cast<MediaSource::ReadOptions::SeekMode>(seekMode)); 1304e1c91dd07fad96ee2387eda510c6da45e5dff0aInsun Kang doRead(&options); 1314e1c91dd07fad96ee2387eda510c6da45e5dff0aInsun Kang } else { 1324e1c91dd07fad96ee2387eda510c6da45e5dff0aInsun Kang doRead(); 1334e1c91dd07fad96ee2387eda510c6da45e5dff0aInsun Kang } 1344e1c91dd07fad96ee2387eda510c6da45e5dff0aInsun Kang break; 1354e1c91dd07fad96ee2387eda510c6da45e5dff0aInsun Kang } 1366655174826330afe66ef766258181ae8c11f3f6cInsun Kang case kWhatSeek: { 137bb6bc8491fe819f96e1902e56694715cb110ce94Insun Kang int64_t seekTimeUs = kInvalidTimeUs; 138bb6bc8491fe819f96e1902e56694715cb110ce94Insun Kang // Clear a displayed timed text before seeking. 139bb6bc8491fe819f96e1902e56694715cb110ce94Insun Kang notifyListener(); 1406655174826330afe66ef766258181ae8c11f3f6cInsun Kang msg->findInt64("seekTimeUs", &seekTimeUs); 141bb6bc8491fe819f96e1902e56694715cb110ce94Insun Kang if (seekTimeUs == kInvalidTimeUs) { 1426655174826330afe66ef766258181ae8c11f3f6cInsun Kang sp<MediaPlayerBase> listener = mListener.promote(); 1436655174826330afe66ef766258181ae8c11f3f6cInsun Kang if (listener != NULL) { 1446655174826330afe66ef766258181ae8c11f3f6cInsun Kang int32_t positionMs = 0; 1456655174826330afe66ef766258181ae8c11f3f6cInsun Kang listener->getCurrentPosition(&positionMs); 1466655174826330afe66ef766258181ae8c11f3f6cInsun Kang seekTimeUs = positionMs * 1000ll; 1476655174826330afe66ef766258181ae8c11f3f6cInsun Kang } 1486655174826330afe66ef766258181ae8c11f3f6cInsun Kang } 1496472badc497a9e748411f8c8c9ed5d83ef335a85Insun Kang if (mPaused) { 1506472badc497a9e748411f8c8c9ed5d83ef335a85Insun Kang mPendingSeekTimeUs = seekTimeUs; 1516472badc497a9e748411f8c8c9ed5d83ef335a85Insun Kang break; 1526472badc497a9e748411f8c8c9ed5d83ef335a85Insun Kang } 1536472badc497a9e748411f8c8c9ed5d83ef335a85Insun Kang mSendSubtitleGeneration++; 1546655174826330afe66ef766258181ae8c11f3f6cInsun Kang doSeekAndRead(seekTimeUs); 1556655174826330afe66ef766258181ae8c11f3f6cInsun Kang break; 1566655174826330afe66ef766258181ae8c11f3f6cInsun Kang } 1576655174826330afe66ef766258181ae8c11f3f6cInsun Kang case kWhatSendSubtitle: { 1586655174826330afe66ef766258181ae8c11f3f6cInsun Kang int32_t generation; 1596655174826330afe66ef766258181ae8c11f3f6cInsun Kang CHECK(msg->findInt32("generation", &generation)); 1606655174826330afe66ef766258181ae8c11f3f6cInsun Kang if (generation != mSendSubtitleGeneration) { 161bb6bc8491fe819f96e1902e56694715cb110ce94Insun Kang // Drop obsolete msg. 162bb6bc8491fe819f96e1902e56694715cb110ce94Insun Kang break; 1636655174826330afe66ef766258181ae8c11f3f6cInsun Kang } 1642f0632f12cd02b0350918720443c888b48f4417bInsun Kang // If current time doesn't reach to the fire time, 1652f0632f12cd02b0350918720443c888b48f4417bInsun Kang // re-post the message with the adjusted delay time. 1662f0632f12cd02b0350918720443c888b48f4417bInsun Kang int64_t fireTimeUs = kInvalidTimeUs; 1672f0632f12cd02b0350918720443c888b48f4417bInsun Kang if (msg->findInt64("fireTimeUs", &fireTimeUs)) { 1682f0632f12cd02b0350918720443c888b48f4417bInsun Kang // TODO: check if fireTimeUs is not kInvalidTimeUs. 1692f0632f12cd02b0350918720443c888b48f4417bInsun Kang int64_t delayUs = delayUsFromCurrentTime(fireTimeUs); 1702f0632f12cd02b0350918720443c888b48f4417bInsun Kang if (delayUs > 0) { 1712f0632f12cd02b0350918720443c888b48f4417bInsun Kang msg->post(delayUs); 1722f0632f12cd02b0350918720443c888b48f4417bInsun Kang break; 1732f0632f12cd02b0350918720443c888b48f4417bInsun Kang } 1742f0632f12cd02b0350918720443c888b48f4417bInsun Kang } 1756655174826330afe66ef766258181ae8c11f3f6cInsun Kang sp<RefBase> obj; 176c4ddeeb06a9defc359e99d1ce20882e1d688d1b3Insun Kang if (msg->findObject("subtitle", &obj)) { 1776655174826330afe66ef766258181ae8c11f3f6cInsun Kang sp<ParcelEvent> parcelEvent; 1786655174826330afe66ef766258181ae8c11f3f6cInsun Kang parcelEvent = static_cast<ParcelEvent*>(obj.get()); 179f9d660a5e0196240add5daf0199f128d471e592cInsun Kang notifyListener(&(parcelEvent->parcel)); 180c4ddeeb06a9defc359e99d1ce20882e1d688d1b3Insun Kang doRead(); 1816655174826330afe66ef766258181ae8c11f3f6cInsun Kang } else { 182f9d660a5e0196240add5daf0199f128d471e592cInsun Kang notifyListener(); 1836655174826330afe66ef766258181ae8c11f3f6cInsun Kang } 1846655174826330afe66ef766258181ae8c11f3f6cInsun Kang break; 1856655174826330afe66ef766258181ae8c11f3f6cInsun Kang } 1866655174826330afe66ef766258181ae8c11f3f6cInsun Kang case kWhatSetSource: { 18723580bb8d6cafbc2b65dd0a4ce1acb52562d1b05Insun Kang mSendSubtitleGeneration++; 1886655174826330afe66ef766258181ae8c11f3f6cInsun Kang sp<RefBase> obj; 1896655174826330afe66ef766258181ae8c11f3f6cInsun Kang msg->findObject("source", &obj); 1906655174826330afe66ef766258181ae8c11f3f6cInsun Kang if (mSource != NULL) { 1916655174826330afe66ef766258181ae8c11f3f6cInsun Kang mSource->stop(); 19223580bb8d6cafbc2b65dd0a4ce1acb52562d1b05Insun Kang mSource.clear(); 19323580bb8d6cafbc2b65dd0a4ce1acb52562d1b05Insun Kang mSource = NULL; 19423580bb8d6cafbc2b65dd0a4ce1acb52562d1b05Insun Kang } 19523580bb8d6cafbc2b65dd0a4ce1acb52562d1b05Insun Kang // null source means deselect track. 19623580bb8d6cafbc2b65dd0a4ce1acb52562d1b05Insun Kang if (obj == NULL) { 19723580bb8d6cafbc2b65dd0a4ce1acb52562d1b05Insun Kang mPendingSeekTimeUs = kInvalidTimeUs; 19823580bb8d6cafbc2b65dd0a4ce1acb52562d1b05Insun Kang mPaused = false; 19923580bb8d6cafbc2b65dd0a4ce1acb52562d1b05Insun Kang notifyListener(); 20023580bb8d6cafbc2b65dd0a4ce1acb52562d1b05Insun Kang break; 2016655174826330afe66ef766258181ae8c11f3f6cInsun Kang } 2026655174826330afe66ef766258181ae8c11f3f6cInsun Kang mSource = static_cast<TimedTextSource*>(obj.get()); 203f9d660a5e0196240add5daf0199f128d471e592cInsun Kang status_t err = mSource->start(); 204f9d660a5e0196240add5daf0199f128d471e592cInsun Kang if (err != OK) { 205f9d660a5e0196240add5daf0199f128d471e592cInsun Kang notifyError(err); 206f9d660a5e0196240add5daf0199f128d471e592cInsun Kang break; 207f9d660a5e0196240add5daf0199f128d471e592cInsun Kang } 2086655174826330afe66ef766258181ae8c11f3f6cInsun Kang Parcel parcel; 209f9d660a5e0196240add5daf0199f128d471e592cInsun Kang err = mSource->extractGlobalDescriptions(&parcel); 210f9d660a5e0196240add5daf0199f128d471e592cInsun Kang if (err != OK) { 211f9d660a5e0196240add5daf0199f128d471e592cInsun Kang notifyError(err); 212f9d660a5e0196240add5daf0199f128d471e592cInsun Kang break; 2136655174826330afe66ef766258181ae8c11f3f6cInsun Kang } 214f9d660a5e0196240add5daf0199f128d471e592cInsun Kang notifyListener(&parcel); 2156655174826330afe66ef766258181ae8c11f3f6cInsun Kang break; 2163b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang } 2177a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang } 2187a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang} 2197a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang 2206655174826330afe66ef766258181ae8c11f3f6cInsun Kangvoid TimedTextPlayer::doSeekAndRead(int64_t seekTimeUs) { 2216655174826330afe66ef766258181ae8c11f3f6cInsun Kang MediaSource::ReadOptions options; 2226655174826330afe66ef766258181ae8c11f3f6cInsun Kang options.setSeekTo(seekTimeUs, MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC); 2236655174826330afe66ef766258181ae8c11f3f6cInsun Kang doRead(&options); 2247a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang} 2257a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang 2266655174826330afe66ef766258181ae8c11f3f6cInsun Kangvoid TimedTextPlayer::doRead(MediaSource::ReadOptions* options) { 227bae00e73c6d1d87cc5fd42b50f95d1d9572162eaInsun Kang int64_t startTimeUs = 0; 228bae00e73c6d1d87cc5fd42b50f95d1d9572162eaInsun Kang int64_t endTimeUs = 0; 2296655174826330afe66ef766258181ae8c11f3f6cInsun Kang sp<ParcelEvent> parcelEvent = new ParcelEvent(); 23023580bb8d6cafbc2b65dd0a4ce1acb52562d1b05Insun Kang CHECK(mSource != NULL); 231bae00e73c6d1d87cc5fd42b50f95d1d9572162eaInsun Kang status_t err = mSource->read(&startTimeUs, &endTimeUs, 232bae00e73c6d1d87cc5fd42b50f95d1d9572162eaInsun Kang &(parcelEvent->parcel), options); 233bae00e73c6d1d87cc5fd42b50f95d1d9572162eaInsun Kang if (err == WOULD_BLOCK) { 2343b963c60693c10276f5ebf5e0abb95f6be78070fInsun Kang sp<AMessage> msg = new AMessage(kWhatRetryRead, id()); 2354e1c91dd07fad96ee2387eda510c6da45e5dff0aInsun Kang if (options != NULL) { 236bb6bc8491fe819f96e1902e56694715cb110ce94Insun Kang int64_t seekTimeUs = kInvalidTimeUs; 237bb6bc8491fe819f96e1902e56694715cb110ce94Insun Kang MediaSource::ReadOptions::SeekMode seekMode = 238bb6bc8491fe819f96e1902e56694715cb110ce94Insun Kang MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC; 2394e1c91dd07fad96ee2387eda510c6da45e5dff0aInsun Kang CHECK(options->getSeekTo(&seekTimeUs, &seekMode)); 2404e1c91dd07fad96ee2387eda510c6da45e5dff0aInsun Kang msg->setInt64("seekTimeUs", seekTimeUs); 2414e1c91dd07fad96ee2387eda510c6da45e5dff0aInsun Kang msg->setInt32("seekMode", seekMode); 2424e1c91dd07fad96ee2387eda510c6da45e5dff0aInsun Kang } 243bb6bc8491fe819f96e1902e56694715cb110ce94Insun Kang msg->setInt32("generation", mSendSubtitleGeneration); 2444e1c91dd07fad96ee2387eda510c6da45e5dff0aInsun Kang msg->post(kWaitTimeUsToRetryRead); 245bae00e73c6d1d87cc5fd42b50f95d1d9572162eaInsun Kang return; 246bae00e73c6d1d87cc5fd42b50f95d1d9572162eaInsun Kang } else if (err != OK) { 247f9d660a5e0196240add5daf0199f128d471e592cInsun Kang notifyError(err); 248bae00e73c6d1d87cc5fd42b50f95d1d9572162eaInsun Kang return; 249bae00e73c6d1d87cc5fd42b50f95d1d9572162eaInsun Kang } 250bae00e73c6d1d87cc5fd42b50f95d1d9572162eaInsun Kang 251bae00e73c6d1d87cc5fd42b50f95d1d9572162eaInsun Kang postTextEvent(parcelEvent, startTimeUs); 252bae00e73c6d1d87cc5fd42b50f95d1d9572162eaInsun Kang if (endTimeUs > 0) { 253bae00e73c6d1d87cc5fd42b50f95d1d9572162eaInsun Kang CHECK_GE(endTimeUs, startTimeUs); 254bae00e73c6d1d87cc5fd42b50f95d1d9572162eaInsun Kang // send an empty timed text to clear the subtitle when it reaches to the 255bae00e73c6d1d87cc5fd42b50f95d1d9572162eaInsun Kang // end time. 256bae00e73c6d1d87cc5fd42b50f95d1d9572162eaInsun Kang postTextEvent(NULL, endTimeUs); 257f9d660a5e0196240add5daf0199f128d471e592cInsun Kang } 2587a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang} 2597a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang 2606655174826330afe66ef766258181ae8c11f3f6cInsun Kangvoid TimedTextPlayer::postTextEvent(const sp<ParcelEvent>& parcel, int64_t timeUs) { 2612f0632f12cd02b0350918720443c888b48f4417bInsun Kang int64_t delayUs = delayUsFromCurrentTime(timeUs); 2626472badc497a9e748411f8c8c9ed5d83ef335a85Insun Kang sp<AMessage> msg = new AMessage(kWhatSendSubtitle, id()); 2636472badc497a9e748411f8c8c9ed5d83ef335a85Insun Kang msg->setInt32("generation", mSendSubtitleGeneration); 2646472badc497a9e748411f8c8c9ed5d83ef335a85Insun Kang if (parcel != NULL) { 2656472badc497a9e748411f8c8c9ed5d83ef335a85Insun Kang msg->setObject("subtitle", parcel); 2667a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang } 2676472badc497a9e748411f8c8c9ed5d83ef335a85Insun Kang msg->setInt64("fireTimeUs", timeUs); 2686472badc497a9e748411f8c8c9ed5d83ef335a85Insun Kang msg->post(delayUs); 2697a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang} 2703b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang 2712f0632f12cd02b0350918720443c888b48f4417bInsun Kangint64_t TimedTextPlayer::delayUsFromCurrentTime(int64_t fireTimeUs) { 2722f0632f12cd02b0350918720443c888b48f4417bInsun Kang sp<MediaPlayerBase> listener = mListener.promote(); 2732f0632f12cd02b0350918720443c888b48f4417bInsun Kang if (listener == NULL) { 2742f0632f12cd02b0350918720443c888b48f4417bInsun Kang // TODO: it may be better to return kInvalidTimeUs 275b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross ALOGE("%s: Listener is NULL. (fireTimeUs = %" PRId64" )", 2763478eaa23c19dbbe473be70e8f3cc0c904d2465cJohn Grossman __FUNCTION__, fireTimeUs); 2772f0632f12cd02b0350918720443c888b48f4417bInsun Kang return 0; 2782f0632f12cd02b0350918720443c888b48f4417bInsun Kang } 2792f0632f12cd02b0350918720443c888b48f4417bInsun Kang int32_t positionMs = 0; 2802f0632f12cd02b0350918720443c888b48f4417bInsun Kang listener->getCurrentPosition(&positionMs); 2812f0632f12cd02b0350918720443c888b48f4417bInsun Kang int64_t positionUs = positionMs * 1000ll; 2822f0632f12cd02b0350918720443c888b48f4417bInsun Kang 2832f0632f12cd02b0350918720443c888b48f4417bInsun Kang if (fireTimeUs <= positionUs + kAdjustmentProcessingTimeUs) { 2842f0632f12cd02b0350918720443c888b48f4417bInsun Kang return 0; 2852f0632f12cd02b0350918720443c888b48f4417bInsun Kang } else { 2862f0632f12cd02b0350918720443c888b48f4417bInsun Kang int64_t delayUs = fireTimeUs - positionUs - kAdjustmentProcessingTimeUs; 2872f0632f12cd02b0350918720443c888b48f4417bInsun Kang if (delayUs > kMaxDelayUs) { 2882f0632f12cd02b0350918720443c888b48f4417bInsun Kang return kMaxDelayUs; 2892f0632f12cd02b0350918720443c888b48f4417bInsun Kang } 2902f0632f12cd02b0350918720443c888b48f4417bInsun Kang return delayUs; 2912f0632f12cd02b0350918720443c888b48f4417bInsun Kang } 2922f0632f12cd02b0350918720443c888b48f4417bInsun Kang} 2932f0632f12cd02b0350918720443c888b48f4417bInsun Kang 294f9d660a5e0196240add5daf0199f128d471e592cInsun Kangvoid TimedTextPlayer::notifyError(int error) { 295f9d660a5e0196240add5daf0199f128d471e592cInsun Kang sp<MediaPlayerBase> listener = mListener.promote(); 2966472badc497a9e748411f8c8c9ed5d83ef335a85Insun Kang if (listener == NULL) { 2976472badc497a9e748411f8c8c9ed5d83ef335a85Insun Kang ALOGE("%s(error=%d): Listener is NULL.", __FUNCTION__, error); 2986472badc497a9e748411f8c8c9ed5d83ef335a85Insun Kang return; 299f9d660a5e0196240add5daf0199f128d471e592cInsun Kang } 3006472badc497a9e748411f8c8c9ed5d83ef335a85Insun Kang listener->sendEvent(MEDIA_INFO, MEDIA_INFO_TIMED_TEXT_ERROR, error); 301f9d660a5e0196240add5daf0199f128d471e592cInsun Kang} 302f9d660a5e0196240add5daf0199f128d471e592cInsun Kang 303f9d660a5e0196240add5daf0199f128d471e592cInsun Kangvoid TimedTextPlayer::notifyListener(const Parcel *parcel) { 3046655174826330afe66ef766258181ae8c11f3f6cInsun Kang sp<MediaPlayerBase> listener = mListener.promote(); 3056472badc497a9e748411f8c8c9ed5d83ef335a85Insun Kang if (listener == NULL) { 3066472badc497a9e748411f8c8c9ed5d83ef335a85Insun Kang ALOGE("%s: Listener is NULL.", __FUNCTION__); 3076472badc497a9e748411f8c8c9ed5d83ef335a85Insun Kang return; 3086472badc497a9e748411f8c8c9ed5d83ef335a85Insun Kang } 3096472badc497a9e748411f8c8c9ed5d83ef335a85Insun Kang if (parcel != NULL && (parcel->dataSize() > 0)) { 3106472badc497a9e748411f8c8c9ed5d83ef335a85Insun Kang listener->sendEvent(MEDIA_TIMED_TEXT, 0, 0, parcel); 3116472badc497a9e748411f8c8c9ed5d83ef335a85Insun Kang } else { // send an empty timed text to clear the screen 3126472badc497a9e748411f8c8c9ed5d83ef335a85Insun Kang listener->sendEvent(MEDIA_TIMED_TEXT); 3133b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang } 3143b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang} 3153b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang 3166655174826330afe66ef766258181ae8c11f3f6cInsun Kang} // namespace android 317