| Andreas Huber | f933441 | 2010-12-15 15:17:42 -0800 | [diff] [blame] | 1 | /* | 
 | 2 |  * Copyright (C) 2010 The Android Open Source Project | 
 | 3 |  * | 
 | 4 |  * Licensed under the Apache License, Version 2.0 (the "License"); | 
 | 5 |  * you may not use this file except in compliance with the License. | 
 | 6 |  * You may obtain a copy of the License at | 
 | 7 |  * | 
 | 8 |  *      http://www.apache.org/licenses/LICENSE-2.0 | 
 | 9 |  * | 
 | 10 |  * Unless required by applicable law or agreed to in writing, software | 
 | 11 |  * distributed under the License is distributed on an "AS IS" BASIS, | 
 | 12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
 | 13 |  * See the License for the specific language governing permissions and | 
 | 14 |  * limitations under the License. | 
 | 15 |  */ | 
 | 16 |  | 
 | 17 | //#define LOG_NDEBUG 0 | 
 | 18 | #define LOG_TAG "NuPlayer" | 
 | 19 | #include <utils/Log.h> | 
 | 20 |  | 
 | 21 | #include "NuPlayer.h" | 
| Andreas Huber | 5bc087c | 2010-12-23 10:27:40 -0800 | [diff] [blame] | 22 |  | 
 | 23 | #include "HTTPLiveSource.h" | 
| Chong Zhang | 7137ec7 | 2014-11-12 16:41:05 -0800 | [diff] [blame] | 24 | #include "NuPlayerCCDecoder.h" | 
| Andreas Huber | f933441 | 2010-12-15 15:17:42 -0800 | [diff] [blame] | 25 | #include "NuPlayerDecoder.h" | 
| Chong Zhang | 7137ec7 | 2014-11-12 16:41:05 -0800 | [diff] [blame] | 26 | #include "NuPlayerDecoderBase.h" | 
| Wei Jia | bc2fb72 | 2014-07-08 16:37:57 -0700 | [diff] [blame] | 27 | #include "NuPlayerDecoderPassThrough.h" | 
| Andreas Huber | 43c3e6c | 2011-01-05 12:17:08 -0800 | [diff] [blame] | 28 | #include "NuPlayerDriver.h" | 
| Andreas Huber | f933441 | 2010-12-15 15:17:42 -0800 | [diff] [blame] | 29 | #include "NuPlayerRenderer.h" | 
| Andreas Huber | 5bc087c | 2010-12-23 10:27:40 -0800 | [diff] [blame] | 30 | #include "NuPlayerSource.h" | 
| Andreas Huber | 2bfdd42 | 2011-10-11 15:24:07 -0700 | [diff] [blame] | 31 | #include "RTSPSource.h" | 
| Andreas Huber | 5bc087c | 2010-12-23 10:27:40 -0800 | [diff] [blame] | 32 | #include "StreamingSource.h" | 
| Andreas Huber | afed0e1 | 2011-09-20 15:39:58 -0700 | [diff] [blame] | 33 | #include "GenericSource.h" | 
| Robert Shih | d3b0bbb | 2014-07-23 15:00:25 -0700 | [diff] [blame] | 34 | #include "TextDescriptions.h" | 
| Andreas Huber | 5bc087c | 2010-12-23 10:27:40 -0800 | [diff] [blame] | 35 |  | 
 | 36 | #include "ATSParser.h" | 
| Andreas Huber | f933441 | 2010-12-15 15:17:42 -0800 | [diff] [blame] | 37 |  | 
| Lajos Molnar | d9fd631 | 2014-11-06 11:00:00 -0800 | [diff] [blame] | 38 | #include <cutils/properties.h> | 
 | 39 |  | 
| Lajos Molnar | 3a474aa | 2015-04-24 17:10:07 -0700 | [diff] [blame] | 40 | #include <media/AudioResamplerPublic.h> | 
 | 41 | #include <media/AVSyncSettings.h> | 
 | 42 |  | 
| Andreas Huber | 3831a06 | 2010-12-21 10:22:33 -0800 | [diff] [blame] | 43 | #include <media/stagefright/foundation/hexdump.h> | 
| Andreas Huber | f933441 | 2010-12-15 15:17:42 -0800 | [diff] [blame] | 44 | #include <media/stagefright/foundation/ABuffer.h> | 
 | 45 | #include <media/stagefright/foundation/ADebug.h> | 
 | 46 | #include <media/stagefright/foundation/AMessage.h> | 
| Lajos Molnar | 0952483 | 2014-07-17 14:29:51 -0700 | [diff] [blame] | 47 | #include <media/stagefright/MediaBuffer.h> | 
| Andreas Huber | 3fe6215 | 2011-09-16 15:09:22 -0700 | [diff] [blame] | 48 | #include <media/stagefright/MediaDefs.h> | 
| Andreas Huber | f933441 | 2010-12-15 15:17:42 -0800 | [diff] [blame] | 49 | #include <media/stagefright/MediaErrors.h> | 
 | 50 | #include <media/stagefright/MetaData.h> | 
| Lajos Molnar | 1de1e25 | 2015-04-30 18:18:34 -0700 | [diff] [blame] | 51 |  | 
| Andy McFadden | 8ba0102 | 2012-12-18 09:46:54 -0800 | [diff] [blame] | 52 | #include <gui/IGraphicBufferProducer.h> | 
| Lajos Molnar | 1de1e25 | 2015-04-30 18:18:34 -0700 | [diff] [blame] | 53 | #include <gui/Surface.h> | 
| Andreas Huber | f933441 | 2010-12-15 15:17:42 -0800 | [diff] [blame] | 54 |  | 
| Andreas Huber | 3fe6215 | 2011-09-16 15:09:22 -0700 | [diff] [blame] | 55 | #include "avc_utils.h" | 
 | 56 |  | 
| Andreas Huber | 8406678 | 2011-08-16 09:34:26 -0700 | [diff] [blame] | 57 | #include "ESDS.h" | 
 | 58 | #include <media/stagefright/Utils.h> | 
 | 59 |  | 
