blob: 8628edcdd0a40e019caa298f1ad37f87c1f75ea0 [file] [log] [blame]
Andreas Huberf9334412010-12-15 15:17:42 -08001/*
Chong Zhang7137ec72014-11-12 16:41:05 -08002 * Copyright 2014 The Android Open Source Project
Andreas Huberf9334412010-12-15 15:17:42 -08003 *
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 "NuPlayerDecoder"
19#include <utils/Log.h>
Lajos Molnar1cd13982014-01-17 15:12:51 -080020#include <inttypes.h>
Andreas Huberf9334412010-12-15 15:17:42 -080021
Lajos Molnar9fb81522016-07-14 07:33:43 -070022#include <algorithm>
23
Chong Zhang7137ec72014-11-12 16:41:05 -080024#include "NuPlayerCCDecoder.h"
Andreas Huberf9334412010-12-15 15:17:42 -080025#include "NuPlayerDecoder.h"
Hassan Shojaniacefac142017-02-06 21:02:02 -080026#include "NuPlayerDrm.h"
Wei Jiac6cfd702014-11-11 16:33:20 -080027#include "NuPlayerRenderer.h"
28#include "NuPlayerSource.h"
29
Andy Hung288da022015-05-31 22:55:59 -070030#include <cutils/properties.h>
Marco Nelissen13aa1a42019-09-27 10:21:55 -070031#include <mediadrm/ICrypto.h>
Dongwon Kangbc8f53b2018-01-25 17:01:44 -080032#include <media/MediaBufferHolder.h>
Wonsik Kim7e34bf52016-08-23 00:09:18 +090033#include <media/MediaCodecBuffer.h>
Andreas Huberf9334412010-12-15 15:17:42 -080034#include <media/stagefright/foundation/ABuffer.h>
35#include <media/stagefright/foundation/ADebug.h>
Andreas Huber5bc087c2010-12-23 10:27:40 -080036#include <media/stagefright/foundation/AMessage.h>
Dongwon Kangd91dc5a2017-10-10 00:07:09 -070037#include <media/stagefright/foundation/avc_utils.h>
Lajos Molnar09524832014-07-17 14:29:51 -070038#include <media/stagefright/MediaBuffer.h>
Lajos Molnar1cd13982014-01-17 15:12:51 -080039#include <media/stagefright/MediaCodec.h>
Andreas Huberf9334412010-12-15 15:17:42 -080040#include <media/stagefright/MediaDefs.h>
Lajos Molnar1cd13982014-01-17 15:12:51 -080041#include <media/stagefright/MediaErrors.h>
Chong Zhang181fd9b2017-02-16 15:53:03 -080042#include <media/stagefright/SurfaceUtils.h>
Lajos Molnar1de1e252015-04-30 18:18:34 -070043#include <gui/Surface.h>
44
Chong Zhang7137ec72014-11-12 16:41:05 -080045#include "ATSParser.h"
46
Andreas Huberf9334412010-12-15 15:17:42 -080047namespace android {
48
Lajos Molnar9fb81522016-07-14 07:33:43 -070049static float kDisplayRefreshingRate = 60.f; // TODO: get this from the display
Praveen Chavanbbaa1442016-04-08 13:33:49 -070050
51// The default total video frame rate of a stream when that info is not available from
52// the source.
53static float kDefaultVideoFrameRateTotal = 30.f;
54
Andy Hung288da022015-05-31 22:55:59 -070055static inline bool getAudioDeepBufferSetting() {
56 return property_get_bool("media.stagefright.audio.deep", false /* default_value */);
57}
58
Andreas Huberf9334412010-12-15 15:17:42 -080059NuPlayer::Decoder::Decoder(
Glenn Kasten11731182011-02-08 17:26:17 -080060 const sp<AMessage> &notify,
Wei Jiac6cfd702014-11-11 16:33:20 -080061 const sp<Source> &source,
Ronghua Wu68845c12015-07-21 09:50:48 -070062 pid_t pid,
Wei Jiaf2ae3e12016-10-27 17:10:59 -070063 uid_t uid,
Wei Jiac6cfd702014-11-11 16:33:20 -080064 const sp<Renderer> &renderer,
Lajos Molnar1de1e252015-04-30 18:18:34 -070065 const sp<Surface> &surface,
Chong Zhang7137ec72014-11-12 16:41:05 -080066 const sp<CCDecoder> &ccDecoder)
Andy Hung202bce12014-12-03 11:47:36 -080067 : DecoderBase(notify),
Lajos Molnar1de1e252015-04-30 18:18:34 -070068 mSurface(surface),
Wei Jiac6cfd702014-11-11 16:33:20 -080069 mSource(source),
70 mRenderer(renderer),
Chong Zhang7137ec72014-11-12 16:41:05 -080071 mCCDecoder(ccDecoder),
Ronghua Wu68845c12015-07-21 09:50:48 -070072 mPid(pid),
Wei Jiaf2ae3e12016-10-27 17:10:59 -070073 mUid(uid),
Chih-Hung Hsieh62309d52018-12-11 13:54:02 -080074 mSkipRenderingUntilMediaTimeUs(-1LL),
75 mNumFramesTotal(0LL),
76 mNumInputFramesDropped(0LL),
77 mNumOutputFramesDropped(0LL),
Praveen Chavane1e5d7a2015-05-19 19:09:48 -070078 mVideoWidth(0),
79 mVideoHeight(0),
Chong Zhang7137ec72014-11-12 16:41:05 -080080 mIsAudio(true),
81 mIsVideoAVC(false),
82 mIsSecure(false),
Hassan Shojania62dec952017-05-18 10:45:27 -070083 mIsEncrypted(false),
84 mIsEncryptedObservedEarlier(false),
Chong Zhang7137ec72014-11-12 16:41:05 -080085 mFormatChangePending(false),
Chong Zhang66704af2015-03-03 19:32:35 -080086 mTimeChangePending(false),
Praveen Chavanbbaa1442016-04-08 13:33:49 -070087 mFrameRateTotal(kDefaultVideoFrameRateTotal),
88 mPlaybackSpeed(1.0f),
Lajos Molnar9fb81522016-07-14 07:33:43 -070089 mNumVideoTemporalLayerTotal(1), // decode all layers
Praveen Chavanbbaa1442016-04-08 13:33:49 -070090 mNumVideoTemporalLayerAllowed(1),
91 mCurrentMaxVideoTemporalLayerId(0),
Chong Zhangf8d71772014-11-26 15:08:34 -080092 mResumePending(false),
Lajos Molnar1cd13982014-01-17 15:12:51 -080093 mComponentName("decoder") {
Lajos Molnar1cd13982014-01-17 15:12:51 -080094 mCodecLooper = new ALooper;
Marco Nelissen9e2b7912014-08-18 16:13:03 -070095 mCodecLooper->setName("NPDecoder-CL");
Lajos Molnar1cd13982014-01-17 15:12:51 -080096 mCodecLooper->start(false, false, ANDROID_PRIORITY_AUDIO);
Praveen Chavanbbaa1442016-04-08 13:33:49 -070097 mVideoTemporalLayerAggregateFps[0] = mFrameRateTotal;
Andreas Huberf9334412010-12-15 15:17:42 -080098}
99
100NuPlayer::Decoder::~Decoder() {
Wei Jia37ff0e62017-04-21 11:24:45 -0700101 // Need to stop looper first since mCodec could be accessed on the mDecoderLooper.
102 stopLooper();
103 if (mCodec != NULL) {
104 mCodec->release();
105 }
Wei Jia4923cee2014-09-24 14:25:19 -0700106 releaseAndResetMediaBuffers();
Andreas Huberf9334412010-12-15 15:17:42 -0800107}
108
Ray Essick83f56b02019-06-23 15:13:46 -0700109sp<AMessage> NuPlayer::Decoder::getStats() {
Ray Essick372e8f22019-02-11 11:38:31 -0800110
Ray Essick83f56b02019-06-23 15:13:46 -0700111 Mutex::Autolock autolock(mStatsLock);
Praveen Chavane1e5d7a2015-05-19 19:09:48 -0700112 mStats->setInt64("frames-total", mNumFramesTotal);
113 mStats->setInt64("frames-dropped-input", mNumInputFramesDropped);
114 mStats->setInt64("frames-dropped-output", mNumOutputFramesDropped);
Ray Essick092f74a2018-11-20 10:25:13 -0800115 mStats->setFloat("frame-rate-total", mFrameRateTotal);
Ray Essick372e8f22019-02-11 11:38:31 -0800116
Ray Essick372e8f22019-02-11 11:38:31 -0800117 // make our own copy, so we aren't victim to any later changes.
118 sp<AMessage> copiedStats = mStats->dup();
Ray Essick83f56b02019-06-23 15:13:46 -0700119
Ray Essick372e8f22019-02-11 11:38:31 -0800120 return copiedStats;
Lajos Molnar09524832014-07-17 14:29:51 -0700121}
122
Lajos Molnara81c6222015-07-10 19:17:45 -0700123status_t NuPlayer::Decoder::setVideoSurface(const sp<Surface> &surface) {
124 if (surface == NULL || ADebug::isExperimentEnabled("legacy-setsurface")) {
125 return BAD_VALUE;
126 }
127
128 sp<AMessage> msg = new AMessage(kWhatSetVideoSurface, this);
129
130 msg->setObject("surface", surface);
131 sp<AMessage> response;
132 status_t err = msg->postAndAwaitResponse(&response);
133 if (err == OK && response != NULL) {
134 CHECK(response->findInt32("err", &err));
135 }
136 return err;
137}
138
Chong Zhang7137ec72014-11-12 16:41:05 -0800139void NuPlayer::Decoder::onMessageReceived(const sp<AMessage> &msg) {
140 ALOGV("[%s] onMessage: %s", mComponentName.c_str(), msg->debugString().c_str());
141
142 switch (msg->what()) {
143 case kWhatCodecNotify:
144 {
Chong Zhang3b032b32015-04-17 15:49:06 -0700145 int32_t cbID;
146 CHECK(msg->findInt32("callbackID", &cbID));
147
148 ALOGV("[%s] kWhatCodecNotify: cbID = %d, paused = %d",
149 mIsAudio ? "audio" : "video", cbID, mPaused);
150
Marco Nelissen421f47c2015-03-25 14:40:32 -0700151 if (mPaused) {
152 break;
Chong Zhang7137ec72014-11-12 16:41:05 -0800153 }
154
Marco Nelissen421f47c2015-03-25 14:40:32 -0700155 switch (cbID) {
156 case MediaCodec::CB_INPUT_AVAILABLE:
157 {
158 int32_t index;
159 CHECK(msg->findInt32("index", &index));
160
161 handleAnInputBuffer(index);
162 break;
163 }
164
165 case MediaCodec::CB_OUTPUT_AVAILABLE:
166 {
167 int32_t index;
168 size_t offset;
169 size_t size;
170 int64_t timeUs;
171 int32_t flags;
172
173 CHECK(msg->findInt32("index", &index));
174 CHECK(msg->findSize("offset", &offset));
175 CHECK(msg->findSize("size", &size));
176 CHECK(msg->findInt64("timeUs", &timeUs));
177 CHECK(msg->findInt32("flags", &flags));
178
179 handleAnOutputBuffer(index, offset, size, timeUs, flags);
180 break;
181 }
182
183 case MediaCodec::CB_OUTPUT_FORMAT_CHANGED:
184 {
185 sp<AMessage> format;
186 CHECK(msg->findMessage("format", &format));
187
188 handleOutputFormatChange(format);
189 break;
190 }
191
192 case MediaCodec::CB_ERROR:
193 {
194 status_t err;
195 CHECK(msg->findInt32("err", &err));
196 ALOGE("Decoder (%s) reported error : 0x%x",
197 mIsAudio ? "audio" : "video", err);
198
199 handleError(err);
200 break;
201 }
202
203 default:
204 {
205 TRESPASS();
206 break;
207 }
208 }
209
Lajos Molnar87603c02014-08-20 19:25:30 -0700210 break;
211 }
Chong Zhang7137ec72014-11-12 16:41:05 -0800212
213 case kWhatRenderBuffer:
214 {
215 if (!isStaleReply(msg)) {
216 onRenderBuffer(msg);
217 }
218 break;
219 }
220
Wei Jia9a3101b2016-11-08 14:34:24 -0800221 case kWhatAudioOutputFormatChanged:
222 {
223 if (!isStaleReply(msg)) {
224 status_t err;
225 if (msg->findInt32("err", &err) && err != OK) {
226 ALOGE("Renderer reported 0x%x when changing audio output format", err);
227 handleError(err);
228 }
229 }
230 break;
231 }
232
Lajos Molnara81c6222015-07-10 19:17:45 -0700233 case kWhatSetVideoSurface:
234 {
235 sp<AReplyToken> replyID;
236 CHECK(msg->senderAwaitsResponse(&replyID));
237
238 sp<RefBase> obj;
239 CHECK(msg->findObject("surface", &obj));
240 sp<Surface> surface = static_cast<Surface *>(obj.get()); // non-null
241 int32_t err = INVALID_OPERATION;
242 // NOTE: in practice mSurface is always non-null, but checking here for completeness
243 if (mCodec != NULL && mSurface != NULL) {
244 // TODO: once AwesomePlayer is removed, remove this automatic connecting
245 // to the surface by MediaPlayerService.
246 //
247 // at this point MediaPlayerService::client has already connected to the
248 // surface, which MediaCodec does not expect
Chong Zhang181fd9b2017-02-16 15:53:03 -0800249 err = nativeWindowDisconnect(surface.get(), "kWhatSetVideoSurface(surface)");
Lajos Molnara81c6222015-07-10 19:17:45 -0700250 if (err == OK) {
251 err = mCodec->setSurface(surface);
252 ALOGI_IF(err, "codec setSurface returned: %d", err);
253 if (err == OK) {
254 // reconnect to the old surface as MPS::Client will expect to
255 // be able to disconnect from it.
Chong Zhang181fd9b2017-02-16 15:53:03 -0800256 (void)nativeWindowConnect(mSurface.get(), "kWhatSetVideoSurface(mSurface)");
Lajos Molnara81c6222015-07-10 19:17:45 -0700257 mSurface = surface;
258 }
259 }
260 if (err != OK) {
261 // reconnect to the new surface on error as MPS::Client will expect to
262 // be able to disconnect from it.
Chong Zhang181fd9b2017-02-16 15:53:03 -0800263 (void)nativeWindowConnect(surface.get(), "kWhatSetVideoSurface(err)");
Lajos Molnara81c6222015-07-10 19:17:45 -0700264 }
265 }
266
267 sp<AMessage> response = new AMessage;
268 response->setInt32("err", err);
269 response->postReply(replyID);
270 break;
271 }
272
Hassan Shojaniacefac142017-02-06 21:02:02 -0800273 case kWhatDrmReleaseCrypto:
274 {
275 ALOGV("kWhatDrmReleaseCrypto");
276 onReleaseCrypto(msg);
277 break;
278 }
279
Chong Zhang7137ec72014-11-12 16:41:05 -0800280 default:
281 DecoderBase::onMessageReceived(msg);
282 break;
Lajos Molnar87603c02014-08-20 19:25:30 -0700283 }
284}
285
Lajos Molnar1cd13982014-01-17 15:12:51 -0800286void NuPlayer::Decoder::onConfigure(const sp<AMessage> &format) {
Andreas Huberf9334412010-12-15 15:17:42 -0800287 CHECK(mCodec == NULL);
Andreas Huberf9334412010-12-15 15:17:42 -0800288
Chong Zhang7137ec72014-11-12 16:41:05 -0800289 mFormatChangePending = false;
Chong Zhang66704af2015-03-03 19:32:35 -0800290 mTimeChangePending = false;
Chong Zhang7137ec72014-11-12 16:41:05 -0800291
Lajos Molnar1cd13982014-01-17 15:12:51 -0800292 ++mBufferGeneration;
293
Andreas Huber84066782011-08-16 09:34:26 -0700294 AString mime;
295 CHECK(format->findString("mime", &mime));
Andreas Huberf9334412010-12-15 15:17:42 -0800296
Chong Zhang7137ec72014-11-12 16:41:05 -0800297 mIsAudio = !strncasecmp("audio/", mime.c_str(), 6);
298 mIsVideoAVC = !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime.c_str());
299
Lajos Molnar1cd13982014-01-17 15:12:51 -0800300 mComponentName = mime;
301 mComponentName.append(" decoder");
Lajos Molnar1de1e252015-04-30 18:18:34 -0700302 ALOGV("[%s] onConfigure (surface=%p)", mComponentName.c_str(), mSurface.get());
Lajos Molnar1cd13982014-01-17 15:12:51 -0800303
Ronghua Wu68845c12015-07-21 09:50:48 -0700304 mCodec = MediaCodec::CreateByType(
Wei Jiaf2ae3e12016-10-27 17:10:59 -0700305 mCodecLooper, mime.c_str(), false /* encoder */, NULL /* err */, mPid, mUid);
Lajos Molnar09524832014-07-17 14:29:51 -0700306 int32_t secure = 0;
307 if (format->findInt32("secure", &secure) && secure != 0) {
308 if (mCodec != NULL) {
309 mCodec->getName(&mComponentName);
310 mComponentName.append(".secure");
311 mCodec->release();
312 ALOGI("[%s] creating", mComponentName.c_str());
313 mCodec = MediaCodec::CreateByComponentName(
Wei Jiaf2ae3e12016-10-27 17:10:59 -0700314 mCodecLooper, mComponentName.c_str(), NULL /* err */, mPid, mUid);
Lajos Molnar09524832014-07-17 14:29:51 -0700315 }
316 }
Lajos Molnar1cd13982014-01-17 15:12:51 -0800317 if (mCodec == NULL) {
Lajos Molnar09524832014-07-17 14:29:51 -0700318 ALOGE("Failed to create %s%s decoder",
319 (secure ? "secure " : ""), mime.c_str());
Lajos Molnar1cd13982014-01-17 15:12:51 -0800320 handleError(UNKNOWN_ERROR);
321 return;
322 }
Chong Zhang7137ec72014-11-12 16:41:05 -0800323 mIsSecure = secure;
Lajos Molnar1cd13982014-01-17 15:12:51 -0800324
325 mCodec->getName(&mComponentName);
326
Lajos Molnar14986f62014-09-15 11:04:44 -0700327 status_t err;
Lajos Molnar1de1e252015-04-30 18:18:34 -0700328 if (mSurface != NULL) {
Lajos Molnar1cd13982014-01-17 15:12:51 -0800329 // disconnect from surface as MediaCodec will reconnect
Chong Zhang181fd9b2017-02-16 15:53:03 -0800330 err = nativeWindowDisconnect(mSurface.get(), "onConfigure");
Lajos Molnar14986f62014-09-15 11:04:44 -0700331 // We treat this as a warning, as this is a preparatory step.
332 // Codec will try to connect to the surface, which is where
333 // any error signaling will occur.
334 ALOGW_IF(err != OK, "failed to disconnect from surface: %d", err);
Lajos Molnar1cd13982014-01-17 15:12:51 -0800335 }
Hassan Shojaniacefac142017-02-06 21:02:02 -0800336
337 // Modular DRM
338 void *pCrypto;
339 if (!format->findPointer("crypto", &pCrypto)) {
340 pCrypto = NULL;
341 }
342 sp<ICrypto> crypto = (ICrypto*)pCrypto;
Hassan Shojania62dec952017-05-18 10:45:27 -0700343 // non-encrypted source won't have a crypto
344 mIsEncrypted = (crypto != NULL);
345 // configure is called once; still using OR in case the behavior changes.
346 mIsEncryptedObservedEarlier = mIsEncryptedObservedEarlier || mIsEncrypted;
Hassan Shojaniacefac142017-02-06 21:02:02 -0800347 ALOGV("onConfigure mCrypto: %p (%d) mIsSecure: %d",
348 crypto.get(), (crypto != NULL ? crypto->getStrongCount() : 0), mIsSecure);
349
Lajos Molnar14986f62014-09-15 11:04:44 -0700350 err = mCodec->configure(
Hassan Shojaniacefac142017-02-06 21:02:02 -0800351 format, mSurface, crypto, 0 /* flags */);
352
Lajos Molnar1cd13982014-01-17 15:12:51 -0800353 if (err != OK) {
Wei Jiafcd87872017-07-28 15:50:04 -0700354 ALOGE("Failed to configure [%s] decoder (err=%d)", mComponentName.c_str(), err);
Andy Hung2abde2c2014-09-30 14:40:32 -0700355 mCodec->release();
356 mCodec.clear();
Lajos Molnar1cd13982014-01-17 15:12:51 -0800357 handleError(err);
358 return;
359 }
Lajos Molnar87603c02014-08-20 19:25:30 -0700360 rememberCodecSpecificData(format);
361
Lajos Molnar1cd13982014-01-17 15:12:51 -0800362 // the following should work in configured state
363 CHECK_EQ((status_t)OK, mCodec->getOutputFormat(&mOutputFormat));
364 CHECK_EQ((status_t)OK, mCodec->getInputFormat(&mInputFormat));
365
Ray Essick83f56b02019-06-23 15:13:46 -0700366 {
367 Mutex::Autolock autolock(mStatsLock);
368 mStats->setString("mime", mime.c_str());
369 mStats->setString("component-name", mComponentName.c_str());
370 }
Praveen Chavane1e5d7a2015-05-19 19:09:48 -0700371
372 if (!mIsAudio) {
373 int32_t width, height;
374 if (mOutputFormat->findInt32("width", &width)
375 && mOutputFormat->findInt32("height", &height)) {
Ray Essick83f56b02019-06-23 15:13:46 -0700376 Mutex::Autolock autolock(mStatsLock);
Praveen Chavane1e5d7a2015-05-19 19:09:48 -0700377 mStats->setInt32("width", width);
378 mStats->setInt32("height", height);
379 }
380 }
381
Marco Nelissen421f47c2015-03-25 14:40:32 -0700382 sp<AMessage> reply = new AMessage(kWhatCodecNotify, this);
383 mCodec->setCallback(reply);
384
Lajos Molnar1cd13982014-01-17 15:12:51 -0800385 err = mCodec->start();
386 if (err != OK) {
Wei Jiafcd87872017-07-28 15:50:04 -0700387 ALOGE("Failed to start [%s] decoder (err=%d)", mComponentName.c_str(), err);
Andy Hung2abde2c2014-09-30 14:40:32 -0700388 mCodec->release();
389 mCodec.clear();
Lajos Molnar1cd13982014-01-17 15:12:51 -0800390 handleError(err);
391 return;
Andreas Huberf9334412010-12-15 15:17:42 -0800392 }
393
Lajos Molnar09524832014-07-17 14:29:51 -0700394 releaseAndResetMediaBuffers();
Marco Nelissen421f47c2015-03-25 14:40:32 -0700395
Wei Jia704e7262014-06-04 16:21:56 -0700396 mPaused = false;
Chong Zhangf8d71772014-11-26 15:08:34 -0800397 mResumePending = false;
Lajos Molnar1cd13982014-01-17 15:12:51 -0800398}
Andreas Huber078cfcf2011-09-15 12:25:04 -0700399
Ronghua Wu8db88132015-04-22 13:51:35 -0700400void NuPlayer::Decoder::onSetParameters(const sp<AMessage> &params) {
Praveen Chavanbbaa1442016-04-08 13:33:49 -0700401 bool needAdjustLayers = false;
402 float frameRateTotal;
403 if (params->findFloat("frame-rate-total", &frameRateTotal)
404 && mFrameRateTotal != frameRateTotal) {
405 needAdjustLayers = true;
406 mFrameRateTotal = frameRateTotal;
Ronghua Wu8db88132015-04-22 13:51:35 -0700407 }
Praveen Chavanbbaa1442016-04-08 13:33:49 -0700408
409 int32_t numVideoTemporalLayerTotal;
410 if (params->findInt32("temporal-layer-count", &numVideoTemporalLayerTotal)
Lajos Molnar9fb81522016-07-14 07:33:43 -0700411 && numVideoTemporalLayerTotal >= 0
Praveen Chavanbbaa1442016-04-08 13:33:49 -0700412 && numVideoTemporalLayerTotal <= kMaxNumVideoTemporalLayers
413 && mNumVideoTemporalLayerTotal != numVideoTemporalLayerTotal) {
414 needAdjustLayers = true;
Lajos Molnar9fb81522016-07-14 07:33:43 -0700415 mNumVideoTemporalLayerTotal = std::max(numVideoTemporalLayerTotal, 1);
Praveen Chavanbbaa1442016-04-08 13:33:49 -0700416 }
417
Lajos Molnar9fb81522016-07-14 07:33:43 -0700418 if (needAdjustLayers && mNumVideoTemporalLayerTotal > 1) {
Praveen Chavanbbaa1442016-04-08 13:33:49 -0700419 // TODO: For now, layer fps is calculated for some specific architectures.
420 // But it really should be extracted from the stream.
421 mVideoTemporalLayerAggregateFps[0] =
Chih-Hung Hsieh62309d52018-12-11 13:54:02 -0800422 mFrameRateTotal / (float)(1LL << (mNumVideoTemporalLayerTotal - 1));
Praveen Chavanbbaa1442016-04-08 13:33:49 -0700423 for (int32_t i = 1; i < mNumVideoTemporalLayerTotal; ++i) {
424 mVideoTemporalLayerAggregateFps[i] =
Chih-Hung Hsieh62309d52018-12-11 13:54:02 -0800425 mFrameRateTotal / (float)(1LL << (mNumVideoTemporalLayerTotal - i))
Praveen Chavanbbaa1442016-04-08 13:33:49 -0700426 + mVideoTemporalLayerAggregateFps[i - 1];
427 }
428 }
429
430 float playbackSpeed;
431 if (params->findFloat("playback-speed", &playbackSpeed)
432 && mPlaybackSpeed != playbackSpeed) {
433 needAdjustLayers = true;
434 mPlaybackSpeed = playbackSpeed;
435 }
436
437 if (needAdjustLayers) {
Lajos Molnar9fb81522016-07-14 07:33:43 -0700438 float decodeFrameRate = mFrameRateTotal;
439 // enable temporal layering optimization only if we know the layering depth
440 if (mNumVideoTemporalLayerTotal > 1) {
441 int32_t layerId;
442 for (layerId = 0; layerId < mNumVideoTemporalLayerTotal - 1; ++layerId) {
443 if (mVideoTemporalLayerAggregateFps[layerId] * mPlaybackSpeed
444 >= kDisplayRefreshingRate * 0.9) {
445 break;
446 }
Praveen Chavanbbaa1442016-04-08 13:33:49 -0700447 }
Lajos Molnar9fb81522016-07-14 07:33:43 -0700448 mNumVideoTemporalLayerAllowed = layerId + 1;
449 decodeFrameRate = mVideoTemporalLayerAggregateFps[layerId];
Praveen Chavanbbaa1442016-04-08 13:33:49 -0700450 }
Lajos Molnar9fb81522016-07-14 07:33:43 -0700451 ALOGV("onSetParameters: allowed layers=%d, decodeFps=%g",
452 mNumVideoTemporalLayerAllowed, decodeFrameRate);
Praveen Chavanbbaa1442016-04-08 13:33:49 -0700453
454 if (mCodec == NULL) {
455 ALOGW("onSetParameters called before codec is created.");
456 return;
457 }
458
459 sp<AMessage> codecParams = new AMessage();
Lajos Molnar9fb81522016-07-14 07:33:43 -0700460 codecParams->setFloat("operating-rate", decodeFrameRate * mPlaybackSpeed);
Praveen Chavanbbaa1442016-04-08 13:33:49 -0700461 mCodec->setParameters(codecParams);
462 }
Ronghua Wu8db88132015-04-22 13:51:35 -0700463}
464
Chong Zhang7137ec72014-11-12 16:41:05 -0800465void NuPlayer::Decoder::onSetRenderer(const sp<Renderer> &renderer) {
Chong Zhang7137ec72014-11-12 16:41:05 -0800466 mRenderer = renderer;
Chong Zhang7137ec72014-11-12 16:41:05 -0800467}
468
Chong Zhangf8d71772014-11-26 15:08:34 -0800469void NuPlayer::Decoder::onResume(bool notifyComplete) {
Chong Zhang7137ec72014-11-12 16:41:05 -0800470 mPaused = false;
Chong Zhangf8d71772014-11-26 15:08:34 -0800471
472 if (notifyComplete) {
473 mResumePending = true;
474 }
Wei Jiafcd87872017-07-28 15:50:04 -0700475
476 if (mCodec == NULL) {
477 ALOGE("[%s] onResume without a valid codec", mComponentName.c_str());
478 handleError(NO_INIT);
479 return;
480 }
Marco Nelissen421f47c2015-03-25 14:40:32 -0700481 mCodec->start();
Chong Zhang7137ec72014-11-12 16:41:05 -0800482}
483
Chong Zhang66704af2015-03-03 19:32:35 -0800484void NuPlayer::Decoder::doFlush(bool notifyComplete) {
Chong Zhang7137ec72014-11-12 16:41:05 -0800485 if (mCCDecoder != NULL) {
486 mCCDecoder->flush();
487 }
488
489 if (mRenderer != NULL) {
490 mRenderer->flush(mIsAudio, notifyComplete);
491 mRenderer->signalTimeDiscontinuity();
492 }
493
494 status_t err = OK;
495 if (mCodec != NULL) {
496 err = mCodec->flush();
497 mCSDsToSubmit = mCSDsForCurrentFormat; // copy operator
498 ++mBufferGeneration;
499 }
500
501 if (err != OK) {
Wei Jiafcd87872017-07-28 15:50:04 -0700502 ALOGE("failed to flush [%s] (err=%d)", mComponentName.c_str(), err);
Chong Zhang7137ec72014-11-12 16:41:05 -0800503 handleError(err);
504 // finish with posting kWhatFlushCompleted.
505 // we attempt to release the buffers even if flush fails.
506 }
507 releaseAndResetMediaBuffers();
Marco Nelissen421f47c2015-03-25 14:40:32 -0700508 mPaused = true;
Chong Zhang66704af2015-03-03 19:32:35 -0800509}
Chong Zhang7137ec72014-11-12 16:41:05 -0800510
Marco Nelissen421f47c2015-03-25 14:40:32 -0700511
Chong Zhang66704af2015-03-03 19:32:35 -0800512void NuPlayer::Decoder::onFlush() {
513 doFlush(true);
514
515 if (isDiscontinuityPending()) {
516 // This could happen if the client starts seeking/shutdown
517 // after we queued an EOS for discontinuities.
518 // We can consider discontinuity handled.
519 finishHandleDiscontinuity(false /* flushOnTimeChange */);
Chong Zhang7137ec72014-11-12 16:41:05 -0800520 }
Chong Zhang66704af2015-03-03 19:32:35 -0800521
522 sp<AMessage> notify = mNotify->dup();
523 notify->setInt32("what", kWhatFlushCompleted);
524 notify->post();
Chong Zhang7137ec72014-11-12 16:41:05 -0800525}
526
527void NuPlayer::Decoder::onShutdown(bool notifyComplete) {
528 status_t err = OK;
Chong Zhangf8d71772014-11-26 15:08:34 -0800529
530 // if there is a pending resume request, notify complete now
531 notifyResumeCompleteIfNecessary();
532
Chong Zhang7137ec72014-11-12 16:41:05 -0800533 if (mCodec != NULL) {
534 err = mCodec->release();
535 mCodec = NULL;
536 ++mBufferGeneration;
537
Lajos Molnar1de1e252015-04-30 18:18:34 -0700538 if (mSurface != NULL) {
Chong Zhang7137ec72014-11-12 16:41:05 -0800539 // reconnect to surface as MediaCodec disconnected from it
Chong Zhang181fd9b2017-02-16 15:53:03 -0800540 status_t error = nativeWindowConnect(mSurface.get(), "onShutdown");
Chong Zhang7137ec72014-11-12 16:41:05 -0800541 ALOGW_IF(error != NO_ERROR,
542 "[%s] failed to connect to native window, error=%d",
543 mComponentName.c_str(), error);
544 }
545 mComponentName = "decoder";
546 }
547
548 releaseAndResetMediaBuffers();
549
550 if (err != OK) {
Wei Jiafcd87872017-07-28 15:50:04 -0700551 ALOGE("failed to release [%s] (err=%d)", mComponentName.c_str(), err);
Chong Zhang7137ec72014-11-12 16:41:05 -0800552 handleError(err);
553 // finish with posting kWhatShutdownCompleted.
554 }
555
556 if (notifyComplete) {
557 sp<AMessage> notify = mNotify->dup();
558 notify->setInt32("what", kWhatShutdownCompleted);
559 notify->post();
560 mPaused = true;
561 }
562}
563
Chong Zhang3b032b32015-04-17 15:49:06 -0700564/*
565 * returns true if we should request more data
566 */
567bool NuPlayer::Decoder::doRequestBuffers() {
Jeff Tinker29b7dcf2016-10-24 10:28:30 -0700568 if (isDiscontinuityPending()) {
Chong Zhang3b032b32015-04-17 15:49:06 -0700569 return false;
Chong Zhang7137ec72014-11-12 16:41:05 -0800570 }
571 status_t err = OK;
Chong Zhang66704af2015-03-03 19:32:35 -0800572 while (err == OK && !mDequeuedInputBuffers.empty()) {
Chong Zhang7137ec72014-11-12 16:41:05 -0800573 size_t bufferIx = *mDequeuedInputBuffers.begin();
574 sp<AMessage> msg = new AMessage();
575 msg->setSize("buffer-ix", bufferIx);
576 err = fetchInputData(msg);
Chong Zhang66704af2015-03-03 19:32:35 -0800577 if (err != OK && err != ERROR_END_OF_STREAM) {
578 // if EOS, need to queue EOS buffer
Chong Zhang7137ec72014-11-12 16:41:05 -0800579 break;
580 }
581 mDequeuedInputBuffers.erase(mDequeuedInputBuffers.begin());
582
583 if (!mPendingInputMessages.empty()
584 || !onInputBufferFetched(msg)) {
585 mPendingInputMessages.push_back(msg);
Lajos Molnar09524832014-07-17 14:29:51 -0700586 }
587 }
Chong Zhang7137ec72014-11-12 16:41:05 -0800588
Chong Zhang3b032b32015-04-17 15:49:06 -0700589 return err == -EWOULDBLOCK
590 && mSource->feedMoreTSData() == OK;
Lajos Molnar09524832014-07-17 14:29:51 -0700591}
592
Marco Nelissen421f47c2015-03-25 14:40:32 -0700593void NuPlayer::Decoder::handleError(int32_t err)
594{
595 // We cannot immediately release the codec due to buffers still outstanding
596 // in the renderer. We signal to the player the error so it can shutdown/release the
597 // decoder after flushing and increment the generation to discard unnecessary messages.
598
599 ++mBufferGeneration;
600
601 sp<AMessage> notify = mNotify->dup();
602 notify->setInt32("what", kWhatError);
603 notify->setInt32("err", err);
604 notify->post();
605}
606
Hassan Shojaniacefac142017-02-06 21:02:02 -0800607status_t NuPlayer::Decoder::releaseCrypto()
608{
609 ALOGV("releaseCrypto");
610
611 sp<AMessage> msg = new AMessage(kWhatDrmReleaseCrypto, this);
612
613 sp<AMessage> response;
614 status_t status = msg->postAndAwaitResponse(&response);
615 if (status == OK && response != NULL) {
616 CHECK(response->findInt32("status", &status));
617 ALOGV("releaseCrypto ret: %d ", status);
618 } else {
619 ALOGE("releaseCrypto err: %d", status);
620 }
621
622 return status;
623}
624
625void NuPlayer::Decoder::onReleaseCrypto(const sp<AMessage>& msg)
626{
627 status_t status = INVALID_OPERATION;
628 if (mCodec != NULL) {
629 status = mCodec->releaseCrypto();
630 } else {
631 // returning OK if the codec has been already released
632 status = OK;
633 ALOGE("onReleaseCrypto No mCodec. err: %d", status);
634 }
635
636 sp<AMessage> response = new AMessage;
637 response->setInt32("status", status);
Hassan Shojania62dec952017-05-18 10:45:27 -0700638 // Clearing the state as it's tied to crypto. mIsEncryptedObservedEarlier is sticky though
639 // and lasts for the lifetime of this codec. See its use in fetchInputData.
640 mIsEncrypted = false;
Hassan Shojaniacefac142017-02-06 21:02:02 -0800641
642 sp<AReplyToken> replyID;
643 CHECK(msg->senderAwaitsResponse(&replyID));
644 response->postReply(replyID);
645}
646
Marco Nelissen421f47c2015-03-25 14:40:32 -0700647bool NuPlayer::Decoder::handleAnInputBuffer(size_t index) {
Chong Zhang66704af2015-03-03 19:32:35 -0800648 if (isDiscontinuityPending()) {
Chong Zhang7137ec72014-11-12 16:41:05 -0800649 return false;
650 }
Marco Nelissen421f47c2015-03-25 14:40:32 -0700651
Wei Jiafcd87872017-07-28 15:50:04 -0700652 if (mCodec == NULL) {
653 ALOGE("[%s] handleAnInputBuffer without a valid codec", mComponentName.c_str());
654 handleError(NO_INIT);
655 return false;
656 }
657
Wonsik Kim7e34bf52016-08-23 00:09:18 +0900658 sp<MediaCodecBuffer> buffer;
Marco Nelissen421f47c2015-03-25 14:40:32 -0700659 mCodec->getInputBuffer(index, &buffer);
660
Wei Jia6301a5e2015-05-13 13:15:18 -0700661 if (buffer == NULL) {
Wei Jiafcd87872017-07-28 15:50:04 -0700662 ALOGE("[%s] handleAnInputBuffer, failed to get input buffer", mComponentName.c_str());
Wei Jia6301a5e2015-05-13 13:15:18 -0700663 handleError(UNKNOWN_ERROR);
664 return false;
665 }
666
Marco Nelissen421f47c2015-03-25 14:40:32 -0700667 if (index >= mInputBuffers.size()) {
668 for (size_t i = mInputBuffers.size(); i <= index; ++i) {
669 mInputBuffers.add();
670 mMediaBuffers.add();
671 mInputBufferIsDequeued.add();
672 mMediaBuffers.editItemAt(i) = NULL;
673 mInputBufferIsDequeued.editItemAt(i) = false;
Lajos Molnar1cd13982014-01-17 15:12:51 -0800674 }
Andreas Huber078cfcf2011-09-15 12:25:04 -0700675 }
Marco Nelissen421f47c2015-03-25 14:40:32 -0700676 mInputBuffers.editItemAt(index) = buffer;
Andreas Huber078cfcf2011-09-15 12:25:04 -0700677
Marco Nelissen421f47c2015-03-25 14:40:32 -0700678 //CHECK_LT(bufferIx, mInputBuffers.size());
Andreas Huberf9334412010-12-15 15:17:42 -0800679
Marco Nelissen421f47c2015-03-25 14:40:32 -0700680 if (mMediaBuffers[index] != NULL) {
681 mMediaBuffers[index]->release();
682 mMediaBuffers.editItemAt(index) = NULL;
Lajos Molnar09524832014-07-17 14:29:51 -0700683 }
Marco Nelissen421f47c2015-03-25 14:40:32 -0700684 mInputBufferIsDequeued.editItemAt(index) = true;
Lajos Molnar09524832014-07-17 14:29:51 -0700685
Lajos Molnar87603c02014-08-20 19:25:30 -0700686 if (!mCSDsToSubmit.isEmpty()) {
Chong Zhang7137ec72014-11-12 16:41:05 -0800687 sp<AMessage> msg = new AMessage();
Marco Nelissen421f47c2015-03-25 14:40:32 -0700688 msg->setSize("buffer-ix", index);
Chong Zhang7137ec72014-11-12 16:41:05 -0800689
Lajos Molnar87603c02014-08-20 19:25:30 -0700690 sp<ABuffer> buffer = mCSDsToSubmit.itemAt(0);
Siarhei Vishniakou6b0b5262019-01-25 19:48:31 -0800691 ALOGV("[%s] resubmitting CSD", mComponentName.c_str());
Chong Zhang7137ec72014-11-12 16:41:05 -0800692 msg->setBuffer("buffer", buffer);
Lajos Molnar87603c02014-08-20 19:25:30 -0700693 mCSDsToSubmit.removeAt(0);
Wei Jia56097a82016-01-07 16:03:03 -0800694 if (!onInputBufferFetched(msg)) {
695 handleError(UNKNOWN_ERROR);
696 return false;
697 }
Wei Jia2245fc62014-10-02 15:12:25 -0700698 return true;
699 }
700
701 while (!mPendingInputMessages.empty()) {
702 sp<AMessage> msg = *mPendingInputMessages.begin();
Chong Zhang7137ec72014-11-12 16:41:05 -0800703 if (!onInputBufferFetched(msg)) {
Wei Jia2245fc62014-10-02 15:12:25 -0700704 break;
705 }
706 mPendingInputMessages.erase(mPendingInputMessages.begin());
707 }
708
Marco Nelissen421f47c2015-03-25 14:40:32 -0700709 if (!mInputBufferIsDequeued.editItemAt(index)) {
Lajos Molnar87603c02014-08-20 19:25:30 -0700710 return true;
711 }
712
Marco Nelissen421f47c2015-03-25 14:40:32 -0700713 mDequeuedInputBuffers.push_back(index);
Chong Zhang7137ec72014-11-12 16:41:05 -0800714
715 onRequestInputBuffers();
Lajos Molnar1cd13982014-01-17 15:12:51 -0800716 return true;
717}
718
Marco Nelissen421f47c2015-03-25 14:40:32 -0700719bool NuPlayer::Decoder::handleAnOutputBuffer(
720 size_t index,
721 size_t offset,
722 size_t size,
723 int64_t timeUs,
724 int32_t flags) {
Wei Jiafcd87872017-07-28 15:50:04 -0700725 if (mCodec == NULL) {
726 ALOGE("[%s] handleAnOutputBuffer without a valid codec", mComponentName.c_str());
727 handleError(NO_INIT);
728 return false;
729 }
730
Marco Nelissen421f47c2015-03-25 14:40:32 -0700731// CHECK_LT(bufferIx, mOutputBuffers.size());
Wonsik Kim7e34bf52016-08-23 00:09:18 +0900732 sp<MediaCodecBuffer> buffer;
Marco Nelissen421f47c2015-03-25 14:40:32 -0700733 mCodec->getOutputBuffer(index, &buffer);
734
Santhosh Behara3539def2015-10-09 17:32:58 -0700735 if (buffer == NULL) {
Wei Jiafcd87872017-07-28 15:50:04 -0700736 ALOGE("[%s] handleAnOutputBuffer, failed to get output buffer", mComponentName.c_str());
Santhosh Behara3539def2015-10-09 17:32:58 -0700737 handleError(UNKNOWN_ERROR);
738 return false;
739 }
740
Marco Nelissen421f47c2015-03-25 14:40:32 -0700741 if (index >= mOutputBuffers.size()) {
742 for (size_t i = mOutputBuffers.size(); i <= index; ++i) {
743 mOutputBuffers.add();
744 }
745 }
746
747 mOutputBuffers.editItemAt(index) = buffer;
748
Chong Zhang7137ec72014-11-12 16:41:05 -0800749 buffer->setRange(offset, size);
750 buffer->meta()->clear();
751 buffer->meta()->setInt64("timeUs", timeUs);
Chong Zhang66704af2015-03-03 19:32:35 -0800752
753 bool eos = flags & MediaCodec::BUFFER_FLAG_EOS;
Chong Zhang7137ec72014-11-12 16:41:05 -0800754 // we do not expect CODECCONFIG or SYNCFRAME for decoder
755
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800756 sp<AMessage> reply = new AMessage(kWhatRenderBuffer, this);
Marco Nelissen421f47c2015-03-25 14:40:32 -0700757 reply->setSize("buffer-ix", index);
Chong Zhang7137ec72014-11-12 16:41:05 -0800758 reply->setInt32("generation", mBufferGeneration);
Praveen Chavanbc5fe9a2018-04-27 16:18:11 -0700759 reply->setSize("size", size);
Chong Zhang7137ec72014-11-12 16:41:05 -0800760
Chong Zhang66704af2015-03-03 19:32:35 -0800761 if (eos) {
Siarhei Vishniakou6b0b5262019-01-25 19:48:31 -0800762 ALOGV("[%s] saw output EOS", mIsAudio ? "audio" : "video");
Chong Zhang66704af2015-03-03 19:32:35 -0800763
764 buffer->meta()->setInt32("eos", true);
765 reply->setInt32("eos", true);
Wei Jiaaec8d822017-08-25 15:27:57 -0700766 }
767
Ray Essickc6e9f6e2017-12-07 16:57:36 -0800768 mNumFramesTotal += !mIsAudio;
769
Wei Jiaaec8d822017-08-25 15:27:57 -0700770 if (mSkipRenderingUntilMediaTimeUs >= 0) {
Chong Zhang7137ec72014-11-12 16:41:05 -0800771 if (timeUs < mSkipRenderingUntilMediaTimeUs) {
772 ALOGV("[%s] dropping buffer at time %lld as requested.",
773 mComponentName.c_str(), (long long)timeUs);
774
775 reply->post();
Wei Jiaaec8d822017-08-25 15:27:57 -0700776 if (eos) {
777 notifyResumeCompleteIfNecessary();
778 if (mRenderer != NULL && !isDiscontinuityPending()) {
779 mRenderer->queueEOS(mIsAudio, ERROR_END_OF_STREAM);
780 }
781 }
Chong Zhang7137ec72014-11-12 16:41:05 -0800782 return true;
783 }
784
785 mSkipRenderingUntilMediaTimeUs = -1;
786 }
787
Chong Zhangf8d71772014-11-26 15:08:34 -0800788 // wait until 1st frame comes out to signal resume complete
789 notifyResumeCompleteIfNecessary();
790
Chong Zhang7137ec72014-11-12 16:41:05 -0800791 if (mRenderer != NULL) {
792 // send the buffer to renderer.
793 mRenderer->queueBuffer(mIsAudio, buffer, reply);
Chong Zhang66704af2015-03-03 19:32:35 -0800794 if (eos && !isDiscontinuityPending()) {
Chong Zhang7137ec72014-11-12 16:41:05 -0800795 mRenderer->queueEOS(mIsAudio, ERROR_END_OF_STREAM);
796 }
797 }
798
799 return true;
800}
801
Marco Nelissen421f47c2015-03-25 14:40:32 -0700802void NuPlayer::Decoder::handleOutputFormatChange(const sp<AMessage> &format) {
803 if (!mIsAudio) {
Praveen Chavane1e5d7a2015-05-19 19:09:48 -0700804 int32_t width, height;
805 if (format->findInt32("width", &width)
806 && format->findInt32("height", &height)) {
Ray Essick83f56b02019-06-23 15:13:46 -0700807 Mutex::Autolock autolock(mStatsLock);
Praveen Chavane1e5d7a2015-05-19 19:09:48 -0700808 mStats->setInt32("width", width);
809 mStats->setInt32("height", height);
810 }
Marco Nelissen421f47c2015-03-25 14:40:32 -0700811 sp<AMessage> notify = mNotify->dup();
812 notify->setInt32("what", kWhatVideoSizeChanged);
813 notify->setMessage("format", format);
814 notify->post();
815 } else if (mRenderer != NULL) {
816 uint32_t flags;
817 int64_t durationUs;
818 bool hasVideo = (mSource->getFormat(false /* audio */) != NULL);
Andy Hung288da022015-05-31 22:55:59 -0700819 if (getAudioDeepBufferSetting() // override regardless of source duration
Andy Hung71c8e5c2017-04-03 15:50:27 -0700820 || (mSource->getDuration(&durationUs) == OK
Andy Hung288da022015-05-31 22:55:59 -0700821 && durationUs > AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US)) {
Marco Nelissen421f47c2015-03-25 14:40:32 -0700822 flags = AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
823 } else {
824 flags = AUDIO_OUTPUT_FLAG_NONE;
825 }
826
Wei Jia9a3101b2016-11-08 14:34:24 -0800827 sp<AMessage> reply = new AMessage(kWhatAudioOutputFormatChanged, this);
828 reply->setInt32("generation", mBufferGeneration);
829 mRenderer->changeAudioFormat(
Dhananjay Kumarc387f2b2015-08-06 10:43:16 +0530830 format, false /* offloadOnly */, hasVideo,
831 flags, mSource->isStreaming(), reply);
Marco Nelissen421f47c2015-03-25 14:40:32 -0700832 }
833}
834
Chong Zhang7137ec72014-11-12 16:41:05 -0800835void NuPlayer::Decoder::releaseAndResetMediaBuffers() {
836 for (size_t i = 0; i < mMediaBuffers.size(); i++) {
837 if (mMediaBuffers[i] != NULL) {
838 mMediaBuffers[i]->release();
839 mMediaBuffers.editItemAt(i) = NULL;
840 }
841 }
842 mMediaBuffers.resize(mInputBuffers.size());
843 for (size_t i = 0; i < mMediaBuffers.size(); i++) {
844 mMediaBuffers.editItemAt(i) = NULL;
845 }
846 mInputBufferIsDequeued.clear();
847 mInputBufferIsDequeued.resize(mInputBuffers.size());
848 for (size_t i = 0; i < mInputBufferIsDequeued.size(); i++) {
849 mInputBufferIsDequeued.editItemAt(i) = false;
850 }
851
852 mPendingInputMessages.clear();
853 mDequeuedInputBuffers.clear();
854 mSkipRenderingUntilMediaTimeUs = -1;
855}
856
857void NuPlayer::Decoder::requestCodecNotification() {
Chong Zhang7137ec72014-11-12 16:41:05 -0800858 if (mCodec != NULL) {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800859 sp<AMessage> reply = new AMessage(kWhatCodecNotify, this);
Chong Zhang7137ec72014-11-12 16:41:05 -0800860 reply->setInt32("generation", mBufferGeneration);
861 mCodec->requestActivityNotification(reply);
862 }
863}
864
865bool NuPlayer::Decoder::isStaleReply(const sp<AMessage> &msg) {
866 int32_t generation;
867 CHECK(msg->findInt32("generation", &generation));
868 return generation != mBufferGeneration;
869}
870
871status_t NuPlayer::Decoder::fetchInputData(sp<AMessage> &reply) {
872 sp<ABuffer> accessUnit;
Robert Shih59e9ca72016-10-20 13:51:42 -0700873 bool dropAccessUnit = true;
Chong Zhang7137ec72014-11-12 16:41:05 -0800874 do {
875 status_t err = mSource->dequeueAccessUnit(mIsAudio, &accessUnit);
876
877 if (err == -EWOULDBLOCK) {
878 return err;
879 } else if (err != OK) {
880 if (err == INFO_DISCONTINUITY) {
881 int32_t type;
882 CHECK(accessUnit->meta()->findInt32("discontinuity", &type));
883
884 bool formatChange =
885 (mIsAudio &&
886 (type & ATSParser::DISCONTINUITY_AUDIO_FORMAT))
887 || (!mIsAudio &&
888 (type & ATSParser::DISCONTINUITY_VIDEO_FORMAT));
889
890 bool timeChange = (type & ATSParser::DISCONTINUITY_TIME) != 0;
891
892 ALOGI("%s discontinuity (format=%d, time=%d)",
893 mIsAudio ? "audio" : "video", formatChange, timeChange);
894
895 bool seamlessFormatChange = false;
896 sp<AMessage> newFormat = mSource->getFormat(mIsAudio);
897 if (formatChange) {
898 seamlessFormatChange =
899 supportsSeamlessFormatChange(newFormat);
900 // treat seamless format change separately
901 formatChange = !seamlessFormatChange;
902 }
903
Chong Zhang66704af2015-03-03 19:32:35 -0800904 // For format or time change, return EOS to queue EOS input,
905 // then wait for EOS on output.
Chong Zhang7137ec72014-11-12 16:41:05 -0800906 if (formatChange /* not seamless */) {
Chong Zhang7137ec72014-11-12 16:41:05 -0800907 mFormatChangePending = true;
Chong Zhang66704af2015-03-03 19:32:35 -0800908 err = ERROR_END_OF_STREAM;
Chong Zhang7137ec72014-11-12 16:41:05 -0800909 } else if (timeChange) {
Chong Zhang7137ec72014-11-12 16:41:05 -0800910 rememberCodecSpecificData(newFormat);
Chong Zhang66704af2015-03-03 19:32:35 -0800911 mTimeChangePending = true;
912 err = ERROR_END_OF_STREAM;
Chong Zhang7137ec72014-11-12 16:41:05 -0800913 } else if (seamlessFormatChange) {
914 // reuse existing decoder and don't flush
915 rememberCodecSpecificData(newFormat);
Chong Zhang66704af2015-03-03 19:32:35 -0800916 continue;
Chong Zhang7137ec72014-11-12 16:41:05 -0800917 } else {
918 // This stream is unaffected by the discontinuity
919 return -EWOULDBLOCK;
920 }
921 }
922
Chong Zhang66704af2015-03-03 19:32:35 -0800923 // reply should only be returned without a buffer set
924 // when there is an error (including EOS)
925 CHECK(err != OK);
926
Chong Zhang7137ec72014-11-12 16:41:05 -0800927 reply->setInt32("err", err);
Chong Zhang66704af2015-03-03 19:32:35 -0800928 return ERROR_END_OF_STREAM;
Chong Zhang7137ec72014-11-12 16:41:05 -0800929 }
930
Chong Zhang7137ec72014-11-12 16:41:05 -0800931 dropAccessUnit = false;
Hassan Shojania62dec952017-05-18 10:45:27 -0700932 if (!mIsAudio && !mIsEncrypted) {
933 // Extra safeguard if higher-level behavior changes. Otherwise, not required now.
934 // Preventing the buffer from being processed (and sent to codec) if this is a later
935 // round of playback but this time without prepareDrm. Or if there is a race between
936 // stop (which is not blocking) and releaseDrm allowing buffers being processed after
937 // Crypto has been released (GenericSource currently prevents this race though).
938 // Particularly doing this check before IsAVCReferenceFrame call to prevent parsing
939 // of encrypted data.
940 if (mIsEncryptedObservedEarlier) {
941 ALOGE("fetchInputData: mismatched mIsEncrypted/mIsEncryptedObservedEarlier (0/1)");
942
943 return INVALID_OPERATION;
944 }
945
Praveen Chavanbbaa1442016-04-08 13:33:49 -0700946 int32_t layerId = 0;
Lajos Molnar9fb81522016-07-14 07:33:43 -0700947 bool haveLayerId = accessUnit->meta()->findInt32("temporal-layer-id", &layerId);
Chih-Hung Hsieh62309d52018-12-11 13:54:02 -0800948 if (mRenderer->getVideoLateByUs() > 100000LL
Praveen Chavanbbaa1442016-04-08 13:33:49 -0700949 && mIsVideoAVC
950 && !IsAVCReferenceFrame(accessUnit)) {
951 dropAccessUnit = true;
Lajos Molnar9fb81522016-07-14 07:33:43 -0700952 } else if (haveLayerId && mNumVideoTemporalLayerTotal > 1) {
Praveen Chavanbbaa1442016-04-08 13:33:49 -0700953 // Add only one layer each time.
954 if (layerId > mCurrentMaxVideoTemporalLayerId + 1
955 || layerId >= mNumVideoTemporalLayerAllowed) {
956 dropAccessUnit = true;
957 ALOGV("dropping layer(%d), speed=%g, allowed layer count=%d, max layerId=%d",
958 layerId, mPlaybackSpeed, mNumVideoTemporalLayerAllowed,
959 mCurrentMaxVideoTemporalLayerId);
960 } else if (layerId > mCurrentMaxVideoTemporalLayerId) {
961 mCurrentMaxVideoTemporalLayerId = layerId;
Dongwon Kangd91dc5a2017-10-10 00:07:09 -0700962 } else if (layerId == 0 && mNumVideoTemporalLayerTotal > 1
963 && IsIDR(accessUnit->data(), accessUnit->size())) {
Lajos Molnar9fb81522016-07-14 07:33:43 -0700964 mCurrentMaxVideoTemporalLayerId = mNumVideoTemporalLayerTotal - 1;
Praveen Chavanbbaa1442016-04-08 13:33:49 -0700965 }
966 }
967 if (dropAccessUnit) {
Lajos Molnar9fb81522016-07-14 07:33:43 -0700968 if (layerId <= mCurrentMaxVideoTemporalLayerId && layerId > 0) {
969 mCurrentMaxVideoTemporalLayerId = layerId - 1;
970 }
Praveen Chavanbbaa1442016-04-08 13:33:49 -0700971 ++mNumInputFramesDropped;
972 }
Chong Zhang7137ec72014-11-12 16:41:05 -0800973 }
974 } while (dropAccessUnit);
975
976 // ALOGV("returned a valid buffer of %s data", mIsAudio ? "mIsAudio" : "video");
977#if 0
978 int64_t mediaTimeUs;
979 CHECK(accessUnit->meta()->findInt64("timeUs", &mediaTimeUs));
Chong Zhang5abbd3d2015-04-20 16:03:00 -0700980 ALOGV("[%s] feeding input buffer at media time %.3f",
Chong Zhang7137ec72014-11-12 16:41:05 -0800981 mIsAudio ? "audio" : "video",
982 mediaTimeUs / 1E6);
983#endif
984
985 if (mCCDecoder != NULL) {
986 mCCDecoder->decode(accessUnit);
987 }
988
989 reply->setBuffer("buffer", accessUnit);
990
991 return OK;
992}
993
994bool NuPlayer::Decoder::onInputBufferFetched(const sp<AMessage> &msg) {
Wei Jiafcd87872017-07-28 15:50:04 -0700995 if (mCodec == NULL) {
996 ALOGE("[%s] onInputBufferFetched without a valid codec", mComponentName.c_str());
997 handleError(NO_INIT);
998 return false;
999 }
1000
Lajos Molnar1cd13982014-01-17 15:12:51 -08001001 size_t bufferIx;
1002 CHECK(msg->findSize("buffer-ix", &bufferIx));
1003 CHECK_LT(bufferIx, mInputBuffers.size());
Wonsik Kim7e34bf52016-08-23 00:09:18 +09001004 sp<MediaCodecBuffer> codecBuffer = mInputBuffers[bufferIx];
Lajos Molnar1cd13982014-01-17 15:12:51 -08001005
1006 sp<ABuffer> buffer;
1007 bool hasBuffer = msg->findBuffer("buffer", &buffer);
Wonsik Kim7e34bf52016-08-23 00:09:18 +09001008 bool needsCopy = true;
Lajos Molnar09524832014-07-17 14:29:51 -07001009
Lajos Molnar1cd13982014-01-17 15:12:51 -08001010 if (buffer == NULL /* includes !hasBuffer */) {
1011 int32_t streamErr = ERROR_END_OF_STREAM;
1012 CHECK(msg->findInt32("err", &streamErr) || !hasBuffer);
1013
Chong Zhang66704af2015-03-03 19:32:35 -08001014 CHECK(streamErr != OK);
Lajos Molnar1cd13982014-01-17 15:12:51 -08001015
1016 // attempt to queue EOS
1017 status_t err = mCodec->queueInputBuffer(
1018 bufferIx,
1019 0,
1020 0,
1021 0,
1022 MediaCodec::BUFFER_FLAG_EOS);
Andy Hungcf31f1e2014-09-23 14:59:01 -07001023 if (err == OK) {
1024 mInputBufferIsDequeued.editItemAt(bufferIx) = false;
1025 } else if (streamErr == ERROR_END_OF_STREAM) {
Lajos Molnar1cd13982014-01-17 15:12:51 -08001026 streamErr = err;
1027 // err will not be ERROR_END_OF_STREAM
1028 }
1029
1030 if (streamErr != ERROR_END_OF_STREAM) {
Wei Jiafcd87872017-07-28 15:50:04 -07001031 ALOGE("Stream error for [%s] (err=%d), EOS %s queued",
Andy Hungcf31f1e2014-09-23 14:59:01 -07001032 mComponentName.c_str(),
1033 streamErr,
1034 err == OK ? "successfully" : "unsuccessfully");
Lajos Molnar1cd13982014-01-17 15:12:51 -08001035 handleError(streamErr);
1036 }
1037 } else {
Wei Jiac6cfd702014-11-11 16:33:20 -08001038 sp<AMessage> extra;
1039 if (buffer->meta()->findMessage("extra", &extra) && extra != NULL) {
1040 int64_t resumeAtMediaTimeUs;
1041 if (extra->findInt64(
1042 "resume-at-mediaTimeUs", &resumeAtMediaTimeUs)) {
Siarhei Vishniakou6b0b5262019-01-25 19:48:31 -08001043 ALOGV("[%s] suppressing rendering until %lld us",
Wei Jiac6cfd702014-11-11 16:33:20 -08001044 mComponentName.c_str(), (long long)resumeAtMediaTimeUs);
1045 mSkipRenderingUntilMediaTimeUs = resumeAtMediaTimeUs;
1046 }
1047 }
1048
Lajos Molnar1cd13982014-01-17 15:12:51 -08001049 int64_t timeUs = 0;
1050 uint32_t flags = 0;
1051 CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
1052
Byeongjo Parkb0225aa2018-04-20 14:00:15 +09001053 int32_t eos, csd, cvo;
Lajos Molnar87603c02014-08-20 19:25:30 -07001054 // we do not expect SYNCFRAME for decoder
Lajos Molnar1cd13982014-01-17 15:12:51 -08001055 if (buffer->meta()->findInt32("eos", &eos) && eos) {
1056 flags |= MediaCodec::BUFFER_FLAG_EOS;
Lajos Molnar87603c02014-08-20 19:25:30 -07001057 } else if (buffer->meta()->findInt32("csd", &csd) && csd) {
1058 flags |= MediaCodec::BUFFER_FLAG_CODECCONFIG;
Lajos Molnar1cd13982014-01-17 15:12:51 -08001059 }
1060
Byeongjo Parkb0225aa2018-04-20 14:00:15 +09001061 if (buffer->meta()->findInt32("cvo", (int32_t*)&cvo)) {
1062 ALOGV("[%s] cvo(%d) found at %lld us", mComponentName.c_str(), cvo, (long long)timeUs);
1063 switch (cvo) {
1064 case 0:
1065 codecBuffer->meta()->setInt32("cvo", MediaCodec::CVO_DEGREE_0);
1066 break;
1067 case 1:
1068 codecBuffer->meta()->setInt32("cvo", MediaCodec::CVO_DEGREE_90);
1069 break;
1070 case 2:
1071 codecBuffer->meta()->setInt32("cvo", MediaCodec::CVO_DEGREE_180);
1072 break;
1073 case 3:
1074 codecBuffer->meta()->setInt32("cvo", MediaCodec::CVO_DEGREE_270);
1075 break;
1076 }
1077 }
1078
Hassan Shojaniacefac142017-02-06 21:02:02 -08001079 // Modular DRM
Dongwon Kang1889c3e2018-02-01 13:44:57 -08001080 MediaBufferBase *mediaBuf = NULL;
Hassan Shojaniacefac142017-02-06 21:02:02 -08001081 NuPlayerDrm::CryptoInfo *cryptInfo = NULL;
1082
Lajos Molnar1cd13982014-01-17 15:12:51 -08001083 // copy into codec buffer
Wonsik Kim7e34bf52016-08-23 00:09:18 +09001084 if (needsCopy) {
Wei Jia56097a82016-01-07 16:03:03 -08001085 if (buffer->size() > codecBuffer->capacity()) {
1086 handleError(ERROR_BUFFER_TOO_SMALL);
1087 mDequeuedInputBuffers.push_back(bufferIx);
1088 return false;
1089 }
Lajos Molnar1cd13982014-01-17 15:12:51 -08001090
Hassan Shojaniacefac142017-02-06 21:02:02 -08001091 if (buffer->data() != NULL) {
1092 codecBuffer->setRange(0, buffer->size());
1093 memcpy(codecBuffer->data(), buffer->data(), buffer->size());
1094 } else { // No buffer->data()
1095 //Modular DRM
Dongwon Kangbc8f53b2018-01-25 17:01:44 -08001096 sp<RefBase> holder;
1097 if (buffer->meta()->findObject("mediaBufferHolder", &holder)) {
1098 mediaBuf = (holder != nullptr) ?
1099 static_cast<MediaBufferHolder*>(holder.get())->mediaBuffer() : nullptr;
1100 }
Hassan Shojaniacefac142017-02-06 21:02:02 -08001101 if (mediaBuf != NULL) {
Wei Jia9b5a7ad2018-07-27 17:33:24 -07001102 if (mediaBuf->size() > codecBuffer->capacity()) {
1103 handleError(ERROR_BUFFER_TOO_SMALL);
1104 mDequeuedInputBuffers.push_back(bufferIx);
1105 return false;
1106 }
1107
Hassan Shojaniacefac142017-02-06 21:02:02 -08001108 codecBuffer->setRange(0, mediaBuf->size());
1109 memcpy(codecBuffer->data(), mediaBuf->data(), mediaBuf->size());
1110
Marco Nelissen3d21ae32018-02-16 08:24:08 -08001111 MetaDataBase &meta_data = mediaBuf->meta_data();
Hassan Shojaniacefac142017-02-06 21:02:02 -08001112 cryptInfo = NuPlayerDrm::getSampleCryptoInfo(meta_data);
Hassan Shojaniacefac142017-02-06 21:02:02 -08001113 } else { // No mediaBuf
1114 ALOGE("onInputBufferFetched: buffer->data()/mediaBuf are NULL for %p",
1115 buffer.get());
1116 handleError(UNKNOWN_ERROR);
1117 return false;
1118 }
1119 } // buffer->data()
1120 } // needsCopy
1121
1122 status_t err;
1123 AString errorDetailMsg;
1124 if (cryptInfo != NULL) {
1125 err = mCodec->queueSecureInputBuffer(
1126 bufferIx,
1127 codecBuffer->offset(),
1128 cryptInfo->subSamples,
1129 cryptInfo->numSubSamples,
1130 cryptInfo->key,
1131 cryptInfo->iv,
1132 cryptInfo->mode,
1133 cryptInfo->pattern,
1134 timeUs,
1135 flags,
1136 &errorDetailMsg);
1137 // synchronous call so done with cryptInfo here
1138 free(cryptInfo);
1139 } else {
1140 err = mCodec->queueInputBuffer(
1141 bufferIx,
1142 codecBuffer->offset(),
1143 codecBuffer->size(),
1144 timeUs,
1145 flags,
1146 &errorDetailMsg);
1147 } // no cryptInfo
1148
Lajos Molnar1cd13982014-01-17 15:12:51 -08001149 if (err != OK) {
Wei Jiafcd87872017-07-28 15:50:04 -07001150 ALOGE("onInputBufferFetched: queue%sInputBuffer failed for [%s] (err=%d, %s)",
Hassan Shojaniacefac142017-02-06 21:02:02 -08001151 (cryptInfo != NULL ? "Secure" : ""),
1152 mComponentName.c_str(), err, errorDetailMsg.c_str());
Lajos Molnar1cd13982014-01-17 15:12:51 -08001153 handleError(err);
Andy Hungcf31f1e2014-09-23 14:59:01 -07001154 } else {
1155 mInputBufferIsDequeued.editItemAt(bufferIx) = false;
Lajos Molnar09524832014-07-17 14:29:51 -07001156 }
Hassan Shojaniacefac142017-02-06 21:02:02 -08001157
1158 } // buffer != NULL
Wei Jia2245fc62014-10-02 15:12:25 -07001159 return true;
Lajos Molnar1cd13982014-01-17 15:12:51 -08001160}
1161
Lajos Molnar1cd13982014-01-17 15:12:51 -08001162void NuPlayer::Decoder::onRenderBuffer(const sp<AMessage> &msg) {
1163 status_t err;
1164 int32_t render;
1165 size_t bufferIx;
Chong Zhang66704af2015-03-03 19:32:35 -08001166 int32_t eos;
Praveen Chavanbc5fe9a2018-04-27 16:18:11 -07001167 size_t size;
Lajos Molnar1cd13982014-01-17 15:12:51 -08001168 CHECK(msg->findSize("buffer-ix", &bufferIx));
Wei Jiac6cfd702014-11-11 16:33:20 -08001169
Chong Zhang7137ec72014-11-12 16:41:05 -08001170 if (!mIsAudio) {
Wei Jiac6cfd702014-11-11 16:33:20 -08001171 int64_t timeUs;
Wonsik Kim7e34bf52016-08-23 00:09:18 +09001172 sp<MediaCodecBuffer> buffer = mOutputBuffers[bufferIx];
Wei Jiac6cfd702014-11-11 16:33:20 -08001173 buffer->meta()->findInt64("timeUs", &timeUs);
Chong Zhang7137ec72014-11-12 16:41:05 -08001174
1175 if (mCCDecoder != NULL && mCCDecoder->isSelected()) {
1176 mCCDecoder->display(timeUs);
1177 }
Wei Jiac6cfd702014-11-11 16:33:20 -08001178 }
1179
Wei Jiafcd87872017-07-28 15:50:04 -07001180 if (mCodec == NULL) {
1181 err = NO_INIT;
1182 } else if (msg->findInt32("render", &render) && render) {
Lajos Molnardc43dfa2014-05-07 15:33:04 -07001183 int64_t timestampNs;
1184 CHECK(msg->findInt64("timestampNs", &timestampNs));
1185 err = mCodec->renderOutputBufferAndRelease(bufferIx, timestampNs);
Lajos Molnar1cd13982014-01-17 15:12:51 -08001186 } else {
Praveen Chavanbc5fe9a2018-04-27 16:18:11 -07001187 if (!msg->findInt32("eos", &eos) || !eos ||
1188 !msg->findSize("size", &size) || size) {
1189 mNumOutputFramesDropped += !mIsAudio;
1190 }
Lajos Molnar1cd13982014-01-17 15:12:51 -08001191 err = mCodec->releaseOutputBuffer(bufferIx);
1192 }
1193 if (err != OK) {
Wei Jiafcd87872017-07-28 15:50:04 -07001194 ALOGE("failed to release output buffer for [%s] (err=%d)",
Lajos Molnar1cd13982014-01-17 15:12:51 -08001195 mComponentName.c_str(), err);
1196 handleError(err);
1197 }
Chong Zhang66704af2015-03-03 19:32:35 -08001198 if (msg->findInt32("eos", &eos) && eos
1199 && isDiscontinuityPending()) {
1200 finishHandleDiscontinuity(true /* flushOnTimeChange */);
1201 }
1202}
1203
1204bool NuPlayer::Decoder::isDiscontinuityPending() const {
1205 return mFormatChangePending || mTimeChangePending;
1206}
1207
1208void NuPlayer::Decoder::finishHandleDiscontinuity(bool flushOnTimeChange) {
1209 ALOGV("finishHandleDiscontinuity: format %d, time %d, flush %d",
1210 mFormatChangePending, mTimeChangePending, flushOnTimeChange);
1211
1212 // If we have format change, pause and wait to be killed;
1213 // If we have time change only, flush and restart fetching.
1214
1215 if (mFormatChangePending) {
1216 mPaused = true;
1217 } else if (mTimeChangePending) {
1218 if (flushOnTimeChange) {
Marco Nelissen421f47c2015-03-25 14:40:32 -07001219 doFlush(false /* notifyComplete */);
1220 signalResume(false /* notifyComplete */);
Chong Zhang66704af2015-03-03 19:32:35 -08001221 }
Chong Zhang66704af2015-03-03 19:32:35 -08001222 }
1223
1224 // Notify NuPlayer to either shutdown decoder, or rescan sources
1225 sp<AMessage> msg = mNotify->dup();
1226 msg->setInt32("what", kWhatInputDiscontinuity);
1227 msg->setInt32("formatChange", mFormatChangePending);
1228 msg->post();
1229
1230 mFormatChangePending = false;
1231 mTimeChangePending = false;
Lajos Molnar1cd13982014-01-17 15:12:51 -08001232}
1233
Chong Zhang7137ec72014-11-12 16:41:05 -08001234bool NuPlayer::Decoder::supportsSeamlessAudioFormatChange(
1235 const sp<AMessage> &targetFormat) const {
Robert Shih6d0a94e2014-01-23 16:18:22 -08001236 if (targetFormat == NULL) {
1237 return true;
1238 }
1239
1240 AString mime;
1241 if (!targetFormat->findString("mime", &mime)) {
1242 return false;
1243 }
1244
1245 if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_AUDIO_AAC)) {
1246 // field-by-field comparison
1247 const char * keys[] = { "channel-count", "sample-rate", "is-adts" };
1248 for (unsigned int i = 0; i < sizeof(keys) / sizeof(keys[0]); i++) {
1249 int32_t oldVal, newVal;
joakim johansson7abbd4c2015-01-30 14:16:03 +01001250 if (!mInputFormat->findInt32(keys[i], &oldVal) ||
Lajos Molnar1cd13982014-01-17 15:12:51 -08001251 !targetFormat->findInt32(keys[i], &newVal) ||
1252 oldVal != newVal) {
Robert Shih6d0a94e2014-01-23 16:18:22 -08001253 return false;
1254 }
1255 }
1256
1257 sp<ABuffer> oldBuf, newBuf;
joakim johansson7abbd4c2015-01-30 14:16:03 +01001258 if (mInputFormat->findBuffer("csd-0", &oldBuf) &&
Lajos Molnar1cd13982014-01-17 15:12:51 -08001259 targetFormat->findBuffer("csd-0", &newBuf)) {
Robert Shih6d0a94e2014-01-23 16:18:22 -08001260 if (oldBuf->size() != newBuf->size()) {
1261 return false;
1262 }
1263 return !memcmp(oldBuf->data(), newBuf->data(), oldBuf->size());
1264 }
1265 }
1266 return false;
1267}
1268
1269bool NuPlayer::Decoder::supportsSeamlessFormatChange(const sp<AMessage> &targetFormat) const {
joakim johansson7abbd4c2015-01-30 14:16:03 +01001270 if (mInputFormat == NULL) {
Robert Shih6d0a94e2014-01-23 16:18:22 -08001271 return false;
1272 }
1273
1274 if (targetFormat == NULL) {
1275 return true;
1276 }
1277
1278 AString oldMime, newMime;
joakim johansson7abbd4c2015-01-30 14:16:03 +01001279 if (!mInputFormat->findString("mime", &oldMime)
Robert Shih6d0a94e2014-01-23 16:18:22 -08001280 || !targetFormat->findString("mime", &newMime)
1281 || !(oldMime == newMime)) {
1282 return false;
1283 }
1284
1285 bool audio = !strncasecmp(oldMime.c_str(), "audio/", strlen("audio/"));
1286 bool seamless;
1287 if (audio) {
1288 seamless = supportsSeamlessAudioFormatChange(targetFormat);
1289 } else {
Lajos Molnar1cd13982014-01-17 15:12:51 -08001290 int32_t isAdaptive;
1291 seamless = (mCodec != NULL &&
1292 mInputFormat->findInt32("adaptive-playback", &isAdaptive) &&
1293 isAdaptive);
Robert Shih6d0a94e2014-01-23 16:18:22 -08001294 }
1295
1296 ALOGV("%s seamless support for %s", seamless ? "yes" : "no", oldMime.c_str());
1297 return seamless;
1298}
1299
Chong Zhang7137ec72014-11-12 16:41:05 -08001300void NuPlayer::Decoder::rememberCodecSpecificData(const sp<AMessage> &format) {
1301 if (format == NULL) {
Chong Zhangb86e68f2014-08-01 13:46:53 -07001302 return;
1303 }
Chong Zhang7137ec72014-11-12 16:41:05 -08001304 mCSDsForCurrentFormat.clear();
1305 for (int32_t i = 0; ; ++i) {
1306 AString tag = "csd-";
1307 tag.append(i);
1308 sp<ABuffer> buffer;
1309 if (!format->findBuffer(tag.c_str(), &buffer)) {
1310 break;
1311 }
1312 mCSDsForCurrentFormat.push(buffer);
Chong Zhanga7fa1d92014-06-11 14:49:23 -07001313 }
Chong Zhangb86e68f2014-08-01 13:46:53 -07001314}
1315
Chong Zhangf8d71772014-11-26 15:08:34 -08001316void NuPlayer::Decoder::notifyResumeCompleteIfNecessary() {
1317 if (mResumePending) {
1318 mResumePending = false;
1319
1320 sp<AMessage> notify = mNotify->dup();
1321 notify->setInt32("what", kWhatResumeCompleted);
1322 notify->post();
1323 }
1324}
1325
Andreas Huberf9334412010-12-15 15:17:42 -08001326} // namespace android
1327