blob: a4a58619c683a22627c8324718e2373377758218 [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>
Lajos Molnar1cd13982014-01-17 15:12:51 -080031#include <media/ICrypto.h>
Wonsik Kim7e34bf52016-08-23 00:09:18 +090032#include <media/MediaCodecBuffer.h>
Andreas Huberf9334412010-12-15 15:17:42 -080033#include <media/stagefright/foundation/ABuffer.h>
34#include <media/stagefright/foundation/ADebug.h>
Andreas Huber5bc087c2010-12-23 10:27:40 -080035#include <media/stagefright/foundation/AMessage.h>
Lajos Molnar09524832014-07-17 14:29:51 -070036#include <media/stagefright/MediaBuffer.h>
Lajos Molnar1cd13982014-01-17 15:12:51 -080037#include <media/stagefright/MediaCodec.h>
Andreas Huberf9334412010-12-15 15:17:42 -080038#include <media/stagefright/MediaDefs.h>
Lajos Molnar1cd13982014-01-17 15:12:51 -080039#include <media/stagefright/MediaErrors.h>
Chong Zhang181fd9b2017-02-16 15:53:03 -080040#include <media/stagefright/SurfaceUtils.h>
Lajos Molnar1de1e252015-04-30 18:18:34 -070041#include <gui/Surface.h>
42
Chong Zhang7137ec72014-11-12 16:41:05 -080043#include "avc_utils.h"
44#include "ATSParser.h"
45
Andreas Huberf9334412010-12-15 15:17:42 -080046namespace android {
47
Lajos Molnar9fb81522016-07-14 07:33:43 -070048static float kDisplayRefreshingRate = 60.f; // TODO: get this from the display
Praveen Chavanbbaa1442016-04-08 13:33:49 -070049
50// The default total video frame rate of a stream when that info is not available from
51// the source.
52static float kDefaultVideoFrameRateTotal = 30.f;
53
Andy Hung288da022015-05-31 22:55:59 -070054static inline bool getAudioDeepBufferSetting() {
55 return property_get_bool("media.stagefright.audio.deep", false /* default_value */);
56}
57
Andreas Huberf9334412010-12-15 15:17:42 -080058NuPlayer::Decoder::Decoder(
Glenn Kasten11731182011-02-08 17:26:17 -080059 const sp<AMessage> &notify,
Wei Jiac6cfd702014-11-11 16:33:20 -080060 const sp<Source> &source,
Ronghua Wu68845c12015-07-21 09:50:48 -070061 pid_t pid,
Wei Jiaf2ae3e12016-10-27 17:10:59 -070062 uid_t uid,
Wei Jiac6cfd702014-11-11 16:33:20 -080063 const sp<Renderer> &renderer,
Lajos Molnar1de1e252015-04-30 18:18:34 -070064 const sp<Surface> &surface,
Chong Zhang7137ec72014-11-12 16:41:05 -080065 const sp<CCDecoder> &ccDecoder)
Andy Hung202bce12014-12-03 11:47:36 -080066 : DecoderBase(notify),
Lajos Molnar1de1e252015-04-30 18:18:34 -070067 mSurface(surface),
Wei Jiac6cfd702014-11-11 16:33:20 -080068 mSource(source),
69 mRenderer(renderer),
Chong Zhang7137ec72014-11-12 16:41:05 -080070 mCCDecoder(ccDecoder),
Ronghua Wu68845c12015-07-21 09:50:48 -070071 mPid(pid),
Wei Jiaf2ae3e12016-10-27 17:10:59 -070072 mUid(uid),
Wei Jiac6cfd702014-11-11 16:33:20 -080073 mSkipRenderingUntilMediaTimeUs(-1ll),
Chong Zhang7137ec72014-11-12 16:41:05 -080074 mNumFramesTotal(0ll),
Praveen Chavane1e5d7a2015-05-19 19:09:48 -070075 mNumInputFramesDropped(0ll),
76 mNumOutputFramesDropped(0ll),
77 mVideoWidth(0),
78 mVideoHeight(0),
Chong Zhang7137ec72014-11-12 16:41:05 -080079 mIsAudio(true),
80 mIsVideoAVC(false),
81 mIsSecure(false),
82 mFormatChangePending(false),
Chong Zhang66704af2015-03-03 19:32:35 -080083 mTimeChangePending(false),
Praveen Chavanbbaa1442016-04-08 13:33:49 -070084 mFrameRateTotal(kDefaultVideoFrameRateTotal),
85 mPlaybackSpeed(1.0f),
Lajos Molnar9fb81522016-07-14 07:33:43 -070086 mNumVideoTemporalLayerTotal(1), // decode all layers
Praveen Chavanbbaa1442016-04-08 13:33:49 -070087 mNumVideoTemporalLayerAllowed(1),
88 mCurrentMaxVideoTemporalLayerId(0),
Chong Zhangf8d71772014-11-26 15:08:34 -080089 mResumePending(false),
Lajos Molnar1cd13982014-01-17 15:12:51 -080090 mComponentName("decoder") {
Lajos Molnar1cd13982014-01-17 15:12:51 -080091 mCodecLooper = new ALooper;
Marco Nelissen9e2b7912014-08-18 16:13:03 -070092 mCodecLooper->setName("NPDecoder-CL");
Lajos Molnar1cd13982014-01-17 15:12:51 -080093 mCodecLooper->start(false, false, ANDROID_PRIORITY_AUDIO);
Praveen Chavanbbaa1442016-04-08 13:33:49 -070094 mVideoTemporalLayerAggregateFps[0] = mFrameRateTotal;
Andreas Huberf9334412010-12-15 15:17:42 -080095}
96
97NuPlayer::Decoder::~Decoder() {
Wei Jia37ff0e62017-04-21 11:24:45 -070098 // Need to stop looper first since mCodec could be accessed on the mDecoderLooper.
99 stopLooper();
100 if (mCodec != NULL) {
101 mCodec->release();
102 }
Wei Jia4923cee2014-09-24 14:25:19 -0700103 releaseAndResetMediaBuffers();
Andreas Huberf9334412010-12-15 15:17:42 -0800104}
105
Praveen Chavane1e5d7a2015-05-19 19:09:48 -0700106sp<AMessage> NuPlayer::Decoder::getStats() const {
107 mStats->setInt64("frames-total", mNumFramesTotal);
108 mStats->setInt64("frames-dropped-input", mNumInputFramesDropped);
109 mStats->setInt64("frames-dropped-output", mNumOutputFramesDropped);
110 return mStats;
Lajos Molnar09524832014-07-17 14:29:51 -0700111}
112
Lajos Molnara81c6222015-07-10 19:17:45 -0700113status_t NuPlayer::Decoder::setVideoSurface(const sp<Surface> &surface) {
114 if (surface == NULL || ADebug::isExperimentEnabled("legacy-setsurface")) {
115 return BAD_VALUE;
116 }
117
118 sp<AMessage> msg = new AMessage(kWhatSetVideoSurface, this);
119
120 msg->setObject("surface", surface);
121 sp<AMessage> response;
122 status_t err = msg->postAndAwaitResponse(&response);
123 if (err == OK && response != NULL) {
124 CHECK(response->findInt32("err", &err));
125 }
126 return err;
127}
128
Chong Zhang7137ec72014-11-12 16:41:05 -0800129void NuPlayer::Decoder::onMessageReceived(const sp<AMessage> &msg) {
130 ALOGV("[%s] onMessage: %s", mComponentName.c_str(), msg->debugString().c_str());
131
132 switch (msg->what()) {
133 case kWhatCodecNotify:
134 {
Chong Zhang3b032b32015-04-17 15:49:06 -0700135 int32_t cbID;
136 CHECK(msg->findInt32("callbackID", &cbID));
137
138 ALOGV("[%s] kWhatCodecNotify: cbID = %d, paused = %d",
139 mIsAudio ? "audio" : "video", cbID, mPaused);
140
Marco Nelissen421f47c2015-03-25 14:40:32 -0700141 if (mPaused) {
142 break;
Chong Zhang7137ec72014-11-12 16:41:05 -0800143 }
144
Marco Nelissen421f47c2015-03-25 14:40:32 -0700145 switch (cbID) {
146 case MediaCodec::CB_INPUT_AVAILABLE:
147 {
148 int32_t index;
149 CHECK(msg->findInt32("index", &index));
150
151 handleAnInputBuffer(index);
152 break;
153 }
154
155 case MediaCodec::CB_OUTPUT_AVAILABLE:
156 {
157 int32_t index;
158 size_t offset;
159 size_t size;
160 int64_t timeUs;
161 int32_t flags;
162
163 CHECK(msg->findInt32("index", &index));
164 CHECK(msg->findSize("offset", &offset));
165 CHECK(msg->findSize("size", &size));
166 CHECK(msg->findInt64("timeUs", &timeUs));
167 CHECK(msg->findInt32("flags", &flags));
168
169 handleAnOutputBuffer(index, offset, size, timeUs, flags);
170 break;
171 }
172
173 case MediaCodec::CB_OUTPUT_FORMAT_CHANGED:
174 {
175 sp<AMessage> format;
176 CHECK(msg->findMessage("format", &format));
177
178 handleOutputFormatChange(format);
179 break;
180 }
181
182 case MediaCodec::CB_ERROR:
183 {
184 status_t err;
185 CHECK(msg->findInt32("err", &err));
186 ALOGE("Decoder (%s) reported error : 0x%x",
187 mIsAudio ? "audio" : "video", err);
188
189 handleError(err);
190 break;
191 }
192
193 default:
194 {
195 TRESPASS();
196 break;
197 }
198 }
199
Lajos Molnar87603c02014-08-20 19:25:30 -0700200 break;
201 }
Chong Zhang7137ec72014-11-12 16:41:05 -0800202
203 case kWhatRenderBuffer:
204 {
205 if (!isStaleReply(msg)) {
206 onRenderBuffer(msg);
207 }
208 break;
209 }
210
Wei Jia9a3101b2016-11-08 14:34:24 -0800211 case kWhatAudioOutputFormatChanged:
212 {
213 if (!isStaleReply(msg)) {
214 status_t err;
215 if (msg->findInt32("err", &err) && err != OK) {
216 ALOGE("Renderer reported 0x%x when changing audio output format", err);
217 handleError(err);
218 }
219 }
220 break;
221 }
222
Lajos Molnara81c6222015-07-10 19:17:45 -0700223 case kWhatSetVideoSurface:
224 {
225 sp<AReplyToken> replyID;
226 CHECK(msg->senderAwaitsResponse(&replyID));
227
228 sp<RefBase> obj;
229 CHECK(msg->findObject("surface", &obj));
230 sp<Surface> surface = static_cast<Surface *>(obj.get()); // non-null
231 int32_t err = INVALID_OPERATION;
232 // NOTE: in practice mSurface is always non-null, but checking here for completeness
233 if (mCodec != NULL && mSurface != NULL) {
234 // TODO: once AwesomePlayer is removed, remove this automatic connecting
235 // to the surface by MediaPlayerService.
236 //
237 // at this point MediaPlayerService::client has already connected to the
238 // surface, which MediaCodec does not expect
Chong Zhang181fd9b2017-02-16 15:53:03 -0800239 err = nativeWindowDisconnect(surface.get(), "kWhatSetVideoSurface(surface)");
Lajos Molnara81c6222015-07-10 19:17:45 -0700240 if (err == OK) {
241 err = mCodec->setSurface(surface);
242 ALOGI_IF(err, "codec setSurface returned: %d", err);
243 if (err == OK) {
244 // reconnect to the old surface as MPS::Client will expect to
245 // be able to disconnect from it.
Chong Zhang181fd9b2017-02-16 15:53:03 -0800246 (void)nativeWindowConnect(mSurface.get(), "kWhatSetVideoSurface(mSurface)");
Lajos Molnara81c6222015-07-10 19:17:45 -0700247 mSurface = surface;
248 }
249 }
250 if (err != OK) {
251 // reconnect to the new surface on error as MPS::Client will expect to
252 // be able to disconnect from it.
Chong Zhang181fd9b2017-02-16 15:53:03 -0800253 (void)nativeWindowConnect(surface.get(), "kWhatSetVideoSurface(err)");
Lajos Molnara81c6222015-07-10 19:17:45 -0700254 }
255 }
256
257 sp<AMessage> response = new AMessage;
258 response->setInt32("err", err);
259 response->postReply(replyID);
260 break;
261 }
262
Hassan Shojaniacefac142017-02-06 21:02:02 -0800263 case kWhatDrmReleaseCrypto:
264 {
265 ALOGV("kWhatDrmReleaseCrypto");
266 onReleaseCrypto(msg);
267 break;
268 }
269
Chong Zhang7137ec72014-11-12 16:41:05 -0800270 default:
271 DecoderBase::onMessageReceived(msg);
272 break;
Lajos Molnar87603c02014-08-20 19:25:30 -0700273 }
274}
275
Lajos Molnar1cd13982014-01-17 15:12:51 -0800276void NuPlayer::Decoder::onConfigure(const sp<AMessage> &format) {
Andreas Huberf9334412010-12-15 15:17:42 -0800277 CHECK(mCodec == NULL);
Andreas Huberf9334412010-12-15 15:17:42 -0800278
Chong Zhang7137ec72014-11-12 16:41:05 -0800279 mFormatChangePending = false;
Chong Zhang66704af2015-03-03 19:32:35 -0800280 mTimeChangePending = false;
Chong Zhang7137ec72014-11-12 16:41:05 -0800281
Lajos Molnar1cd13982014-01-17 15:12:51 -0800282 ++mBufferGeneration;
283
Andreas Huber84066782011-08-16 09:34:26 -0700284 AString mime;
285 CHECK(format->findString("mime", &mime));
Andreas Huberf9334412010-12-15 15:17:42 -0800286
Chong Zhang7137ec72014-11-12 16:41:05 -0800287 mIsAudio = !strncasecmp("audio/", mime.c_str(), 6);
288 mIsVideoAVC = !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime.c_str());
289
Lajos Molnar1cd13982014-01-17 15:12:51 -0800290 mComponentName = mime;
291 mComponentName.append(" decoder");
Lajos Molnar1de1e252015-04-30 18:18:34 -0700292 ALOGV("[%s] onConfigure (surface=%p)", mComponentName.c_str(), mSurface.get());
Lajos Molnar1cd13982014-01-17 15:12:51 -0800293
Ronghua Wu68845c12015-07-21 09:50:48 -0700294 mCodec = MediaCodec::CreateByType(
Wei Jiaf2ae3e12016-10-27 17:10:59 -0700295 mCodecLooper, mime.c_str(), false /* encoder */, NULL /* err */, mPid, mUid);
Lajos Molnar09524832014-07-17 14:29:51 -0700296 int32_t secure = 0;
297 if (format->findInt32("secure", &secure) && secure != 0) {
298 if (mCodec != NULL) {
299 mCodec->getName(&mComponentName);
300 mComponentName.append(".secure");
301 mCodec->release();
302 ALOGI("[%s] creating", mComponentName.c_str());
303 mCodec = MediaCodec::CreateByComponentName(
Wei Jiaf2ae3e12016-10-27 17:10:59 -0700304 mCodecLooper, mComponentName.c_str(), NULL /* err */, mPid, mUid);
Lajos Molnar09524832014-07-17 14:29:51 -0700305 }
306 }
Lajos Molnar1cd13982014-01-17 15:12:51 -0800307 if (mCodec == NULL) {
Lajos Molnar09524832014-07-17 14:29:51 -0700308 ALOGE("Failed to create %s%s decoder",
309 (secure ? "secure " : ""), mime.c_str());
Lajos Molnar1cd13982014-01-17 15:12:51 -0800310 handleError(UNKNOWN_ERROR);
311 return;
312 }
Chong Zhang7137ec72014-11-12 16:41:05 -0800313 mIsSecure = secure;
Lajos Molnar1cd13982014-01-17 15:12:51 -0800314
315 mCodec->getName(&mComponentName);
316
Lajos Molnar14986f62014-09-15 11:04:44 -0700317 status_t err;
Lajos Molnar1de1e252015-04-30 18:18:34 -0700318 if (mSurface != NULL) {
Lajos Molnar1cd13982014-01-17 15:12:51 -0800319 // disconnect from surface as MediaCodec will reconnect
Chong Zhang181fd9b2017-02-16 15:53:03 -0800320 err = nativeWindowDisconnect(mSurface.get(), "onConfigure");
Lajos Molnar14986f62014-09-15 11:04:44 -0700321 // We treat this as a warning, as this is a preparatory step.
322 // Codec will try to connect to the surface, which is where
323 // any error signaling will occur.
324 ALOGW_IF(err != OK, "failed to disconnect from surface: %d", err);
Lajos Molnar1cd13982014-01-17 15:12:51 -0800325 }
Hassan Shojaniacefac142017-02-06 21:02:02 -0800326
327 // Modular DRM
328 void *pCrypto;
329 if (!format->findPointer("crypto", &pCrypto)) {
330 pCrypto = NULL;
331 }
332 sp<ICrypto> crypto = (ICrypto*)pCrypto;
333 ALOGV("onConfigure mCrypto: %p (%d) mIsSecure: %d",
334 crypto.get(), (crypto != NULL ? crypto->getStrongCount() : 0), mIsSecure);
335
Lajos Molnar14986f62014-09-15 11:04:44 -0700336 err = mCodec->configure(
Hassan Shojaniacefac142017-02-06 21:02:02 -0800337 format, mSurface, crypto, 0 /* flags */);
338
Lajos Molnar1cd13982014-01-17 15:12:51 -0800339 if (err != OK) {
340 ALOGE("Failed to configure %s decoder (err=%d)", mComponentName.c_str(), err);
Andy Hung2abde2c2014-09-30 14:40:32 -0700341 mCodec->release();
342 mCodec.clear();
Lajos Molnar1cd13982014-01-17 15:12:51 -0800343 handleError(err);
344 return;
345 }
Lajos Molnar87603c02014-08-20 19:25:30 -0700346 rememberCodecSpecificData(format);
347
Lajos Molnar1cd13982014-01-17 15:12:51 -0800348 // the following should work in configured state
349 CHECK_EQ((status_t)OK, mCodec->getOutputFormat(&mOutputFormat));
350 CHECK_EQ((status_t)OK, mCodec->getInputFormat(&mInputFormat));
351
Praveen Chavane1e5d7a2015-05-19 19:09:48 -0700352 mStats->setString("mime", mime.c_str());
353 mStats->setString("component-name", mComponentName.c_str());
354
355 if (!mIsAudio) {
356 int32_t width, height;
357 if (mOutputFormat->findInt32("width", &width)
358 && mOutputFormat->findInt32("height", &height)) {
359 mStats->setInt32("width", width);
360 mStats->setInt32("height", height);
361 }
362 }
363
Marco Nelissen421f47c2015-03-25 14:40:32 -0700364 sp<AMessage> reply = new AMessage(kWhatCodecNotify, this);
365 mCodec->setCallback(reply);
366
Lajos Molnar1cd13982014-01-17 15:12:51 -0800367 err = mCodec->start();
368 if (err != OK) {
369 ALOGE("Failed to start %s decoder (err=%d)", mComponentName.c_str(), err);
Andy Hung2abde2c2014-09-30 14:40:32 -0700370 mCodec->release();
371 mCodec.clear();
Lajos Molnar1cd13982014-01-17 15:12:51 -0800372 handleError(err);
373 return;
Andreas Huberf9334412010-12-15 15:17:42 -0800374 }
375
Lajos Molnar09524832014-07-17 14:29:51 -0700376 releaseAndResetMediaBuffers();
Marco Nelissen421f47c2015-03-25 14:40:32 -0700377
Wei Jia704e7262014-06-04 16:21:56 -0700378 mPaused = false;
Chong Zhangf8d71772014-11-26 15:08:34 -0800379 mResumePending = false;
Lajos Molnar1cd13982014-01-17 15:12:51 -0800380}
Andreas Huber078cfcf2011-09-15 12:25:04 -0700381
Ronghua Wu8db88132015-04-22 13:51:35 -0700382void NuPlayer::Decoder::onSetParameters(const sp<AMessage> &params) {
Praveen Chavanbbaa1442016-04-08 13:33:49 -0700383 bool needAdjustLayers = false;
384 float frameRateTotal;
385 if (params->findFloat("frame-rate-total", &frameRateTotal)
386 && mFrameRateTotal != frameRateTotal) {
387 needAdjustLayers = true;
388 mFrameRateTotal = frameRateTotal;
Ronghua Wu8db88132015-04-22 13:51:35 -0700389 }
Praveen Chavanbbaa1442016-04-08 13:33:49 -0700390
391 int32_t numVideoTemporalLayerTotal;
392 if (params->findInt32("temporal-layer-count", &numVideoTemporalLayerTotal)
Lajos Molnar9fb81522016-07-14 07:33:43 -0700393 && numVideoTemporalLayerTotal >= 0
Praveen Chavanbbaa1442016-04-08 13:33:49 -0700394 && numVideoTemporalLayerTotal <= kMaxNumVideoTemporalLayers
395 && mNumVideoTemporalLayerTotal != numVideoTemporalLayerTotal) {
396 needAdjustLayers = true;
Lajos Molnar9fb81522016-07-14 07:33:43 -0700397 mNumVideoTemporalLayerTotal = std::max(numVideoTemporalLayerTotal, 1);
Praveen Chavanbbaa1442016-04-08 13:33:49 -0700398 }
399
Lajos Molnar9fb81522016-07-14 07:33:43 -0700400 if (needAdjustLayers && mNumVideoTemporalLayerTotal > 1) {
Praveen Chavanbbaa1442016-04-08 13:33:49 -0700401 // TODO: For now, layer fps is calculated for some specific architectures.
402 // But it really should be extracted from the stream.
403 mVideoTemporalLayerAggregateFps[0] =
404 mFrameRateTotal / (float)(1ll << (mNumVideoTemporalLayerTotal - 1));
405 for (int32_t i = 1; i < mNumVideoTemporalLayerTotal; ++i) {
406 mVideoTemporalLayerAggregateFps[i] =
407 mFrameRateTotal / (float)(1ll << (mNumVideoTemporalLayerTotal - i))
408 + mVideoTemporalLayerAggregateFps[i - 1];
409 }
410 }
411
412 float playbackSpeed;
413 if (params->findFloat("playback-speed", &playbackSpeed)
414 && mPlaybackSpeed != playbackSpeed) {
415 needAdjustLayers = true;
416 mPlaybackSpeed = playbackSpeed;
417 }
418
419 if (needAdjustLayers) {
Lajos Molnar9fb81522016-07-14 07:33:43 -0700420 float decodeFrameRate = mFrameRateTotal;
421 // enable temporal layering optimization only if we know the layering depth
422 if (mNumVideoTemporalLayerTotal > 1) {
423 int32_t layerId;
424 for (layerId = 0; layerId < mNumVideoTemporalLayerTotal - 1; ++layerId) {
425 if (mVideoTemporalLayerAggregateFps[layerId] * mPlaybackSpeed
426 >= kDisplayRefreshingRate * 0.9) {
427 break;
428 }
Praveen Chavanbbaa1442016-04-08 13:33:49 -0700429 }
Lajos Molnar9fb81522016-07-14 07:33:43 -0700430 mNumVideoTemporalLayerAllowed = layerId + 1;
431 decodeFrameRate = mVideoTemporalLayerAggregateFps[layerId];
Praveen Chavanbbaa1442016-04-08 13:33:49 -0700432 }
Lajos Molnar9fb81522016-07-14 07:33:43 -0700433 ALOGV("onSetParameters: allowed layers=%d, decodeFps=%g",
434 mNumVideoTemporalLayerAllowed, decodeFrameRate);
Praveen Chavanbbaa1442016-04-08 13:33:49 -0700435
436 if (mCodec == NULL) {
437 ALOGW("onSetParameters called before codec is created.");
438 return;
439 }
440
441 sp<AMessage> codecParams = new AMessage();
Lajos Molnar9fb81522016-07-14 07:33:43 -0700442 codecParams->setFloat("operating-rate", decodeFrameRate * mPlaybackSpeed);
Praveen Chavanbbaa1442016-04-08 13:33:49 -0700443 mCodec->setParameters(codecParams);
444 }
Ronghua Wu8db88132015-04-22 13:51:35 -0700445}
446
Chong Zhang7137ec72014-11-12 16:41:05 -0800447void NuPlayer::Decoder::onSetRenderer(const sp<Renderer> &renderer) {
Chong Zhang7137ec72014-11-12 16:41:05 -0800448 mRenderer = renderer;
Chong Zhang7137ec72014-11-12 16:41:05 -0800449}
450
Chong Zhangf8d71772014-11-26 15:08:34 -0800451void NuPlayer::Decoder::onResume(bool notifyComplete) {
Chong Zhang7137ec72014-11-12 16:41:05 -0800452 mPaused = false;
Chong Zhangf8d71772014-11-26 15:08:34 -0800453
454 if (notifyComplete) {
455 mResumePending = true;
456 }
Marco Nelissen421f47c2015-03-25 14:40:32 -0700457 mCodec->start();
Chong Zhang7137ec72014-11-12 16:41:05 -0800458}
459
Chong Zhang66704af2015-03-03 19:32:35 -0800460void NuPlayer::Decoder::doFlush(bool notifyComplete) {
Chong Zhang7137ec72014-11-12 16:41:05 -0800461 if (mCCDecoder != NULL) {
462 mCCDecoder->flush();
463 }
464
465 if (mRenderer != NULL) {
466 mRenderer->flush(mIsAudio, notifyComplete);
467 mRenderer->signalTimeDiscontinuity();
468 }
469
470 status_t err = OK;
471 if (mCodec != NULL) {
472 err = mCodec->flush();
473 mCSDsToSubmit = mCSDsForCurrentFormat; // copy operator
474 ++mBufferGeneration;
475 }
476
477 if (err != OK) {
478 ALOGE("failed to flush %s (err=%d)", mComponentName.c_str(), err);
479 handleError(err);
480 // finish with posting kWhatFlushCompleted.
481 // we attempt to release the buffers even if flush fails.
482 }
483 releaseAndResetMediaBuffers();
Marco Nelissen421f47c2015-03-25 14:40:32 -0700484 mPaused = true;
Chong Zhang66704af2015-03-03 19:32:35 -0800485}
Chong Zhang7137ec72014-11-12 16:41:05 -0800486
Marco Nelissen421f47c2015-03-25 14:40:32 -0700487
Chong Zhang66704af2015-03-03 19:32:35 -0800488void NuPlayer::Decoder::onFlush() {
489 doFlush(true);
490
491 if (isDiscontinuityPending()) {
492 // This could happen if the client starts seeking/shutdown
493 // after we queued an EOS for discontinuities.
494 // We can consider discontinuity handled.
495 finishHandleDiscontinuity(false /* flushOnTimeChange */);
Chong Zhang7137ec72014-11-12 16:41:05 -0800496 }
Chong Zhang66704af2015-03-03 19:32:35 -0800497
498 sp<AMessage> notify = mNotify->dup();
499 notify->setInt32("what", kWhatFlushCompleted);
500 notify->post();
Chong Zhang7137ec72014-11-12 16:41:05 -0800501}
502
503void NuPlayer::Decoder::onShutdown(bool notifyComplete) {
504 status_t err = OK;
Chong Zhangf8d71772014-11-26 15:08:34 -0800505
506 // if there is a pending resume request, notify complete now
507 notifyResumeCompleteIfNecessary();
508
Chong Zhang7137ec72014-11-12 16:41:05 -0800509 if (mCodec != NULL) {
510 err = mCodec->release();
511 mCodec = NULL;
512 ++mBufferGeneration;
513
Lajos Molnar1de1e252015-04-30 18:18:34 -0700514 if (mSurface != NULL) {
Chong Zhang7137ec72014-11-12 16:41:05 -0800515 // reconnect to surface as MediaCodec disconnected from it
Chong Zhang181fd9b2017-02-16 15:53:03 -0800516 status_t error = nativeWindowConnect(mSurface.get(), "onShutdown");
Chong Zhang7137ec72014-11-12 16:41:05 -0800517 ALOGW_IF(error != NO_ERROR,
518 "[%s] failed to connect to native window, error=%d",
519 mComponentName.c_str(), error);
520 }
521 mComponentName = "decoder";
522 }
523
524 releaseAndResetMediaBuffers();
525
526 if (err != OK) {
527 ALOGE("failed to release %s (err=%d)", mComponentName.c_str(), err);
528 handleError(err);
529 // finish with posting kWhatShutdownCompleted.
530 }
531
532 if (notifyComplete) {
533 sp<AMessage> notify = mNotify->dup();
534 notify->setInt32("what", kWhatShutdownCompleted);
535 notify->post();
536 mPaused = true;
537 }
538}
539
Chong Zhang3b032b32015-04-17 15:49:06 -0700540/*
541 * returns true if we should request more data
542 */
543bool NuPlayer::Decoder::doRequestBuffers() {
Jeff Tinker29b7dcf2016-10-24 10:28:30 -0700544 if (isDiscontinuityPending()) {
Chong Zhang3b032b32015-04-17 15:49:06 -0700545 return false;
Chong Zhang7137ec72014-11-12 16:41:05 -0800546 }
547 status_t err = OK;
Chong Zhang66704af2015-03-03 19:32:35 -0800548 while (err == OK && !mDequeuedInputBuffers.empty()) {
Chong Zhang7137ec72014-11-12 16:41:05 -0800549 size_t bufferIx = *mDequeuedInputBuffers.begin();
550 sp<AMessage> msg = new AMessage();
551 msg->setSize("buffer-ix", bufferIx);
552 err = fetchInputData(msg);
Chong Zhang66704af2015-03-03 19:32:35 -0800553 if (err != OK && err != ERROR_END_OF_STREAM) {
554 // if EOS, need to queue EOS buffer
Chong Zhang7137ec72014-11-12 16:41:05 -0800555 break;
556 }
557 mDequeuedInputBuffers.erase(mDequeuedInputBuffers.begin());
558
559 if (!mPendingInputMessages.empty()
560 || !onInputBufferFetched(msg)) {
561 mPendingInputMessages.push_back(msg);
Lajos Molnar09524832014-07-17 14:29:51 -0700562 }
563 }
Chong Zhang7137ec72014-11-12 16:41:05 -0800564
Chong Zhang3b032b32015-04-17 15:49:06 -0700565 return err == -EWOULDBLOCK
566 && mSource->feedMoreTSData() == OK;
Lajos Molnar09524832014-07-17 14:29:51 -0700567}
568
Marco Nelissen421f47c2015-03-25 14:40:32 -0700569void NuPlayer::Decoder::handleError(int32_t err)
570{
571 // We cannot immediately release the codec due to buffers still outstanding
572 // in the renderer. We signal to the player the error so it can shutdown/release the
573 // decoder after flushing and increment the generation to discard unnecessary messages.
574
575 ++mBufferGeneration;
576
577 sp<AMessage> notify = mNotify->dup();
578 notify->setInt32("what", kWhatError);
579 notify->setInt32("err", err);
580 notify->post();
581}
582
Hassan Shojaniacefac142017-02-06 21:02:02 -0800583status_t NuPlayer::Decoder::releaseCrypto()
584{
585 ALOGV("releaseCrypto");
586
587 sp<AMessage> msg = new AMessage(kWhatDrmReleaseCrypto, this);
588
589 sp<AMessage> response;
590 status_t status = msg->postAndAwaitResponse(&response);
591 if (status == OK && response != NULL) {
592 CHECK(response->findInt32("status", &status));
593 ALOGV("releaseCrypto ret: %d ", status);
594 } else {
595 ALOGE("releaseCrypto err: %d", status);
596 }
597
598 return status;
599}
600
601void NuPlayer::Decoder::onReleaseCrypto(const sp<AMessage>& msg)
602{
603 status_t status = INVALID_OPERATION;
604 if (mCodec != NULL) {
605 status = mCodec->releaseCrypto();
606 } else {
607 // returning OK if the codec has been already released
608 status = OK;
609 ALOGE("onReleaseCrypto No mCodec. err: %d", status);
610 }
611
612 sp<AMessage> response = new AMessage;
613 response->setInt32("status", status);
614
615 sp<AReplyToken> replyID;
616 CHECK(msg->senderAwaitsResponse(&replyID));
617 response->postReply(replyID);
618}
619
Marco Nelissen421f47c2015-03-25 14:40:32 -0700620bool NuPlayer::Decoder::handleAnInputBuffer(size_t index) {
Chong Zhang66704af2015-03-03 19:32:35 -0800621 if (isDiscontinuityPending()) {
Chong Zhang7137ec72014-11-12 16:41:05 -0800622 return false;
623 }
Marco Nelissen421f47c2015-03-25 14:40:32 -0700624
Wonsik Kim7e34bf52016-08-23 00:09:18 +0900625 sp<MediaCodecBuffer> buffer;
Marco Nelissen421f47c2015-03-25 14:40:32 -0700626 mCodec->getInputBuffer(index, &buffer);
627
Wei Jia6301a5e2015-05-13 13:15:18 -0700628 if (buffer == NULL) {
629 handleError(UNKNOWN_ERROR);
630 return false;
631 }
632
Marco Nelissen421f47c2015-03-25 14:40:32 -0700633 if (index >= mInputBuffers.size()) {
634 for (size_t i = mInputBuffers.size(); i <= index; ++i) {
635 mInputBuffers.add();
636 mMediaBuffers.add();
637 mInputBufferIsDequeued.add();
638 mMediaBuffers.editItemAt(i) = NULL;
639 mInputBufferIsDequeued.editItemAt(i) = false;
Lajos Molnar1cd13982014-01-17 15:12:51 -0800640 }
Andreas Huber078cfcf2011-09-15 12:25:04 -0700641 }
Marco Nelissen421f47c2015-03-25 14:40:32 -0700642 mInputBuffers.editItemAt(index) = buffer;
Andreas Huber078cfcf2011-09-15 12:25:04 -0700643
Marco Nelissen421f47c2015-03-25 14:40:32 -0700644 //CHECK_LT(bufferIx, mInputBuffers.size());
Andreas Huberf9334412010-12-15 15:17:42 -0800645
Marco Nelissen421f47c2015-03-25 14:40:32 -0700646 if (mMediaBuffers[index] != NULL) {
647 mMediaBuffers[index]->release();
648 mMediaBuffers.editItemAt(index) = NULL;
Lajos Molnar09524832014-07-17 14:29:51 -0700649 }
Marco Nelissen421f47c2015-03-25 14:40:32 -0700650 mInputBufferIsDequeued.editItemAt(index) = true;
Lajos Molnar09524832014-07-17 14:29:51 -0700651
Lajos Molnar87603c02014-08-20 19:25:30 -0700652 if (!mCSDsToSubmit.isEmpty()) {
Chong Zhang7137ec72014-11-12 16:41:05 -0800653 sp<AMessage> msg = new AMessage();
Marco Nelissen421f47c2015-03-25 14:40:32 -0700654 msg->setSize("buffer-ix", index);
Chong Zhang7137ec72014-11-12 16:41:05 -0800655
Lajos Molnar87603c02014-08-20 19:25:30 -0700656 sp<ABuffer> buffer = mCSDsToSubmit.itemAt(0);
657 ALOGI("[%s] resubmitting CSD", mComponentName.c_str());
Chong Zhang7137ec72014-11-12 16:41:05 -0800658 msg->setBuffer("buffer", buffer);
Lajos Molnar87603c02014-08-20 19:25:30 -0700659 mCSDsToSubmit.removeAt(0);
Wei Jia56097a82016-01-07 16:03:03 -0800660 if (!onInputBufferFetched(msg)) {
661 handleError(UNKNOWN_ERROR);
662 return false;
663 }
Wei Jia2245fc62014-10-02 15:12:25 -0700664 return true;
665 }
666
667 while (!mPendingInputMessages.empty()) {
668 sp<AMessage> msg = *mPendingInputMessages.begin();
Chong Zhang7137ec72014-11-12 16:41:05 -0800669 if (!onInputBufferFetched(msg)) {
Wei Jia2245fc62014-10-02 15:12:25 -0700670 break;
671 }
672 mPendingInputMessages.erase(mPendingInputMessages.begin());
673 }
674
Marco Nelissen421f47c2015-03-25 14:40:32 -0700675 if (!mInputBufferIsDequeued.editItemAt(index)) {
Lajos Molnar87603c02014-08-20 19:25:30 -0700676 return true;
677 }
678
Marco Nelissen421f47c2015-03-25 14:40:32 -0700679 mDequeuedInputBuffers.push_back(index);
Chong Zhang7137ec72014-11-12 16:41:05 -0800680
681 onRequestInputBuffers();
Lajos Molnar1cd13982014-01-17 15:12:51 -0800682 return true;
683}
684
Marco Nelissen421f47c2015-03-25 14:40:32 -0700685bool NuPlayer::Decoder::handleAnOutputBuffer(
686 size_t index,
687 size_t offset,
688 size_t size,
689 int64_t timeUs,
690 int32_t flags) {
Marco Nelissen421f47c2015-03-25 14:40:32 -0700691// CHECK_LT(bufferIx, mOutputBuffers.size());
Wonsik Kim7e34bf52016-08-23 00:09:18 +0900692 sp<MediaCodecBuffer> buffer;
Marco Nelissen421f47c2015-03-25 14:40:32 -0700693 mCodec->getOutputBuffer(index, &buffer);
694
Santhosh Behara3539def2015-10-09 17:32:58 -0700695 if (buffer == NULL) {
696 handleError(UNKNOWN_ERROR);
697 return false;
698 }
699
Marco Nelissen421f47c2015-03-25 14:40:32 -0700700 if (index >= mOutputBuffers.size()) {
701 for (size_t i = mOutputBuffers.size(); i <= index; ++i) {
702 mOutputBuffers.add();
703 }
704 }
705
706 mOutputBuffers.editItemAt(index) = buffer;
707
Chong Zhang7137ec72014-11-12 16:41:05 -0800708 buffer->setRange(offset, size);
709 buffer->meta()->clear();
710 buffer->meta()->setInt64("timeUs", timeUs);
Chong Zhang66704af2015-03-03 19:32:35 -0800711
712 bool eos = flags & MediaCodec::BUFFER_FLAG_EOS;
Chong Zhang7137ec72014-11-12 16:41:05 -0800713 // we do not expect CODECCONFIG or SYNCFRAME for decoder
714
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800715 sp<AMessage> reply = new AMessage(kWhatRenderBuffer, this);
Marco Nelissen421f47c2015-03-25 14:40:32 -0700716 reply->setSize("buffer-ix", index);
Chong Zhang7137ec72014-11-12 16:41:05 -0800717 reply->setInt32("generation", mBufferGeneration);
718
Chong Zhang66704af2015-03-03 19:32:35 -0800719 if (eos) {
720 ALOGI("[%s] saw output EOS", mIsAudio ? "audio" : "video");
721
722 buffer->meta()->setInt32("eos", true);
723 reply->setInt32("eos", true);
724 } else if (mSkipRenderingUntilMediaTimeUs >= 0) {
Chong Zhang7137ec72014-11-12 16:41:05 -0800725 if (timeUs < mSkipRenderingUntilMediaTimeUs) {
726 ALOGV("[%s] dropping buffer at time %lld as requested.",
727 mComponentName.c_str(), (long long)timeUs);
728
729 reply->post();
730 return true;
731 }
732
733 mSkipRenderingUntilMediaTimeUs = -1;
734 }
735
Praveen Chavane1e5d7a2015-05-19 19:09:48 -0700736 mNumFramesTotal += !mIsAudio;
737
Chong Zhangf8d71772014-11-26 15:08:34 -0800738 // wait until 1st frame comes out to signal resume complete
739 notifyResumeCompleteIfNecessary();
740
Chong Zhang7137ec72014-11-12 16:41:05 -0800741 if (mRenderer != NULL) {
742 // send the buffer to renderer.
743 mRenderer->queueBuffer(mIsAudio, buffer, reply);
Chong Zhang66704af2015-03-03 19:32:35 -0800744 if (eos && !isDiscontinuityPending()) {
Chong Zhang7137ec72014-11-12 16:41:05 -0800745 mRenderer->queueEOS(mIsAudio, ERROR_END_OF_STREAM);
746 }
747 }
748
749 return true;
750}
751
Marco Nelissen421f47c2015-03-25 14:40:32 -0700752void NuPlayer::Decoder::handleOutputFormatChange(const sp<AMessage> &format) {
753 if (!mIsAudio) {
Praveen Chavane1e5d7a2015-05-19 19:09:48 -0700754 int32_t width, height;
755 if (format->findInt32("width", &width)
756 && format->findInt32("height", &height)) {
757 mStats->setInt32("width", width);
758 mStats->setInt32("height", height);
759 }
Marco Nelissen421f47c2015-03-25 14:40:32 -0700760 sp<AMessage> notify = mNotify->dup();
761 notify->setInt32("what", kWhatVideoSizeChanged);
762 notify->setMessage("format", format);
763 notify->post();
764 } else if (mRenderer != NULL) {
765 uint32_t flags;
766 int64_t durationUs;
767 bool hasVideo = (mSource->getFormat(false /* audio */) != NULL);
Andy Hung288da022015-05-31 22:55:59 -0700768 if (getAudioDeepBufferSetting() // override regardless of source duration
Andy Hung71c8e5c2017-04-03 15:50:27 -0700769 || (mSource->getDuration(&durationUs) == OK
Andy Hung288da022015-05-31 22:55:59 -0700770 && durationUs > AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US)) {
Marco Nelissen421f47c2015-03-25 14:40:32 -0700771 flags = AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
772 } else {
773 flags = AUDIO_OUTPUT_FLAG_NONE;
774 }
775
Wei Jia9a3101b2016-11-08 14:34:24 -0800776 sp<AMessage> reply = new AMessage(kWhatAudioOutputFormatChanged, this);
777 reply->setInt32("generation", mBufferGeneration);
778 mRenderer->changeAudioFormat(
Dhananjay Kumarc387f2b2015-08-06 10:43:16 +0530779 format, false /* offloadOnly */, hasVideo,
780 flags, mSource->isStreaming(), reply);
Marco Nelissen421f47c2015-03-25 14:40:32 -0700781 }
782}
783
Chong Zhang7137ec72014-11-12 16:41:05 -0800784void NuPlayer::Decoder::releaseAndResetMediaBuffers() {
785 for (size_t i = 0; i < mMediaBuffers.size(); i++) {
786 if (mMediaBuffers[i] != NULL) {
787 mMediaBuffers[i]->release();
788 mMediaBuffers.editItemAt(i) = NULL;
789 }
790 }
791 mMediaBuffers.resize(mInputBuffers.size());
792 for (size_t i = 0; i < mMediaBuffers.size(); i++) {
793 mMediaBuffers.editItemAt(i) = NULL;
794 }
795 mInputBufferIsDequeued.clear();
796 mInputBufferIsDequeued.resize(mInputBuffers.size());
797 for (size_t i = 0; i < mInputBufferIsDequeued.size(); i++) {
798 mInputBufferIsDequeued.editItemAt(i) = false;
799 }
800
801 mPendingInputMessages.clear();
802 mDequeuedInputBuffers.clear();
803 mSkipRenderingUntilMediaTimeUs = -1;
804}
805
806void NuPlayer::Decoder::requestCodecNotification() {
Chong Zhang7137ec72014-11-12 16:41:05 -0800807 if (mCodec != NULL) {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800808 sp<AMessage> reply = new AMessage(kWhatCodecNotify, this);
Chong Zhang7137ec72014-11-12 16:41:05 -0800809 reply->setInt32("generation", mBufferGeneration);
810 mCodec->requestActivityNotification(reply);
811 }
812}
813
814bool NuPlayer::Decoder::isStaleReply(const sp<AMessage> &msg) {
815 int32_t generation;
816 CHECK(msg->findInt32("generation", &generation));
817 return generation != mBufferGeneration;
818}
819
820status_t NuPlayer::Decoder::fetchInputData(sp<AMessage> &reply) {
821 sp<ABuffer> accessUnit;
Robert Shih59e9ca72016-10-20 13:51:42 -0700822 bool dropAccessUnit = true;
Chong Zhang7137ec72014-11-12 16:41:05 -0800823 do {
824 status_t err = mSource->dequeueAccessUnit(mIsAudio, &accessUnit);
825
826 if (err == -EWOULDBLOCK) {
827 return err;
828 } else if (err != OK) {
829 if (err == INFO_DISCONTINUITY) {
830 int32_t type;
831 CHECK(accessUnit->meta()->findInt32("discontinuity", &type));
832
833 bool formatChange =
834 (mIsAudio &&
835 (type & ATSParser::DISCONTINUITY_AUDIO_FORMAT))
836 || (!mIsAudio &&
837 (type & ATSParser::DISCONTINUITY_VIDEO_FORMAT));
838
839 bool timeChange = (type & ATSParser::DISCONTINUITY_TIME) != 0;
840
841 ALOGI("%s discontinuity (format=%d, time=%d)",
842 mIsAudio ? "audio" : "video", formatChange, timeChange);
843
844 bool seamlessFormatChange = false;
845 sp<AMessage> newFormat = mSource->getFormat(mIsAudio);
846 if (formatChange) {
847 seamlessFormatChange =
848 supportsSeamlessFormatChange(newFormat);
849 // treat seamless format change separately
850 formatChange = !seamlessFormatChange;
851 }
852
Chong Zhang66704af2015-03-03 19:32:35 -0800853 // For format or time change, return EOS to queue EOS input,
854 // then wait for EOS on output.
Chong Zhang7137ec72014-11-12 16:41:05 -0800855 if (formatChange /* not seamless */) {
Chong Zhang7137ec72014-11-12 16:41:05 -0800856 mFormatChangePending = true;
Chong Zhang66704af2015-03-03 19:32:35 -0800857 err = ERROR_END_OF_STREAM;
Chong Zhang7137ec72014-11-12 16:41:05 -0800858 } else if (timeChange) {
Chong Zhang7137ec72014-11-12 16:41:05 -0800859 rememberCodecSpecificData(newFormat);
Chong Zhang66704af2015-03-03 19:32:35 -0800860 mTimeChangePending = true;
861 err = ERROR_END_OF_STREAM;
Chong Zhang7137ec72014-11-12 16:41:05 -0800862 } else if (seamlessFormatChange) {
863 // reuse existing decoder and don't flush
864 rememberCodecSpecificData(newFormat);
Chong Zhang66704af2015-03-03 19:32:35 -0800865 continue;
Chong Zhang7137ec72014-11-12 16:41:05 -0800866 } else {
867 // This stream is unaffected by the discontinuity
868 return -EWOULDBLOCK;
869 }
870 }
871
Chong Zhang66704af2015-03-03 19:32:35 -0800872 // reply should only be returned without a buffer set
873 // when there is an error (including EOS)
874 CHECK(err != OK);
875
Chong Zhang7137ec72014-11-12 16:41:05 -0800876 reply->setInt32("err", err);
Chong Zhang66704af2015-03-03 19:32:35 -0800877 return ERROR_END_OF_STREAM;
Chong Zhang7137ec72014-11-12 16:41:05 -0800878 }
879
Chong Zhang7137ec72014-11-12 16:41:05 -0800880 dropAccessUnit = false;
Praveen Chavanbbaa1442016-04-08 13:33:49 -0700881 if (!mIsAudio && !mIsSecure) {
882 int32_t layerId = 0;
Lajos Molnar9fb81522016-07-14 07:33:43 -0700883 bool haveLayerId = accessUnit->meta()->findInt32("temporal-layer-id", &layerId);
Praveen Chavanbbaa1442016-04-08 13:33:49 -0700884 if (mRenderer->getVideoLateByUs() > 100000ll
885 && mIsVideoAVC
886 && !IsAVCReferenceFrame(accessUnit)) {
887 dropAccessUnit = true;
Lajos Molnar9fb81522016-07-14 07:33:43 -0700888 } else if (haveLayerId && mNumVideoTemporalLayerTotal > 1) {
Praveen Chavanbbaa1442016-04-08 13:33:49 -0700889 // Add only one layer each time.
890 if (layerId > mCurrentMaxVideoTemporalLayerId + 1
891 || layerId >= mNumVideoTemporalLayerAllowed) {
892 dropAccessUnit = true;
893 ALOGV("dropping layer(%d), speed=%g, allowed layer count=%d, max layerId=%d",
894 layerId, mPlaybackSpeed, mNumVideoTemporalLayerAllowed,
895 mCurrentMaxVideoTemporalLayerId);
896 } else if (layerId > mCurrentMaxVideoTemporalLayerId) {
897 mCurrentMaxVideoTemporalLayerId = layerId;
Lajos Molnar9fb81522016-07-14 07:33:43 -0700898 } else if (layerId == 0 && mNumVideoTemporalLayerTotal > 1 && IsIDR(accessUnit)) {
899 mCurrentMaxVideoTemporalLayerId = mNumVideoTemporalLayerTotal - 1;
Praveen Chavanbbaa1442016-04-08 13:33:49 -0700900 }
901 }
902 if (dropAccessUnit) {
Lajos Molnar9fb81522016-07-14 07:33:43 -0700903 if (layerId <= mCurrentMaxVideoTemporalLayerId && layerId > 0) {
904 mCurrentMaxVideoTemporalLayerId = layerId - 1;
905 }
Praveen Chavanbbaa1442016-04-08 13:33:49 -0700906 ++mNumInputFramesDropped;
907 }
Chong Zhang7137ec72014-11-12 16:41:05 -0800908 }
909 } while (dropAccessUnit);
910
911 // ALOGV("returned a valid buffer of %s data", mIsAudio ? "mIsAudio" : "video");
912#if 0
913 int64_t mediaTimeUs;
914 CHECK(accessUnit->meta()->findInt64("timeUs", &mediaTimeUs));
Chong Zhang5abbd3d2015-04-20 16:03:00 -0700915 ALOGV("[%s] feeding input buffer at media time %.3f",
Chong Zhang7137ec72014-11-12 16:41:05 -0800916 mIsAudio ? "audio" : "video",
917 mediaTimeUs / 1E6);
918#endif
919
920 if (mCCDecoder != NULL) {
921 mCCDecoder->decode(accessUnit);
922 }
923
924 reply->setBuffer("buffer", accessUnit);
925
926 return OK;
927}
928
929bool NuPlayer::Decoder::onInputBufferFetched(const sp<AMessage> &msg) {
Lajos Molnar1cd13982014-01-17 15:12:51 -0800930 size_t bufferIx;
931 CHECK(msg->findSize("buffer-ix", &bufferIx));
932 CHECK_LT(bufferIx, mInputBuffers.size());
Wonsik Kim7e34bf52016-08-23 00:09:18 +0900933 sp<MediaCodecBuffer> codecBuffer = mInputBuffers[bufferIx];
Lajos Molnar1cd13982014-01-17 15:12:51 -0800934
935 sp<ABuffer> buffer;
936 bool hasBuffer = msg->findBuffer("buffer", &buffer);
Wonsik Kim7e34bf52016-08-23 00:09:18 +0900937 bool needsCopy = true;
Lajos Molnar09524832014-07-17 14:29:51 -0700938
Lajos Molnar1cd13982014-01-17 15:12:51 -0800939 if (buffer == NULL /* includes !hasBuffer */) {
940 int32_t streamErr = ERROR_END_OF_STREAM;
941 CHECK(msg->findInt32("err", &streamErr) || !hasBuffer);
942
Chong Zhang66704af2015-03-03 19:32:35 -0800943 CHECK(streamErr != OK);
Lajos Molnar1cd13982014-01-17 15:12:51 -0800944
945 // attempt to queue EOS
946 status_t err = mCodec->queueInputBuffer(
947 bufferIx,
948 0,
949 0,
950 0,
951 MediaCodec::BUFFER_FLAG_EOS);
Andy Hungcf31f1e2014-09-23 14:59:01 -0700952 if (err == OK) {
953 mInputBufferIsDequeued.editItemAt(bufferIx) = false;
954 } else if (streamErr == ERROR_END_OF_STREAM) {
Lajos Molnar1cd13982014-01-17 15:12:51 -0800955 streamErr = err;
956 // err will not be ERROR_END_OF_STREAM
957 }
958
959 if (streamErr != ERROR_END_OF_STREAM) {
Andy Hungcf31f1e2014-09-23 14:59:01 -0700960 ALOGE("Stream error for %s (err=%d), EOS %s queued",
961 mComponentName.c_str(),
962 streamErr,
963 err == OK ? "successfully" : "unsuccessfully");
Lajos Molnar1cd13982014-01-17 15:12:51 -0800964 handleError(streamErr);
965 }
966 } else {
Wei Jiac6cfd702014-11-11 16:33:20 -0800967 sp<AMessage> extra;
968 if (buffer->meta()->findMessage("extra", &extra) && extra != NULL) {
969 int64_t resumeAtMediaTimeUs;
970 if (extra->findInt64(
971 "resume-at-mediaTimeUs", &resumeAtMediaTimeUs)) {
972 ALOGI("[%s] suppressing rendering until %lld us",
973 mComponentName.c_str(), (long long)resumeAtMediaTimeUs);
974 mSkipRenderingUntilMediaTimeUs = resumeAtMediaTimeUs;
975 }
976 }
977
Lajos Molnar1cd13982014-01-17 15:12:51 -0800978 int64_t timeUs = 0;
979 uint32_t flags = 0;
980 CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
981
Lajos Molnar87603c02014-08-20 19:25:30 -0700982 int32_t eos, csd;
983 // we do not expect SYNCFRAME for decoder
Lajos Molnar1cd13982014-01-17 15:12:51 -0800984 if (buffer->meta()->findInt32("eos", &eos) && eos) {
985 flags |= MediaCodec::BUFFER_FLAG_EOS;
Lajos Molnar87603c02014-08-20 19:25:30 -0700986 } else if (buffer->meta()->findInt32("csd", &csd) && csd) {
987 flags |= MediaCodec::BUFFER_FLAG_CODECCONFIG;
Lajos Molnar1cd13982014-01-17 15:12:51 -0800988 }
989
Hassan Shojaniacefac142017-02-06 21:02:02 -0800990 // Modular DRM
991 MediaBuffer *mediaBuf = NULL;
992 NuPlayerDrm::CryptoInfo *cryptInfo = NULL;
993
Lajos Molnar1cd13982014-01-17 15:12:51 -0800994 // copy into codec buffer
Wonsik Kim7e34bf52016-08-23 00:09:18 +0900995 if (needsCopy) {
Wei Jia56097a82016-01-07 16:03:03 -0800996 if (buffer->size() > codecBuffer->capacity()) {
997 handleError(ERROR_BUFFER_TOO_SMALL);
998 mDequeuedInputBuffers.push_back(bufferIx);
999 return false;
1000 }
Lajos Molnar1cd13982014-01-17 15:12:51 -08001001
Hassan Shojaniacefac142017-02-06 21:02:02 -08001002 if (buffer->data() != NULL) {
1003 codecBuffer->setRange(0, buffer->size());
1004 memcpy(codecBuffer->data(), buffer->data(), buffer->size());
1005 } else { // No buffer->data()
1006 //Modular DRM
1007 mediaBuf = (MediaBuffer*)buffer->getMediaBufferBase();
1008 if (mediaBuf != NULL) {
1009 codecBuffer->setRange(0, mediaBuf->size());
1010 memcpy(codecBuffer->data(), mediaBuf->data(), mediaBuf->size());
1011
1012 sp<MetaData> meta_data = mediaBuf->meta_data();
1013 cryptInfo = NuPlayerDrm::getSampleCryptoInfo(meta_data);
1014
1015 // since getMediaBuffer() has incremented the refCount
1016 mediaBuf->release();
1017 } else { // No mediaBuf
1018 ALOGE("onInputBufferFetched: buffer->data()/mediaBuf are NULL for %p",
1019 buffer.get());
1020 handleError(UNKNOWN_ERROR);
1021 return false;
1022 }
1023 } // buffer->data()
1024 } // needsCopy
1025
1026 status_t err;
1027 AString errorDetailMsg;
1028 if (cryptInfo != NULL) {
1029 err = mCodec->queueSecureInputBuffer(
1030 bufferIx,
1031 codecBuffer->offset(),
1032 cryptInfo->subSamples,
1033 cryptInfo->numSubSamples,
1034 cryptInfo->key,
1035 cryptInfo->iv,
1036 cryptInfo->mode,
1037 cryptInfo->pattern,
1038 timeUs,
1039 flags,
1040 &errorDetailMsg);
1041 // synchronous call so done with cryptInfo here
1042 free(cryptInfo);
1043 } else {
1044 err = mCodec->queueInputBuffer(
1045 bufferIx,
1046 codecBuffer->offset(),
1047 codecBuffer->size(),
1048 timeUs,
1049 flags,
1050 &errorDetailMsg);
1051 } // no cryptInfo
1052
Lajos Molnar1cd13982014-01-17 15:12:51 -08001053 if (err != OK) {
Hassan Shojaniacefac142017-02-06 21:02:02 -08001054 ALOGE("onInputBufferFetched: queue%sInputBuffer failed for %s (err=%d, %s)",
1055 (cryptInfo != NULL ? "Secure" : ""),
1056 mComponentName.c_str(), err, errorDetailMsg.c_str());
Lajos Molnar1cd13982014-01-17 15:12:51 -08001057 handleError(err);
Andy Hungcf31f1e2014-09-23 14:59:01 -07001058 } else {
1059 mInputBufferIsDequeued.editItemAt(bufferIx) = false;
Lajos Molnar09524832014-07-17 14:29:51 -07001060 }
Hassan Shojaniacefac142017-02-06 21:02:02 -08001061
1062 } // buffer != NULL
Wei Jia2245fc62014-10-02 15:12:25 -07001063 return true;
Lajos Molnar1cd13982014-01-17 15:12:51 -08001064}
1065
Lajos Molnar1cd13982014-01-17 15:12:51 -08001066void NuPlayer::Decoder::onRenderBuffer(const sp<AMessage> &msg) {
1067 status_t err;
1068 int32_t render;
1069 size_t bufferIx;
Chong Zhang66704af2015-03-03 19:32:35 -08001070 int32_t eos;
Lajos Molnar1cd13982014-01-17 15:12:51 -08001071 CHECK(msg->findSize("buffer-ix", &bufferIx));
Wei Jiac6cfd702014-11-11 16:33:20 -08001072
Chong Zhang7137ec72014-11-12 16:41:05 -08001073 if (!mIsAudio) {
Wei Jiac6cfd702014-11-11 16:33:20 -08001074 int64_t timeUs;
Wonsik Kim7e34bf52016-08-23 00:09:18 +09001075 sp<MediaCodecBuffer> buffer = mOutputBuffers[bufferIx];
Wei Jiac6cfd702014-11-11 16:33:20 -08001076 buffer->meta()->findInt64("timeUs", &timeUs);
Chong Zhang7137ec72014-11-12 16:41:05 -08001077
1078 if (mCCDecoder != NULL && mCCDecoder->isSelected()) {
1079 mCCDecoder->display(timeUs);
1080 }
Wei Jiac6cfd702014-11-11 16:33:20 -08001081 }
1082
Lajos Molnar1cd13982014-01-17 15:12:51 -08001083 if (msg->findInt32("render", &render) && render) {
Lajos Molnardc43dfa2014-05-07 15:33:04 -07001084 int64_t timestampNs;
1085 CHECK(msg->findInt64("timestampNs", &timestampNs));
1086 err = mCodec->renderOutputBufferAndRelease(bufferIx, timestampNs);
Lajos Molnar1cd13982014-01-17 15:12:51 -08001087 } else {
Praveen Chavane1e5d7a2015-05-19 19:09:48 -07001088 mNumOutputFramesDropped += !mIsAudio;
Lajos Molnar1cd13982014-01-17 15:12:51 -08001089 err = mCodec->releaseOutputBuffer(bufferIx);
1090 }
1091 if (err != OK) {
1092 ALOGE("failed to release output buffer for %s (err=%d)",
1093 mComponentName.c_str(), err);
1094 handleError(err);
1095 }
Chong Zhang66704af2015-03-03 19:32:35 -08001096 if (msg->findInt32("eos", &eos) && eos
1097 && isDiscontinuityPending()) {
1098 finishHandleDiscontinuity(true /* flushOnTimeChange */);
1099 }
1100}
1101
1102bool NuPlayer::Decoder::isDiscontinuityPending() const {
1103 return mFormatChangePending || mTimeChangePending;
1104}
1105
1106void NuPlayer::Decoder::finishHandleDiscontinuity(bool flushOnTimeChange) {
1107 ALOGV("finishHandleDiscontinuity: format %d, time %d, flush %d",
1108 mFormatChangePending, mTimeChangePending, flushOnTimeChange);
1109
1110 // If we have format change, pause and wait to be killed;
1111 // If we have time change only, flush and restart fetching.
1112
1113 if (mFormatChangePending) {
1114 mPaused = true;
1115 } else if (mTimeChangePending) {
1116 if (flushOnTimeChange) {
Marco Nelissen421f47c2015-03-25 14:40:32 -07001117 doFlush(false /* notifyComplete */);
1118 signalResume(false /* notifyComplete */);
Chong Zhang66704af2015-03-03 19:32:35 -08001119 }
Chong Zhang66704af2015-03-03 19:32:35 -08001120 }
1121
1122 // Notify NuPlayer to either shutdown decoder, or rescan sources
1123 sp<AMessage> msg = mNotify->dup();
1124 msg->setInt32("what", kWhatInputDiscontinuity);
1125 msg->setInt32("formatChange", mFormatChangePending);
1126 msg->post();
1127
1128 mFormatChangePending = false;
1129 mTimeChangePending = false;
Lajos Molnar1cd13982014-01-17 15:12:51 -08001130}
1131
Chong Zhang7137ec72014-11-12 16:41:05 -08001132bool NuPlayer::Decoder::supportsSeamlessAudioFormatChange(
1133 const sp<AMessage> &targetFormat) const {
Robert Shih6d0a94e2014-01-23 16:18:22 -08001134 if (targetFormat == NULL) {
1135 return true;
1136 }
1137
1138 AString mime;
1139 if (!targetFormat->findString("mime", &mime)) {
1140 return false;
1141 }
1142
1143 if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_AUDIO_AAC)) {
1144 // field-by-field comparison
1145 const char * keys[] = { "channel-count", "sample-rate", "is-adts" };
1146 for (unsigned int i = 0; i < sizeof(keys) / sizeof(keys[0]); i++) {
1147 int32_t oldVal, newVal;
joakim johansson7abbd4c2015-01-30 14:16:03 +01001148 if (!mInputFormat->findInt32(keys[i], &oldVal) ||
Lajos Molnar1cd13982014-01-17 15:12:51 -08001149 !targetFormat->findInt32(keys[i], &newVal) ||
1150 oldVal != newVal) {
Robert Shih6d0a94e2014-01-23 16:18:22 -08001151 return false;
1152 }
1153 }
1154
1155 sp<ABuffer> oldBuf, newBuf;
joakim johansson7abbd4c2015-01-30 14:16:03 +01001156 if (mInputFormat->findBuffer("csd-0", &oldBuf) &&
Lajos Molnar1cd13982014-01-17 15:12:51 -08001157 targetFormat->findBuffer("csd-0", &newBuf)) {
Robert Shih6d0a94e2014-01-23 16:18:22 -08001158 if (oldBuf->size() != newBuf->size()) {
1159 return false;
1160 }
1161 return !memcmp(oldBuf->data(), newBuf->data(), oldBuf->size());
1162 }
1163 }
1164 return false;
1165}
1166
1167bool NuPlayer::Decoder::supportsSeamlessFormatChange(const sp<AMessage> &targetFormat) const {
joakim johansson7abbd4c2015-01-30 14:16:03 +01001168 if (mInputFormat == NULL) {
Robert Shih6d0a94e2014-01-23 16:18:22 -08001169 return false;
1170 }
1171
1172 if (targetFormat == NULL) {
1173 return true;
1174 }
1175
1176 AString oldMime, newMime;
joakim johansson7abbd4c2015-01-30 14:16:03 +01001177 if (!mInputFormat->findString("mime", &oldMime)
Robert Shih6d0a94e2014-01-23 16:18:22 -08001178 || !targetFormat->findString("mime", &newMime)
1179 || !(oldMime == newMime)) {
1180 return false;
1181 }
1182
1183 bool audio = !strncasecmp(oldMime.c_str(), "audio/", strlen("audio/"));
1184 bool seamless;
1185 if (audio) {
1186 seamless = supportsSeamlessAudioFormatChange(targetFormat);
1187 } else {
Lajos Molnar1cd13982014-01-17 15:12:51 -08001188 int32_t isAdaptive;
1189 seamless = (mCodec != NULL &&
1190 mInputFormat->findInt32("adaptive-playback", &isAdaptive) &&
1191 isAdaptive);
Robert Shih6d0a94e2014-01-23 16:18:22 -08001192 }
1193
1194 ALOGV("%s seamless support for %s", seamless ? "yes" : "no", oldMime.c_str());
1195 return seamless;
1196}
1197
Chong Zhang7137ec72014-11-12 16:41:05 -08001198void NuPlayer::Decoder::rememberCodecSpecificData(const sp<AMessage> &format) {
1199 if (format == NULL) {
Chong Zhangb86e68f2014-08-01 13:46:53 -07001200 return;
1201 }
Chong Zhang7137ec72014-11-12 16:41:05 -08001202 mCSDsForCurrentFormat.clear();
1203 for (int32_t i = 0; ; ++i) {
1204 AString tag = "csd-";
1205 tag.append(i);
1206 sp<ABuffer> buffer;
1207 if (!format->findBuffer(tag.c_str(), &buffer)) {
1208 break;
1209 }
1210 mCSDsForCurrentFormat.push(buffer);
Chong Zhanga7fa1d92014-06-11 14:49:23 -07001211 }
Chong Zhangb86e68f2014-08-01 13:46:53 -07001212}
1213
Chong Zhangf8d71772014-11-26 15:08:34 -08001214void NuPlayer::Decoder::notifyResumeCompleteIfNecessary() {
1215 if (mResumePending) {
1216 mResumePending = false;
1217
1218 sp<AMessage> notify = mNotify->dup();
1219 notify->setInt32("what", kWhatResumeCompleted);
1220 notify->post();
1221 }
1222}
1223
Andreas Huberf9334412010-12-15 15:17:42 -08001224} // namespace android
1225