| Andreas Huber | f933441 | 2010-12-15 15:17:42 -0800 | [diff] [blame] | 60 | namespace android { | 
 | 61 |  | 
| Andreas Huber | a1f8ab0 | 2012-11-30 10:53:22 -0800 | [diff] [blame] | 62 | struct NuPlayer::Action : public RefBase { | 
 | 63 |     Action() {} | 
 | 64 |  | 
 | 65 |     virtual void execute(NuPlayer *player) = 0; | 
 | 66 |  | 
 | 67 | private: | 
 | 68 |     DISALLOW_EVIL_CONSTRUCTORS(Action); | 
 | 69 | }; | 
 | 70 |  | 
 | 71 | struct NuPlayer::SeekAction : public Action { | 
| Wei Jia | 2984080 | 2015-05-15 17:11:38 -0700 | [diff] [blame] | 72 |     SeekAction(int64_t seekTimeUs) | 
 | 73 |         : mSeekTimeUs(seekTimeUs) { | 
| Andreas Huber | a1f8ab0 | 2012-11-30 10:53:22 -0800 | [diff] [blame] | 74 |     } | 
 | 75 |  | 
 | 76 |     virtual void execute(NuPlayer *player) { | 
| Wei Jia | 2984080 | 2015-05-15 17:11:38 -0700 | [diff] [blame] | 77 |         player->performSeek(mSeekTimeUs); | 
| Andreas Huber | a1f8ab0 | 2012-11-30 10:53:22 -0800 | [diff] [blame] | 78 |     } | 
 | 79 |  | 
 | 80 | private: | 
 | 81 |     int64_t mSeekTimeUs; | 
 | 82 |  | 
 | 83 |     DISALLOW_EVIL_CONSTRUCTORS(SeekAction); | 
 | 84 | }; | 
 | 85 |  | 
| Chong Zhang | f8d7177 | 2014-11-26 15:08:34 -0800 | [diff] [blame] | 86 | struct NuPlayer::ResumeDecoderAction : public Action { | 
 | 87 |     ResumeDecoderAction(bool needNotify) | 
 | 88 |         : mNeedNotify(needNotify) { | 
 | 89 |     } | 
 | 90 |  | 
 | 91 |     virtual void execute(NuPlayer *player) { | 
 | 92 |         player->performResumeDecoders(mNeedNotify); | 
 | 93 |     } | 
 | 94 |  | 
 | 95 | private: | 
 | 96 |     bool mNeedNotify; | 
 | 97 |  | 
 | 98 |     DISALLOW_EVIL_CONSTRUCTORS(ResumeDecoderAction); | 
 | 99 | }; | 
 | 100 |  | 
| Andreas Huber | 57a339c | 2012-12-03 11:18:00 -0800 | [diff] [blame] | 101 | struct NuPlayer::SetSurfaceAction : public Action { | 
| Lajos Molnar | 1de1e25 | 2015-04-30 18:18:34 -0700 | [diff] [blame] | 102 |     SetSurfaceAction(const sp<Surface> &surface) | 
 | 103 |         : mSurface(surface) { | 
| Andreas Huber | 57a339c | 2012-12-03 11:18:00 -0800 | [diff] [blame] | 104 |     } | 
 | 105 |  | 
 | 106 |     virtual void execute(NuPlayer *player) { | 
| Lajos Molnar | 1de1e25 | 2015-04-30 18:18:34 -0700 | [diff] [blame] | 107 |         player->performSetSurface(mSurface); | 
| Andreas Huber | 57a339c | 2012-12-03 11:18:00 -0800 | [diff] [blame] | 108 |     } | 
 | 109 |  | 
 | 110 | private: | 
| Lajos Molnar | 1de1e25 | 2015-04-30 18:18:34 -0700 | [diff] [blame] | 111 |     sp<Surface> mSurface; | 
| Andreas Huber | 57a339c | 2012-12-03 11:18:00 -0800 | [diff] [blame] | 112 |  | 
 | 113 |     DISALLOW_EVIL_CONSTRUCTORS(SetSurfaceAction); | 
 | 114 | }; | 
 | 115 |  | 
| Wei Jia | fef808d | 2014-10-31 17:57:05 -0700 | [diff] [blame] | 116 | struct NuPlayer::FlushDecoderAction : public Action { | 
 | 117 |     FlushDecoderAction(FlushCommand audio, FlushCommand video) | 
| Andreas Huber | 14f7672 | 2013-01-15 09:04:18 -0800 | [diff] [blame] | 118 |         : mAudio(audio), | 
 | 119 |           mVideo(video) { | 
 | 120 |     } | 
 | 121 |  | 
 | 122 |     virtual void execute(NuPlayer *player) { | 
| Wei Jia | fef808d | 2014-10-31 17:57:05 -0700 | [diff] [blame] | 123 |         player->performDecoderFlush(mAudio, mVideo); | 
| Andreas Huber | 14f7672 | 2013-01-15 09:04:18 -0800 | [diff] [blame] | 124 |     } | 
 | 125 |  | 
 | 126 | private: | 
| Wei Jia | fef808d | 2014-10-31 17:57:05 -0700 | [diff] [blame] | 127 |     FlushCommand mAudio; | 
 | 128 |     FlushCommand mVideo; | 
| Andreas Huber | 14f7672 | 2013-01-15 09:04:18 -0800 | [diff] [blame] | 129 |  | 
| Wei Jia | fef808d | 2014-10-31 17:57:05 -0700 | [diff] [blame] | 130 |     DISALLOW_EVIL_CONSTRUCTORS(FlushDecoderAction); | 
| Andreas Huber | 14f7672 | 2013-01-15 09:04:18 -0800 | [diff] [blame] | 131 | }; | 
 | 132 |  | 
 | 133 | struct NuPlayer::PostMessageAction : public Action { | 
 | 134 |     PostMessageAction(const sp<AMessage> &msg) | 
 | 135 |         : mMessage(msg) { | 
 | 136 |     } | 
 | 137 |  | 
 | 138 |     virtual void execute(NuPlayer *) { | 
 | 139 |         mMessage->post(); | 
 | 140 |     } | 
 | 141 |  | 
 | 142 | private: | 
 | 143 |     sp<AMessage> mMessage; | 
 | 144 |  | 
 | 145 |     DISALLOW_EVIL_CONSTRUCTORS(PostMessageAction); | 
 | 146 | }; | 
 | 147 |  | 
| Andreas Huber | a1f8ab0 | 2012-11-30 10:53:22 -0800 | [diff] [blame] | 148 | // Use this if there's no state necessary to save in order to execute | 
 | 149 | // the action. | 
 | 150 | struct NuPlayer::SimpleAction : public Action { | 
 | 151 |     typedef void (NuPlayer::*ActionFunc)(); | 
 | 152 |  | 
 | 153 |     SimpleAction(ActionFunc func) | 
 | 154 |         : mFunc(func) { | 
 | 155 |     } | 
 | 156 |  | 
 | 157 |     virtual void execute(NuPlayer *player) { | 
 | 158 |         (player->*mFunc)(); | 
 | 159 |     } | 
 | 160 |  | 
 | 161 | private: | 
 | 162 |     ActionFunc mFunc; | 
 | 163 |  | 
 | 164 |     DISALLOW_EVIL_CONSTRUCTORS(SimpleAction); | 
 | 165 | }; | 
 | 166 |  | 
| Andreas Huber | f933441 | 2010-12-15 15:17:42 -0800 | [diff] [blame] | 167 | //////////////////////////////////////////////////////////////////////////////// | 
 | 168 |  | 
| Ronghua Wu | 68845c1 | 2015-07-21 09:50:48 -0700 | [diff] [blame] | 169 | NuPlayer::NuPlayer(pid_t pid) | 
| Andreas Huber | 9b80c2b | 2011-06-30 15:47:02 -0700 | [diff] [blame] | 170 |     : mUIDValid(false), | 
| Ronghua Wu | 68845c1 | 2015-07-21 09:50:48 -0700 | [diff] [blame] | 171 |       mPID(pid), | 
| Andreas Huber | 9575c96 | 2013-02-05 13:59:56 -0800 | [diff] [blame] | 172 |       mSourceFlags(0), | 
| Wei Jia | bc2fb72 | 2014-07-08 16:37:57 -0700 | [diff] [blame] | 173 |       mOffloadAudio(false), | 
| Wei Jia | 88703c3 | 2014-08-06 11:24:07 -0700 | [diff] [blame] | 174 |       mAudioDecoderGeneration(0), | 
 | 175 |       mVideoDecoderGeneration(0), | 
| Wei Jia | 57568df | 2014-09-22 10:16:29 -0700 | [diff] [blame] | 176 |       mRendererGeneration(0), | 
| Robert Shih | 1a5c859 | 2015-08-04 18:07:44 -0700 | [diff] [blame] | 177 |       mPreviousSeekTimeUs(0), | 
| Andreas Huber | 9b80c2b | 2011-06-30 15:47:02 -0700 | [diff] [blame] | 178 |       mAudioEOS(false), | 
| Andreas Huber | f933441 | 2010-12-15 15:17:42 -0800 | [diff] [blame] | 179 |       mVideoEOS(false), | 
| Andreas Huber | 5bc087c | 2010-12-23 10:27:40 -0800 | [diff] [blame] | 180 |       mScanSourcesPending(false), | 
| Andreas Huber | 1aef211 | 2011-01-04 14:01:29 -0800 | [diff] [blame] | 181 |       mScanSourcesGeneration(0), | 
| Andreas Huber | b7c8e91 | 2012-11-27 15:02:53 -0800 | [diff] [blame] | 182 |       mPollDurationGeneration(0), | 
| Robert Shih | d3b0bbb | 2014-07-23 15:00:25 -0700 | [diff] [blame] | 183 |       mTimedTextGeneration(0), | 
| Andreas Huber | f933441 | 2010-12-15 15:17:42 -0800 | [diff] [blame] | 184 |       mFlushingAudio(NONE), | 
| Andreas Huber | 1aef211 | 2011-01-04 14:01:29 -0800 | [diff] [blame] | 185 |       mFlushingVideo(NONE), | 
| Chong Zhang | f8d7177 | 2014-11-26 15:08:34 -0800 | [diff] [blame] | 186 |       mResumePending(false), | 
| Andreas Huber | 57a339c | 2012-12-03 11:18:00 -0800 | [diff] [blame] | 187 |       mVideoScalingMode(NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW), | 
| Lajos Molnar | 3a474aa | 2015-04-24 17:10:07 -0700 | [diff] [blame] | 188 |       mPlaybackSettings(AUDIO_PLAYBACK_RATE_DEFAULT), | 
 | 189 |       mVideoFpsHint(-1.f), | 
| Chong Zhang | efbb619 | 2015-01-30 17:13:27 -0800 | [diff] [blame] | 190 |       mStarted(false), | 
| Ronghua Wu | 64c2d17 | 2015-10-07 16:52:19 -0700 | [diff] [blame] | 191 |       mResetting(false), | 
| Robert Shih | 0c61a0d | 2015-07-06 15:09:10 -0700 | [diff] [blame] | 192 |       mSourceStarted(false), | 
| Chong Zhang | efbb619 | 2015-01-30 17:13:27 -0800 | [diff] [blame] | 193 |       mPaused(false), | 
| Wei Jia | 71c75e0 | 2016-02-04 09:40:47 -0800 | [diff] [blame] | 194 |       mPausedByClient(true), | 
 | 195 |       mPendingBufferingFlag(PENDING_BUFFERING_FLAG_NONE), | 
| Chong Zhang | 8a04833 | 2015-05-06 15:16:28 -0700 | [diff] [blame] | 196 |       mPausedForBuffering(false) { | 
| Andy Hung | 8d121d4 | 2014-10-03 09:53:53 -0700 | [diff] [blame] | 197 |     clearFlushComplete(); | 
| Andreas Huber | f933441 | 2010-12-15 15:17:42 -0800 | [diff] [blame] | 198 | } | 
 | 199 |  | 
 | 200 | NuPlayer::~NuPlayer() { | 
 | 201 | } | 
 | 202 |  | 
| Andreas Huber | 9b80c2b | 2011-06-30 15:47:02 -0700 | [diff] [blame] | 203 | void NuPlayer::setUID(uid_t uid) { | 
 | 204 |     mUIDValid = true; | 
 | 205 |     mUID = uid; | 
 | 206 | } | 
 | 207 |  | 
| Andreas Huber | 43c3e6c | 2011-01-05 12:17:08 -0800 | [diff] [blame] | 208 | void NuPlayer::setDriver(const wp<NuPlayerDriver> &driver) { | 
 | 209 |     mDriver = driver; | 
| Andreas Huber | f933441 | 2010-12-15 15:17:42 -0800 | [diff] [blame] | 210 | } | 
 | 211 |  | 
| Andreas Huber | 9575c96 | 2013-02-05 13:59:56 -0800 | [diff] [blame] | 212 | void NuPlayer::setDataSourceAsync(const sp<IStreamSource> &source) { | 
| Lajos Molnar | 1d15ab5 | 2015-03-04 16:46:34 -0800 | [diff] [blame] | 213 |     sp<AMessage> msg = new AMessage(kWhatSetDataSource, this); | 
| Andreas Huber | f933441 | 2010-12-15 15:17:42 -0800 | [diff] [blame] | 214 |  | 
| Lajos Molnar | 1d15ab5 | 2015-03-04 16:46:34 -0800 | [diff] [blame] | 215 |     sp<AMessage> notify = new AMessage(kWhatSourceNotify, this); | 
| Andreas Huber | b5f25f0 | 2013-02-05 10:14:26 -0800 | [diff] [blame] | 216 |  | 
| Andreas Huber | 240abcc | 2014-02-13 13:32:37 -0800 | [diff] [blame] | 217 |     msg->setObject("source", new StreamingSource(notify, source)); | 
| Andreas Huber | 5bc087c | 2010-12-23 10:27:40 -0800 | [diff] [blame] | 218 |     msg->post(); | 
 | 219 | } | 
| Andreas Huber | f933441 | 2010-12-15 15:17:42 -0800 | [diff] [blame] | 220 |  | 
| Andreas Huber | afed0e1 | 2011-09-20 15:39:58 -0700 | [diff] [blame] | 221 | static bool IsHTTPLiveURL(const char *url) { | 
 | 222 |     if (!strncasecmp("http://", url, 7) | 
| Andreas Huber | 9975940 | 2013-04-01 14:28:31 -0700 | [diff] [blame] | 223 |             || !strncasecmp("https://", url, 8) | 
 | 224 |             || !strncasecmp("file://", url, 7)) { | 
| Andreas Huber | afed0e1 | 2011-09-20 15:39:58 -0700 | [diff] [blame] | 225 |         size_t len = strlen(url); | 
 | 226 |         if (len >= 5 && !strcasecmp(".m3u8", &url[len - 5])) { | 
 | 227 |             return true; | 
 | 228 |         } | 
 | 229 |  | 
 | 230 |         if (strstr(url,"m3u8")) { | 
 | 231 |             return true; | 
 | 232 |         } | 
 | 233 |     } | 
 | 234 |  | 
 | 235 |     return false; | 
 | 236 | } | 
 | 237 |  | 
| Andreas Huber | 9575c96 | 2013-02-05 13:59:56 -0800 | [diff] [blame] | 238 | void NuPlayer::setDataSourceAsync( | 
| Andreas Huber | 1b86fe0 | 2014-01-29 11:13:26 -0800 | [diff] [blame] | 239 |         const sp<IMediaHTTPService> &httpService, | 
 | 240 |         const char *url, | 
 | 241 |         const KeyedVector<String8, String8> *headers) { | 
| Chong Zhang | 3de157d | 2014-08-05 20:54:44 -0700 | [diff] [blame] | 242 |  | 
| Lajos Molnar | 1d15ab5 | 2015-03-04 16:46:34 -0800 | [diff] [blame] | 243 |     sp<AMessage> msg = new AMessage(kWhatSetDataSource, this); | 
| Oscar Rydhé | 7a33b77 | 2012-02-20 10:15:48 +0100 | [diff] [blame] | 244 |     size_t len = strlen(url); | 
| Andreas Huber | 5bc087c | 2010-12-23 10:27:40 -0800 | [diff] [blame] | 245 |  | 
| Lajos Molnar | 1d15ab5 | 2015-03-04 16:46:34 -0800 | [diff] [blame] | 246 |     sp<AMessage> notify = new AMessage(kWhatSourceNotify, this); | 
| Andreas Huber | b5f25f0 | 2013-02-05 10:14:26 -0800 | [diff] [blame] | 247 |  | 
| Andreas Huber | afed0e1 | 2011-09-20 15:39:58 -0700 | [diff] [blame] | 248 |     sp<Source> source; | 
 | 249 |     if (IsHTTPLiveURL(url)) { | 
| Andreas Huber | 81e6844 | 2014-02-05 11:52:33 -0800 | [diff] [blame] | 250 |         source = new HTTPLiveSource(notify, httpService, url, headers); | 
| Andreas Huber | afed0e1 | 2011-09-20 15:39:58 -0700 | [diff] [blame] | 251 |     } else if (!strncasecmp(url, "rtsp://", 7)) { | 
| Andreas Huber | 1b86fe0 | 2014-01-29 11:13:26 -0800 | [diff] [blame] | 252 |         source = new RTSPSource( | 
 | 253 |                 notify, httpService, url, headers, mUIDValid, mUID); | 
| Oscar Rydhé | 7a33b77 | 2012-02-20 10:15:48 +0100 | [diff] [blame] | 254 |     } else if ((!strncasecmp(url, "http://", 7) | 
 | 255 |                 || !strncasecmp(url, "https://", 8)) | 
 | 256 |                     && ((len >= 4 && !strcasecmp(".sdp", &url[len - 4])) | 
 | 257 |                     || strstr(url, ".sdp?"))) { | 
| Andreas Huber | 1b86fe0 | 2014-01-29 11:13:26 -0800 | [diff] [blame] | 258 |         source = new RTSPSource( | 
 | 259 |                 notify, httpService, url, headers, mUIDValid, mUID, true); | 
| Andreas Huber | 2bfdd42 | 2011-10-11 15:24:07 -0700 | [diff] [blame] | 260 |     } else { | 
| Chong Zhang | 3de157d | 2014-08-05 20:54:44 -0700 | [diff] [blame] | 261 |         sp<GenericSource> genericSource = | 
 | 262 |                 new GenericSource(notify, mUIDValid, mUID); | 
 | 263 |         // Don't set FLAG_SECURE on mSourceFlags here for widevine. | 
 | 264 |         // The correct flags will be updated in Source::kWhatFlagsChanged | 
 | 265 |         // handler when  GenericSource is prepared. | 
| Andreas Huber | 2bfdd42 | 2011-10-11 15:24:07 -0700 | [diff] [blame] | 266 |  | 
| Chong Zhang | a19f33e | 2014-08-07 15:35:07 -0700 | [diff] [blame] | 267 |         status_t err = genericSource->setDataSource(httpService, url, headers); | 
| Chong Zhang | 3de157d | 2014-08-05 20:54:44 -0700 | [diff] [blame] | 268 |  | 
 | 269 |         if (err == OK) { | 
 | 270 |             source = genericSource; | 
 | 271 |         } else { | 
| Chong Zhang | a19f33e | 2014-08-07 15:35:07 -0700 | [diff] [blame] | 272 |             ALOGE("Failed to set data source!"); | 
| Chong Zhang | 3de157d | 2014-08-05 20:54:44 -0700 | [diff] [blame] | 273 |         } | 
 | 274 |     } | 
| Andreas Huber | afed0e1 | 2011-09-20 15:39:58 -0700 | [diff] [blame] | 275 |     msg->setObject("source", source); | 
 | 276 |     msg->post(); | 
 | 277 | } | 
 | 278 |  | 
| Andreas Huber | 9575c96 | 2013-02-05 13:59:56 -0800 | [diff] [blame] | 279 | void NuPlayer::setDataSourceAsync(int fd, int64_t offset, int64_t length) { | 
| Lajos Molnar | 1d15ab5 | 2015-03-04 16:46:34 -0800 | [diff] [blame] | 280 |     sp<AMessage> msg = new AMessage(kWhatSetDataSource, this); | 
| Andreas Huber | afed0e1 | 2011-09-20 15:39:58 -0700 | [diff] [blame] | 281 |  | 
| Lajos Molnar | 1d15ab5 | 2015-03-04 16:46:34 -0800 | [diff] [blame] | 282 |     sp<AMessage> notify = new AMessage(kWhatSourceNotify, this); | 
| Andreas Huber | b5f25f0 | 2013-02-05 10:14:26 -0800 | [diff] [blame] | 283 |  | 
| Chong Zhang | 3de157d | 2014-08-05 20:54:44 -0700 | [diff] [blame] | 284 |     sp<GenericSource> source = | 
 | 285 |             new GenericSource(notify, mUIDValid, mUID); | 
 | 286 |  | 
| Chong Zhang | a19f33e | 2014-08-07 15:35:07 -0700 | [diff] [blame] | 287 |     status_t err = source->setDataSource(fd, offset, length); | 
| Chong Zhang | 3de157d | 2014-08-05 20:54:44 -0700 | [diff] [blame] | 288 |  | 
 | 289 |     if (err != OK) { | 
| Chong Zhang | a19f33e | 2014-08-07 15:35:07 -0700 | [diff] [blame] | 290 |         ALOGE("Failed to set data source!"); | 
| Chong Zhang | 3de157d | 2014-08-05 20:54:44 -0700 | [diff] [blame] | 291 |         source = NULL; | 
 | 292 |     } | 
 | 293 |  | 
| Andreas Huber | afed0e1 | 2011-09-20 15:39:58 -0700 | [diff] [blame] | 294 |     msg->setObject("source", source); | 
| Andreas Huber | f933441 | 2010-12-15 15:17:42 -0800 | [diff] [blame] | 295 |     msg->post(); | 
 | 296 | } | 
 | 297 |  | 
| Chris Watkins | 99f3160 | 2015-03-20 13:06:33 -0700 | [diff] [blame] | 298 | void NuPlayer::setDataSourceAsync(const sp<DataSource> &dataSource) { | 
 | 299 |     sp<AMessage> msg = new AMessage(kWhatSetDataSource, this); | 
 | 300 |     sp<AMessage> notify = new AMessage(kWhatSourceNotify, this); | 
 | 301 |  | 
 | 302 |     sp<GenericSource> source = new GenericSource(notify, mUIDValid, mUID); | 
 | 303 |     status_t err = source->setDataSource(dataSource); | 
 | 304 |  | 
 | 305 |     if (err != OK) { | 
 | 306 |         ALOGE("Failed to set data source!"); | 
 | 307 |         source = NULL; | 
 | 308 |     } | 
 | 309 |  | 
 | 310 |     msg->setObject("source", source); | 
 | 311 |     msg->post(); | 
 | 312 | } | 
 | 313 |  | 
| Andreas Huber | 9575c96 | 2013-02-05 13:59:56 -0800 | [diff] [blame] | 314 | void NuPlayer::prepareAsync() { | 
| Lajos Molnar | 1d15ab5 | 2015-03-04 16:46:34 -0800 | [diff] [blame] | 315 |     (new AMessage(kWhatPrepare, this))->post(); | 
| Andreas Huber | 9575c96 | 2013-02-05 13:59:56 -0800 | [diff] [blame] | 316 | } | 
 | 317 |  | 
| Andreas Huber | 57a339c | 2012-12-03 11:18:00 -0800 | [diff] [blame] | 318 | void NuPlayer::setVideoSurfaceTextureAsync( | 
| Andy McFadden | 8ba0102 | 2012-12-18 09:46:54 -0800 | [diff] [blame] | 319 |         const sp<IGraphicBufferProducer> &bufferProducer) { | 
| Lajos Molnar | 1de1e25 | 2015-04-30 18:18:34 -0700 | [diff] [blame] | 320 |     sp<AMessage> msg = new AMessage(kWhatSetVideoSurface, this); | 
| Andreas Huber | 57a339c | 2012-12-03 11:18:00 -0800 | [diff] [blame] | 321 |  | 
| Andy McFadden | 8ba0102 | 2012-12-18 09:46:54 -0800 | [diff] [blame] | 322 |     if (bufferProducer == NULL) { | 
| Lajos Molnar | 1de1e25 | 2015-04-30 18:18:34 -0700 | [diff] [blame] | 323 |         msg->setObject("surface", NULL); | 
| Andreas Huber | 57a339c | 2012-12-03 11:18:00 -0800 | [diff] [blame] | 324 |     } else { | 
| Lajos Molnar | 1de1e25 | 2015-04-30 18:18:34 -0700 | [diff] [blame] | 325 |         msg->setObject("surface", new Surface(bufferProducer, true /* controlledByApp */)); | 
| Andreas Huber | 57a339c | 2012-12-03 11:18:00 -0800 | [diff] [blame] | 326 |     } | 
 | 327 |  | 
| Andreas Huber | f933441 | 2010-12-15 15:17:42 -0800 | [diff] [blame] | 328 |     msg->post(); | 
 | 329 | } | 
 | 330 |  | 
 | 331 | void NuPlayer::setAudioSink(const sp<MediaPlayerBase::AudioSink> &sink) { | 
| Lajos Molnar | 1d15ab5 | 2015-03-04 16:46:34 -0800 | [diff] [blame] | 332 |     sp<AMessage> msg = new AMessage(kWhatSetAudioSink, this); | 
| Andreas Huber | f933441 | 2010-12-15 15:17:42 -0800 | [diff] [blame] | 333 |     msg->setObject("sink", sink); | 
 | 334 |     msg->post(); | 
 | 335 | } | 
 | 336 |  | 
 | 337 | void NuPlayer::start() { | 
| Lajos Molnar | 1d15ab5 | 2015-03-04 16:46:34 -0800 | [diff] [blame] | 338 |     (new AMessage(kWhatStart, this))->post(); | 
| Andreas Huber | f933441 | 2010-12-15 15:17:42 -0800 | [diff] [blame] | 339 | } | 
 | 340 |  | 
| Lajos Molnar | 3a474aa | 2015-04-24 17:10:07 -0700 | [diff] [blame] | 341 | status_t NuPlayer::setPlaybackSettings(const AudioPlaybackRate &rate) { | 
 | 342 |     // do some cursory validation of the settings here. audio modes are | 
 | 343 |     // only validated when set on the audiosink. | 
 | 344 |      if ((rate.mSpeed != 0.f && rate.mSpeed < AUDIO_TIMESTRETCH_SPEED_MIN) | 
 | 345 |             || rate.mSpeed > AUDIO_TIMESTRETCH_SPEED_MAX | 
 | 346 |             || rate.mPitch < AUDIO_TIMESTRETCH_SPEED_MIN | 
 | 347 |             || rate.mPitch > AUDIO_TIMESTRETCH_SPEED_MAX) { | 
 | 348 |         return BAD_VALUE; | 
 | 349 |     } | 
 | 350 |     sp<AMessage> msg = new AMessage(kWhatConfigPlayback, this); | 
 | 351 |     writeToAMessage(msg, rate); | 
 | 352 |     sp<AMessage> response; | 
 | 353 |     status_t err = msg->postAndAwaitResponse(&response); | 
 | 354 |     if (err == OK && response != NULL) { | 
 | 355 |         CHECK(response->findInt32("err", &err)); | 
 | 356 |     } | 
 | 357 |     return err; | 
 | 358 | } | 
 | 359 |  | 
 | 360 | status_t NuPlayer::getPlaybackSettings(AudioPlaybackRate *rate /* nonnull */) { | 
 | 361 |     sp<AMessage> msg = new AMessage(kWhatGetPlaybackSettings, this); | 
 | 362 |     sp<AMessage> response; | 
 | 363 |     status_t err = msg->postAndAwaitResponse(&response); | 
 | 364 |     if (err == OK && response != NULL) { | 
 | 365 |         CHECK(response->findInt32("err", &err)); | 
 | 366 |         if (err == OK) { | 
 | 367 |             readFromAMessage(response, rate); | 
 | 368 |         } | 
 | 369 |     } | 
 | 370 |     return err; | 
 | 371 | } | 
 | 372 |  | 
 | 373 | status_t NuPlayer::setSyncSettings(const AVSyncSettings &sync, float videoFpsHint) { | 
 | 374 |     sp<AMessage> msg = new AMessage(kWhatConfigSync, this); | 
 | 375 |     writeToAMessage(msg, sync, videoFpsHint); | 
 | 376 |     sp<AMessage> response; | 
 | 377 |     status_t err = msg->postAndAwaitResponse(&response); | 
 | 378 |     if (err == OK && response != NULL) { | 
 | 379 |         CHECK(response->findInt32("err", &err)); | 
 | 380 |     } | 
 | 381 |     return err; | 
 | 382 | } | 
 | 383 |  | 
 | 384 | status_t NuPlayer::getSyncSettings( | 
 | 385 |         AVSyncSettings *sync /* nonnull */, float *videoFps /* nonnull */) { | 
 | 386 |     sp<AMessage> msg = new AMessage(kWhatGetSyncSettings, this); | 
 | 387 |     sp<AMessage> response; | 
 | 388 |     status_t err = msg->postAndAwaitResponse(&response); | 
 | 389 |     if (err == OK && response != NULL) { | 
 | 390 |         CHECK(response->findInt32("err", &err)); | 
 | 391 |         if (err == OK) { | 
 | 392 |             readFromAMessage(response, sync, videoFps); | 
 | 393 |         } | 
 | 394 |     } | 
 | 395 |     return err; | 
| Wei Jia | 9816016 | 2015-02-04 17:01:11 -0800 | [diff] [blame] | 396 | } | 
 | 397 |  | 
| Andreas Huber | 43c3e6c | 2011-01-05 12:17:08 -0800 | [diff] [blame] | 398 | void NuPlayer::pause() { | 
| Lajos Molnar | 1d15ab5 | 2015-03-04 16:46:34 -0800 | [diff] [blame] | 399 |     (new AMessage(kWhatPause, this))->post(); | 
| Andreas Huber | 43c3e6c | 2011-01-05 12:17:08 -0800 | [diff] [blame] | 400 | } | 
 | 401 |  | 
| Andreas Huber | 1aef211 | 2011-01-04 14:01:29 -0800 | [diff] [blame] | 402 | void NuPlayer::resetAsync() { | 
| Wei Jia | c45a4b2 | 2016-04-15 15:30:23 -0700 | [diff] [blame] | 403 |     sp<Source> source; | 
 | 404 |     { | 
 | 405 |         Mutex::Autolock autoLock(mSourceLock); | 
 | 406 |         source = mSource; | 
 | 407 |     } | 
 | 408 |  | 
 | 409 |     if (source != NULL) { | 
| Chong Zhang | 48296b7 | 2014-09-14 14:28:45 -0700 | [diff] [blame] | 410 |         // During a reset, the data source might be unresponsive already, we need to | 
 | 411 |         // disconnect explicitly so that reads exit promptly. | 
 | 412 |         // We can't queue the disconnect request to the looper, as it might be | 
 | 413 |         // queued behind a stuck read and never gets processed. | 
 | 414 |         // Doing a disconnect outside the looper to allows the pending reads to exit | 
 | 415 |         // (either successfully or with error). | 
| Wei Jia | c45a4b2 | 2016-04-15 15:30:23 -0700 | [diff] [blame] | 416 |         source->disconnect(); | 
| Chong Zhang | 48296b7 | 2014-09-14 14:28:45 -0700 | [diff] [blame] | 417 |     } | 
 | 418 |  | 
| Lajos Molnar | 1d15ab5 | 2015-03-04 16:46:34 -0800 | [diff] [blame] | 419 |     (new AMessage(kWhatReset, this))->post(); | 
| Andreas Huber | 1aef211 | 2011-01-04 14:01:29 -0800 | [diff] [blame] | 420 | } | 
 | 421 |  | 
| Wei Jia | e427abf | 2014-09-22 15:21:11 -0700 | [diff] [blame] | 422 | void NuPlayer::seekToAsync(int64_t seekTimeUs, bool needNotify) { | 
| Lajos Molnar | 1d15ab5 | 2015-03-04 16:46:34 -0800 | [diff] [blame] | 423 |     sp<AMessage> msg = new AMessage(kWhatSeek, this); | 
| Andreas Huber | 43c3e6c | 2011-01-05 12:17:08 -0800 | [diff] [blame] | 424 |     msg->setInt64("seekTimeUs", seekTimeUs); | 
| Wei Jia | e427abf | 2014-09-22 15:21:11 -0700 | [diff] [blame] | 425 |     msg->setInt32("needNotify", needNotify); | 
| Andreas Huber | 43c3e6c | 2011-01-05 12:17:08 -0800 | [diff] [blame] | 426 |     msg->post(); | 
 | 427 | } | 
 | 428 |  | 
| Andreas Huber | 53df1a4 | 2010-12-22 10:03:04 -0800 | [diff] [blame] | 429 |  | 
| Chong Zhang | 404fced | 2014-06-11 14:45:31 -0700 | [diff] [blame] | 430 | void NuPlayer::writeTrackInfo( | 
 | 431 |         Parcel* reply, const sp<AMessage> format) const { | 
| Marco Nelissen | c367ca1 | 2015-09-15 09:51:59 -0700 | [diff] [blame] | 432 |     if (format == NULL) { | 
 | 433 |         ALOGE("NULL format"); | 
 | 434 |         return; | 
 | 435 |     } | 
| Chong Zhang | 404fced | 2014-06-11 14:45:31 -0700 | [diff] [blame] | 436 |     int32_t trackType; | 
| Marco Nelissen | 9436e48 | 2015-09-15 10:21:53 -0700 | [diff] [blame] | 437 |     if (!format->findInt32("type", &trackType)) { | 
| Marco Nelissen | c367ca1 | 2015-09-15 09:51:59 -0700 | [diff] [blame] | 438 |         ALOGE("no track type"); | 
 | 439 |         return; | 
 | 440 |     } | 
| Chong Zhang | 404fced | 2014-06-11 14:45:31 -0700 | [diff] [blame] | 441 |  | 
| Robert Shih | 755106e | 2015-04-30 14:36:45 -0700 | [diff] [blame] | 442 |     AString mime; | 
| Robert Shih | 2e3a425 | 2015-05-06 10:21:15 -0700 | [diff] [blame] | 443 |     if (!format->findString("mime", &mime)) { | 
 | 444 |         // Java MediaPlayer only uses mimetype for subtitle and timedtext tracks. | 
 | 445 |         // If we can't find the mimetype here it means that we wouldn't be needing | 
 | 446 |         // the mimetype on the Java end. We still write a placeholder mime to keep the | 
 | 447 |         // (de)serialization logic simple. | 
 | 448 |         if (trackType == MEDIA_TRACK_TYPE_AUDIO) { | 
 | 449 |             mime = "audio/"; | 
 | 450 |         } else if (trackType == MEDIA_TRACK_TYPE_VIDEO) { | 
 | 451 |             mime = "video/"; | 
 | 452 |         } else { | 
| Marco Nelissen | c367ca1 | 2015-09-15 09:51:59 -0700 | [diff] [blame] | 453 |             ALOGE("unknown track type: %d", trackType); | 
 | 454 |             return; | 
| Robert Shih | 2e3a425 | 2015-05-06 10:21:15 -0700 | [diff] [blame] | 455 |         } | 
 | 456 |     } | 
| Robert Shih | 755106e | 2015-04-30 14:36:45 -0700 | [diff] [blame] | 457 |  | 
| Chong Zhang | 404fced | 2014-06-11 14:45:31 -0700 | [diff] [blame] | 458 |     AString lang; | 
| Marco Nelissen | 9436e48 | 2015-09-15 10:21:53 -0700 | [diff] [blame] | 459 |     if (!format->findString("language", &lang)) { | 
| Marco Nelissen | c367ca1 | 2015-09-15 09:51:59 -0700 | [diff] [blame] | 460 |         ALOGE("no language"); | 
 | 461 |         return; | 
 | 462 |     } | 
| Chong Zhang | 404fced | 2014-06-11 14:45:31 -0700 | [diff] [blame] | 463 |  | 
 | 464 |     reply->writeInt32(2); // write something non-zero | 
 | 465 |     reply->writeInt32(trackType); | 
| Robert Shih | 755106e | 2015-04-30 14:36:45 -0700 | [diff] [blame] | 466 |     reply->writeString16(String16(mime.c_str())); | 
| Chong Zhang | 404fced | 2014-06-11 14:45:31 -0700 | [diff] [blame] | 467 |     reply->writeString16(String16(lang.c_str())); | 
 | 468 |  | 
 | 469 |     if (trackType == MEDIA_TRACK_TYPE_SUBTITLE) { | 
| Chong Zhang | 404fced | 2014-06-11 14:45:31 -0700 | [diff] [blame] | 470 |         int32_t isAuto, isDefault, isForced; | 
 | 471 |         CHECK(format->findInt32("auto", &isAuto)); | 
 | 472 |         CHECK(format->findInt32("default", &isDefault)); | 
 | 473 |         CHECK(format->findInt32("forced", &isForced)); | 
 | 474 |  | 
| Chong Zhang | 404fced | 2014-06-11 14:45:31 -0700 | [diff] [blame] | 475 |         reply->writeInt32(isAuto); | 
 | 476 |         reply->writeInt32(isDefault); | 
 | 477 |         reply->writeInt32(isForced); | 
 | 478 |     } | 
 | 479 | } | 
 | 480 |  | 
| Andreas Huber | f933441 | 2010-12-15 15:17:42 -0800 | [diff] [blame] | 481 | void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { | 
 | 482 |     switch (msg->what()) { | 
 | 483 |         case kWhatSetDataSource: | 
 | 484 |         { | 
| Steve Block | 3856b09 | 2011-10-20 11:56:00 +0100 | [diff] [blame] | 485 |             ALOGV("kWhatSetDataSource"); | 
| Andreas Huber | f933441 | 2010-12-15 15:17:42 -0800 | [diff] [blame] | 486 |  | 
 | 487 |             CHECK(mSource == NULL); | 
 | 488 |  | 
| Chong Zhang | 3de157d | 2014-08-05 20:54:44 -0700 | [diff] [blame] | 489 |             status_t err = OK; | 
| Andreas Huber | 5bc087c | 2010-12-23 10:27:40 -0800 | [diff] [blame] | 490 |             sp<RefBase> obj; | 
 | 491 |             CHECK(msg->findObject("source", &obj)); | 
| Chong Zhang | 3de157d | 2014-08-05 20:54:44 -0700 | [diff] [blame] | 492 |             if (obj != NULL) { | 
| Wei Jia | c45a4b2 | 2016-04-15 15:30:23 -0700 | [diff] [blame] | 493 |                 Mutex::Autolock autoLock(mSourceLock); | 
| Chong Zhang | 3de157d | 2014-08-05 20:54:44 -0700 | [diff] [blame] | 494 |                 mSource = static_cast<Source *>(obj.get()); | 
| Chong Zhang | 3de157d | 2014-08-05 20:54:44 -0700 | [diff] [blame] | 495 |             } else { | 
 | 496 |                 err = UNKNOWN_ERROR; | 
 | 497 |             } | 
| Andreas Huber | 9575c96 | 2013-02-05 13:59:56 -0800 | [diff] [blame] | 498 |  | 
 | 499 |             CHECK(mDriver != NULL); | 
 | 500 |             sp<NuPlayerDriver> driver = mDriver.promote(); | 
 | 501 |             if (driver != NULL) { | 
| Chong Zhang | 3de157d | 2014-08-05 20:54:44 -0700 | [diff] [blame] | 502 |                 driver->notifySetDataSourceCompleted(err); | 
| Andreas Huber | 9575c96 | 2013-02-05 13:59:56 -0800 | [diff] [blame] | 503 |             } | 
 | 504 |             break; | 
 | 505 |         } | 
 | 506 |  | 
 | 507 |         case kWhatPrepare: | 
 | 508 |         { | 
 | 509 |             mSource->prepareAsync(); | 
| Andreas Huber | f933441 | 2010-12-15 15:17:42 -0800 | [diff] [blame] | 510 |             break; | 
 | 511 |         } | 
 | 512 |  | 
| Chong Zhang | dcb89b3 | 2013-08-06 09:44:47 -0700 | [diff] [blame] | 513 |         case kWhatGetTrackInfo: | 
 | 514 |         { | 
| Lajos Molnar | 3f27436 | 2015-03-05 14:35:41 -0800 | [diff] [blame] | 515 |             sp<AReplyToken> replyID; | 
| Chong Zhang | dcb89b3 | 2013-08-06 09:44:47 -0700 | [diff] [blame] | 516 |             CHECK(msg->senderAwaitsResponse(&replyID)); | 
 | 517 |  | 
| Chong Zhang | 404fced | 2014-06-11 14:45:31 -0700 | [diff] [blame] | 518 |             Parcel* reply; | 
 | 519 |             CHECK(msg->findPointer("reply", (void**)&reply)); | 
 | 520 |  | 
 | 521 |             size_t inbandTracks = 0; | 
| Chong Zhang | dcb89b3 | 2013-08-06 09:44:47 -0700 | [diff] [blame] | 522 |             if (mSource != NULL) { | 
| Chong Zhang | 404fced | 2014-06-11 14:45:31 -0700 | [diff] [blame] | 523 |                 inbandTracks = mSource->getTrackCount(); | 
 | 524 |             } | 
 | 525 |  | 
| Chong Zhang | a7fa1d9 | 2014-06-11 14:49:23 -0700 | [diff] [blame] | 526 |             size_t ccTracks = 0; | 
 | 527 |             if (mCCDecoder != NULL) { | 
 | 528 |                 ccTracks = mCCDecoder->getTrackCount(); | 
 | 529 |             } | 
 | 530 |  | 
| Chong Zhang | 404fced | 2014-06-11 14:45:31 -0700 | [diff] [blame] | 531 |             // total track count | 
| Chong Zhang | a7fa1d9 | 2014-06-11 14:49:23 -0700 | [diff] [blame] | 532 |             reply->writeInt32(inbandTracks + ccTracks); | 
| Chong Zhang | 404fced | 2014-06-11 14:45:31 -0700 | [diff] [blame] | 533 |  | 
 | 534 |             // write inband tracks | 
 | 535 |             for (size_t i = 0; i < inbandTracks; ++i) { | 
 | 536 |                 writeTrackInfo(reply, mSource->getTrackInfo(i)); | 
| Chong Zhang | dcb89b3 | 2013-08-06 09:44:47 -0700 | [diff] [blame] | 537 |             } | 
 | 538 |  | 
| Chong Zhang | a7fa1d9 | 2014-06-11 14:49:23 -0700 | [diff] [blame] | 539 |             // write CC track | 
 | 540 |             for (size_t i = 0; i < ccTracks; ++i) { | 
 | 541 |                 writeTrackInfo(reply, mCCDecoder->getTrackInfo(i)); | 
 | 542 |             } | 
 | 543 |  | 
| Chong Zhang | dcb89b3 | 2013-08-06 09:44:47 -0700 | [diff] [blame] | 544 |             sp<AMessage> response = new AMessage; | 
| Chong Zhang | dcb89b3 | 2013-08-06 09:44:47 -0700 | [diff] [blame] | 545 |             response->postReply(replyID); | 
 | 546 |             break; | 
 | 547 |         } | 
 | 548 |  | 
| Robert Shih | 7c4f0d7 | 2014-07-09 18:53:31 -0700 | [diff] [blame] | 549 |         case kWhatGetSelectedTrack: | 
 | 550 |         { | 
 | 551 |             status_t err = INVALID_OPERATION; | 
 | 552 |             if (mSource != NULL) { | 
 | 553 |                 err = OK; | 
 | 554 |  | 
 | 555 |                 int32_t type32; | 
 | 556 |                 CHECK(msg->findInt32("type", (int32_t*)&type32)); | 
 | 557 |                 media_track_type type = (media_track_type)type32; | 
 | 558 |                 ssize_t selectedTrack = mSource->getSelectedTrack(type); | 
 | 559 |  | 
 | 560 |                 Parcel* reply; | 
 | 561 |                 CHECK(msg->findPointer("reply", (void**)&reply)); | 
 | 562 |                 reply->writeInt32(selectedTrack); | 
 | 563 |             } | 
 | 564 |  | 
 | 565 |             sp<AMessage> response = new AMessage; | 
 | 566 |             response->setInt32("err", err); | 
 | 567 |  | 
| Lajos Molnar | 3f27436 | 2015-03-05 14:35:41 -0800 | [diff] [blame] | 568 |             sp<AReplyToken> replyID; | 
| Robert Shih | 7c4f0d7 | 2014-07-09 18:53:31 -0700 | [diff] [blame] | 569 |             CHECK(msg->senderAwaitsResponse(&replyID)); | 
 | 570 |             response->postReply(replyID); | 
 | 571 |             break; | 
 | 572 |         } | 
 | 573 |  | 
| Chong Zhang | dcb89b3 | 2013-08-06 09:44:47 -0700 | [diff] [blame] | 574 |         case kWhatSelectTrack: | 
 | 575 |         { | 
| Lajos Molnar | 3f27436 | 2015-03-05 14:35:41 -0800 | [diff] [blame] | 576 |             sp<AReplyToken> replyID; | 
| Chong Zhang | dcb89b3 | 2013-08-06 09:44:47 -0700 | [diff] [blame] | 577 |             CHECK(msg->senderAwaitsResponse(&replyID)); | 
 | 578 |  | 
| Chong Zhang | 404fced | 2014-06-11 14:45:31 -0700 | [diff] [blame] | 579 |             size_t trackIndex; | 
 | 580 |             int32_t select; | 
| Robert Shih | 6ffb1fd | 2014-10-29 16:24:32 -0700 | [diff] [blame] | 581 |             int64_t timeUs; | 
| Chong Zhang | 404fced | 2014-06-11 14:45:31 -0700 | [diff] [blame] | 582 |             CHECK(msg->findSize("trackIndex", &trackIndex)); | 
 | 583 |             CHECK(msg->findInt32("select", &select)); | 
| Robert Shih | 6ffb1fd | 2014-10-29 16:24:32 -0700 | [diff] [blame] | 584 |             CHECK(msg->findInt64("timeUs", &timeUs)); | 
| Chong Zhang | 404fced | 2014-06-11 14:45:31 -0700 | [diff] [blame] | 585 |  | 
| Chong Zhang | dcb89b3 | 2013-08-06 09:44:47 -0700 | [diff] [blame] | 586 |             status_t err = INVALID_OPERATION; | 
| Chong Zhang | 404fced | 2014-06-11 14:45:31 -0700 | [diff] [blame] | 587 |  | 
 | 588 |             size_t inbandTracks = 0; | 
| Chong Zhang | dcb89b3 | 2013-08-06 09:44:47 -0700 | [diff] [blame] | 589 |             if (mSource != NULL) { | 
| Chong Zhang | 404fced | 2014-06-11 14:45:31 -0700 | [diff] [blame] | 590 |                 inbandTracks = mSource->getTrackCount(); | 
 | 591 |             } | 
| Chong Zhang | a7fa1d9 | 2014-06-11 14:49:23 -0700 | [diff] [blame] | 592 |             size_t ccTracks = 0; | 
 | 593 |             if (mCCDecoder != NULL) { | 
 | 594 |                 ccTracks = mCCDecoder->getTrackCount(); | 
 | 595 |             } | 
| Chong Zhang | 404fced | 2014-06-11 14:45:31 -0700 | [diff] [blame] | 596 |  | 
 | 597 |             if (trackIndex < inbandTracks) { | 
| Robert Shih | 6ffb1fd | 2014-10-29 16:24:32 -0700 | [diff] [blame] | 598 |                 err = mSource->selectTrack(trackIndex, select, timeUs); | 
| Robert Shih | d3b0bbb | 2014-07-23 15:00:25 -0700 | [diff] [blame] | 599 |  | 
 | 600 |                 if (!select && err == OK) { | 
 | 601 |                     int32_t type; | 
 | 602 |                     sp<AMessage> info = mSource->getTrackInfo(trackIndex); | 
 | 603 |                     if (info != NULL | 
 | 604 |                             && info->findInt32("type", &type) | 
 | 605 |                             && type == MEDIA_TRACK_TYPE_TIMEDTEXT) { | 
 | 606 |                         ++mTimedTextGeneration; | 
 | 607 |                     } | 
 | 608 |                 } | 
| Chong Zhang | a7fa1d9 | 2014-06-11 14:49:23 -0700 | [diff] [blame] | 609 |             } else { | 
 | 610 |                 trackIndex -= inbandTracks; | 
 | 611 |  | 
 | 612 |                 if (trackIndex < ccTracks) { | 
 | 613 |                     err = mCCDecoder->selectTrack(trackIndex, select); | 
 | 614 |                 } | 
| Chong Zhang | dcb89b3 | 2013-08-06 09:44:47 -0700 | [diff] [blame] | 615 |             } | 
 | 616 |  | 
 | 617 |             sp<AMessage> response = new AMessage; | 
 | 618 |             response->setInt32("err", err); | 
 | 619 |  | 
 | 620 |             response->postReply(replyID); | 
 | 621 |             break; | 
 | 622 |         } | 
 | 623 |  | 
| Andreas Huber | b7c8e91 | 2012-11-27 15:02:53 -0800 | [diff] [blame] | 624 |         case kWhatPollDuration: | 
 | 625 |         { | 
 | 626 |             int32_t generation; | 
 | 627 |             CHECK(msg->findInt32("generation", &generation)); | 
 | 628 |  | 
 | 629 |             if (generation != mPollDurationGeneration) { | 
 | 630 |                 // stale | 
 | 631 |                 break; | 
 | 632 |             } | 
 | 633 |  | 
 | 634 |             int64_t durationUs; | 
 | 635 |             if (mDriver != NULL && mSource->getDuration(&durationUs) == OK) { | 
 | 636 |                 sp<NuPlayerDriver> driver = mDriver.promote(); | 
 | 637 |                 if (driver != NULL) { | 
 | 638 |                     driver->notifyDuration(durationUs); | 
 | 639 |                 } | 
 | 640 |             } | 
 | 641 |  | 
 | 642 |             msg->post(1000000ll);  // poll again in a second. | 
 | 643 |             break; | 
 | 644 |         } | 
 | 645 |  | 
| Lajos Molnar | 1de1e25 | 2015-04-30 18:18:34 -0700 | [diff] [blame] | 646 |         case kWhatSetVideoSurface: | 
| Andreas Huber | f933441 | 2010-12-15 15:17:42 -0800 | [diff] [blame] | 647 |         { | 
| Andreas Huber | f933441 | 2010-12-15 15:17:42 -0800 | [diff] [blame] | 648 |  | 
 | 649 |             sp<RefBase> obj; | 
| Lajos Molnar | 1de1e25 | 2015-04-30 18:18:34 -0700 | [diff] [blame] | 650 |             CHECK(msg->findObject("surface", &obj)); | 
 | 651 |             sp<Surface> surface = static_cast<Surface *>(obj.get()); | 
| Lajos Molnar | a81c622 | 2015-07-10 19:17:45 -0700 | [diff] [blame] | 652 |  | 
 | 653 |             ALOGD("onSetVideoSurface(%p, %s video decoder)", | 
 | 654 |                     surface.get(), | 
| Wei Jia | 6b7d2ed | 2015-08-10 15:11:54 -0700 | [diff] [blame] | 655 |                     (mSource != NULL && mStarted && mSource->getFormat(false /* audio */) != NULL | 
| Lajos Molnar | a81c622 | 2015-07-10 19:17:45 -0700 | [diff] [blame] | 656 |                             && mVideoDecoder != NULL) ? "have" : "no"); | 
 | 657 |  | 
| Wei Jia | 6b7d2ed | 2015-08-10 15:11:54 -0700 | [diff] [blame] | 658 |             // Need to check mStarted before calling mSource->getFormat because NuPlayer might | 
 | 659 |             // be in preparing state and it could take long time. | 
 | 660 |             // When mStarted is true, mSource must have been set. | 
 | 661 |             if (mSource == NULL || !mStarted || mSource->getFormat(false /* audio */) == NULL | 
| Lajos Molnar | a81c622 | 2015-07-10 19:17:45 -0700 | [diff] [blame] | 662 |                     // NOTE: mVideoDecoder's mSurface is always non-null | 
 | 663 |                     || (mVideoDecoder != NULL && mVideoDecoder->setVideoSurface(surface) == OK)) { | 
| Lajos Molnar | 1de1e25 | 2015-04-30 18:18:34 -0700 | [diff] [blame] | 664 |                 performSetSurface(surface); | 
| Wei Jia | fef808d | 2014-10-31 17:57:05 -0700 | [diff] [blame] | 665 |                 break; | 
 | 666 |             } | 
 | 667 |  | 
 | 668 |             mDeferredActions.push_back( | 
 | 669 |                     new FlushDecoderAction(FLUSH_CMD_FLUSH /* audio */, | 
 | 670 |                                            FLUSH_CMD_SHUTDOWN /* video */)); | 
 | 671 |  | 
| Lajos Molnar | 1de1e25 | 2015-04-30 18:18:34 -0700 | [diff] [blame] | 672 |             mDeferredActions.push_back(new SetSurfaceAction(surface)); | 
| James Dong | 0d268a3 | 2012-08-31 12:18:27 -0700 | [diff] [blame] | 673 |  | 
| Wei Jia | c6e5841 | 2015-07-10 18:04:55 -0700 | [diff] [blame] | 674 |             if (obj != NULL || mAudioDecoder != NULL) { | 
| Wei Jia | fef808d | 2014-10-31 17:57:05 -0700 | [diff] [blame] | 675 |                 if (mStarted) { | 
| Andy Hung | 7353585 | 2014-09-05 11:42:58 -0700 | [diff] [blame] | 676 |                     // Issue a seek to refresh the video screen only if started otherwise | 
 | 677 |                     // the extractor may not yet be started and will assert. | 
 | 678 |                     // If the video decoder is not set (perhaps audio only in this case) | 
 | 679 |                     // do not perform a seek as it is not needed. | 
| Ronghua Wu | a73d9e0 | 2014-10-08 15:13:29 -0700 | [diff] [blame] | 680 |                     int64_t currentPositionUs = 0; | 
 | 681 |                     if (getCurrentPosition(¤tPositionUs) == OK) { | 
 | 682 |                         mDeferredActions.push_back( | 
| Wei Jia | 2984080 | 2015-05-15 17:11:38 -0700 | [diff] [blame] | 683 |                                 new SeekAction(currentPositionUs)); | 
| Ronghua Wu | a73d9e0 | 2014-10-08 15:13:29 -0700 | [diff] [blame] | 684 |                     } | 
| Andy Hung | 7353585 | 2014-09-05 11:42:58 -0700 | [diff] [blame] | 685 |                 } | 
| Wei Jia | ac428aa | 2014-09-02 19:01:34 -0700 | [diff] [blame] | 686 |  | 
| Andreas Huber | 57a339c | 2012-12-03 11:18:00 -0800 | [diff] [blame] | 687 |                 // If there is a new surface texture, instantiate decoders | 
 | 688 |                 // again if possible. | 
 | 689 |                 mDeferredActions.push_back( | 
 | 690 |                         new SimpleAction(&NuPlayer::performScanSources)); | 
 | 691 |             } | 
 | 692 |  | 
| Chong Zhang | f8d7177 | 2014-11-26 15:08:34 -0800 | [diff] [blame] | 693 |             // After a flush without shutdown, decoder is paused. | 
 | 694 |             // Don't resume it until source seek is done, otherwise it could | 
| Chong Zhang | 7137ec7 | 2014-11-12 16:41:05 -0800 | [diff] [blame] | 695 |             // start pulling stale data too soon. | 
 | 696 |             mDeferredActions.push_back( | 
| Chong Zhang | f8d7177 | 2014-11-26 15:08:34 -0800 | [diff] [blame] | 697 |                     new ResumeDecoderAction(false /* needNotify */)); | 
| Chong Zhang | 7137ec7 | 2014-11-12 16:41:05 -0800 | [diff] [blame] | 698 |  | 
| Andreas Huber | 57a339c | 2012-12-03 11:18:00 -0800 | [diff] [blame] | 699 |             processDeferredActions(); | 
| Andreas Huber | f933441 | 2010-12-15 15:17:42 -0800 | [diff] [blame] | 700 |             break; | 
 | 701 |         } | 
 | 702 |  | 
 | 703 |         case kWhatSetAudioSink: | 
 | 704 |         { | 
| Steve Block | 3856b09 | 2011-10-20 11:56:00 +0100 | [diff] [blame] | 705 |             ALOGV("kWhatSetAudioSink"); | 
| Andreas Huber | f933441 | 2010-12-15 15:17:42 -0800 | [diff] [blame] | 706 |  | 
 | 707 |             sp<RefBase> obj; | 
 | 708 |             CHECK(msg->findObject("sink", &obj)); | 
 | 709 |  | 
 | 710 |             mAudioSink = static_cast<MediaPlayerBase::AudioSink *>(obj.get()); | 
 | 711 |             break; | 
 | 712 |         } | 
 | 713 |  | 
 | 714 |         case kWhatStart: | 
 | 715 |         { | 
| Steve Block | 3856b09 | 2011-10-20 11:56:00 +0100 | [diff] [blame] | 716 |             ALOGV("kWhatStart"); | 
| Wei Jia | 9421174 | 2014-10-28 17:09:06 -0700 | [diff] [blame] | 717 |             if (mStarted) { | 
| Chong Zhang | 8a04833 | 2015-05-06 15:16:28 -0700 | [diff] [blame] | 718 |                 // do not resume yet if the source is still buffering | 
 | 719 |                 if (!mPausedForBuffering) { | 
 | 720 |                     onResume(); | 
 | 721 |                 } | 
| Wei Jia | 9421174 | 2014-10-28 17:09:06 -0700 | [diff] [blame] | 722 |             } else { | 
 | 723 |                 onStart(); | 
| Lajos Molnar | 0952483 | 2014-07-17 14:29:51 -0700 | [diff] [blame] | 724 |             } | 
| Chong Zhang | efbb619 | 2015-01-30 17:13:27 -0800 | [diff] [blame] | 725 |             mPausedByClient = false; | 
| Wei Jia | 71c75e0 | 2016-02-04 09:40:47 -0800 | [diff] [blame] | 726 |             if (mPendingBufferingFlag != PENDING_BUFFERING_FLAG_NONE) { | 
 | 727 |                 notifyListener(MEDIA_INFO, mPendingBufferingFlag, 0); | 
 | 728 |                 mPendingBufferingFlag = PENDING_BUFFERING_FLAG_NONE; | 
 | 729 |             } | 
| Andreas Huber | f933441 | 2010-12-15 15:17:42 -0800 | [diff] [blame] | 730 |             break; | 
 | 731 |         } | 
 | 732 |  | 
| Lajos Molnar | 3a474aa | 2015-04-24 17:10:07 -0700 | [diff] [blame] | 733 |         case kWhatConfigPlayback: | 
| Wei Jia | 9816016 | 2015-02-04 17:01:11 -0800 | [diff] [blame] | 734 |         { | 
| Lajos Molnar | 3a474aa | 2015-04-24 17:10:07 -0700 | [diff] [blame] | 735 |             sp<AReplyToken> replyID; | 
 | 736 |             CHECK(msg->senderAwaitsResponse(&replyID)); | 
 | 737 |             AudioPlaybackRate rate /* sanitized */; | 
 | 738 |             readFromAMessage(msg, &rate); | 
 | 739 |             status_t err = OK; | 
| Wei Jia | 9816016 | 2015-02-04 17:01:11 -0800 | [diff] [blame] | 740 |             if (mRenderer != NULL) { | 
| Wei Jia | bf70feb | 2016-02-19 15:47:16 -0800 | [diff] [blame] | 741 |                 // AudioSink allows only 1.f and 0.f for offload mode. | 
 | 742 |                 // For other speed, switch to non-offload mode. | 
 | 743 |                 if (mOffloadAudio && ((rate.mSpeed != 0.f && rate.mSpeed != 1.f) | 
 | 744 |                         || rate.mPitch != 1.f)) { | 
 | 745 |                     int64_t currentPositionUs; | 
 | 746 |                     if (getCurrentPosition(¤tPositionUs) != OK) { | 
 | 747 |                         currentPositionUs = mPreviousSeekTimeUs; | 
 | 748 |                     } | 
 | 749 |  | 
 | 750 |                     // Set mPlaybackSettings so that the new audio decoder can | 
 | 751 |                     // be created correctly. | 
 | 752 |                     mPlaybackSettings = rate; | 
 | 753 |                     if (!mPaused) { | 
 | 754 |                         mRenderer->pause(); | 
 | 755 |                     } | 
| Wei Jia | 5031b2f | 2016-02-25 11:19:31 -0800 | [diff] [blame] | 756 |                     restartAudio( | 
| Wei Jia | bf70feb | 2016-02-19 15:47:16 -0800 | [diff] [blame] | 757 |                             currentPositionUs, true /* forceNonOffload */, | 
 | 758 |                             true /* needsToCreateAudioDecoder */); | 
 | 759 |                     if (!mPaused) { | 
 | 760 |                         mRenderer->resume(); | 
 | 761 |                     } | 
 | 762 |                 } | 
 | 763 |  | 
| Lajos Molnar | 3a474aa | 2015-04-24 17:10:07 -0700 | [diff] [blame] | 764 |                 err = mRenderer->setPlaybackSettings(rate); | 
 | 765 |             } | 
 | 766 |             if (err == OK) { | 
 | 767 |                 if (rate.mSpeed == 0.f) { | 
 | 768 |                     onPause(); | 
| Wei Jia | 351ce87 | 2016-02-10 13:21:59 -0800 | [diff] [blame] | 769 |                     mPausedByClient = true; | 
| Lajos Molnar | 3a474aa | 2015-04-24 17:10:07 -0700 | [diff] [blame] | 770 |                     // save all other settings (using non-paused speed) | 
 | 771 |                     // so we can restore them on start | 
 | 772 |                     AudioPlaybackRate newRate = rate; | 
 | 773 |                     newRate.mSpeed = mPlaybackSettings.mSpeed; | 
 | 774 |                     mPlaybackSettings = newRate; | 
 | 775 |                 } else { /* rate.mSpeed != 0.f */ | 
 | 776 |                     onResume(); | 
| Wei Jia | 351ce87 | 2016-02-10 13:21:59 -0800 | [diff] [blame] | 777 |                     mPausedByClient = false; | 
| Lajos Molnar | 3a474aa | 2015-04-24 17:10:07 -0700 | [diff] [blame] | 778 |                     mPlaybackSettings = rate; | 
 | 779 |                 } | 
| Wei Jia | 9816016 | 2015-02-04 17:01:11 -0800 | [diff] [blame] | 780 |             } | 
| Ronghua Wu | 8db8813 | 2015-04-22 13:51:35 -0700 | [diff] [blame] | 781 |  | 
 | 782 |             if (mVideoDecoder != NULL) { | 
| Ronghua Wu | c8a70d3 | 2015-04-29 16:26:34 -0700 | [diff] [blame] | 783 |                 float rate = getFrameRate(); | 
 | 784 |                 if (rate > 0) { | 
| Ronghua Wu | 8db8813 | 2015-04-22 13:51:35 -0700 | [diff] [blame] | 785 |                     sp<AMessage> params = new AMessage(); | 
| Lajos Molnar | 3a474aa | 2015-04-24 17:10:07 -0700 | [diff] [blame] | 786 |                     params->setFloat("operating-rate", rate * mPlaybackSettings.mSpeed); | 
| Ronghua Wu | 8db8813 | 2015-04-22 13:51:35 -0700 | [diff] [blame] | 787 |                     mVideoDecoder->setParameters(params); | 
 | 788 |                 } | 
 | 789 |             } | 
 | 790 |  | 
| Lajos Molnar | 3a474aa | 2015-04-24 17:10:07 -0700 | [diff] [blame] | 791 |             sp<AMessage> response = new AMessage; | 
 | 792 |             response->setInt32("err", err); | 
 | 793 |             response->postReply(replyID); | 
 | 794 |             break; | 
 | 795 |         } | 
 | 796 |  | 
 | 797 |         case kWhatGetPlaybackSettings: | 
 | 798 |         { | 
 | 799 |             sp<AReplyToken> replyID; | 
 | 800 |             CHECK(msg->senderAwaitsResponse(&replyID)); | 
 | 801 |             AudioPlaybackRate rate = mPlaybackSettings; | 
 | 802 |             status_t err = OK; | 
 | 803 |             if (mRenderer != NULL) { | 
 | 804 |                 err = mRenderer->getPlaybackSettings(&rate); | 
 | 805 |             } | 
 | 806 |             if (err == OK) { | 
 | 807 |                 // get playback settings used by renderer, as it may be | 
 | 808 |                 // slightly off due to audiosink not taking small changes. | 
 | 809 |                 mPlaybackSettings = rate; | 
 | 810 |                 if (mPaused) { | 
 | 811 |                     rate.mSpeed = 0.f; | 
 | 812 |                 } | 
 | 813 |             } | 
 | 814 |             sp<AMessage> response = new AMessage; | 
 | 815 |             if (err == OK) { | 
 | 816 |                 writeToAMessage(response, rate); | 
 | 817 |             } | 
 | 818 |             response->setInt32("err", err); | 
 | 819 |             response->postReply(replyID); | 
 | 820 |             break; | 
 | 821 |         } | 
 | 822 |  | 
 | 823 |         case kWhatConfigSync: | 
 | 824 |         { | 
 | 825 |             sp<AReplyToken> replyID; | 
 | 826 |             CHECK(msg->senderAwaitsResponse(&replyID)); | 
 | 827 |  | 
 | 828 |             ALOGV("kWhatConfigSync"); | 
 | 829 |             AVSyncSettings sync; | 
 | 830 |             float videoFpsHint; | 
 | 831 |             readFromAMessage(msg, &sync, &videoFpsHint); | 
 | 832 |             status_t err = OK; | 
 | 833 |             if (mRenderer != NULL) { | 
 | 834 |                 err = mRenderer->setSyncSettings(sync, videoFpsHint); | 
 | 835 |             } | 
 | 836 |             if (err == OK) { | 
 | 837 |                 mSyncSettings = sync; | 
 | 838 |                 mVideoFpsHint = videoFpsHint; | 
 | 839 |             } | 
 | 840 |             sp<AMessage> response = new AMessage; | 
 | 841 |             response->setInt32("err", err); | 
 | 842 |             response->postReply(replyID); | 
 | 843 |             break; | 
 | 844 |         } | 
 | 845 |  | 
 | 846 |         case kWhatGetSyncSettings: | 
 | 847 |         { | 
 | 848 |             sp<AReplyToken> replyID; | 
 | 849 |             CHECK(msg->senderAwaitsResponse(&replyID)); | 
 | 850 |             AVSyncSettings sync = mSyncSettings; | 
 | 851 |             float videoFps = mVideoFpsHint; | 
 | 852 |             status_t err = OK; | 
 | 853 |             if (mRenderer != NULL) { | 
 | 854 |                 err = mRenderer->getSyncSettings(&sync, &videoFps); | 
 | 855 |                 if (err == OK) { | 
 | 856 |                     mSyncSettings = sync; | 
 | 857 |                     mVideoFpsHint = videoFps; | 
 | 858 |                 } | 
 | 859 |             } | 
 | 860 |             sp<AMessage> response = new AMessage; | 
 | 861 |             if (err == OK) { | 
 | 862 |                 writeToAMessage(response, sync, videoFps); | 
 | 863 |             } | 
 | 864 |             response->setInt32("err", err); | 
 | 865 |             response->postReply(replyID); | 
| Wei Jia | 9816016 | 2015-02-04 17:01:11 -0800 | [diff] [blame] | 866 |             break; | 
 | 867 |         } | 
 | 868 |  | 
| Andreas Huber | f933441 | 2010-12-15 15:17:42 -0800 | [diff] [blame] | 869 |         case kWhatScanSources: | 
 | 870 |         { | 
| Andreas Huber | 1aef211 | 2011-01-04 14:01:29 -0800 | [diff] [blame] | 871 |             int32_t generation; | 
 | 872 |             CHECK(msg->findInt32("generation", &generation)); | 
 | 873 |             if (generation != mScanSourcesGeneration) { | 
 | 874 |                 // Drop obsolete msg. | 
 | 875 |                 break; | 
 | 876 |             } | 
 | 877 |  | 
| Andreas Huber | 5bc087c | 2010-12-23 10:27:40 -0800 | [diff] [blame] | 878 |             mScanSourcesPending = false; | 
 | 879 |  | 
| Steve Block | 3856b09 | 2011-10-20 11:56:00 +0100 | [diff] [blame] | 880 |             ALOGV("scanning sources haveAudio=%d, haveVideo=%d", | 
| Andreas Huber | 43c3e6c | 2011-01-05 12:17:08 -0800 | [diff] [blame] | 881 |                  mAudioDecoder != NULL, mVideoDecoder != NULL); | 
 | 882 |  | 
| Andreas Huber | b7c8e91 | 2012-11-27 15:02:53 -0800 | [diff] [blame] | 883 |             bool mHadAnySourcesBefore = | 
 | 884 |                 (mAudioDecoder != NULL) || (mVideoDecoder != NULL); | 
| Robert Shih | 7350b05 | 2015-10-01 15:50:14 -0700 | [diff] [blame] | 885 |             bool rescan = false; | 
| Andreas Huber | b7c8e91 | 2012-11-27 15:02:53 -0800 | [diff] [blame] | 886 |  | 
| Andy Hung | 282a7e3 | 2014-08-14 15:56:34 -0700 | [diff] [blame] | 887 |             // initialize video before audio because successful initialization of | 
 | 888 |             // video may change deep buffer mode of audio. | 
| Lajos Molnar | 1de1e25 | 2015-04-30 18:18:34 -0700 | [diff] [blame] | 889 |             if (mSurface != NULL) { | 
| Robert Shih | 7350b05 | 2015-10-01 15:50:14 -0700 | [diff] [blame] | 890 |                 if (instantiateDecoder(false, &mVideoDecoder) == -EWOULDBLOCK) { | 
 | 891 |                     rescan = true; | 
 | 892 |                 } | 
| Haynes Mathew George | 5d246ef | 2012-07-09 10:36:57 -0700 | [diff] [blame] | 893 |             } | 
| Andreas Huber | f933441 | 2010-12-15 15:17:42 -0800 | [diff] [blame] | 894 |  | 
| Ronghua Wu | a10fd23 | 2014-11-06 16:15:20 -0800 | [diff] [blame] | 895 |             // Don't try to re-open audio sink if there's an existing decoder. | 
 | 896 |             if (mAudioSink != NULL && mAudioDecoder == NULL) { | 
| Robert Shih | 7350b05 | 2015-10-01 15:50:14 -0700 | [diff] [blame] | 897 |                 if (instantiateDecoder(true, &mAudioDecoder) == -EWOULDBLOCK) { | 
 | 898 |                     rescan = true; | 
 | 899 |                 } | 
| Andreas Huber | f933441 | 2010-12-15 15:17:42 -0800 | [diff] [blame] | 900 |             } | 
 | 901 |  | 
| Andreas Huber | b7c8e91 | 2012-11-27 15:02:53 -0800 | [diff] [blame] | 902 |             if (!mHadAnySourcesBefore | 
 | 903 |                     && (mAudioDecoder != NULL || mVideoDecoder != NULL)) { | 
 | 904 |                 // This is the first time we've found anything playable. | 
 | 905 |  | 
| Andreas Huber | 9575c96 | 2013-02-05 13:59:56 -0800 | [diff] [blame] | 906 |                 if (mSourceFlags & Source::FLAG_DYNAMIC_DURATION) { | 
| Andreas Huber | b7c8e91 | 2012-11-27 15:02:53 -0800 | [diff] [blame] | 907 |                     schedulePollDuration(); | 
 | 908 |                 } | 
 | 909 |             } | 
 | 910 |  | 
| Andreas Huber | eac68ba | 2011-09-27 12:12:25 -0700 | [diff] [blame] | 911 |             status_t err; | 
 | 912 |             if ((err = mSource->feedMoreTSData()) != OK) { | 
| Andreas Huber | 1aef211 | 2011-01-04 14:01:29 -0800 | [diff] [blame] | 913 |                 if (mAudioDecoder == NULL && mVideoDecoder == NULL) { | 
 | 914 |                     // We're not currently decoding anything (no audio or | 
 | 915 |                     // video tracks found) and we just ran out of input data. | 
| Andreas Huber | eac68ba | 2011-09-27 12:12:25 -0700 | [diff] [blame] | 916 |  | 
 | 917 |                     if (err == ERROR_END_OF_STREAM) { | 
 | 918 |                         notifyListener(MEDIA_PLAYBACK_COMPLETE, 0, 0); | 
 | 919 |                     } else { | 
 | 920 |                         notifyListener(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err); | 
 | 921 |                     } | 
| Andreas Huber | 1aef211 | 2011-01-04 14:01:29 -0800 | [diff] [blame] | 922 |                 } | 
| Andreas Huber | f933441 | 2010-12-15 15:17:42 -0800 | [diff] [blame] | 923 |                 break; | 
 | 924 |             } | 
 | 925 |  | 
| Robert Shih | 7350b05 | 2015-10-01 15:50:14 -0700 | [diff] [blame] | 926 |             if (rescan) { | 
| Andreas Huber | f933441 | 2010-12-15 15:17:42 -0800 | [diff] [blame] | 927 |                 msg->post(100000ll); | 
| Andreas Huber | 5bc087c | 2010-12-23 10:27:40 -0800 | [diff] [blame] | 928 |                 mScanSourcesPending = true; | 
| Andreas Huber | f933441 | 2010-12-15 15:17:42 -0800 | [diff] [blame] | 929 |             } | 
 | 930 |             break; | 
 | 931 |         } | 
 | 932 |  | 
 | 933 |         case kWhatVideoNotify: | 
 | 934 |         case kWhatAudioNotify: | 
 | 935 |         { | 
 | 936 |             bool audio = msg->what() == kWhatAudioNotify; | 
 | 937 |  | 
| Wei Jia | 88703c3 | 2014-08-06 11:24:07 -0700 | [diff] [blame] | 938 |             int32_t currentDecoderGeneration = | 
 | 939 |                 (audio? mAudioDecoderGeneration : mVideoDecoderGeneration); | 
 | 940 |             int32_t requesterGeneration = currentDecoderGeneration - 1; | 
 | 941 |             CHECK(msg->findInt32("generation", &requesterGeneration)); | 
 | 942 |  | 
 | 943 |             if (requesterGeneration != currentDecoderGeneration) { | 
 | 944 |                 ALOGV("got message from old %s decoder, generation(%d:%d)", | 
 | 945 |                         audio ? "audio" : "video", requesterGeneration, | 
 | 946 |                         currentDecoderGeneration); | 
 | 947 |                 sp<AMessage> reply; | 
 | 948 |                 if (!(msg->findMessage("reply", &reply))) { | 
 | 949 |                     return; | 
 | 950 |                 } | 
 | 951 |  | 
 | 952 |                 reply->setInt32("err", INFO_DISCONTINUITY); | 
 | 953 |                 reply->post(); | 
 | 954 |                 return; | 
 | 955 |             } | 
 | 956 |  | 
| Andreas Huber | f933441 | 2010-12-15 15:17:42 -0800 | [diff] [blame] | 957 |             int32_t what; | 
| Lajos Molnar | 1cd1398 | 2014-01-17 15:12:51 -0800 | [diff] [blame] | 958 |             CHECK(msg->findInt32("what", &what)); | 
| Andreas Huber | f933441 | 2010-12-15 15:17:42 -0800 | [diff] [blame] | 959 |  | 
| Chong Zhang | 7137ec7 | 2014-11-12 16:41:05 -0800 | [diff] [blame] | 960 |             if (what == DecoderBase::kWhatInputDiscontinuity) { | 
 | 961 |                 int32_t formatChange; | 
 | 962 |                 CHECK(msg->findInt32("formatChange", &formatChange)); | 
| Andreas Huber | f933441 | 2010-12-15 15:17:42 -0800 | [diff] [blame] | 963 |  | 
| Chong Zhang | 7137ec7 | 2014-11-12 16:41:05 -0800 | [diff] [blame] | 964 |                 ALOGV("%s discontinuity: formatChange %d", | 
 | 965 |                         audio ? "audio" : "video", formatChange); | 
 | 966 |  | 
 | 967 |                 if (formatChange) { | 
 | 968 |                     mDeferredActions.push_back( | 
 | 969 |                             new FlushDecoderAction( | 
 | 970 |                                 audio ? FLUSH_CMD_SHUTDOWN : FLUSH_CMD_NONE, | 
 | 971 |                                 audio ? FLUSH_CMD_NONE : FLUSH_CMD_SHUTDOWN)); | 
| Andreas Huber | f933441 | 2010-12-15 15:17:42 -0800 | [diff] [blame] | 972 |                 } | 
| Chong Zhang | 7137ec7 | 2014-11-12 16:41:05 -0800 | [diff] [blame] | 973 |  | 
 | 974 |                 mDeferredActions.push_back( | 
 | 975 |                         new SimpleAction( | 
 | 976 |                                 &NuPlayer::performScanSources)); | 
 | 977 |  | 
 | 978 |                 processDeferredActions(); | 
 | 979 |             } else if (what == DecoderBase::kWhatEOS) { | 
| Andreas Huber | dc9bacd | 2011-09-26 10:53:29 -0700 | [diff] [blame] | 980 |                 int32_t err; | 
| Lajos Molnar | 1cd1398 | 2014-01-17 15:12:51 -0800 | [diff] [blame] | 981 |                 CHECK(msg->findInt32("err", &err)); | 
| Andreas Huber | dc9bacd | 2011-09-26 10:53:29 -0700 | [diff] [blame] | 982 |  | 
 | 983 |                 if (err == ERROR_END_OF_STREAM) { | 
| Steve Block | 3856b09 | 2011-10-20 11:56:00 +0100 | [diff] [blame] | 984 |                     ALOGV("got %s decoder EOS", audio ? "audio" : "video"); | 
| Andreas Huber | dc9bacd | 2011-09-26 10:53:29 -0700 | [diff] [blame] | 985 |                 } else { | 
| Steve Block | 3856b09 | 2011-10-20 11:56:00 +0100 | [diff] [blame] | 986 |                     ALOGV("got %s decoder EOS w/ error %d", | 
| Andreas Huber | dc9bacd | 2011-09-26 10:53:29 -0700 | [diff] [blame] | 987 |                          audio ? "audio" : "video", | 
 | 988 |                          err); | 
 | 989 |                 } | 
 | 990 |  | 
 | 991 |                 mRenderer->queueEOS(audio, err); | 
| Chong Zhang | 7137ec7 | 2014-11-12 16:41:05 -0800 | [diff] [blame] | 992 |             } else if (what == DecoderBase::kWhatFlushCompleted) { | 
| Steve Block | 3856b09 | 2011-10-20 11:56:00 +0100 | [diff] [blame] | 993 |                 ALOGV("decoder %s flush completed", audio ? "audio" : "video"); | 
| Andreas Huber | f933441 | 2010-12-15 15:17:42 -0800 | [diff] [blame] | 994 |  | 
| Andy Hung | 8d121d4 | 2014-10-03 09:53:53 -0700 | [diff] [blame] | 995 |                 handleFlushComplete(audio, true /* isDecoder */); | 
| Andreas Huber | 3831a06 | 2010-12-21 10:22:33 -0800 | [diff] [blame] | 996 |                 finishFlushIfPossible(); | 
| Chong Zhang | 7137ec7 | 2014-11-12 16:41:05 -0800 | [diff] [blame] | 997 |             } else if (what == DecoderBase::kWhatVideoSizeChanged) { | 
| Lajos Molnar | 1cd1398 | 2014-01-17 15:12:51 -0800 | [diff] [blame] | 998 |                 sp<AMessage> format; | 
 | 999 |                 CHECK(msg->findMessage("format", &format)); | 
 | 1000 |  | 
| Wei Jia | c6cfd70 | 2014-11-11 16:33:20 -0800 | [diff] [blame] | 1001 |                 sp<AMessage> inputFormat = | 
 | 1002 |                         mSource->getFormat(false /* audio */); | 
| Andreas Huber | 3831a06 | 2010-12-21 10:22:33 -0800 | [diff] [blame] | 1003 |  | 
| Wei Jia | c6cfd70 | 2014-11-11 16:33:20 -0800 | [diff] [blame] | 1004 |                 updateVideoSize(inputFormat, format); | 
| Chong Zhang | 7137ec7 | 2014-11-12 16:41:05 -0800 | [diff] [blame] | 1005 |             } else if (what == DecoderBase::kWhatShutdownCompleted) { | 
| Steve Block | 3856b09 | 2011-10-20 11:56:00 +0100 | [diff] [blame] | 1006 |                 ALOGV("%s shutdown completed", audio ? "audio" : "video"); | 
| Andreas Huber | 3831a06 | 2010-12-21 10:22:33 -0800 | [diff] [blame] | 1007 |                 if (audio) { | 
 | 1008 |                     mAudioDecoder.clear(); | 
| Wei Jia | 57568df | 2014-09-22 10:16:29 -0700 | [diff] [blame] | 1009 |                     ++mAudioDecoderGeneration; | 
| Andreas Huber | 3831a06 | 2010-12-21 10:22:33 -0800 | [diff] [blame] | 1010 |  | 
 | 1011 |                     CHECK_EQ((int)mFlushingAudio, (int)SHUTTING_DOWN_DECODER); | 
 | 1012 |                     mFlushingAudio = SHUT_DOWN; | 
 | 1013 |                 } else { | 
 | 1014 |                     mVideoDecoder.clear(); | 
| Wei Jia | 57568df | 2014-09-22 10:16:29 -0700 | [diff] [blame] | 1015 |                     ++mVideoDecoderGeneration; | 
| Andreas Huber | 3831a06 | 2010-12-21 10:22:33 -0800 | [diff] [blame] | 1016 |  | 
 | 1017 |                     CHECK_EQ((int)mFlushingVideo, (int)SHUTTING_DOWN_DECODER); | 
 | 1018 |                     mFlushingVideo = SHUT_DOWN; | 
 | 1019 |                 } | 
 | 1020 |  | 
 | 1021 |                 finishFlushIfPossible(); | 
| Chong Zhang | f8d7177 | 2014-11-26 15:08:34 -0800 | [diff] [blame] | 1022 |             } else if (what == DecoderBase::kWhatResumeCompleted) { | 
 | 1023 |                 finishResume(); | 
| Chong Zhang | 7137ec7 | 2014-11-12 16:41:05 -0800 | [diff] [blame] | 1024 |             } else if (what == DecoderBase::kWhatError) { | 
| Chong Zhang | f4c0a94 | 2014-08-11 15:14:10 -0700 | [diff] [blame] | 1025 |                 status_t err; | 
| Andy Hung | 2abde2c | 2014-09-30 14:40:32 -0700 | [diff] [blame] | 1026 |                 if (!msg->findInt32("err", &err) || err == OK) { | 
| Chong Zhang | f4c0a94 | 2014-08-11 15:14:10 -0700 | [diff] [blame] | 1027 |                     err = UNKNOWN_ERROR; | 
 | 1028 |                 } | 
| Andy Hung | cf31f1e | 2014-09-23 14:59:01 -0700 | [diff] [blame] | 1029 |  | 
| Andy Hung | 2abde2c | 2014-09-30 14:40:32 -0700 | [diff] [blame] | 1030 |                 // Decoder errors can be due to Source (e.g. from streaming), | 
 | 1031 |                 // or from decoding corrupted bitstreams, or from other decoder | 
 | 1032 |                 // MediaCodec operations (e.g. from an ongoing reset or seek). | 
| Andy Hung | 202bce1 | 2014-12-03 11:47:36 -0800 | [diff] [blame] | 1033 |                 // They may also be due to openAudioSink failure at | 
 | 1034 |                 // decoder start or after a format change. | 
| Andy Hung | 2abde2c | 2014-09-30 14:40:32 -0700 | [diff] [blame] | 1035 |                 // | 
 | 1036 |                 // We try to gracefully shut down the affected decoder if possible, | 
 | 1037 |                 // rather than trying to force the shutdown with something | 
 | 1038 |                 // similar to performReset(). This method can lead to a hang | 
 | 1039 |                 // if MediaCodec functions block after an error, but they should | 
 | 1040 |                 // typically return INVALID_OPERATION instead of blocking. | 
 | 1041 |  | 
 | 1042 |                 FlushStatus *flushing = audio ? &mFlushingAudio : &mFlushingVideo; | 
 | 1043 |                 ALOGE("received error(%#x) from %s decoder, flushing(%d), now shutting down", | 
 | 1044 |                         err, audio ? "audio" : "video", *flushing); | 
 | 1045 |  | 
 | 1046 |                 switch (*flushing) { | 
 | 1047 |                     case NONE: | 
 | 1048 |                         mDeferredActions.push_back( | 
| Wei Jia | fef808d | 2014-10-31 17:57:05 -0700 | [diff] [blame] | 1049 |                                 new FlushDecoderAction( | 
 | 1050 |                                     audio ? FLUSH_CMD_SHUTDOWN : FLUSH_CMD_NONE, | 
 | 1051 |                                     audio ? FLUSH_CMD_NONE : FLUSH_CMD_SHUTDOWN)); | 
| Andy Hung | 2abde2c | 2014-09-30 14:40:32 -0700 | [diff] [blame] | 1052 |                         processDeferredActions(); | 
 | 1053 |                         break; | 
 | 1054 |                     case FLUSHING_DECODER: | 
 | 1055 |                         *flushing = FLUSHING_DECODER_SHUTDOWN; // initiate shutdown after flush. | 
 | 1056 |                         break; // Wait for flush to complete. | 
 | 1057 |                     case FLUSHING_DECODER_SHUTDOWN: | 
 | 1058 |                         break; // Wait for flush to complete. | 
 | 1059 |                     case SHUTTING_DOWN_DECODER: | 
 | 1060 |                         break; // Wait for shutdown to complete. | 
 | 1061 |                     case FLUSHED: | 
 | 1062 |                         // Widevine source reads must stop before releasing the video decoder. | 
 | 1063 |                         if (!audio && mSource != NULL && mSourceFlags & Source::FLAG_SECURE) { | 
 | 1064 |                             mSource->stop(); | 
| Robert Shih | 0c61a0d | 2015-07-06 15:09:10 -0700 | [diff] [blame] | 1065 |                             mSourceStarted = false; | 
| Andy Hung | 2abde2c | 2014-09-30 14:40:32 -0700 | [diff] [blame] | 1066 |                         } | 
 | 1067 |                         getDecoder(audio)->initiateShutdown(); // In the middle of a seek. | 
 | 1068 |                         *flushing = SHUTTING_DOWN_DECODER;     // Shut down. | 
 | 1069 |                         break; | 
 | 1070 |                     case SHUT_DOWN: | 
 | 1071 |                         finishFlushIfPossible();  // Should not occur. | 
 | 1072 |                         break;                    // Finish anyways. | 
| Marco Nelissen | 9e2b791 | 2014-08-18 16:13:03 -0700 | [diff] [blame] | 1073 |                 } | 
| Andy Hung | 2abde2c | 2014-09-30 14:40:32 -0700 | [diff] [blame] | 1074 |                 notifyListener(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err); | 
| Lajos Molnar | 1cd1398 | 2014-01-17 15:12:51 -0800 | [diff] [blame] | 1075 |             } else { | 
 | 1076 |                 ALOGV("Unhandled decoder notification %d '%c%c%c%c'.", | 
| Andreas Huber | a1f8ab0 | 2012-11-30 10:53:22 -0800 | [diff] [blame] | 1077 |                       what, | 
 | 1078 |                       what >> 24, | 
 | 1079 |                       (what >> 16) & 0xff, | 
 | 1080 |                       (what >> 8) & 0xff, | 
 | 1081 |                       what & 0xff); | 
| Andreas Huber | f933441 | 2010-12-15 15:17:42 -0800 | [diff] [blame] | 1082 |             } | 
 | 1083 |  | 
 | 1084 |             break; | 
 | 1085 |         } | 
 | 1086 |  | 
 | 1087 |         case kWhatRendererNotify: | 
 | 1088 |         { | 
| Wei Jia | 57568df | 2014-09-22 10:16:29 -0700 | [diff] [blame] | 1089 |             int32_t requesterGeneration = mRendererGeneration - 1; | 
 | 1090 |             CHECK(msg->findInt32("generation", &requesterGeneration)); | 
 | 1091 |             if (requesterGeneration != mRendererGeneration) { | 
 | 1092 |                 ALOGV("got message from old renderer, generation(%d:%d)", | 
 | 1093 |                         requesterGeneration, mRendererGeneration); | 
 | 1094 |                 return; | 
 | 1095 |             } | 
 | 1096 |  | 
| Andreas Huber | f933441 | 2010-12-15 15:17:42 -0800 | [diff] [blame] | 1097 |             int32_t what; | 
 | 1098 |             CHECK(msg->findInt32("what", &what)); | 
 | 1099 |  | 
 | 1100 |             if (what == Renderer::kWhatEOS) { | 
 | 1101 |                 int32_t audio; | 
 | 1102 |                 CHECK(msg->findInt32("audio", &audio)); | 
 | 1103 |  | 
| Andreas Huber | c92fd24 | 2011-08-16 13:48:44 -0700 | [diff] [blame] | 1104 |                 int32_t finalResult; | 
 | 1105 |                 CHECK(msg->findInt32("finalResult", &finalResult)); | 
 | 1106 |  | 
| Andreas Huber | f933441 | 2010-12-15 15:17:42 -0800 | [diff] [blame] | 1107 |                 if (audio) { | 
 | 1108 |                     mAudioEOS = true; | 
 | 1109 |                 } else { | 
 | 1110 |                     mVideoEOS = true; | 
 | 1111 |                 } | 
 | 1112 |  | 
| Andreas Huber | c92fd24 | 2011-08-16 13:48:44 -0700 | [diff] [blame] | 1113 |                 if (finalResult == ERROR_END_OF_STREAM) { | 
| Steve Block | 3856b09 | 2011-10-20 11:56:00 +0100 | [diff] [blame] | 1114 |                     ALOGV("reached %s EOS", audio ? "audio" : "video"); | 
| Andreas Huber | c92fd24 | 2011-08-16 13:48:44 -0700 | [diff] [blame] | 1115 |                 } else { | 
| Steve Block | 29357bc | 2012-01-06 19:20:56 +0000 | [diff] [blame] | 1116 |                     ALOGE("%s track encountered an error (%d)", | 
| Andreas Huber | c92fd24 | 2011-08-16 13:48:44 -0700 | [diff] [blame] | 1117 |                          audio ? "audio" : "video", finalResult); | 
 | 1118 |  | 
 | 1119 |                     notifyListener( | 
 | 1120 |                             MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, finalResult); | 
 | 1121 |                 } | 
| Andreas Huber | f933441 | 2010-12-15 15:17:42 -0800 | [diff] [blame] | 1122 |  | 
 | 1123 |                 if ((mAudioEOS || mAudioDecoder == NULL) | 
 | 1124 |                         && (mVideoEOS || mVideoDecoder == NULL)) { | 
 | 1125 |                     notifyListener(MEDIA_PLAYBACK_COMPLETE, 0, 0); | 
 | 1126 |                 } | 
| Andreas Huber | 3fe6215 | 2011-09-16 15:09:22 -0700 | [diff] [blame] | 1127 |             } else if (what == Renderer::kWhatFlushComplete) { | 
| Andreas Huber | f933441 | 2010-12-15 15:17:42 -0800 | [diff] [blame] | 1128 |                 int32_t audio; | 
 | 1129 |                 CHECK(msg->findInt32("audio", &audio)); | 
 | 1130 |  | 
| Wei Jia | 3261f0d | 2015-10-08 13:58:33 -0700 | [diff] [blame] | 1131 |                 if (audio) { | 
 | 1132 |                     mAudioEOS = false; | 
 | 1133 |                 } else { | 
 | 1134 |                     mVideoEOS = false; | 
 | 1135 |                 } | 
 | 1136 |  | 
| Steve Block | 3856b09 | 2011-10-20 11:56:00 +0100 | [diff] [blame] | 1137 |                 ALOGV("renderer %s flush completed.", audio ? "audio" : "video"); | 
| Wei Jia | da4252f | 2015-07-14 18:15:28 -0700 | [diff] [blame] | 1138 |                 if (audio && (mFlushingAudio == NONE || mFlushingAudio == FLUSHED | 
 | 1139 |                         || mFlushingAudio == SHUT_DOWN)) { | 
 | 1140 |                     // Flush has been handled by tear down. | 
 | 1141 |                     break; | 
 | 1142 |                 } | 
| Andy Hung | 8d121d4 | 2014-10-03 09:53:53 -0700 | [diff] [blame] | 1143 |                 handleFlushComplete(audio, false /* isDecoder */); | 
 | 1144 |                 finishFlushIfPossible(); | 
| James Dong | f57b4ea | 2012-07-20 13:38:36 -0700 | [diff] [blame] | 1145 |             } else if (what == Renderer::kWhatVideoRenderingStart) { | 
 | 1146 |                 notifyListener(MEDIA_INFO, MEDIA_INFO_RENDERING_START, 0); | 
| Lajos Molnar | cbaffcf | 2013-08-14 18:30:38 -0700 | [diff] [blame] | 1147 |             } else if (what == Renderer::kWhatMediaRenderingStart) { | 
 | 1148 |                 ALOGV("media rendering started"); | 
 | 1149 |                 notifyListener(MEDIA_STARTED, 0, 0); | 
| Ronghua Wu | faeb0f2 | 2015-05-21 12:20:21 -0700 | [diff] [blame] | 1150 |             } else if (what == Renderer::kWhatAudioTearDown) { | 
| Ronghua Wu | 0852917 | 2014-10-02 16:55:52 -0700 | [diff] [blame] | 1151 |                 int32_t reason; | 
 | 1152 |                 CHECK(msg->findInt32("reason", &reason)); | 
| Ronghua Wu | faeb0f2 | 2015-05-21 12:20:21 -0700 | [diff] [blame] | 1153 |                 ALOGV("Tear down audio with reason %d.", reason); | 
| Wei Jia | 8456ddd | 2016-04-22 14:46:43 -0700 | [diff] [blame] | 1154 |                 if (reason == Renderer::kDueToTimeout && !(mPaused && mOffloadAudio)) { | 
 | 1155 |                     // TimeoutWhenPaused is only for offload mode. | 
 | 1156 |                     ALOGW("Receive a stale message for teardown."); | 
 | 1157 |                     break; | 
 | 1158 |                 } | 
| Wei Jia | da4252f | 2015-07-14 18:15:28 -0700 | [diff] [blame] | 1159 |                 int64_t positionUs; | 
| Robert Shih | 1a5c859 | 2015-08-04 18:07:44 -0700 | [diff] [blame] | 1160 |                 if (!msg->findInt64("positionUs", &positionUs)) { | 
 | 1161 |                     positionUs = mPreviousSeekTimeUs; | 
 | 1162 |                 } | 
| Ronghua Wu | faeb0f2 | 2015-05-21 12:20:21 -0700 | [diff] [blame] | 1163 |  | 
| Wei Jia | 5031b2f | 2016-02-25 11:19:31 -0800 | [diff] [blame] | 1164 |                 restartAudio( | 
| Wei Jia | a05f1e3 | 2016-03-25 16:31:22 -0700 | [diff] [blame] | 1165 |                         positionUs, reason == Renderer::kForceNonOffload /* forceNonOffload */, | 
 | 1166 |                         reason != Renderer::kDueToTimeout /* needsToCreateAudioDecoder */); | 
| Andreas Huber | f933441 | 2010-12-15 15:17:42 -0800 | [diff] [blame] | 1167 |             } | 
 | 1168 |             break; | 
 | 1169 |         } | 
 | 1170 |  | 
 | 1171 |         case kWhatMoreDataQueued: | 
 | 1172 |         { | 
 | 1173 |             break; | 
 | 1174 |         } | 
 | 1175 |  | 
| Andreas Huber | 1aef211 | 2011-01-04 14:01:29 -0800 | [diff] [blame] | 1176 |         case kWhatReset: | 
 | 1177 |         { | 
| Steve Block | 3856b09 | 2011-10-20 11:56:00 +0100 | [diff] [blame] | 1178 |             ALOGV("kWhatReset"); | 
| Andreas Huber | 1aef211 | 2011-01-04 14:01:29 -0800 | [diff] [blame] | 1179 |  | 
| Ronghua Wu | 64c2d17 | 2015-10-07 16:52:19 -0700 | [diff] [blame] | 1180 |             mResetting = true; | 
 | 1181 |  | 
| Andreas Huber | a1f8ab0 | 2012-11-30 10:53:22 -0800 | [diff] [blame] | 1182 |             mDeferredActions.push_back( | 
| Wei Jia | fef808d | 2014-10-31 17:57:05 -0700 | [diff] [blame] | 1183 |                     new FlushDecoderAction( | 
 | 1184 |                         FLUSH_CMD_SHUTDOWN /* audio */, | 
 | 1185 |                         FLUSH_CMD_SHUTDOWN /* video */)); | 
| Andreas Huber | b7c8e91 | 2012-11-27 15:02:53 -0800 | [diff] [blame] | 1186 |  | 
| Andreas Huber | a1f8ab0 | 2012-11-30 10:53:22 -0800 | [diff] [blame] | 1187 |             mDeferredActions.push_back( | 
 | 1188 |                     new SimpleAction(&NuPlayer::performReset)); | 
| Andreas Huber | b58ce9f | 2011-11-28 16:27:35 -0800 | [diff] [blame] | 1189 |  | 
| Andreas Huber | a1f8ab0 | 2012-11-30 10:53:22 -0800 | [diff] [blame] | 1190 |             processDeferredActions(); | 
| Andreas Huber | 1aef211 | 2011-01-04 14:01:29 -0800 | [diff] [blame] | 1191 |             break; | 
 | 1192 |         } | 
 | 1193 |  | 
| Andreas Huber | 43c3e6c | 2011-01-05 12:17:08 -0800 | [diff] [blame] | 1194 |         case kWhatSeek: | 
 | 1195 |         { | 
 | 1196 |             int64_t seekTimeUs; | 
| Wei Jia | e427abf | 2014-09-22 15:21:11 -0700 | [diff] [blame] | 1197 |             int32_t needNotify; | 
| Andreas Huber | 43c3e6c | 2011-01-05 12:17:08 -0800 | [diff] [blame] | 1198 |             CHECK(msg->findInt64("seekTimeUs", &seekTimeUs)); | 
| Wei Jia | e427abf | 2014-09-22 15:21:11 -0700 | [diff] [blame] | 1199 |             CHECK(msg->findInt32("needNotify", &needNotify)); | 
| Andreas Huber | 43c3e6c | 2011-01-05 12:17:08 -0800 | [diff] [blame] | 1200 |  | 
| Wei Jia | e427abf | 2014-09-22 15:21:11 -0700 | [diff] [blame] | 1201 |             ALOGV("kWhatSeek seekTimeUs=%lld us, needNotify=%d", | 
| Lajos Molnar | 6d339f1 | 2015-04-17 16:15:53 -0700 | [diff] [blame] | 1202 |                     (long long)seekTimeUs, needNotify); | 
| Andreas Huber | 43c3e6c | 2011-01-05 12:17:08 -0800 | [diff] [blame] | 1203 |  | 
| Wei Jia | 1061c9c | 2015-05-19 16:02:17 -0700 | [diff] [blame] | 1204 |             if (!mStarted) { | 
 | 1205 |                 // Seek before the player is started. In order to preview video, | 
 | 1206 |                 // need to start the player and pause it. This branch is called | 
 | 1207 |                 // only once if needed. After the player is started, any seek | 
 | 1208 |                 // operation will go through normal path. | 
| Robert Shih | 0c61a0d | 2015-07-06 15:09:10 -0700 | [diff] [blame] | 1209 |                 // Audio-only cases are handled separately. | 
| Wei Jia | 1061c9c | 2015-05-19 16:02:17 -0700 | [diff] [blame] | 1210 |                 onStart(seekTimeUs); | 
| Robert Shih | 0c61a0d | 2015-07-06 15:09:10 -0700 | [diff] [blame] | 1211 |                 if (mStarted) { | 
 | 1212 |                     onPause(); | 
 | 1213 |                     mPausedByClient = true; | 
 | 1214 |                 } | 
| Wei Jia | 1061c9c | 2015-05-19 16:02:17 -0700 | [diff] [blame] | 1215 |                 if (needNotify) { | 
 | 1216 |                     notifyDriverSeekComplete(); | 
 | 1217 |                 } | 
 | 1218 |                 break; | 
 | 1219 |             } | 
 | 1220 |  | 
| Wei Jia | 351ce87 | 2016-02-10 13:21:59 -0800 | [diff] [blame] | 1221 |             mPendingBufferingFlag = PENDING_BUFFERING_FLAG_NONE; | 
 | 1222 |  | 
| Andreas Huber | a1f8ab0 | 2012-11-30 10:53:22 -0800 | [diff] [blame] | 1223 |             mDeferredActions.push_back( | 
| Wei Jia | fef808d | 2014-10-31 17:57:05 -0700 | [diff] [blame] | 1224 |                     new FlushDecoderAction(FLUSH_CMD_FLUSH /* audio */, | 
 | 1225 |                                            FLUSH_CMD_FLUSH /* video */)); | 
| Andreas Huber | 43c3e6c | 2011-01-05 12:17:08 -0800 | [diff] [blame] | 1226 |  | 
| Wei Jia | e427abf | 2014-09-22 15:21:11 -0700 | [diff] [blame] | 1227 |             mDeferredActions.push_back( | 
| Wei Jia | 2984080 | 2015-05-15 17:11:38 -0700 | [diff] [blame] | 1228 |                     new SeekAction(seekTimeUs)); | 
| Andreas Huber | 43c3e6c | 2011-01-05 12:17:08 -0800 | [diff] [blame] | 1229 |  | 
| Chong Zhang | f8d7177 | 2014-11-26 15:08:34 -0800 | [diff] [blame] | 1230 |             // After a flush without shutdown, decoder is paused. | 
 | 1231 |             // Don't resume it until source seek is done, otherwise it could | 
| Chong Zhang | 7137ec7 | 2014-11-12 16:41:05 -0800 | [diff] [blame] | 1232 |             // start pulling stale data too soon. | 
 | 1233 |             mDeferredActions.push_back( | 
| Chong Zhang | f8d7177 | 2014-11-26 15:08:34 -0800 | [diff] [blame] | 1234 |                     new ResumeDecoderAction(needNotify)); | 
| Chong Zhang | 7137ec7 | 2014-11-12 16:41:05 -0800 | [diff] [blame] | 1235 |  | 
| Andreas Huber | a1f8ab0 | 2012-11-30 10:53:22 -0800 | [diff] [blame] | 1236 |             processDeferredActions(); | 
| Andreas Huber | 43c3e6c | 2011-01-05 12:17:08 -0800 | [diff] [blame] | 1237 |             break; | 
 | 1238 |         } | 
 | 1239 |  | 
| Andreas Huber | b408222 | 2011-01-20 15:23:04 -0800 | [diff] [blame] | 1240 |         case kWhatPause: | 
 | 1241 |         { | 
| Chong Zhang | efbb619 | 2015-01-30 17:13:27 -0800 | [diff] [blame] | 1242 |             onPause(); | 
 | 1243 |             mPausedByClient = true; | 
| Andreas Huber | b408222 | 2011-01-20 15:23:04 -0800 | [diff] [blame] | 1244 |             break; | 
 | 1245 |         } | 
 | 1246 |  | 
| Andreas Huber | b5f25f0 | 2013-02-05 10:14:26 -0800 | [diff] [blame] | 1247 |         case kWhatSourceNotify: | 
 | 1248 |         { | 
| Andreas Huber | 9575c96 | 2013-02-05 13:59:56 -0800 | [diff] [blame] | 1249 |             onSourceNotify(msg); | 
| Andreas Huber | b5f25f0 | 2013-02-05 10:14:26 -0800 | [diff] [blame] | 1250 |             break; | 
 | 1251 |         } | 
 | 1252 |  | 
| Chong Zhang | a7fa1d9 | 2014-06-11 14:49:23 -0700 | [diff] [blame] | 1253 |         case kWhatClosedCaptionNotify: | 
 | 1254 |         { | 
 | 1255 |             onClosedCaptionNotify(msg); | 
 | 1256 |             break; | 
 | 1257 |         } | 
 | 1258 |  | 
| Andreas Huber | f933441 | 2010-12-15 15:17:42 -0800 | [diff] [blame] | 1259 |         default: | 
 | 1260 |             TRESPASS(); | 
 | 1261 |             break; | 
 | 1262 |     } | 
 | 1263 | } | 
 | 1264 |  | 
| Wei Jia | 9421174 | 2014-10-28 17:09:06 -0700 | [diff] [blame] | 1265 | void NuPlayer::onResume() { | 
| Ronghua Wu | 64c2d17 | 2015-10-07 16:52:19 -0700 | [diff] [blame] | 1266 |     if (!mPaused || mResetting) { | 
 | 1267 |         ALOGD_IF(mResetting, "resetting, onResume discarded"); | 
| Chong Zhang | efbb619 | 2015-01-30 17:13:27 -0800 | [diff] [blame] | 1268 |         return; | 
 | 1269 |     } | 
 | 1270 |     mPaused = false; | 
| Wei Jia | 9421174 | 2014-10-28 17:09:06 -0700 | [diff] [blame] | 1271 |     if (mSource != NULL) { | 
 | 1272 |         mSource->resume(); | 
 | 1273 |     } else { | 
 | 1274 |         ALOGW("resume called when source is gone or not set"); | 
 | 1275 |     } | 
 | 1276 |     // |mAudioDecoder| may have been released due to the pause timeout, so re-create it if | 
 | 1277 |     // needed. | 
 | 1278 |     if (audioDecoderStillNeeded() && mAudioDecoder == NULL) { | 
 | 1279 |         instantiateDecoder(true /* audio */, &mAudioDecoder); | 
 | 1280 |     } | 
 | 1281 |     if (mRenderer != NULL) { | 
 | 1282 |         mRenderer->resume(); | 
 | 1283 |     } else { | 
 | 1284 |         ALOGW("resume called when renderer is gone or not set"); | 
 | 1285 |     } | 
 | 1286 | } | 
 | 1287 |  | 
| Lajos Molnar | fcd3e94 | 2015-03-31 10:06:48 -0700 | [diff] [blame] | 1288 | status_t NuPlayer::onInstantiateSecureDecoders() { | 
 | 1289 |     status_t err; | 
 | 1290 |     if (!(mSourceFlags & Source::FLAG_SECURE)) { | 
 | 1291 |         return BAD_TYPE; | 
 | 1292 |     } | 
 | 1293 |  | 
 | 1294 |     if (mRenderer != NULL) { | 
 | 1295 |         ALOGE("renderer should not be set when instantiating secure decoders"); | 
 | 1296 |         return UNKNOWN_ERROR; | 
 | 1297 |     } | 
 | 1298 |  | 
 | 1299 |     // TRICKY: We rely on mRenderer being null, so that decoder does not start requesting | 
 | 1300 |     // data on instantiation. | 
| Lajos Molnar | 1de1e25 | 2015-04-30 18:18:34 -0700 | [diff] [blame] | 1301 |     if (mSurface != NULL) { | 
| Lajos Molnar | fcd3e94 | 2015-03-31 10:06:48 -0700 | [diff] [blame] | 1302 |         err = instantiateDecoder(false, &mVideoDecoder); | 
 | 1303 |         if (err != OK) { | 
 | 1304 |             return err; | 
 | 1305 |         } | 
 | 1306 |     } | 
 | 1307 |  | 
 | 1308 |     if (mAudioSink != NULL) { | 
 | 1309 |         err = instantiateDecoder(true, &mAudioDecoder); | 
 | 1310 |         if (err != OK) { | 
 | 1311 |             return err; | 
 | 1312 |         } | 
 | 1313 |     } | 
 | 1314 |     return OK; | 
 | 1315 | } | 
 | 1316 |  | 
| Wei Jia | 1061c9c | 2015-05-19 16:02:17 -0700 | [diff] [blame] | 1317 | void NuPlayer::onStart(int64_t startPositionUs) { | 
| Robert Shih | 0c61a0d | 2015-07-06 15:09:10 -0700 | [diff] [blame] | 1318 |     if (!mSourceStarted) { | 
 | 1319 |         mSourceStarted = true; | 
 | 1320 |         mSource->start(); | 
 | 1321 |     } | 
 | 1322 |     if (startPositionUs > 0) { | 
 | 1323 |         performSeek(startPositionUs); | 
 | 1324 |         if (mSource->getFormat(false /* audio */) == NULL) { | 
 | 1325 |             return; | 
 | 1326 |         } | 
 | 1327 |     } | 
 | 1328 |  | 
| Wei Jia | 9421174 | 2014-10-28 17:09:06 -0700 | [diff] [blame] | 1329 |     mOffloadAudio = false; | 
 | 1330 |     mAudioEOS = false; | 
 | 1331 |     mVideoEOS = false; | 
| Wei Jia | 9421174 | 2014-10-28 17:09:06 -0700 | [diff] [blame] | 1332 |     mStarted = true; | 
 | 1333 |  | 
| Wei Jia | 9421174 | 2014-10-28 17:09:06 -0700 | [diff] [blame] | 1334 |     uint32_t flags = 0; | 
 | 1335 |  | 
 | 1336 |     if (mSource->isRealTime()) { | 
 | 1337 |         flags |= Renderer::FLAG_REAL_TIME; | 
 | 1338 |     } | 
 | 1339 |  | 
 | 1340 |     sp<MetaData> audioMeta = mSource->getFormatMeta(true /* audio */); | 
| Andy Hung | 12a8413 | 2015-10-20 16:09:21 -0700 | [diff] [blame] | 1341 |     ALOGV_IF(audioMeta == NULL, "no metadata for audio source");  // video only stream | 
| Wei Jia | 9421174 | 2014-10-28 17:09:06 -0700 | [diff] [blame] | 1342 |     audio_stream_type_t streamType = AUDIO_STREAM_MUSIC; | 
 | 1343 |     if (mAudioSink != NULL) { | 
 | 1344 |         streamType = mAudioSink->getAudioStreamType(); | 
 | 1345 |     } | 
 | 1346 |  | 
 | 1347 |     sp<AMessage> videoFormat = mSource->getFormat(false /* audio */); | 
 | 1348 |  | 
 | 1349 |     mOffloadAudio = | 
| Wei Jia | bf70feb | 2016-02-19 15:47:16 -0800 | [diff] [blame] | 1350 |         canOffloadStream(audioMeta, (videoFormat != NULL), mSource->isStreaming(), streamType) | 
 | 1351 |                 && (mPlaybackSettings.mSpeed == 1.f && mPlaybackSettings.mPitch == 1.f); | 
| Wei Jia | 9421174 | 2014-10-28 17:09:06 -0700 | [diff] [blame] | 1352 |     if (mOffloadAudio) { | 
 | 1353 |         flags |= Renderer::FLAG_OFFLOAD_AUDIO; | 
 | 1354 |     } | 
 | 1355 |  | 
| Lajos Molnar | 1d15ab5 | 2015-03-04 16:46:34 -0800 | [diff] [blame] | 1356 |     sp<AMessage> notify = new AMessage(kWhatRendererNotify, this); | 
| Wei Jia | 9421174 | 2014-10-28 17:09:06 -0700 | [diff] [blame] | 1357 |     ++mRendererGeneration; | 
 | 1358 |     notify->setInt32("generation", mRendererGeneration); | 
 | 1359 |     mRenderer = new Renderer(mAudioSink, notify, flags); | 
| Wei Jia | 9421174 | 2014-10-28 17:09:06 -0700 | [diff] [blame] | 1360 |     mRendererLooper = new ALooper; | 
 | 1361 |     mRendererLooper->setName("NuPlayerRenderer"); | 
 | 1362 |     mRendererLooper->start(false, false, ANDROID_PRIORITY_AUDIO); | 
 | 1363 |     mRendererLooper->registerHandler(mRenderer); | 
| Lajos Molnar | 3a474aa | 2015-04-24 17:10:07 -0700 | [diff] [blame] | 1364 |  | 
 | 1365 |     status_t err = mRenderer->setPlaybackSettings(mPlaybackSettings); | 
 | 1366 |     if (err != OK) { | 
 | 1367 |         mSource->stop(); | 
| Robert Shih | 0c61a0d | 2015-07-06 15:09:10 -0700 | [diff] [blame] | 1368 |         mSourceStarted = false; | 
| Lajos Molnar | 3a474aa | 2015-04-24 17:10:07 -0700 | [diff] [blame] | 1369 |         notifyListener(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err); | 
 | 1370 |         return; | 
| Wei Jia | c8206ff | 2015-03-04 13:59:37 -0800 | [diff] [blame] | 1371 |     } | 
| Wei Jia | 9421174 | 2014-10-28 17:09:06 -0700 | [diff] [blame] | 1372 |  | 
| Ronghua Wu | c8a70d3 | 2015-04-29 16:26:34 -0700 | [diff] [blame] | 1373 |     float rate = getFrameRate(); | 
 | 1374 |     if (rate > 0) { | 
| Wei Jia | 9421174 | 2014-10-28 17:09:06 -0700 | [diff] [blame] | 1375 |         mRenderer->setVideoFrameRate(rate); | 
 | 1376 |     } | 
 | 1377 |  | 
| Wei Jia | c6cfd70 | 2014-11-11 16:33:20 -0800 | [diff] [blame] | 1378 |     if (mVideoDecoder != NULL) { | 
 | 1379 |         mVideoDecoder->setRenderer(mRenderer); | 
 | 1380 |     } | 
 | 1381 |     if (mAudioDecoder != NULL) { | 
 | 1382 |         mAudioDecoder->setRenderer(mRenderer); | 
 | 1383 |     } | 
 | 1384 |  | 
| Wei Jia | 9421174 | 2014-10-28 17:09:06 -0700 | [diff] [blame] | 1385 |     postScanSources(); | 
 | 1386 | } | 
 | 1387 |  | 
| Chong Zhang | efbb619 | 2015-01-30 17:13:27 -0800 | [diff] [blame] | 1388 | void NuPlayer::onPause() { | 
 | 1389 |     if (mPaused) { | 
 | 1390 |         return; | 
 | 1391 |     } | 
 | 1392 |     mPaused = true; | 
 | 1393 |     if (mSource != NULL) { | 
 | 1394 |         mSource->pause(); | 
 | 1395 |     } else { | 
 | 1396 |         ALOGW("pause called when source is gone or not set"); | 
 | 1397 |     } | 
 | 1398 |     if (mRenderer != NULL) { | 
 | 1399 |         mRenderer->pause(); | 
 | 1400 |     } else { | 
 | 1401 |         ALOGW("pause called when renderer is gone or not set"); | 
 | 1402 |     } | 
 | 1403 | } | 
 | 1404 |  | 
| Ronghua Wu | d7988b1 | 2014-10-03 15:19:10 -0700 | [diff] [blame] | 1405 | bool NuPlayer::audioDecoderStillNeeded() { | 
 | 1406 |     // Audio decoder is no longer needed if it's in shut/shutting down status. | 
 | 1407 |     return ((mFlushingAudio != SHUT_DOWN) && (mFlushingAudio != SHUTTING_DOWN_DECODER)); | 
 | 1408 | } | 
 | 1409 |  | 
| Andy Hung | 8d121d4 | 2014-10-03 09:53:53 -0700 | [diff] [blame] | 1410 | void NuPlayer::handleFlushComplete(bool audio, bool isDecoder) { | 
 | 1411 |     // We wait for both the decoder flush and the renderer flush to complete | 
 | 1412 |     // before entering either the FLUSHED or the SHUTTING_DOWN_DECODER state. | 
 | 1413 |  | 
 | 1414 |     mFlushComplete[audio][isDecoder] = true; | 
 | 1415 |     if (!mFlushComplete[audio][!isDecoder]) { | 
 | 1416 |         return; | 
 | 1417 |     } | 
 | 1418 |  | 
 | 1419 |     FlushStatus *state = audio ? &mFlushingAudio : &mFlushingVideo; | 
 | 1420 |     switch (*state) { | 
 | 1421 |         case FLUSHING_DECODER: | 
 | 1422 |         { | 
 | 1423 |             *state = FLUSHED; | 
| Andy Hung | 8d121d4 | 2014-10-03 09:53:53 -0700 | [diff] [blame] | 1424 |             break; | 
 | 1425 |         } | 
 | 1426 |  | 
 | 1427 |         case FLUSHING_DECODER_SHUTDOWN: | 
 | 1428 |         { | 
 | 1429 |             *state = SHUTTING_DOWN_DECODER; | 
 | 1430 |  | 
 | 1431 |             ALOGV("initiating %s decoder shutdown", audio ? "audio" : "video"); | 
 | 1432 |             if (!audio) { | 
| Andy Hung | 8d121d4 | 2014-10-03 09:53:53 -0700 | [diff] [blame] | 1433 |                 // Widevine source reads must stop before releasing the video decoder. | 
 | 1434 |                 if (mSource != NULL && mSourceFlags & Source::FLAG_SECURE) { | 
 | 1435 |                     mSource->stop(); | 
| Robert Shih | 0c61a0d | 2015-07-06 15:09:10 -0700 | [diff] [blame] | 1436 |                     mSourceStarted = false; | 
| Andy Hung | 8d121d4 | 2014-10-03 09:53:53 -0700 | [diff] [blame] | 1437 |                 } | 
 | 1438 |             } | 
 | 1439 |             getDecoder(audio)->initiateShutdown(); | 
 | 1440 |             break; | 
 | 1441 |         } | 
 | 1442 |  | 
 | 1443 |         default: | 
 | 1444 |             // decoder flush completes only occur in a flushing state. | 
 | 1445 |             LOG_ALWAYS_FATAL_IF(isDecoder, "decoder flush in invalid state %d", *state); | 
 | 1446 |             break; | 
 | 1447 |     } | 
 | 1448 | } | 
 | 1449 |  | 
| Andreas Huber | 3831a06 | 2010-12-21 10:22:33 -0800 | [diff] [blame] | 1450 | void NuPlayer::finishFlushIfPossible() { | 
| Wei Jia | 53904f3 | 2014-07-29 10:22:53 -0700 | [diff] [blame] | 1451 |     if (mFlushingAudio != NONE && mFlushingAudio != FLUSHED | 
 | 1452 |             && mFlushingAudio != SHUT_DOWN) { | 
| Andreas Huber | 3831a06 | 2010-12-21 10:22:33 -0800 | [diff] [blame] | 1453 |         return; | 
 | 1454 |     } | 
 | 1455 |  | 
| Wei Jia | 53904f3 | 2014-07-29 10:22:53 -0700 | [diff] [blame] | 1456 |     if (mFlushingVideo != NONE && mFlushingVideo != FLUSHED | 
 | 1457 |             && mFlushingVideo != SHUT_DOWN) { | 
| Andreas Huber | 3831a06 | 2010-12-21 10:22:33 -0800 | [diff] [blame] | 1458 |         return; | 
 | 1459 |     } | 
 | 1460 |  | 
| Steve Block | 3856b09 | 2011-10-20 11:56:00 +0100 | [diff] [blame] | 1461 |     ALOGV("both audio and video are flushed now."); | 
| Andreas Huber | 3831a06 | 2010-12-21 10:22:33 -0800 | [diff] [blame] | 1462 |  | 
| Andreas Huber | 3831a06 | 2010-12-21 10:22:33 -0800 | [diff] [blame] | 1463 |     mFlushingAudio = NONE; | 
 | 1464 |     mFlushingVideo = NONE; | 
| Andreas Huber | 3831a06 | 2010-12-21 10:22:33 -0800 | [diff] [blame] | 1465 |  | 
| Andy Hung | 8d121d4 | 2014-10-03 09:53:53 -0700 | [diff] [blame] | 1466 |     clearFlushComplete(); | 
 | 1467 |  | 
| Andreas Huber | a1f8ab0 | 2012-11-30 10:53:22 -0800 | [diff] [blame] | 1468 |     processDeferredActions(); | 
| Andreas Huber | 1aef211 | 2011-01-04 14:01:29 -0800 | [diff] [blame] | 1469 | } | 
 | 1470 |  | 
 | 1471 | void NuPlayer::postScanSources() { | 
 | 1472 |     if (mScanSourcesPending) { | 
 | 1473 |         return; | 
 | 1474 |     } | 
 | 1475 |  | 
| Lajos Molnar | 1d15ab5 | 2015-03-04 16:46:34 -0800 | [diff] [blame] | 1476 |     sp<AMessage> msg = new AMessage(kWhatScanSources, this); | 
| Andreas Huber | 1aef211 | 2011-01-04 14:01:29 -0800 | [diff] [blame] | 1477 |     msg->setInt32("generation", mScanSourcesGeneration); | 
 | 1478 |     msg->post(); | 
 | 1479 |  | 
 | 1480 |     mScanSourcesPending = true; | 
 | 1481 | } | 
 | 1482 |  | 
| Andy Hung | 202bce1 | 2014-12-03 11:47:36 -0800 | [diff] [blame] | 1483 | void NuPlayer::tryOpenAudioSinkForOffload(const sp<AMessage> &format, bool hasVideo) { | 
 | 1484 |     // Note: This is called early in NuPlayer to determine whether offloading | 
 | 1485 |     // is possible; otherwise the decoders call the renderer openAudioSink directly. | 
| Andy Hung | 282a7e3 | 2014-08-14 15:56:34 -0700 | [diff] [blame] | 1486 |  | 
| Andy Hung | 202bce1 | 2014-12-03 11:47:36 -0800 | [diff] [blame] | 1487 |     status_t err = mRenderer->openAudioSink( | 
 | 1488 |             format, true /* offloadOnly */, hasVideo, AUDIO_OUTPUT_FLAG_NONE, &mOffloadAudio); | 
 | 1489 |     if (err != OK) { | 
 | 1490 |         // Any failure we turn off mOffloadAudio. | 
 | 1491 |         mOffloadAudio = false; | 
 | 1492 |     } else if (mOffloadAudio) { | 
| Chong Zhang | 3b9eb1f | 2014-10-15 17:05:08 -0700 | [diff] [blame] | 1493 |         sp<MetaData> audioMeta = | 
 | 1494 |                 mSource->getFormatMeta(true /* audio */); | 
 | 1495 |         sendMetaDataToHal(mAudioSink, audioMeta); | 
| Andy Hung | 282a7e3 | 2014-08-14 15:56:34 -0700 | [diff] [blame] | 1496 |     } | 
 | 1497 | } | 
 | 1498 |  | 
 | 1499 | void NuPlayer::closeAudioSink() { | 
| Chong Zhang | 3b9eb1f | 2014-10-15 17:05:08 -0700 | [diff] [blame] | 1500 |     mRenderer->closeAudioSink(); | 
| Andy Hung | 282a7e3 | 2014-08-14 15:56:34 -0700 | [diff] [blame] | 1501 | } | 
 | 1502 |  | 
| Wei Jia | 5031b2f | 2016-02-25 11:19:31 -0800 | [diff] [blame] | 1503 | void NuPlayer::restartAudio( | 
| Wei Jia | bf70feb | 2016-02-19 15:47:16 -0800 | [diff] [blame] | 1504 |         int64_t currentPositionUs, bool forceNonOffload, bool needsToCreateAudioDecoder) { | 
| Wei Jia | a05f1e3 | 2016-03-25 16:31:22 -0700 | [diff] [blame] | 1505 |     if (mAudioDecoder != NULL) { | 
 | 1506 |         mAudioDecoder->pause(); | 
 | 1507 |         mAudioDecoder.clear(); | 
 | 1508 |         ++mAudioDecoderGeneration; | 
 | 1509 |     } | 
| Wei Jia | bf70feb | 2016-02-19 15:47:16 -0800 | [diff] [blame] | 1510 |     if (mFlushingAudio == FLUSHING_DECODER) { | 
 | 1511 |         mFlushComplete[1 /* audio */][1 /* isDecoder */] = true; | 
 | 1512 |         mFlushingAudio = FLUSHED; | 
 | 1513 |         finishFlushIfPossible(); | 
 | 1514 |     } else if (mFlushingAudio == FLUSHING_DECODER_SHUTDOWN | 
 | 1515 |             || mFlushingAudio == SHUTTING_DOWN_DECODER) { | 
 | 1516 |         mFlushComplete[1 /* audio */][1 /* isDecoder */] = true; | 
 | 1517 |         mFlushingAudio = SHUT_DOWN; | 
 | 1518 |         finishFlushIfPossible(); | 
 | 1519 |         needsToCreateAudioDecoder = false; | 
 | 1520 |     } | 
 | 1521 |     if (mRenderer == NULL) { | 
 | 1522 |         return; | 
 | 1523 |     } | 
 | 1524 |     closeAudioSink(); | 
 | 1525 |     mRenderer->flush(true /* audio */, false /* notifyComplete */); | 
 | 1526 |     if (mVideoDecoder != NULL) { | 
 | 1527 |         mRenderer->flush(false /* audio */, false /* notifyComplete */); | 
 | 1528 |     } | 
 | 1529 |  | 
 | 1530 |     performSeek(currentPositionUs); | 
 | 1531 |  | 
 | 1532 |     if (forceNonOffload) { | 
 | 1533 |         mRenderer->signalDisableOffloadAudio(); | 
 | 1534 |         mOffloadAudio = false; | 
 | 1535 |     } | 
 | 1536 |     if (needsToCreateAudioDecoder) { | 
| Wei Jia | a05f1e3 | 2016-03-25 16:31:22 -0700 | [diff] [blame] | 1537 |         instantiateDecoder(true /* audio */, &mAudioDecoder, !forceNonOffload); | 
| Wei Jia | bf70feb | 2016-02-19 15:47:16 -0800 | [diff] [blame] | 1538 |     } | 
 | 1539 | } | 
 | 1540 |  | 
| Wei Jia | e4d18c7 | 2015-07-13 17:58:11 -0700 | [diff] [blame] | 1541 | void NuPlayer::determineAudioModeChange() { | 
 | 1542 |     if (mSource == NULL || mAudioSink == NULL) { | 
 | 1543 |         return; | 
 | 1544 |     } | 
 | 1545 |  | 
 | 1546 |     if (mRenderer == NULL) { | 
 | 1547 |         ALOGW("No renderer can be used to determine audio mode. Use non-offload for safety."); | 
 | 1548 |         mOffloadAudio = false; | 
 | 1549 |         return; | 
 | 1550 |     } | 
 | 1551 |  | 
 | 1552 |     sp<MetaData> audioMeta = mSource->getFormatMeta(true /* audio */); | 
 | 1553 |     sp<AMessage> videoFormat = mSource->getFormat(false /* audio */); | 
 | 1554 |     audio_stream_type_t streamType = mAudioSink->getAudioStreamType(); | 
 | 1555 |     const bool hasVideo = (videoFormat != NULL); | 
 | 1556 |     const bool canOffload = canOffloadStream( | 
| Wei Jia | bf70feb | 2016-02-19 15:47:16 -0800 | [diff] [blame] | 1557 |             audioMeta, hasVideo, mSource->isStreaming(), streamType) | 
 | 1558 |                     && (mPlaybackSettings.mSpeed == 1.f && mPlaybackSettings.mPitch == 1.f); | 
| Wei Jia | e4d18c7 | 2015-07-13 17:58:11 -0700 | [diff] [blame] | 1559 |     if (canOffload) { | 
 | 1560 |         if (!mOffloadAudio) { | 
 | 1561 |             mRenderer->signalEnableOffloadAudio(); | 
 | 1562 |         } | 
 | 1563 |         // open audio sink early under offload mode. | 
 | 1564 |         sp<AMessage> format = mSource->getFormat(true /*audio*/); | 
 | 1565 |         tryOpenAudioSinkForOffload(format, hasVideo); | 
 | 1566 |     } else { | 
| Robert Shih | e1d7019 | 2015-07-23 17:54:13 -0700 | [diff] [blame] | 1567 |         if (mOffloadAudio) { | 
 | 1568 |             mRenderer->signalDisableOffloadAudio(); | 
 | 1569 |             mOffloadAudio = false; | 
 | 1570 |         } | 
| Wei Jia | e4d18c7 | 2015-07-13 17:58:11 -0700 | [diff] [blame] | 1571 |     } | 
 | 1572 | } | 
 | 1573 |  | 
| Wei Jia | a05f1e3 | 2016-03-25 16:31:22 -0700 | [diff] [blame] | 1574 | status_t NuPlayer::instantiateDecoder( | 
 | 1575 |         bool audio, sp<DecoderBase> *decoder, bool checkAudioModeChange) { | 
| Wei Jia | 566da80 | 2015-08-27 13:59:30 -0700 | [diff] [blame] | 1576 |     // The audio decoder could be cleared by tear down. If still in shut down | 
 | 1577 |     // process, no need to create a new audio decoder. | 
 | 1578 |     if (*decoder != NULL || (audio && mFlushingAudio == SHUT_DOWN)) { | 
| Andreas Huber | f933441 | 2010-12-15 15:17:42 -0800 | [diff] [blame] | 1579 |         return OK; | 
 | 1580 |     } | 
 | 1581 |  | 
| Andreas Huber | 8406678 | 2011-08-16 09:34:26 -0700 | [diff] [blame] | 1582 |     sp<AMessage> format = mSource->getFormat(audio); | 
| Andreas Huber | f933441 | 2010-12-15 15:17:42 -0800 | [diff] [blame] | 1583 |  | 
| Andreas Huber | 8406678 | 2011-08-16 09:34:26 -0700 | [diff] [blame] | 1584 |     if (format == NULL) { | 
| Robert Shih | 7350b05 | 2015-10-01 15:50:14 -0700 | [diff] [blame] | 1585 |         return UNKNOWN_ERROR; | 
 | 1586 |     } else { | 
 | 1587 |         status_t err; | 
 | 1588 |         if (format->findInt32("err", &err) && err) { | 
 | 1589 |             return err; | 
 | 1590 |         } | 
| Andreas Huber | f933441 | 2010-12-15 15:17:42 -0800 | [diff] [blame] | 1591 |     } | 
 | 1592 |  | 
| Ronghua Wu | 8db8813 | 2015-04-22 13:51:35 -0700 | [diff] [blame] | 1593 |     format->setInt32("priority", 0 /* realtime */); | 
 | 1594 |  | 
| Andreas Huber | 3fe6215 | 2011-09-16 15:09:22 -0700 | [diff] [blame] | 1595 |     if (!audio) { | 
| Andreas Huber | 8406678 | 2011-08-16 09:34:26 -0700 | [diff] [blame] | 1596 |         AString mime; | 
 | 1597 |         CHECK(format->findString("mime", &mime)); | 
| Chong Zhang | a7fa1d9 | 2014-06-11 14:49:23 -0700 | [diff] [blame] | 1598 |  | 
| Lajos Molnar | 1d15ab5 | 2015-03-04 16:46:34 -0800 | [diff] [blame] | 1599 |         sp<AMessage> ccNotify = new AMessage(kWhatClosedCaptionNotify, this); | 
| Chong Zhang | 341ab6e | 2015-02-04 13:37:18 -0800 | [diff] [blame] | 1600 |         if (mCCDecoder == NULL) { | 
 | 1601 |             mCCDecoder = new CCDecoder(ccNotify); | 
 | 1602 |         } | 
| Lajos Molnar | 0952483 | 2014-07-17 14:29:51 -0700 | [diff] [blame] | 1603 |  | 
 | 1604 |         if (mSourceFlags & Source::FLAG_SECURE) { | 
 | 1605 |             format->setInt32("secure", true); | 
 | 1606 |         } | 
| Chong Zhang | 1713460 | 2015-01-07 16:14:34 -0800 | [diff] [blame] | 1607 |  | 
 | 1608 |         if (mSourceFlags & Source::FLAG_PROTECTED) { | 
 | 1609 |             format->setInt32("protected", true); | 
 | 1610 |         } | 
| Ronghua Wu | 8db8813 | 2015-04-22 13:51:35 -0700 | [diff] [blame] | 1611 |  | 
| Ronghua Wu | c8a70d3 | 2015-04-29 16:26:34 -0700 | [diff] [blame] | 1612 |         float rate = getFrameRate(); | 
 | 1613 |         if (rate > 0) { | 
| Lajos Molnar | 3a474aa | 2015-04-24 17:10:07 -0700 | [diff] [blame] | 1614 |             format->setFloat("operating-rate", rate * mPlaybackSettings.mSpeed); | 
| Ronghua Wu | 8db8813 | 2015-04-22 13:51:35 -0700 | [diff] [blame] | 1615 |         } | 
| Andreas Huber | 3fe6215 | 2011-09-16 15:09:22 -0700 | [diff] [blame] | 1616 |     } | 
 | 1617 |  | 
| Wei Jia | bc2fb72 | 2014-07-08 16:37:57 -0700 | [diff] [blame] | 1618 |     if (audio) { | 
| Lajos Molnar | 1d15ab5 | 2015-03-04 16:46:34 -0800 | [diff] [blame] | 1619 |         sp<AMessage> notify = new AMessage(kWhatAudioNotify, this); | 
| Wei Jia | 88703c3 | 2014-08-06 11:24:07 -0700 | [diff] [blame] | 1620 |         ++mAudioDecoderGeneration; | 
 | 1621 |         notify->setInt32("generation", mAudioDecoderGeneration); | 
 | 1622 |  | 
| Wei Jia | a05f1e3 | 2016-03-25 16:31:22 -0700 | [diff] [blame] | 1623 |         if (checkAudioModeChange) { | 
 | 1624 |             determineAudioModeChange(); | 
 | 1625 |         } | 
| Wei Jia | bc2fb72 | 2014-07-08 16:37:57 -0700 | [diff] [blame] | 1626 |         if (mOffloadAudio) { | 
| Wei Jia | 14532f2 | 2015-12-29 11:28:15 -0800 | [diff] [blame] | 1627 |             mSource->setOffloadAudio(true /* offload */); | 
 | 1628 |  | 
| Haynes Mathew George | 8b63533 | 2015-03-30 17:59:47 -0700 | [diff] [blame] | 1629 |             const bool hasVideo = (mSource->getFormat(false /*audio */) != NULL); | 
 | 1630 |             format->setInt32("has-video", hasVideo); | 
| Wei Jia | c6cfd70 | 2014-11-11 16:33:20 -0800 | [diff] [blame] | 1631 |             *decoder = new DecoderPassThrough(notify, mSource, mRenderer); | 
| Wei Jia | bc2fb72 | 2014-07-08 16:37:57 -0700 | [diff] [blame] | 1632 |         } else { | 
| Wei Jia | 14532f2 | 2015-12-29 11:28:15 -0800 | [diff] [blame] | 1633 |             mSource->setOffloadAudio(false /* offload */); | 
 | 1634 |  | 
| Ronghua Wu | 68845c1 | 2015-07-21 09:50:48 -0700 | [diff] [blame] | 1635 |             *decoder = new Decoder(notify, mSource, mPID, mRenderer); | 
| Wei Jia | bc2fb72 | 2014-07-08 16:37:57 -0700 | [diff] [blame] | 1636 |         } | 
 | 1637 |     } else { | 
| Lajos Molnar | 1d15ab5 | 2015-03-04 16:46:34 -0800 | [diff] [blame] | 1638 |         sp<AMessage> notify = new AMessage(kWhatVideoNotify, this); | 
| Wei Jia | 88703c3 | 2014-08-06 11:24:07 -0700 | [diff] [blame] | 1639 |         ++mVideoDecoderGeneration; | 
 | 1640 |         notify->setInt32("generation", mVideoDecoderGeneration); | 
 | 1641 |  | 
| Chong Zhang | 7137ec7 | 2014-11-12 16:41:05 -0800 | [diff] [blame] | 1642 |         *decoder = new Decoder( | 
| Ronghua Wu | 68845c1 | 2015-07-21 09:50:48 -0700 | [diff] [blame] | 1643 |                 notify, mSource, mPID, mRenderer, mSurface, mCCDecoder); | 
| Lajos Molnar | d9fd631 | 2014-11-06 11:00:00 -0800 | [diff] [blame] | 1644 |  | 
 | 1645 |         // enable FRC if high-quality AV sync is requested, even if not | 
| Lajos Molnar | 1de1e25 | 2015-04-30 18:18:34 -0700 | [diff] [blame] | 1646 |         // directly queuing to display, as this will even improve textureview | 
| Lajos Molnar | d9fd631 | 2014-11-06 11:00:00 -0800 | [diff] [blame] | 1647 |         // playback. | 
 | 1648 |         { | 
 | 1649 |             char value[PROPERTY_VALUE_MAX]; | 
 | 1650 |             if (property_get("persist.sys.media.avsync", value, NULL) && | 
 | 1651 |                     (!strcmp("1", value) || !strcasecmp("true", value))) { | 
 | 1652 |                 format->setInt32("auto-frc", 1); | 
 | 1653 |             } | 
 | 1654 |         } | 
| Wei Jia | bc2fb72 | 2014-07-08 16:37:57 -0700 | [diff] [blame] | 1655 |     } | 
| Lajos Molnar | 1cd1398 | 2014-01-17 15:12:51 -0800 | [diff] [blame] | 1656 |     (*decoder)->init(); | 
| Andreas Huber | 8406678 | 2011-08-16 09:34:26 -0700 | [diff] [blame] | 1657 |     (*decoder)->configure(format); | 
| Andreas Huber | f933441 | 2010-12-15 15:17:42 -0800 | [diff] [blame] | 1658 |  | 
| Lajos Molnar | 0952483 | 2014-07-17 14:29:51 -0700 | [diff] [blame] | 1659 |     // allocate buffers to decrypt widevine source buffers | 
 | 1660 |     if (!audio && (mSourceFlags & Source::FLAG_SECURE)) { | 
 | 1661 |         Vector<sp<ABuffer> > inputBufs; | 
 | 1662 |         CHECK_EQ((*decoder)->getInputBuffers(&inputBufs), (status_t)OK); | 
 | 1663 |  | 
 | 1664 |         Vector<MediaBuffer *> mediaBufs; | 
 | 1665 |         for (size_t i = 0; i < inputBufs.size(); i++) { | 
 | 1666 |             const sp<ABuffer> &buffer = inputBufs[i]; | 
 | 1667 |             MediaBuffer *mbuf = new MediaBuffer(buffer->data(), buffer->size()); | 
 | 1668 |             mediaBufs.push(mbuf); | 
 | 1669 |         } | 
 | 1670 |  | 
 | 1671 |         status_t err = mSource->setBuffers(audio, mediaBufs); | 
 | 1672 |         if (err != OK) { | 
 | 1673 |             for (size_t i = 0; i < mediaBufs.size(); ++i) { | 
 | 1674 |                 mediaBufs[i]->release(); | 
 | 1675 |             } | 
 | 1676 |             mediaBufs.clear(); | 
 | 1677 |             ALOGE("Secure source didn't support secure mediaBufs."); | 
 | 1678 |             return err; | 
 | 1679 |         } | 
 | 1680 |     } | 
| Andreas Huber | f933441 | 2010-12-15 15:17:42 -0800 | [diff] [blame] | 1681 |     return OK; | 
 | 1682 | } | 
 | 1683 |  | 
| Chong Zhang | ced1c2f | 2014-08-08 15:22:35 -0700 | [diff] [blame] | 1684 | void NuPlayer::updateVideoSize( | 
 | 1685 |         const sp<AMessage> &inputFormat, | 
 | 1686 |         const sp<AMessage> &outputFormat) { | 
 | 1687 |     if (inputFormat == NULL) { | 
 | 1688 |         ALOGW("Unknown video size, reporting 0x0!"); | 
 | 1689 |         notifyListener(MEDIA_SET_VIDEO_SIZE, 0, 0); | 
 | 1690 |         return; | 
 | 1691 |     } | 
 | 1692 |  | 
 | 1693 |     int32_t displayWidth, displayHeight; | 
| Chong Zhang | ced1c2f | 2014-08-08 15:22:35 -0700 | [diff] [blame] | 1694 |     if (outputFormat != NULL) { | 
 | 1695 |         int32_t width, height; | 
 | 1696 |         CHECK(outputFormat->findInt32("width", &width)); | 
 | 1697 |         CHECK(outputFormat->findInt32("height", &height)); | 
 | 1698 |  | 
 | 1699 |         int32_t cropLeft, cropTop, cropRight, cropBottom; | 
 | 1700 |         CHECK(outputFormat->findRect( | 
 | 1701 |                     "crop", | 
 | 1702 |                     &cropLeft, &cropTop, &cropRight, &cropBottom)); | 
 | 1703 |  | 
 | 1704 |         displayWidth = cropRight - cropLeft + 1; | 
 | 1705 |         displayHeight = cropBottom - cropTop + 1; | 
 | 1706 |  | 
 | 1707 |         ALOGV("Video output format changed to %d x %d " | 
 | 1708 |              "(crop: %d x %d @ (%d, %d))", | 
 | 1709 |              width, height, | 
 | 1710 |              displayWidth, | 
 | 1711 |              displayHeight, | 
 | 1712 |              cropLeft, cropTop); | 
 | 1713 |     } else { | 
 | 1714 |         CHECK(inputFormat->findInt32("width", &displayWidth)); | 
 | 1715 |         CHECK(inputFormat->findInt32("height", &displayHeight)); | 
 | 1716 |  | 
 | 1717 |         ALOGV("Video input format %d x %d", displayWidth, displayHeight); | 
 | 1718 |     } | 
 | 1719 |  | 
 | 1720 |     // Take into account sample aspect ratio if necessary: | 
 | 1721 |     int32_t sarWidth, sarHeight; | 
 | 1722 |     if (inputFormat->findInt32("sar-width", &sarWidth) | 
 | 1723 |             && inputFormat->findInt32("sar-height", &sarHeight)) { | 
 | 1724 |         ALOGV("Sample aspect ratio %d : %d", sarWidth, sarHeight); | 
 | 1725 |  | 
 | 1726 |         displayWidth = (displayWidth * sarWidth) / sarHeight; | 
 | 1727 |  | 
 | 1728 |         ALOGV("display dimensions %d x %d", displayWidth, displayHeight); | 
 | 1729 |     } | 
 | 1730 |  | 
 | 1731 |     int32_t rotationDegrees; | 
 | 1732 |     if (!inputFormat->findInt32("rotation-degrees", &rotationDegrees)) { | 
 | 1733 |         rotationDegrees = 0; | 
 | 1734 |     } | 
 | 1735 |  | 
 | 1736 |     if (rotationDegrees == 90 || rotationDegrees == 270) { | 
 | 1737 |         int32_t tmp = displayWidth; | 
 | 1738 |         displayWidth = displayHeight; | 
 | 1739 |         displayHeight = tmp; | 
 | 1740 |     } | 
 | 1741 |  | 
 | 1742 |     notifyListener( | 
 | 1743 |             MEDIA_SET_VIDEO_SIZE, | 
 | 1744 |             displayWidth, | 
 | 1745 |             displayHeight); | 
 | 1746 | } | 
 | 1747 |  | 
| Chong Zhang | dcb89b3 | 2013-08-06 09:44:47 -0700 | [diff] [blame] | 1748 | void NuPlayer::notifyListener(int msg, int ext1, int ext2, const Parcel *in) { | 
| Andreas Huber | 43c3e6c | 2011-01-05 12:17:08 -0800 | [diff] [blame] | 1749 |     if (mDriver == NULL) { | 
| Andreas Huber | f933441 | 2010-12-15 15:17:42 -0800 | [diff] [blame] | 1750 |         return; | 
 | 1751 |     } | 
 | 1752 |  | 
| Andreas Huber | 43c3e6c | 2011-01-05 12:17:08 -0800 | [diff] [blame] | 1753 |     sp<NuPlayerDriver> driver = mDriver.promote(); | 
| Andreas Huber | f933441 | 2010-12-15 15:17:42 -0800 | [diff] [blame] | 1754 |  | 
| Andreas Huber | 43c3e6c | 2011-01-05 12:17:08 -0800 | [diff] [blame] | 1755 |     if (driver == NULL) { | 
| Andreas Huber | f933441 | 2010-12-15 15:17:42 -0800 | [diff] [blame] | 1756 |         return; | 
 | 1757 |     } | 
 | 1758 |  | 
| Chong Zhang | dcb89b3 | 2013-08-06 09:44:47 -0700 | [diff] [blame] | 1759 |     driver->notifyListener(msg, ext1, ext2, in); | 
| Andreas Huber | f933441 | 2010-12-15 15:17:42 -0800 | [diff] [blame] | 1760 | } | 
 | 1761 |  | 
| Chong Zhang | 7137ec7 | 2014-11-12 16:41:05 -0800 | [diff] [blame] | 1762 | void NuPlayer::flushDecoder(bool audio, bool needShutdown) { | 
| Andreas Huber | 14f7672 | 2013-01-15 09:04:18 -0800 | [diff] [blame] | 1763 |     ALOGV("[%s] flushDecoder needShutdown=%d", | 
 | 1764 |           audio ? "audio" : "video", needShutdown); | 
 | 1765 |  | 
| Chong Zhang | 7137ec7 | 2014-11-12 16:41:05 -0800 | [diff] [blame] | 1766 |     const sp<DecoderBase> &decoder = getDecoder(audio); | 
| Lajos Molnar | 87603c0 | 2014-08-20 19:25:30 -0700 | [diff] [blame] | 1767 |     if (decoder == NULL) { | 
| Steve Block | df64d15 | 2012-01-04 20:05:49 +0000 | [diff] [blame] | 1768 |         ALOGI("flushDecoder %s without decoder present", | 
| Andreas Huber | 6e3d311 | 2011-11-28 12:36:11 -0800 | [diff] [blame] | 1769 |              audio ? "audio" : "video"); | 
| Lajos Molnar | 87603c0 | 2014-08-20 19:25:30 -0700 | [diff] [blame] | 1770 |         return; | 
| Andreas Huber | 6e3d311 | 2011-11-28 12:36:11 -0800 | [diff] [blame] | 1771 |     } | 
 | 1772 |  | 
| Andreas Huber | 1aef211 | 2011-01-04 14:01:29 -0800 | [diff] [blame] | 1773 |     // Make sure we don't continue to scan sources until we finish flushing. | 
 | 1774 |     ++mScanSourcesGeneration; | 
| Chong Zhang | 3b032b3 | 2015-04-17 15:49:06 -0700 | [diff] [blame] | 1775 |     if (mScanSourcesPending) { | 
 | 1776 |         mDeferredActions.push_back( | 
 | 1777 |                 new SimpleAction(&NuPlayer::performScanSources)); | 
 | 1778 |         mScanSourcesPending = false; | 
 | 1779 |     } | 
| Andreas Huber | 1aef211 | 2011-01-04 14:01:29 -0800 | [diff] [blame] | 1780 |  | 
| Chong Zhang | 7137ec7 | 2014-11-12 16:41:05 -0800 | [diff] [blame] | 1781 |     decoder->signalFlush(); | 
| Andreas Huber | 1aef211 | 2011-01-04 14:01:29 -0800 | [diff] [blame] | 1782 |  | 
 | 1783 |     FlushStatus newStatus = | 
 | 1784 |         needShutdown ? FLUSHING_DECODER_SHUTDOWN : FLUSHING_DECODER; | 
 | 1785 |  | 
| Lajos Molnar | fcd3e94 | 2015-03-31 10:06:48 -0700 | [diff] [blame] | 1786 |     mFlushComplete[audio][false /* isDecoder */] = (mRenderer == NULL); | 
| Andy Hung | 8d121d4 | 2014-10-03 09:53:53 -0700 | [diff] [blame] | 1787 |     mFlushComplete[audio][true /* isDecoder */] = false; | 
| Andreas Huber | 1aef211 | 2011-01-04 14:01:29 -0800 | [diff] [blame] | 1788 |     if (audio) { | 
| Wei Jia | 53904f3 | 2014-07-29 10:22:53 -0700 | [diff] [blame] | 1789 |         ALOGE_IF(mFlushingAudio != NONE, | 
 | 1790 |                 "audio flushDecoder() is called in state %d", mFlushingAudio); | 
| Andreas Huber | 1aef211 | 2011-01-04 14:01:29 -0800 | [diff] [blame] | 1791 |         mFlushingAudio = newStatus; | 
| Andreas Huber | 1aef211 | 2011-01-04 14:01:29 -0800 | [diff] [blame] | 1792 |     } else { | 
| Wei Jia | 53904f3 | 2014-07-29 10:22:53 -0700 | [diff] [blame] | 1793 |         ALOGE_IF(mFlushingVideo != NONE, | 
 | 1794 |                 "video flushDecoder() is called in state %d", mFlushingVideo); | 
| Andreas Huber | 1aef211 | 2011-01-04 14:01:29 -0800 | [diff] [blame] | 1795 |         mFlushingVideo = newStatus; | 
| Andreas Huber | 1aef211 | 2011-01-04 14:01:29 -0800 | [diff] [blame] | 1796 |     } | 
 | 1797 | } | 
 | 1798 |  | 
| Chong Zhang | ced1c2f | 2014-08-08 15:22:35 -0700 | [diff] [blame] | 1799 | void NuPlayer::queueDecoderShutdown( | 
 | 1800 |         bool audio, bool video, const sp<AMessage> &reply) { | 
 | 1801 |     ALOGI("queueDecoderShutdown audio=%d, video=%d", audio, video); | 
| Andreas Huber | 8406678 | 2011-08-16 09:34:26 -0700 | [diff] [blame] | 1802 |  | 
| Chong Zhang | ced1c2f | 2014-08-08 15:22:35 -0700 | [diff] [blame] | 1803 |     mDeferredActions.push_back( | 
| Wei Jia | fef808d | 2014-10-31 17:57:05 -0700 | [diff] [blame] | 1804 |             new FlushDecoderAction( | 
 | 1805 |                 audio ? FLUSH_CMD_SHUTDOWN : FLUSH_CMD_NONE, | 
 | 1806 |                 video ? FLUSH_CMD_SHUTDOWN : FLUSH_CMD_NONE)); | 
| Andreas Huber | 8406678 | 2011-08-16 09:34:26 -0700 | [diff] [blame] | 1807 |  | 
| Chong Zhang | ced1c2f | 2014-08-08 15:22:35 -0700 | [diff] [blame] | 1808 |     mDeferredActions.push_back( | 
 | 1809 |             new SimpleAction(&NuPlayer::performScanSources)); | 
| Andreas Huber | 8406678 | 2011-08-16 09:34:26 -0700 | [diff] [blame] | 1810 |  | 
| Chong Zhang | ced1c2f | 2014-08-08 15:22:35 -0700 | [diff] [blame] | 1811 |     mDeferredActions.push_back(new PostMessageAction(reply)); | 
 | 1812 |  | 
 | 1813 |     processDeferredActions(); | 
| Andreas Huber | 8406678 | 2011-08-16 09:34:26 -0700 | [diff] [blame] | 1814 | } | 
 | 1815 |  | 
| James Dong | 0d268a3 | 2012-08-31 12:18:27 -0700 | [diff] [blame] | 1816 | status_t NuPlayer::setVideoScalingMode(int32_t mode) { | 
 | 1817 |     mVideoScalingMode = mode; | 
| Lajos Molnar | 1de1e25 | 2015-04-30 18:18:34 -0700 | [diff] [blame] | 1818 |     if (mSurface != NULL) { | 
 | 1819 |         status_t ret = native_window_set_scaling_mode(mSurface.get(), mVideoScalingMode); | 
| James Dong | 0d268a3 | 2012-08-31 12:18:27 -0700 | [diff] [blame] | 1820 |         if (ret != OK) { | 
 | 1821 |             ALOGE("Failed to set scaling mode (%d): %s", | 
 | 1822 |                 -ret, strerror(-ret)); | 
 | 1823 |             return ret; | 
 | 1824 |         } | 
 | 1825 |     } | 
 | 1826 |     return OK; | 
 | 1827 | } | 
 | 1828 |  | 
| Chong Zhang | dcb89b3 | 2013-08-06 09:44:47 -0700 | [diff] [blame] | 1829 | status_t NuPlayer::getTrackInfo(Parcel* reply) const { | 
| Lajos Molnar | 1d15ab5 | 2015-03-04 16:46:34 -0800 | [diff] [blame] | 1830 |     sp<AMessage> msg = new AMessage(kWhatGetTrackInfo, this); | 
| Chong Zhang | dcb89b3 | 2013-08-06 09:44:47 -0700 | [diff] [blame] | 1831 |     msg->setPointer("reply", reply); | 
 | 1832 |  | 
 | 1833 |     sp<AMessage> response; | 
 | 1834 |     status_t err = msg->postAndAwaitResponse(&response); | 
 | 1835 |     return err; | 
 | 1836 | } | 
 | 1837 |  | 
| Robert Shih | 7c4f0d7 | 2014-07-09 18:53:31 -0700 | [diff] [blame] | 1838 | status_t NuPlayer::getSelectedTrack(int32_t type, Parcel* reply) const { | 
| Lajos Molnar | 1d15ab5 | 2015-03-04 16:46:34 -0800 | [diff] [blame] | 1839 |     sp<AMessage> msg = new AMessage(kWhatGetSelectedTrack, this); | 
| Robert Shih | 7c4f0d7 | 2014-07-09 18:53:31 -0700 | [diff] [blame] | 1840 |     msg->setPointer("reply", reply); | 
 | 1841 |     msg->setInt32("type", type); | 
 | 1842 |  | 
 | 1843 |     sp<AMessage> response; | 
 | 1844 |     status_t err = msg->postAndAwaitResponse(&response); | 
 | 1845 |     if (err == OK && response != NULL) { | 
 | 1846 |         CHECK(response->findInt32("err", &err)); | 
 | 1847 |     } | 
 | 1848 |     return err; | 
 | 1849 | } | 
 | 1850 |  | 
| Robert Shih | 6ffb1fd | 2014-10-29 16:24:32 -0700 | [diff] [blame] | 1851 | status_t NuPlayer::selectTrack(size_t trackIndex, bool select, int64_t timeUs) { | 
| Lajos Molnar | 1d15ab5 | 2015-03-04 16:46:34 -0800 | [diff] [blame] | 1852 |     sp<AMessage> msg = new AMessage(kWhatSelectTrack, this); | 
| Chong Zhang | dcb89b3 | 2013-08-06 09:44:47 -0700 | [diff] [blame] | 1853 |     msg->setSize("trackIndex", trackIndex); | 
 | 1854 |     msg->setInt32("select", select); | 
| Robert Shih | 6ffb1fd | 2014-10-29 16:24:32 -0700 | [diff] [blame] | 1855 |     msg->setInt64("timeUs", timeUs); | 
| Chong Zhang | dcb89b3 | 2013-08-06 09:44:47 -0700 | [diff] [blame] | 1856 |  | 
 | 1857 |     sp<AMessage> response; | 
 | 1858 |     status_t err = msg->postAndAwaitResponse(&response); | 
 | 1859 |  | 
| Chong Zhang | 404fced | 2014-06-11 14:45:31 -0700 | [diff] [blame] | 1860 |     if (err != OK) { | 
 | 1861 |         return err; | 
 | 1862 |     } | 
 | 1863 |  | 
 | 1864 |     if (!response->findInt32("err", &err)) { | 
 | 1865 |         err = OK; | 
 | 1866 |     } | 
 | 1867 |  | 
| Chong Zhang | dcb89b3 | 2013-08-06 09:44:47 -0700 | [diff] [blame] | 1868 |     return err; | 
 | 1869 | } | 
 | 1870 |  | 
| Ronghua Wu | a73d9e0 | 2014-10-08 15:13:29 -0700 | [diff] [blame] | 1871 | status_t NuPlayer::getCurrentPosition(int64_t *mediaUs) { | 
 | 1872 |     sp<Renderer> renderer = mRenderer; | 
 | 1873 |     if (renderer == NULL) { | 
 | 1874 |         return NO_INIT; | 
 | 1875 |     } | 
 | 1876 |  | 
 | 1877 |     return renderer->getCurrentPosition(mediaUs); | 
 | 1878 | } | 
 | 1879 |  | 
| Praveen Chavan | e1e5d7a | 2015-05-19 19:09:48 -0700 | [diff] [blame] | 1880 | void NuPlayer::getStats(Vector<sp<AMessage> > *mTrackStats) { | 
 | 1881 |     CHECK(mTrackStats != NULL); | 
 | 1882 |  | 
 | 1883 |     mTrackStats->clear(); | 
 | 1884 |     if (mVideoDecoder != NULL) { | 
 | 1885 |         mTrackStats->push_back(mVideoDecoder->getStats()); | 
 | 1886 |     } | 
 | 1887 |     if (mAudioDecoder != NULL) { | 
 | 1888 |         mTrackStats->push_back(mAudioDecoder->getStats()); | 
| Chong Zhang | 7137ec7 | 2014-11-12 16:41:05 -0800 | [diff] [blame] | 1889 |     } | 
| Ronghua Wu | a73d9e0 | 2014-10-08 15:13:29 -0700 | [diff] [blame] | 1890 | } | 
 | 1891 |  | 
| Marco Nelissen | f0b72b5 | 2014-09-16 15:43:44 -0700 | [diff] [blame] | 1892 | sp<MetaData> NuPlayer::getFileMeta() { | 
 | 1893 |     return mSource->getFileFormatMeta(); | 
 | 1894 | } | 
 | 1895 |  | 
| Ronghua Wu | c8a70d3 | 2015-04-29 16:26:34 -0700 | [diff] [blame] | 1896 | float NuPlayer::getFrameRate() { | 
 | 1897 |     sp<MetaData> meta = mSource->getFormatMeta(false /* audio */); | 
 | 1898 |     if (meta == NULL) { | 
 | 1899 |         return 0; | 
 | 1900 |     } | 
 | 1901 |     int32_t rate; | 
 | 1902 |     if (!meta->findInt32(kKeyFrameRate, &rate)) { | 
 | 1903 |         // fall back to try file meta | 
 | 1904 |         sp<MetaData> fileMeta = getFileMeta(); | 
 | 1905 |         if (fileMeta == NULL) { | 
 | 1906 |             ALOGW("source has video meta but not file meta"); | 
 | 1907 |             return -1; | 
 | 1908 |         } | 
 | 1909 |         int32_t fileMetaRate; | 
 | 1910 |         if (!fileMeta->findInt32(kKeyFrameRate, &fileMetaRate)) { | 
 | 1911 |             return -1; | 
 | 1912 |         } | 
 | 1913 |         return fileMetaRate; | 
 | 1914 |     } | 
 | 1915 |     return rate; | 
 | 1916 | } | 
 | 1917 |  | 
| Andreas Huber | b7c8e91 | 2012-11-27 15:02:53 -0800 | [diff] [blame] | 1918 | void NuPlayer::schedulePollDuration() { | 
| Lajos Molnar | 1d15ab5 | 2015-03-04 16:46:34 -0800 | [diff] [blame] | 1919 |     sp<AMessage> msg = new AMessage(kWhatPollDuration, this); | 
| Andreas Huber | b7c8e91 | 2012-11-27 15:02:53 -0800 | [diff] [blame] | 1920 |     msg->setInt32("generation", mPollDurationGeneration); | 
 | 1921 |     msg->post(); | 
 | 1922 | } | 
 | 1923 |  | 
 | 1924 | void NuPlayer::cancelPollDuration() { | 
 | 1925 |     ++mPollDurationGeneration; | 
 | 1926 | } | 
 | 1927 |  | 
| Andreas Huber | a1f8ab0 | 2012-11-30 10:53:22 -0800 | [diff] [blame] | 1928 | void NuPlayer::processDeferredActions() { | 
 | 1929 |     while (!mDeferredActions.empty()) { | 
 | 1930 |         // We won't execute any deferred actions until we're no longer in | 
 | 1931 |         // an intermediate state, i.e. one more more decoders are currently | 
 | 1932 |         // flushing or shutting down. | 
 | 1933 |  | 
| Andreas Huber | a1f8ab0 | 2012-11-30 10:53:22 -0800 | [diff] [blame] | 1934 |         if (mFlushingAudio != NONE || mFlushingVideo != NONE) { | 
 | 1935 |             // We're currently flushing, postpone the reset until that's | 
 | 1936 |             // completed. | 
 | 1937 |  | 
 | 1938 |             ALOGV("postponing action mFlushingAudio=%d, mFlushingVideo=%d", | 
 | 1939 |                   mFlushingAudio, mFlushingVideo); | 
 | 1940 |  | 
 | 1941 |             break; | 
 | 1942 |         } | 
 | 1943 |  | 
 | 1944 |         sp<Action> action = *mDeferredActions.begin(); | 
 | 1945 |         mDeferredActions.erase(mDeferredActions.begin()); | 
 | 1946 |  | 
 | 1947 |         action->execute(this); | 
 | 1948 |     } | 
 | 1949 | } | 
 | 1950 |  | 
| Wei Jia | 2984080 | 2015-05-15 17:11:38 -0700 | [diff] [blame] | 1951 | void NuPlayer::performSeek(int64_t seekTimeUs) { | 
 | 1952 |     ALOGV("performSeek seekTimeUs=%lld us (%.2f secs)", | 
| Lajos Molnar | 6d339f1 | 2015-04-17 16:15:53 -0700 | [diff] [blame] | 1953 |           (long long)seekTimeUs, | 
| Wei Jia | 2984080 | 2015-05-15 17:11:38 -0700 | [diff] [blame] | 1954 |           seekTimeUs / 1E6); | 
| Andreas Huber | a1f8ab0 | 2012-11-30 10:53:22 -0800 | [diff] [blame] | 1955 |  | 
| Andy Hung | adf34bf | 2014-09-03 18:22:22 -0700 | [diff] [blame] | 1956 |     if (mSource == NULL) { | 
 | 1957 |         // This happens when reset occurs right before the loop mode | 
 | 1958 |         // asynchronously seeks to the start of the stream. | 
 | 1959 |         LOG_ALWAYS_FATAL_IF(mAudioDecoder != NULL || mVideoDecoder != NULL, | 
 | 1960 |                 "mSource is NULL and decoders not NULL audio(%p) video(%p)", | 
 | 1961 |                 mAudioDecoder.get(), mVideoDecoder.get()); | 
 | 1962 |         return; | 
 | 1963 |     } | 
| Robert Shih | 1a5c859 | 2015-08-04 18:07:44 -0700 | [diff] [blame] | 1964 |     mPreviousSeekTimeUs = seekTimeUs; | 
| Andreas Huber | a1f8ab0 | 2012-11-30 10:53:22 -0800 | [diff] [blame] | 1965 |     mSource->seekTo(seekTimeUs); | 
| Wei Jia | 351ce87 | 2016-02-10 13:21:59 -0800 | [diff] [blame] | 1966 |     mPendingBufferingFlag = PENDING_BUFFERING_FLAG_NONE; | 
| Robert Shih | d3b0bbb | 2014-07-23 15:00:25 -0700 | [diff] [blame] | 1967 |     ++mTimedTextGeneration; | 
| Andreas Huber | a1f8ab0 | 2012-11-30 10:53:22 -0800 | [diff] [blame] | 1968 |  | 
| Andreas Huber | a1f8ab0 | 2012-11-30 10:53:22 -0800 | [diff] [blame] | 1969 |     // everything's flushed, continue playback. | 
 | 1970 | } | 
 | 1971 |  | 
| Wei Jia | fef808d | 2014-10-31 17:57:05 -0700 | [diff] [blame] | 1972 | void NuPlayer::performDecoderFlush(FlushCommand audio, FlushCommand video) { | 
 | 1973 |     ALOGV("performDecoderFlush audio=%d, video=%d", audio, video); | 
| Andreas Huber | a1f8ab0 | 2012-11-30 10:53:22 -0800 | [diff] [blame] | 1974 |  | 
| Wei Jia | fef808d | 2014-10-31 17:57:05 -0700 | [diff] [blame] | 1975 |     if ((audio == FLUSH_CMD_NONE || mAudioDecoder == NULL) | 
 | 1976 |             && (video == FLUSH_CMD_NONE || mVideoDecoder == NULL)) { | 
| Andreas Huber | a1f8ab0 | 2012-11-30 10:53:22 -0800 | [diff] [blame] | 1977 |         return; | 
 | 1978 |     } | 
 | 1979 |  | 
| Wei Jia | fef808d | 2014-10-31 17:57:05 -0700 | [diff] [blame] | 1980 |     if (audio != FLUSH_CMD_NONE && mAudioDecoder != NULL) { | 
 | 1981 |         flushDecoder(true /* audio */, (audio == FLUSH_CMD_SHUTDOWN)); | 
| Andreas Huber | a1f8ab0 | 2012-11-30 10:53:22 -0800 | [diff] [blame] | 1982 |     } | 
 | 1983 |  | 
| Wei Jia | fef808d | 2014-10-31 17:57:05 -0700 | [diff] [blame] | 1984 |     if (video != FLUSH_CMD_NONE && mVideoDecoder != NULL) { | 
 | 1985 |         flushDecoder(false /* audio */, (video == FLUSH_CMD_SHUTDOWN)); | 
| Andreas Huber | a1f8ab0 | 2012-11-30 10:53:22 -0800 | [diff] [blame] | 1986 |     } | 
 | 1987 | } | 
 | 1988 |  | 
 | 1989 | void NuPlayer::performReset() { | 
 | 1990 |     ALOGV("performReset"); | 
 | 1991 |  | 
 | 1992 |     CHECK(mAudioDecoder == NULL); | 
 | 1993 |     CHECK(mVideoDecoder == NULL); | 
 | 1994 |  | 
 | 1995 |     cancelPollDuration(); | 
 | 1996 |  | 
 | 1997 |     ++mScanSourcesGeneration; | 
 | 1998 |     mScanSourcesPending = false; | 
 | 1999 |  | 
| Lajos Molnar | 0952483 | 2014-07-17 14:29:51 -0700 | [diff] [blame] | 2000 |     if (mRendererLooper != NULL) { | 
 | 2001 |         if (mRenderer != NULL) { | 
 | 2002 |             mRendererLooper->unregisterHandler(mRenderer->id()); | 
 | 2003 |         } | 
 | 2004 |         mRendererLooper->stop(); | 
 | 2005 |         mRendererLooper.clear(); | 
 | 2006 |     } | 
| Andreas Huber | a1f8ab0 | 2012-11-30 10:53:22 -0800 | [diff] [blame] | 2007 |     mRenderer.clear(); | 
| Wei Jia | 57568df | 2014-09-22 10:16:29 -0700 | [diff] [blame] | 2008 |     ++mRendererGeneration; | 
| Andreas Huber | a1f8ab0 | 2012-11-30 10:53:22 -0800 | [diff] [blame] | 2009 |  | 
 | 2010 |     if (mSource != NULL) { | 
 | 2011 |         mSource->stop(); | 
| Andreas Huber | b5f25f0 | 2013-02-05 10:14:26 -0800 | [diff] [blame] | 2012 |  | 
| Wei Jia | c45a4b2 | 2016-04-15 15:30:23 -0700 | [diff] [blame] | 2013 |         Mutex::Autolock autoLock(mSourceLock); | 
| Andreas Huber | a1f8ab0 | 2012-11-30 10:53:22 -0800 | [diff] [blame] | 2014 |         mSource.clear(); | 
 | 2015 |     } | 
 | 2016 |  | 
 | 2017 |     if (mDriver != NULL) { | 
 | 2018 |         sp<NuPlayerDriver> driver = mDriver.promote(); | 
 | 2019 |         if (driver != NULL) { | 
 | 2020 |             driver->notifyResetComplete(); | 
 | 2021 |         } | 
 | 2022 |     } | 
| Andreas Huber | 57a339c | 2012-12-03 11:18:00 -0800 | [diff] [blame] | 2023 |  | 
 | 2024 |     mStarted = false; | 
| Ronghua Wu | 64c2d17 | 2015-10-07 16:52:19 -0700 | [diff] [blame] | 2025 |     mResetting = false; | 
| Robert Shih | 0c61a0d | 2015-07-06 15:09:10 -0700 | [diff] [blame] | 2026 |     mSourceStarted = false; | 
| Andreas Huber | a1f8ab0 | 2012-11-30 10:53:22 -0800 | [diff] [blame] | 2027 | } | 
 | 2028 |  | 
 | 2029 | void NuPlayer::performScanSources() { | 
 | 2030 |     ALOGV("performScanSources"); | 
 | 2031 |  | 
| Andreas Huber | 57a339c | 2012-12-03 11:18:00 -0800 | [diff] [blame] | 2032 |     if (!mStarted) { | 
 | 2033 |         return; | 
 | 2034 |     } | 
 | 2035 |  | 
| Andreas Huber | a1f8ab0 | 2012-11-30 10:53:22 -0800 | [diff] [blame] | 2036 |     if (mAudioDecoder == NULL || mVideoDecoder == NULL) { | 
 | 2037 |         postScanSources(); | 
 | 2038 |     } | 
 | 2039 | } | 
 | 2040 |  | 
| Lajos Molnar | 1de1e25 | 2015-04-30 18:18:34 -0700 | [diff] [blame] | 2041 | void NuPlayer::performSetSurface(const sp<Surface> &surface) { | 
| Andreas Huber | 57a339c | 2012-12-03 11:18:00 -0800 | [diff] [blame] | 2042 |     ALOGV("performSetSurface"); | 
 | 2043 |  | 
| Lajos Molnar | 1de1e25 | 2015-04-30 18:18:34 -0700 | [diff] [blame] | 2044 |     mSurface = surface; | 
| Andreas Huber | 57a339c | 2012-12-03 11:18:00 -0800 | [diff] [blame] | 2045 |  | 
 | 2046 |     // XXX - ignore error from setVideoScalingMode for now | 
 | 2047 |     setVideoScalingMode(mVideoScalingMode); | 
| Chong Zhang | 13d6faa | 2014-08-22 15:35:28 -0700 | [diff] [blame] | 2048 |  | 
 | 2049 |     if (mDriver != NULL) { | 
 | 2050 |         sp<NuPlayerDriver> driver = mDriver.promote(); | 
 | 2051 |         if (driver != NULL) { | 
 | 2052 |             driver->notifySetSurfaceComplete(); | 
 | 2053 |         } | 
 | 2054 |     } | 
| Andreas Huber | 57a339c | 2012-12-03 11:18:00 -0800 | [diff] [blame] | 2055 | } | 
 | 2056 |  | 
| Chong Zhang | f8d7177 | 2014-11-26 15:08:34 -0800 | [diff] [blame] | 2057 | void NuPlayer::performResumeDecoders(bool needNotify) { | 
 | 2058 |     if (needNotify) { | 
 | 2059 |         mResumePending = true; | 
 | 2060 |         if (mVideoDecoder == NULL) { | 
 | 2061 |             // if audio-only, we can notify seek complete now, | 
 | 2062 |             // as the resume operation will be relatively fast. | 
 | 2063 |             finishResume(); | 
 | 2064 |         } | 
 | 2065 |     } | 
 | 2066 |  | 
| Chong Zhang | 7137ec7 | 2014-11-12 16:41:05 -0800 | [diff] [blame] | 2067 |     if (mVideoDecoder != NULL) { | 
| Chong Zhang | f8d7177 | 2014-11-26 15:08:34 -0800 | [diff] [blame] | 2068 |         // When there is continuous seek, MediaPlayer will cache the seek | 
 | 2069 |         // position, and send down new seek request when previous seek is | 
 | 2070 |         // complete. Let's wait for at least one video output frame before | 
 | 2071 |         // notifying seek complete, so that the video thumbnail gets updated | 
 | 2072 |         // when seekbar is dragged. | 
 | 2073 |         mVideoDecoder->signalResume(needNotify); | 
| Chong Zhang | 7137ec7 | 2014-11-12 16:41:05 -0800 | [diff] [blame] | 2074 |     } | 
 | 2075 |  | 
 | 2076 |     if (mAudioDecoder != NULL) { | 
| Chong Zhang | f8d7177 | 2014-11-26 15:08:34 -0800 | [diff] [blame] | 2077 |         mAudioDecoder->signalResume(false /* needNotify */); | 
 | 2078 |     } | 
 | 2079 | } | 
 | 2080 |  | 
 | 2081 | void NuPlayer::finishResume() { | 
 | 2082 |     if (mResumePending) { | 
 | 2083 |         mResumePending = false; | 
| Wei Jia | 1061c9c | 2015-05-19 16:02:17 -0700 | [diff] [blame] | 2084 |         notifyDriverSeekComplete(); | 
 | 2085 |     } | 
 | 2086 | } | 
 | 2087 |  | 
 | 2088 | void NuPlayer::notifyDriverSeekComplete() { | 
 | 2089 |     if (mDriver != NULL) { | 
 | 2090 |         sp<NuPlayerDriver> driver = mDriver.promote(); | 
 | 2091 |         if (driver != NULL) { | 
 | 2092 |             driver->notifySeekComplete(); | 
| Chong Zhang | f8d7177 | 2014-11-26 15:08:34 -0800 | [diff] [blame] | 2093 |         } | 
| Chong Zhang | 7137ec7 | 2014-11-12 16:41:05 -0800 | [diff] [blame] | 2094 |     } | 
 | 2095 | } | 
 | 2096 |  | 
| Andreas Huber | 9575c96 | 2013-02-05 13:59:56 -0800 | [diff] [blame] | 2097 | void NuPlayer::onSourceNotify(const sp<AMessage> &msg) { | 
 | 2098 |     int32_t what; | 
 | 2099 |     CHECK(msg->findInt32("what", &what)); | 
 | 2100 |  | 
 | 2101 |     switch (what) { | 
| Lajos Molnar | fcd3e94 | 2015-03-31 10:06:48 -0700 | [diff] [blame] | 2102 |         case Source::kWhatInstantiateSecureDecoders: | 
 | 2103 |         { | 
 | 2104 |             if (mSource == NULL) { | 
 | 2105 |                 // This is a stale notification from a source that was | 
 | 2106 |                 // asynchronously preparing when the client called reset(). | 
 | 2107 |                 // We handled the reset, the source is gone. | 
 | 2108 |                 break; | 
 | 2109 |             } | 
 | 2110 |  | 
 | 2111 |             sp<AMessage> reply; | 
 | 2112 |             CHECK(msg->findMessage("reply", &reply)); | 
 | 2113 |             status_t err = onInstantiateSecureDecoders(); | 
 | 2114 |             reply->setInt32("err", err); | 
 | 2115 |             reply->post(); | 
 | 2116 |             break; | 
 | 2117 |         } | 
 | 2118 |  | 
| Andreas Huber | 9575c96 | 2013-02-05 13:59:56 -0800 | [diff] [blame] | 2119 |         case Source::kWhatPrepared: | 
 | 2120 |         { | 
| Andreas Huber | b5f28d4 | 2013-04-25 15:11:19 -0700 | [diff] [blame] | 2121 |             if (mSource == NULL) { | 
 | 2122 |                 // This is a stale notification from a source that was | 
 | 2123 |                 // asynchronously preparing when the client called reset(). | 
 | 2124 |                 // We handled the reset, the source is gone. | 
 | 2125 |                 break; | 
 | 2126 |             } | 
 | 2127 |  | 
| Andreas Huber | ec0c597 | 2013-02-05 14:47:13 -0800 | [diff] [blame] | 2128 |             int32_t err; | 
 | 2129 |             CHECK(msg->findInt32("err", &err)); | 
 | 2130 |  | 
| Lajos Molnar | fcd3e94 | 2015-03-31 10:06:48 -0700 | [diff] [blame] | 2131 |             if (err != OK) { | 
 | 2132 |                 // shut down potential secure codecs in case client never calls reset | 
 | 2133 |                 mDeferredActions.push_back( | 
 | 2134 |                         new FlushDecoderAction(FLUSH_CMD_SHUTDOWN /* audio */, | 
 | 2135 |                                                FLUSH_CMD_SHUTDOWN /* video */)); | 
 | 2136 |                 processDeferredActions(); | 
 | 2137 |             } | 
 | 2138 |  | 
| Andreas Huber | 9575c96 | 2013-02-05 13:59:56 -0800 | [diff] [blame] | 2139 |             sp<NuPlayerDriver> driver = mDriver.promote(); | 
 | 2140 |             if (driver != NULL) { | 
| Marco Nelissen | dd114d1 | 2014-05-28 15:23:14 -0700 | [diff] [blame] | 2141 |                 // notify duration first, so that it's definitely set when | 
 | 2142 |                 // the app received the "prepare complete" callback. | 
 | 2143 |                 int64_t durationUs; | 
 | 2144 |                 if (mSource->getDuration(&durationUs) == OK) { | 
 | 2145 |                     driver->notifyDuration(durationUs); | 
 | 2146 |                 } | 
| Andreas Huber | ec0c597 | 2013-02-05 14:47:13 -0800 | [diff] [blame] | 2147 |                 driver->notifyPrepareCompleted(err); | 
| Andreas Huber | 9575c96 | 2013-02-05 13:59:56 -0800 | [diff] [blame] | 2148 |             } | 
| Andreas Huber | 9975940 | 2013-04-01 14:28:31 -0700 | [diff] [blame] | 2149 |  | 
| Andreas Huber | 9575c96 | 2013-02-05 13:59:56 -0800 | [diff] [blame] | 2150 |             break; | 
 | 2151 |         } | 
 | 2152 |  | 
 | 2153 |         case Source::kWhatFlagsChanged: | 
 | 2154 |         { | 
 | 2155 |             uint32_t flags; | 
 | 2156 |             CHECK(msg->findInt32("flags", (int32_t *)&flags)); | 
 | 2157 |  | 
| Chong Zhang | 4b7069d | 2013-09-11 12:52:43 -0700 | [diff] [blame] | 2158 |             sp<NuPlayerDriver> driver = mDriver.promote(); | 
 | 2159 |             if (driver != NULL) { | 
| Wei Jia | 895651b | 2014-12-10 17:31:52 -0800 | [diff] [blame] | 2160 |                 if ((flags & NuPlayer::Source::FLAG_CAN_SEEK) == 0) { | 
 | 2161 |                     driver->notifyListener( | 
 | 2162 |                             MEDIA_INFO, MEDIA_INFO_NOT_SEEKABLE, 0); | 
 | 2163 |                 } | 
| Chong Zhang | 4b7069d | 2013-09-11 12:52:43 -0700 | [diff] [blame] | 2164 |                 driver->notifyFlagsChanged(flags); | 
 | 2165 |             } | 
 | 2166 |  | 
| Andreas Huber | 9575c96 | 2013-02-05 13:59:56 -0800 | [diff] [blame] | 2167 |             if ((mSourceFlags & Source::FLAG_DYNAMIC_DURATION) | 
 | 2168 |                     && (!(flags & Source::FLAG_DYNAMIC_DURATION))) { | 
 | 2169 |                 cancelPollDuration(); | 
 | 2170 |             } else if (!(mSourceFlags & Source::FLAG_DYNAMIC_DURATION) | 
 | 2171 |                     && (flags & Source::FLAG_DYNAMIC_DURATION) | 
 | 2172 |                     && (mAudioDecoder != NULL || mVideoDecoder != NULL)) { | 
 | 2173 |                 schedulePollDuration(); | 
 | 2174 |             } | 
 | 2175 |  | 
 | 2176 |             mSourceFlags = flags; | 
 | 2177 |             break; | 
 | 2178 |         } | 
 | 2179 |  | 
 | 2180 |         case Source::kWhatVideoSizeChanged: | 
 | 2181 |         { | 
| Chong Zhang | ced1c2f | 2014-08-08 15:22:35 -0700 | [diff] [blame] | 2182 |             sp<AMessage> format; | 
 | 2183 |             CHECK(msg->findMessage("format", &format)); | 
| Andreas Huber | 9575c96 | 2013-02-05 13:59:56 -0800 | [diff] [blame] | 2184 |  | 
| Chong Zhang | ced1c2f | 2014-08-08 15:22:35 -0700 | [diff] [blame] | 2185 |             updateVideoSize(format); | 
| Andreas Huber | 9575c96 | 2013-02-05 13:59:56 -0800 | [diff] [blame] | 2186 |             break; | 
 | 2187 |         } | 
 | 2188 |  | 
| Chong Zhang | 2a3cc9a | 2014-08-21 17:48:26 -0700 | [diff] [blame] | 2189 |         case Source::kWhatBufferingUpdate: | 
 | 2190 |         { | 
 | 2191 |             int32_t percentage; | 
 | 2192 |             CHECK(msg->findInt32("percentage", &percentage)); | 
 | 2193 |  | 
 | 2194 |             notifyListener(MEDIA_BUFFERING_UPDATE, percentage, 0); | 
 | 2195 |             break; | 
 | 2196 |         } | 
 | 2197 |  | 
| Chong Zhang | efbb619 | 2015-01-30 17:13:27 -0800 | [diff] [blame] | 2198 |         case Source::kWhatPauseOnBufferingStart: | 
 | 2199 |         { | 
 | 2200 |             // ignore if not playing | 
| Chong Zhang | 8a04833 | 2015-05-06 15:16:28 -0700 | [diff] [blame] | 2201 |             if (mStarted) { | 
| Chong Zhang | efbb619 | 2015-01-30 17:13:27 -0800 | [diff] [blame] | 2202 |                 ALOGI("buffer low, pausing..."); | 
 | 2203 |  | 
| Chong Zhang | 8a04833 | 2015-05-06 15:16:28 -0700 | [diff] [blame] | 2204 |                 mPausedForBuffering = true; | 
| Chong Zhang | efbb619 | 2015-01-30 17:13:27 -0800 | [diff] [blame] | 2205 |                 onPause(); | 
 | 2206 |             } | 
| Wei Jia | e67ba38 | 2016-02-03 01:41:49 +0000 | [diff] [blame] | 2207 |             // fall-thru | 
 | 2208 |         } | 
| Chong Zhang | efbb619 | 2015-01-30 17:13:27 -0800 | [diff] [blame] | 2209 |  | 
| Wei Jia | e67ba38 | 2016-02-03 01:41:49 +0000 | [diff] [blame] | 2210 |         case Source::kWhatBufferingStart: | 
 | 2211 |         { | 
| Wei Jia | 71c75e0 | 2016-02-04 09:40:47 -0800 | [diff] [blame] | 2212 |             if (mPausedByClient) { | 
 | 2213 |                 mPendingBufferingFlag = PENDING_BUFFERING_FLAG_START; | 
 | 2214 |             } else { | 
 | 2215 |                 notifyListener(MEDIA_INFO, MEDIA_INFO_BUFFERING_START, 0); | 
 | 2216 |                 mPendingBufferingFlag = PENDING_BUFFERING_FLAG_NONE; | 
 | 2217 |             } | 
| Roger Jönsson | b50e83e | 2013-01-21 16:26:41 +0100 | [diff] [blame] | 2218 |             break; | 
 | 2219 |         } | 
 | 2220 |  | 
| Chong Zhang | efbb619 | 2015-01-30 17:13:27 -0800 | [diff] [blame] | 2221 |         case Source::kWhatResumeOnBufferingEnd: | 
 | 2222 |         { | 
 | 2223 |             // ignore if not playing | 
| Chong Zhang | 8a04833 | 2015-05-06 15:16:28 -0700 | [diff] [blame] | 2224 |             if (mStarted) { | 
| Chong Zhang | efbb619 | 2015-01-30 17:13:27 -0800 | [diff] [blame] | 2225 |                 ALOGI("buffer ready, resuming..."); | 
 | 2226 |  | 
| Chong Zhang | 8a04833 | 2015-05-06 15:16:28 -0700 | [diff] [blame] | 2227 |                 mPausedForBuffering = false; | 
 | 2228 |  | 
 | 2229 |                 // do not resume yet if client didn't unpause | 
 | 2230 |                 if (!mPausedByClient) { | 
 | 2231 |                     onResume(); | 
 | 2232 |                 } | 
| Chong Zhang | efbb619 | 2015-01-30 17:13:27 -0800 | [diff] [blame] | 2233 |             } | 
| Wei Jia | e67ba38 | 2016-02-03 01:41:49 +0000 | [diff] [blame] | 2234 |             // fall-thru | 
 | 2235 |         } | 
| Chong Zhang | efbb619 | 2015-01-30 17:13:27 -0800 | [diff] [blame] | 2236 |  | 
| Wei Jia | e67ba38 | 2016-02-03 01:41:49 +0000 | [diff] [blame] | 2237 |         case Source::kWhatBufferingEnd: | 
 | 2238 |         { | 
| Wei Jia | 3bed45a | 2016-02-17 11:06:47 -0800 | [diff] [blame] | 2239 |             notifyListener(MEDIA_INFO, MEDIA_INFO_BUFFERING_END, 0); | 
 | 2240 |             mPendingBufferingFlag = PENDING_BUFFERING_FLAG_NONE; | 
| Roger Jönsson | b50e83e | 2013-01-21 16:26:41 +0100 | [diff] [blame] | 2241 |             break; | 
 | 2242 |         } | 
 | 2243 |  | 
| Chong Zhang | efbb619 | 2015-01-30 17:13:27 -0800 | [diff] [blame] | 2244 |         case Source::kWhatCacheStats: | 
 | 2245 |         { | 
 | 2246 |             int32_t kbps; | 
 | 2247 |             CHECK(msg->findInt32("bandwidth", &kbps)); | 
 | 2248 |  | 
 | 2249 |             notifyListener(MEDIA_INFO, MEDIA_INFO_NETWORK_BANDWIDTH, kbps); | 
 | 2250 |             break; | 
 | 2251 |         } | 
 | 2252 |  | 
| Chong Zhang | dcb89b3 | 2013-08-06 09:44:47 -0700 | [diff] [blame] | 2253 |         case Source::kWhatSubtitleData: | 
 | 2254 |         { | 
 | 2255 |             sp<ABuffer> buffer; | 
 | 2256 |             CHECK(msg->findBuffer("buffer", &buffer)); | 
 | 2257 |  | 
| Chong Zhang | 404fced | 2014-06-11 14:45:31 -0700 | [diff] [blame] | 2258 |             sendSubtitleData(buffer, 0 /* baseIndex */); | 
| Chong Zhang | dcb89b3 | 2013-08-06 09:44:47 -0700 | [diff] [blame] | 2259 |             break; | 
 | 2260 |         } | 
 | 2261 |  | 
| Robert Shih | 0852843 | 2015-04-08 09:06:54 -0700 | [diff] [blame] | 2262 |         case Source::kWhatTimedMetaData: | 
 | 2263 |         { | 
 | 2264 |             sp<ABuffer> buffer; | 
 | 2265 |             if (!msg->findBuffer("buffer", &buffer)) { | 
 | 2266 |                 notifyListener(MEDIA_INFO, MEDIA_INFO_METADATA_UPDATE, 0); | 
 | 2267 |             } else { | 
 | 2268 |                 sendTimedMetaData(buffer); | 
 | 2269 |             } | 
 | 2270 |             break; | 
 | 2271 |         } | 
 | 2272 |  | 
| Robert Shih | d3b0bbb | 2014-07-23 15:00:25 -0700 | [diff] [blame] | 2273 |         case Source::kWhatTimedTextData: | 
 | 2274 |         { | 
 | 2275 |             int32_t generation; | 
 | 2276 |             if (msg->findInt32("generation", &generation) | 
 | 2277 |                     && generation != mTimedTextGeneration) { | 
 | 2278 |                 break; | 
 | 2279 |             } | 
 | 2280 |  | 
 | 2281 |             sp<ABuffer> buffer; | 
 | 2282 |             CHECK(msg->findBuffer("buffer", &buffer)); | 
 | 2283 |  | 
 | 2284 |             sp<NuPlayerDriver> driver = mDriver.promote(); | 
 | 2285 |             if (driver == NULL) { | 
 | 2286 |                 break; | 
 | 2287 |             } | 
 | 2288 |  | 
 | 2289 |             int posMs; | 
 | 2290 |             int64_t timeUs, posUs; | 
 | 2291 |             driver->getCurrentPosition(&posMs); | 
| Patrik2 Carlsson | 24d484b | 2015-01-27 16:49:45 +0100 | [diff] [blame] | 2292 |             posUs = (int64_t) posMs * 1000ll; | 
| Robert Shih | d3b0bbb | 2014-07-23 15:00:25 -0700 | [diff] [blame] | 2293 |             CHECK(buffer->meta()->findInt64("timeUs", &timeUs)); | 
 | 2294 |  | 
 | 2295 |             if (posUs < timeUs) { | 
 | 2296 |                 if (!msg->findInt32("generation", &generation)) { | 
 | 2297 |                     msg->setInt32("generation", mTimedTextGeneration); | 
 | 2298 |                 } | 
 | 2299 |                 msg->post(timeUs - posUs); | 
 | 2300 |             } else { | 
 | 2301 |                 sendTimedTextData(buffer); | 
 | 2302 |             } | 
 | 2303 |             break; | 
 | 2304 |         } | 
 | 2305 |  | 
| Andreas Huber | 14f7672 | 2013-01-15 09:04:18 -0800 | [diff] [blame] | 2306 |         case Source::kWhatQueueDecoderShutdown: | 
 | 2307 |         { | 
 | 2308 |             int32_t audio, video; | 
 | 2309 |             CHECK(msg->findInt32("audio", &audio)); | 
 | 2310 |             CHECK(msg->findInt32("video", &video)); | 
 | 2311 |  | 
 | 2312 |             sp<AMessage> reply; | 
 | 2313 |             CHECK(msg->findMessage("reply", &reply)); | 
 | 2314 |  | 
 | 2315 |             queueDecoderShutdown(audio, video, reply); | 
 | 2316 |             break; | 
 | 2317 |         } | 
 | 2318 |  | 
| Ronghua Wu | 8027687 | 2014-08-28 15:50:29 -0700 | [diff] [blame] | 2319 |         case Source::kWhatDrmNoLicense: | 
 | 2320 |         { | 
 | 2321 |             notifyListener(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ERROR_DRM_NO_LICENSE); | 
 | 2322 |             break; | 
 | 2323 |         } | 
 | 2324 |  | 
| Andreas Huber | 9575c96 | 2013-02-05 13:59:56 -0800 | [diff] [blame] | 2325 |         default: | 
 | 2326 |             TRESPASS(); | 
 | 2327 |     } | 
 | 2328 | } | 
 | 2329 |  | 
| Chong Zhang | a7fa1d9 | 2014-06-11 14:49:23 -0700 | [diff] [blame] | 2330 | void NuPlayer::onClosedCaptionNotify(const sp<AMessage> &msg) { | 
 | 2331 |     int32_t what; | 
 | 2332 |     CHECK(msg->findInt32("what", &what)); | 
 | 2333 |  | 
 | 2334 |     switch (what) { | 
 | 2335 |         case NuPlayer::CCDecoder::kWhatClosedCaptionData: | 
 | 2336 |         { | 
 | 2337 |             sp<ABuffer> buffer; | 
 | 2338 |             CHECK(msg->findBuffer("buffer", &buffer)); | 
 | 2339 |  | 
 | 2340 |             size_t inbandTracks = 0; | 
 | 2341 |             if (mSource != NULL) { | 
 | 2342 |                 inbandTracks = mSource->getTrackCount(); | 
 | 2343 |             } | 
 | 2344 |  | 
 | 2345 |             sendSubtitleData(buffer, inbandTracks); | 
 | 2346 |             break; | 
 | 2347 |         } | 
 | 2348 |  | 
 | 2349 |         case NuPlayer::CCDecoder::kWhatTrackAdded: | 
 | 2350 |         { | 
 | 2351 |             notifyListener(MEDIA_INFO, MEDIA_INFO_METADATA_UPDATE, 0); | 
 | 2352 |  | 
 | 2353 |             break; | 
 | 2354 |         } | 
 | 2355 |  | 
 | 2356 |         default: | 
 | 2357 |             TRESPASS(); | 
 | 2358 |     } | 
 | 2359 |  | 
 | 2360 |  | 
 | 2361 | } | 
 | 2362 |  | 
| Chong Zhang | 404fced | 2014-06-11 14:45:31 -0700 | [diff] [blame] | 2363 | void NuPlayer::sendSubtitleData(const sp<ABuffer> &buffer, int32_t baseIndex) { | 
 | 2364 |     int32_t trackIndex; | 
 | 2365 |     int64_t timeUs, durationUs; | 
 | 2366 |     CHECK(buffer->meta()->findInt32("trackIndex", &trackIndex)); | 
 | 2367 |     CHECK(buffer->meta()->findInt64("timeUs", &timeUs)); | 
 | 2368 |     CHECK(buffer->meta()->findInt64("durationUs", &durationUs)); | 
 | 2369 |  | 
 | 2370 |     Parcel in; | 
 | 2371 |     in.writeInt32(trackIndex + baseIndex); | 
 | 2372 |     in.writeInt64(timeUs); | 
 | 2373 |     in.writeInt64(durationUs); | 
 | 2374 |     in.writeInt32(buffer->size()); | 
 | 2375 |     in.writeInt32(buffer->size()); | 
 | 2376 |     in.write(buffer->data(), buffer->size()); | 
 | 2377 |  | 
 | 2378 |     notifyListener(MEDIA_SUBTITLE_DATA, 0, 0, &in); | 
 | 2379 | } | 
| Robert Shih | d3b0bbb | 2014-07-23 15:00:25 -0700 | [diff] [blame] | 2380 |  | 
| Robert Shih | 0852843 | 2015-04-08 09:06:54 -0700 | [diff] [blame] | 2381 | void NuPlayer::sendTimedMetaData(const sp<ABuffer> &buffer) { | 
 | 2382 |     int64_t timeUs; | 
 | 2383 |     CHECK(buffer->meta()->findInt64("timeUs", &timeUs)); | 
 | 2384 |  | 
 | 2385 |     Parcel in; | 
 | 2386 |     in.writeInt64(timeUs); | 
 | 2387 |     in.writeInt32(buffer->size()); | 
 | 2388 |     in.writeInt32(buffer->size()); | 
 | 2389 |     in.write(buffer->data(), buffer->size()); | 
 | 2390 |  | 
 | 2391 |     notifyListener(MEDIA_META_DATA, 0, 0, &in); | 
 | 2392 | } | 
 | 2393 |  | 
| Robert Shih | d3b0bbb | 2014-07-23 15:00:25 -0700 | [diff] [blame] | 2394 | void NuPlayer::sendTimedTextData(const sp<ABuffer> &buffer) { | 
 | 2395 |     const void *data; | 
 | 2396 |     size_t size = 0; | 
 | 2397 |     int64_t timeUs; | 
| Marco Nelissen | 55e2f4c | 2015-09-04 15:57:15 -0700 | [diff] [blame] | 2398 |     int32_t flag = TextDescriptions::IN_BAND_TEXT_3GPP; | 
| Robert Shih | d3b0bbb | 2014-07-23 15:00:25 -0700 | [diff] [blame] | 2399 |  | 
 | 2400 |     AString mime; | 
 | 2401 |     CHECK(buffer->meta()->findString("mime", &mime)); | 
 | 2402 |     CHECK(strcasecmp(mime.c_str(), MEDIA_MIMETYPE_TEXT_3GPP) == 0); | 
 | 2403 |  | 
 | 2404 |     data = buffer->data(); | 
 | 2405 |     size = buffer->size(); | 
 | 2406 |  | 
 | 2407 |     Parcel parcel; | 
 | 2408 |     if (size > 0) { | 
 | 2409 |         CHECK(buffer->meta()->findInt64("timeUs", &timeUs)); | 
| Marco Nelissen | 55e2f4c | 2015-09-04 15:57:15 -0700 | [diff] [blame] | 2410 |         int32_t global = 0; | 
 | 2411 |         if (buffer->meta()->findInt32("global", &global) && global) { | 
 | 2412 |             flag |= TextDescriptions::GLOBAL_DESCRIPTIONS; | 
 | 2413 |         } else { | 
 | 2414 |             flag |= TextDescriptions::LOCAL_DESCRIPTIONS; | 
 | 2415 |         } | 
| Robert Shih | d3b0bbb | 2014-07-23 15:00:25 -0700 | [diff] [blame] | 2416 |         TextDescriptions::getParcelOfDescriptions( | 
 | 2417 |                 (const uint8_t *)data, size, flag, timeUs / 1000, &parcel); | 
 | 2418 |     } | 
 | 2419 |  | 
 | 2420 |     if ((parcel.dataSize() > 0)) { | 
 | 2421 |         notifyListener(MEDIA_TIMED_TEXT, 0, 0, &parcel); | 
 | 2422 |     } else {  // send an empty timed text | 
 | 2423 |         notifyListener(MEDIA_TIMED_TEXT, 0, 0); | 
 | 2424 |     } | 
 | 2425 | } | 
| Andreas Huber | b5f25f0 | 2013-02-05 10:14:26 -0800 | [diff] [blame] | 2426 | //////////////////////////////////////////////////////////////////////////////// | 
 | 2427 |  | 
| Chong Zhang | ced1c2f | 2014-08-08 15:22:35 -0700 | [diff] [blame] | 2428 | sp<AMessage> NuPlayer::Source::getFormat(bool audio) { | 
 | 2429 |     sp<MetaData> meta = getFormatMeta(audio); | 
 | 2430 |  | 
 | 2431 |     if (meta == NULL) { | 
 | 2432 |         return NULL; | 
 | 2433 |     } | 
 | 2434 |  | 
 | 2435 |     sp<AMessage> msg = new AMessage; | 
 | 2436 |  | 
 | 2437 |     if(convertMetaDataToMessage(meta, &msg) == OK) { | 
 | 2438 |         return msg; | 
 | 2439 |     } | 
 | 2440 |     return NULL; | 
 | 2441 | } | 
 | 2442 |  | 
| Andreas Huber | 9575c96 | 2013-02-05 13:59:56 -0800 | [diff] [blame] | 2443 | void NuPlayer::Source::notifyFlagsChanged(uint32_t flags) { | 
 | 2444 |     sp<AMessage> notify = dupNotify(); | 
 | 2445 |     notify->setInt32("what", kWhatFlagsChanged); | 
 | 2446 |     notify->setInt32("flags", flags); | 
 | 2447 |     notify->post(); | 
 | 2448 | } | 
 | 2449 |  | 
| Chong Zhang | ced1c2f | 2014-08-08 15:22:35 -0700 | [diff] [blame] | 2450 | void NuPlayer::Source::notifyVideoSizeChanged(const sp<AMessage> &format) { | 
| Andreas Huber | 9575c96 | 2013-02-05 13:59:56 -0800 | [diff] [blame] | 2451 |     sp<AMessage> notify = dupNotify(); | 
 | 2452 |     notify->setInt32("what", kWhatVideoSizeChanged); | 
| Chong Zhang | ced1c2f | 2014-08-08 15:22:35 -0700 | [diff] [blame] | 2453 |     notify->setMessage("format", format); | 
| Andreas Huber | 9575c96 | 2013-02-05 13:59:56 -0800 | [diff] [blame] | 2454 |     notify->post(); | 
 | 2455 | } | 
 | 2456 |  | 
| Andreas Huber | ec0c597 | 2013-02-05 14:47:13 -0800 | [diff] [blame] | 2457 | void NuPlayer::Source::notifyPrepared(status_t err) { | 
| Andreas Huber | 9575c96 | 2013-02-05 13:59:56 -0800 | [diff] [blame] | 2458 |     sp<AMessage> notify = dupNotify(); | 
 | 2459 |     notify->setInt32("what", kWhatPrepared); | 
| Andreas Huber | ec0c597 | 2013-02-05 14:47:13 -0800 | [diff] [blame] | 2460 |     notify->setInt32("err", err); | 
| Andreas Huber | 9575c96 | 2013-02-05 13:59:56 -0800 | [diff] [blame] | 2461 |     notify->post(); | 
 | 2462 | } | 
 | 2463 |  | 
| Lajos Molnar | fcd3e94 | 2015-03-31 10:06:48 -0700 | [diff] [blame] | 2464 | void NuPlayer::Source::notifyInstantiateSecureDecoders(const sp<AMessage> &reply) { | 
 | 2465 |     sp<AMessage> notify = dupNotify(); | 
 | 2466 |     notify->setInt32("what", kWhatInstantiateSecureDecoders); | 
 | 2467 |     notify->setMessage("reply", reply); | 
 | 2468 |     notify->post(); | 
 | 2469 | } | 
 | 2470 |  | 
| Andreas Huber | 84333e0 | 2014-02-07 15:36:10 -0800 | [diff] [blame] | 2471 | void NuPlayer::Source::onMessageReceived(const sp<AMessage> & /* msg */) { | 
| Andreas Huber | b5f25f0 | 2013-02-05 10:14:26 -0800 | [diff] [blame] | 2472 |     TRESPASS(); | 
 | 2473 | } | 
 | 2474 |  | 
| Andreas Huber | f933441 | 2010-12-15 15:17:42 -0800 | [diff] [blame] | 2475 | }  // namespace android |