blob: 5aaf48ce74779806e9241c93bb104b53b1d6d1a6 [file] [log] [blame]
Andreas Huberf9334412010-12-15 15:17:42 -08001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//#define LOG_NDEBUG 0
18#define LOG_TAG "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
22#include "NuPlayerDecoder.h"
23
Lajos Molnar1cd13982014-01-17 15:12:51 -080024#include <media/ICrypto.h>
Chong Zhanga7fa1d92014-06-11 14:49:23 -070025#include <media/stagefright/foundation/ABitReader.h>
Andreas Huberf9334412010-12-15 15:17:42 -080026#include <media/stagefright/foundation/ABuffer.h>
27#include <media/stagefright/foundation/ADebug.h>
Andreas Huber5bc087c2010-12-23 10:27:40 -080028#include <media/stagefright/foundation/AMessage.h>
Lajos Molnar09524832014-07-17 14:29:51 -070029#include <media/stagefright/MediaBuffer.h>
Lajos Molnar1cd13982014-01-17 15:12:51 -080030#include <media/stagefright/MediaCodec.h>
Andreas Huberf9334412010-12-15 15:17:42 -080031#include <media/stagefright/MediaDefs.h>
Lajos Molnar1cd13982014-01-17 15:12:51 -080032#include <media/stagefright/MediaErrors.h>
Andreas Huberf9334412010-12-15 15:17:42 -080033
34namespace android {
35
36NuPlayer::Decoder::Decoder(
Glenn Kasten11731182011-02-08 17:26:17 -080037 const sp<AMessage> &notify,
38 const sp<NativeWindowWrapper> &nativeWindow)
Andreas Huberf9334412010-12-15 15:17:42 -080039 : mNotify(notify),
Lajos Molnar1cd13982014-01-17 15:12:51 -080040 mNativeWindow(nativeWindow),
41 mBufferGeneration(0),
Wei Jia704e7262014-06-04 16:21:56 -070042 mPaused(true),
Lajos Molnar1cd13982014-01-17 15:12:51 -080043 mComponentName("decoder") {
44 // Every decoder has its own looper because MediaCodec operations
45 // are blocking, but NuPlayer needs asynchronous operations.
46 mDecoderLooper = new ALooper;
Marco Nelissen9e2b7912014-08-18 16:13:03 -070047 mDecoderLooper->setName("NPDecoder");
Lajos Molnar1cd13982014-01-17 15:12:51 -080048 mDecoderLooper->start(false, false, ANDROID_PRIORITY_AUDIO);
49
50 mCodecLooper = new ALooper;
Marco Nelissen9e2b7912014-08-18 16:13:03 -070051 mCodecLooper->setName("NPDecoder-CL");
Lajos Molnar1cd13982014-01-17 15:12:51 -080052 mCodecLooper->start(false, false, ANDROID_PRIORITY_AUDIO);
Andreas Huberf9334412010-12-15 15:17:42 -080053}
54
55NuPlayer::Decoder::~Decoder() {
56}
57
Lajos Molnar09524832014-07-17 14:29:51 -070058static
59status_t PostAndAwaitResponse(
60 const sp<AMessage> &msg, sp<AMessage> *response) {
61 status_t err = msg->postAndAwaitResponse(response);
62
63 if (err != OK) {
64 return err;
65 }
66
67 if (!(*response)->findInt32("err", &err)) {
68 err = OK;
69 }
70
71 return err;
72}
73
Lajos Molnar87603c02014-08-20 19:25:30 -070074void NuPlayer::Decoder::rememberCodecSpecificData(const sp<AMessage> &format) {
75 mCSDsForCurrentFormat.clear();
76 for (int32_t i = 0; ; ++i) {
77 AString tag = "csd-";
78 tag.append(i);
79 sp<ABuffer> buffer;
80 if (!format->findBuffer(tag.c_str(), &buffer)) {
81 break;
82 }
83 mCSDsForCurrentFormat.push(buffer);
84 }
85}
86
Lajos Molnar1cd13982014-01-17 15:12:51 -080087void NuPlayer::Decoder::onConfigure(const sp<AMessage> &format) {
Andreas Huberf9334412010-12-15 15:17:42 -080088 CHECK(mCodec == NULL);
Andreas Huberf9334412010-12-15 15:17:42 -080089
Lajos Molnar1cd13982014-01-17 15:12:51 -080090 ++mBufferGeneration;
91
Andreas Huber84066782011-08-16 09:34:26 -070092 AString mime;
93 CHECK(format->findString("mime", &mime));
Andreas Huberf9334412010-12-15 15:17:42 -080094
Lajos Molnar1cd13982014-01-17 15:12:51 -080095 sp<Surface> surface = NULL;
96 if (mNativeWindow != NULL) {
97 surface = mNativeWindow->getSurfaceTextureClient();
Andreas Huber84066782011-08-16 09:34:26 -070098 }
Andreas Huberf9334412010-12-15 15:17:42 -080099
Lajos Molnar1cd13982014-01-17 15:12:51 -0800100 mComponentName = mime;
101 mComponentName.append(" decoder");
102 ALOGV("[%s] onConfigure (surface=%p)", mComponentName.c_str(), surface.get());
103
104 mCodec = MediaCodec::CreateByType(mCodecLooper, mime.c_str(), false /* encoder */);
Lajos Molnar09524832014-07-17 14:29:51 -0700105 int32_t secure = 0;
106 if (format->findInt32("secure", &secure) && secure != 0) {
107 if (mCodec != NULL) {
108 mCodec->getName(&mComponentName);
109 mComponentName.append(".secure");
110 mCodec->release();
111 ALOGI("[%s] creating", mComponentName.c_str());
112 mCodec = MediaCodec::CreateByComponentName(
113 mCodecLooper, mComponentName.c_str());
114 }
115 }
Lajos Molnar1cd13982014-01-17 15:12:51 -0800116 if (mCodec == NULL) {
Lajos Molnar09524832014-07-17 14:29:51 -0700117 ALOGE("Failed to create %s%s decoder",
118 (secure ? "secure " : ""), mime.c_str());
Lajos Molnar1cd13982014-01-17 15:12:51 -0800119 handleError(UNKNOWN_ERROR);
120 return;
121 }
122
123 mCodec->getName(&mComponentName);
124
Glenn Kasten11731182011-02-08 17:26:17 -0800125 if (mNativeWindow != NULL) {
Lajos Molnar1cd13982014-01-17 15:12:51 -0800126 // disconnect from surface as MediaCodec will reconnect
127 CHECK_EQ((int)NO_ERROR,
128 native_window_api_disconnect(
129 surface.get(),
130 NATIVE_WINDOW_API_MEDIA));
131 }
132 status_t err = mCodec->configure(
133 format, surface, NULL /* crypto */, 0 /* flags */);
134 if (err != OK) {
135 ALOGE("Failed to configure %s decoder (err=%d)", mComponentName.c_str(), err);
136 handleError(err);
137 return;
138 }
Lajos Molnar87603c02014-08-20 19:25:30 -0700139 rememberCodecSpecificData(format);
140
Lajos Molnar1cd13982014-01-17 15:12:51 -0800141 // the following should work in configured state
142 CHECK_EQ((status_t)OK, mCodec->getOutputFormat(&mOutputFormat));
143 CHECK_EQ((status_t)OK, mCodec->getInputFormat(&mInputFormat));
144
145 err = mCodec->start();
146 if (err != OK) {
147 ALOGE("Failed to start %s decoder (err=%d)", mComponentName.c_str(), err);
148 handleError(err);
149 return;
Andreas Huberf9334412010-12-15 15:17:42 -0800150 }
151
Lajos Molnar1cd13982014-01-17 15:12:51 -0800152 // the following should work after start
153 CHECK_EQ((status_t)OK, mCodec->getInputBuffers(&mInputBuffers));
Lajos Molnar09524832014-07-17 14:29:51 -0700154 releaseAndResetMediaBuffers();
Lajos Molnar1cd13982014-01-17 15:12:51 -0800155 CHECK_EQ((status_t)OK, mCodec->getOutputBuffers(&mOutputBuffers));
156 ALOGV("[%s] got %zu input and %zu output buffers",
157 mComponentName.c_str(),
158 mInputBuffers.size(),
159 mOutputBuffers.size());
Andreas Huber078cfcf2011-09-15 12:25:04 -0700160
Lajos Molnar1cd13982014-01-17 15:12:51 -0800161 requestCodecNotification();
Wei Jia704e7262014-06-04 16:21:56 -0700162 mPaused = false;
Lajos Molnar1cd13982014-01-17 15:12:51 -0800163}
Andreas Huber078cfcf2011-09-15 12:25:04 -0700164
Lajos Molnar09524832014-07-17 14:29:51 -0700165void NuPlayer::Decoder::releaseAndResetMediaBuffers() {
166 for (size_t i = 0; i < mMediaBuffers.size(); i++) {
167 if (mMediaBuffers[i] != NULL) {
168 mMediaBuffers[i]->release();
169 mMediaBuffers.editItemAt(i) = NULL;
170 }
171 }
172 mMediaBuffers.resize(mInputBuffers.size());
Wei Jia81e50d02014-07-24 10:28:47 -0700173 for (size_t i = 0; i < mMediaBuffers.size(); i++) {
174 mMediaBuffers.editItemAt(i) = NULL;
175 }
Lajos Molnar09524832014-07-17 14:29:51 -0700176 mInputBufferIsDequeued.clear();
177 mInputBufferIsDequeued.resize(mInputBuffers.size());
Wei Jia81e50d02014-07-24 10:28:47 -0700178 for (size_t i = 0; i < mInputBufferIsDequeued.size(); i++) {
179 mInputBufferIsDequeued.editItemAt(i) = false;
180 }
Lajos Molnar09524832014-07-17 14:29:51 -0700181}
182
Lajos Molnar1cd13982014-01-17 15:12:51 -0800183void NuPlayer::Decoder::requestCodecNotification() {
184 if (mCodec != NULL) {
185 sp<AMessage> reply = new AMessage(kWhatCodecNotify, id());
186 reply->setInt32("generation", mBufferGeneration);
187 mCodec->requestActivityNotification(reply);
188 }
189}
190
191bool NuPlayer::Decoder::isStaleReply(const sp<AMessage> &msg) {
192 int32_t generation;
193 CHECK(msg->findInt32("generation", &generation));
194 return generation != mBufferGeneration;
195}
196
197void NuPlayer::Decoder::init() {
198 mDecoderLooper->registerHandler(this);
199}
200
201void NuPlayer::Decoder::configure(const sp<AMessage> &format) {
202 sp<AMessage> msg = new AMessage(kWhatConfigure, id());
203 msg->setMessage("format", format);
204 msg->post();
205}
206
Lajos Molnar87603c02014-08-20 19:25:30 -0700207void NuPlayer::Decoder::signalUpdateFormat(const sp<AMessage> &format) {
208 sp<AMessage> msg = new AMessage(kWhatUpdateFormat, id());
209 msg->setMessage("format", format);
210 msg->post();
211}
212
Lajos Molnar09524832014-07-17 14:29:51 -0700213status_t NuPlayer::Decoder::getInputBuffers(Vector<sp<ABuffer> > *buffers) const {
214 sp<AMessage> msg = new AMessage(kWhatGetInputBuffers, id());
215 msg->setPointer("buffers", buffers);
216
217 sp<AMessage> response;
218 return PostAndAwaitResponse(msg, &response);
219}
220
Lajos Molnar1cd13982014-01-17 15:12:51 -0800221void NuPlayer::Decoder::handleError(int32_t err)
222{
Wei Jiac22c6952014-08-29 14:47:50 -0700223 mCodec->release();
224
Lajos Molnar1cd13982014-01-17 15:12:51 -0800225 sp<AMessage> notify = mNotify->dup();
226 notify->setInt32("what", kWhatError);
227 notify->setInt32("err", err);
228 notify->post();
229}
230
231bool NuPlayer::Decoder::handleAnInputBuffer() {
232 size_t bufferIx = -1;
233 status_t res = mCodec->dequeueInputBuffer(&bufferIx);
234 ALOGV("[%s] dequeued input: %d",
235 mComponentName.c_str(), res == OK ? (int)bufferIx : res);
236 if (res != OK) {
237 if (res != -EAGAIN) {
238 handleError(res);
239 }
240 return false;
Andreas Huber078cfcf2011-09-15 12:25:04 -0700241 }
242
Lajos Molnar1cd13982014-01-17 15:12:51 -0800243 CHECK_LT(bufferIx, mInputBuffers.size());
Andreas Huberf9334412010-12-15 15:17:42 -0800244
Lajos Molnar09524832014-07-17 14:29:51 -0700245 if (mMediaBuffers[bufferIx] != NULL) {
246 mMediaBuffers[bufferIx]->release();
247 mMediaBuffers.editItemAt(bufferIx) = NULL;
248 }
249 mInputBufferIsDequeued.editItemAt(bufferIx) = true;
250
Lajos Molnar1cd13982014-01-17 15:12:51 -0800251 sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, id());
252 reply->setSize("buffer-ix", bufferIx);
253 reply->setInt32("generation", mBufferGeneration);
254
Lajos Molnar87603c02014-08-20 19:25:30 -0700255 if (!mCSDsToSubmit.isEmpty()) {
256 sp<ABuffer> buffer = mCSDsToSubmit.itemAt(0);
257 ALOGI("[%s] resubmitting CSD", mComponentName.c_str());
258 reply->setBuffer("buffer", buffer);
259 mCSDsToSubmit.removeAt(0);
260 reply->post();
261 return true;
262 }
263
Lajos Molnar1cd13982014-01-17 15:12:51 -0800264 sp<AMessage> notify = mNotify->dup();
265 notify->setInt32("what", kWhatFillThisBuffer);
266 notify->setBuffer("buffer", mInputBuffers[bufferIx]);
267 notify->setMessage("reply", reply);
268 notify->post();
269 return true;
270}
271
272void android::NuPlayer::Decoder::onInputBufferFilled(const sp<AMessage> &msg) {
273 size_t bufferIx;
274 CHECK(msg->findSize("buffer-ix", &bufferIx));
275 CHECK_LT(bufferIx, mInputBuffers.size());
276 sp<ABuffer> codecBuffer = mInputBuffers[bufferIx];
277
278 sp<ABuffer> buffer;
279 bool hasBuffer = msg->findBuffer("buffer", &buffer);
Lajos Molnar09524832014-07-17 14:29:51 -0700280
281 // handle widevine classic source - that fills an arbitrary input buffer
282 MediaBuffer *mediaBuffer = NULL;
283 if (hasBuffer && buffer->meta()->findPointer(
284 "mediaBuffer", (void **)&mediaBuffer)) {
285 if (mediaBuffer == NULL) {
286 // received no actual buffer
287 ALOGW("[%s] received null MediaBuffer %s",
288 mComponentName.c_str(), msg->debugString().c_str());
289 buffer = NULL;
290 } else {
291 // likely filled another buffer than we requested: adjust buffer index
292 size_t ix;
293 for (ix = 0; ix < mInputBuffers.size(); ix++) {
294 const sp<ABuffer> &buf = mInputBuffers[ix];
295 if (buf->data() == mediaBuffer->data()) {
296 // all input buffers are dequeued on start, hence the check
297 CHECK(mInputBufferIsDequeued[ix]);
298 ALOGV("[%s] received MediaBuffer for #%zu instead of #%zu",
299 mComponentName.c_str(), ix, bufferIx);
300
301 // TRICKY: need buffer for the metadata, so instead, set
302 // codecBuffer to the same (though incorrect) buffer to
303 // avoid a memcpy into the codecBuffer
304 codecBuffer = buffer;
305 codecBuffer->setRange(
306 mediaBuffer->range_offset(),
307 mediaBuffer->range_length());
308 bufferIx = ix;
309 break;
310 }
311 }
312 CHECK(ix < mInputBuffers.size());
313 }
314 }
315
316 mInputBufferIsDequeued.editItemAt(bufferIx) = false;
317
Lajos Molnar1cd13982014-01-17 15:12:51 -0800318 if (buffer == NULL /* includes !hasBuffer */) {
319 int32_t streamErr = ERROR_END_OF_STREAM;
320 CHECK(msg->findInt32("err", &streamErr) || !hasBuffer);
321
322 if (streamErr == OK) {
323 /* buffers are returned to hold on to */
324 return;
325 }
326
327 // attempt to queue EOS
328 status_t err = mCodec->queueInputBuffer(
329 bufferIx,
330 0,
331 0,
332 0,
333 MediaCodec::BUFFER_FLAG_EOS);
334 if (streamErr == ERROR_END_OF_STREAM && err != OK) {
335 streamErr = err;
336 // err will not be ERROR_END_OF_STREAM
337 }
338
339 if (streamErr != ERROR_END_OF_STREAM) {
340 handleError(streamErr);
341 }
342 } else {
343 int64_t timeUs = 0;
344 uint32_t flags = 0;
345 CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
346
Lajos Molnar87603c02014-08-20 19:25:30 -0700347 int32_t eos, csd;
348 // we do not expect SYNCFRAME for decoder
Lajos Molnar1cd13982014-01-17 15:12:51 -0800349 if (buffer->meta()->findInt32("eos", &eos) && eos) {
350 flags |= MediaCodec::BUFFER_FLAG_EOS;
Lajos Molnar87603c02014-08-20 19:25:30 -0700351 } else if (buffer->meta()->findInt32("csd", &csd) && csd) {
352 flags |= MediaCodec::BUFFER_FLAG_CODECCONFIG;
Lajos Molnar1cd13982014-01-17 15:12:51 -0800353 }
354
355 // copy into codec buffer
356 if (buffer != codecBuffer) {
357 CHECK_LE(buffer->size(), codecBuffer->capacity());
358 codecBuffer->setRange(0, buffer->size());
359 memcpy(codecBuffer->data(), buffer->data(), buffer->size());
360 }
361
362 status_t err = mCodec->queueInputBuffer(
363 bufferIx,
364 codecBuffer->offset(),
365 codecBuffer->size(),
366 timeUs,
367 flags);
368 if (err != OK) {
369 ALOGE("Failed to queue input buffer for %s (err=%d)",
370 mComponentName.c_str(), err);
371 handleError(err);
372 }
Lajos Molnar09524832014-07-17 14:29:51 -0700373
374 if (mediaBuffer != NULL) {
375 CHECK(mMediaBuffers[bufferIx] == NULL);
376 mMediaBuffers.editItemAt(bufferIx) = mediaBuffer;
377 }
Lajos Molnar1cd13982014-01-17 15:12:51 -0800378 }
379}
380
381bool NuPlayer::Decoder::handleAnOutputBuffer() {
382 size_t bufferIx = -1;
383 size_t offset;
384 size_t size;
385 int64_t timeUs;
386 uint32_t flags;
387 status_t res = mCodec->dequeueOutputBuffer(
388 &bufferIx, &offset, &size, &timeUs, &flags);
389
390 if (res != OK) {
391 ALOGV("[%s] dequeued output: %d", mComponentName.c_str(), res);
392 } else {
393 ALOGV("[%s] dequeued output: %d (time=%lld flags=%" PRIu32 ")",
394 mComponentName.c_str(), (int)bufferIx, timeUs, flags);
395 }
396
397 if (res == INFO_OUTPUT_BUFFERS_CHANGED) {
398 res = mCodec->getOutputBuffers(&mOutputBuffers);
399 if (res != OK) {
400 ALOGE("Failed to get output buffers for %s after INFO event (err=%d)",
401 mComponentName.c_str(), res);
402 handleError(res);
403 return false;
404 }
405 // NuPlayer ignores this
406 return true;
407 } else if (res == INFO_FORMAT_CHANGED) {
408 sp<AMessage> format = new AMessage();
409 res = mCodec->getOutputFormat(&format);
410 if (res != OK) {
411 ALOGE("Failed to get output format for %s after INFO event (err=%d)",
412 mComponentName.c_str(), res);
413 handleError(res);
414 return false;
415 }
416
417 sp<AMessage> notify = mNotify->dup();
418 notify->setInt32("what", kWhatOutputFormatChanged);
419 notify->setMessage("format", format);
420 notify->post();
421 return true;
422 } else if (res == INFO_DISCONTINUITY) {
423 // nothing to do
424 return true;
425 } else if (res != OK) {
426 if (res != -EAGAIN) {
427 handleError(res);
428 }
429 return false;
430 }
431
432 CHECK_LT(bufferIx, mOutputBuffers.size());
433 sp<ABuffer> buffer = mOutputBuffers[bufferIx];
434 buffer->setRange(offset, size);
435 buffer->meta()->clear();
436 buffer->meta()->setInt64("timeUs", timeUs);
437 if (flags & MediaCodec::BUFFER_FLAG_EOS) {
438 buffer->meta()->setInt32("eos", true);
439 }
440 // we do not expect CODECCONFIG or SYNCFRAME for decoder
441
442 sp<AMessage> reply = new AMessage(kWhatRenderBuffer, id());
443 reply->setSize("buffer-ix", bufferIx);
444 reply->setInt32("generation", mBufferGeneration);
445
446 sp<AMessage> notify = mNotify->dup();
447 notify->setInt32("what", kWhatDrainThisBuffer);
448 notify->setBuffer("buffer", buffer);
449 notify->setMessage("reply", reply);
450 notify->post();
451
452 // FIXME: This should be handled after rendering is complete,
453 // but Renderer needs it now
454 if (flags & MediaCodec::BUFFER_FLAG_EOS) {
455 ALOGV("queueing eos [%s]", mComponentName.c_str());
456 sp<AMessage> notify = mNotify->dup();
457 notify->setInt32("what", kWhatEOS);
458 notify->setInt32("err", ERROR_END_OF_STREAM);
459 notify->post();
460 }
461 return true;
462}
463
464void NuPlayer::Decoder::onRenderBuffer(const sp<AMessage> &msg) {
465 status_t err;
466 int32_t render;
467 size_t bufferIx;
468 CHECK(msg->findSize("buffer-ix", &bufferIx));
469 if (msg->findInt32("render", &render) && render) {
470 err = mCodec->renderOutputBufferAndRelease(bufferIx);
471 } else {
472 err = mCodec->releaseOutputBuffer(bufferIx);
473 }
474 if (err != OK) {
475 ALOGE("failed to release output buffer for %s (err=%d)",
476 mComponentName.c_str(), err);
477 handleError(err);
478 }
479}
480
481void NuPlayer::Decoder::onFlush() {
482 status_t err = OK;
483 if (mCodec != NULL) {
484 err = mCodec->flush();
Lajos Molnar87603c02014-08-20 19:25:30 -0700485 mCSDsToSubmit = mCSDsForCurrentFormat; // copy operator
Lajos Molnar1cd13982014-01-17 15:12:51 -0800486 ++mBufferGeneration;
487 }
488
489 if (err != OK) {
490 ALOGE("failed to flush %s (err=%d)", mComponentName.c_str(), err);
491 handleError(err);
492 return;
493 }
494
Lajos Molnar09524832014-07-17 14:29:51 -0700495 releaseAndResetMediaBuffers();
496
Lajos Molnar1cd13982014-01-17 15:12:51 -0800497 sp<AMessage> notify = mNotify->dup();
498 notify->setInt32("what", kWhatFlushCompleted);
499 notify->post();
Wei Jia704e7262014-06-04 16:21:56 -0700500 mPaused = true;
501}
502
503void NuPlayer::Decoder::onResume() {
504 mPaused = false;
Lajos Molnar1cd13982014-01-17 15:12:51 -0800505}
506
507void NuPlayer::Decoder::onShutdown() {
508 status_t err = OK;
509 if (mCodec != NULL) {
510 err = mCodec->release();
511 mCodec = NULL;
512 ++mBufferGeneration;
513
514 if (mNativeWindow != NULL) {
515 // reconnect to surface as MediaCodec disconnected from it
Wei Jia3fb9f682014-08-20 14:30:09 -0700516 status_t error =
Lajos Molnar1cd13982014-01-17 15:12:51 -0800517 native_window_api_connect(
518 mNativeWindow->getNativeWindow().get(),
Wei Jia3fb9f682014-08-20 14:30:09 -0700519 NATIVE_WINDOW_API_MEDIA);
520 ALOGW_IF(error != NO_ERROR,
521 "[%s] failed to connect to native window, error=%d",
522 mComponentName.c_str(), error);
Lajos Molnar1cd13982014-01-17 15:12:51 -0800523 }
524 mComponentName = "decoder";
525 }
526
Lajos Molnar09524832014-07-17 14:29:51 -0700527 releaseAndResetMediaBuffers();
528
Lajos Molnar1cd13982014-01-17 15:12:51 -0800529 if (err != OK) {
530 ALOGE("failed to release %s (err=%d)", mComponentName.c_str(), err);
531 handleError(err);
532 return;
533 }
534
535 sp<AMessage> notify = mNotify->dup();
536 notify->setInt32("what", kWhatShutdownCompleted);
537 notify->post();
Wei Jia704e7262014-06-04 16:21:56 -0700538 mPaused = true;
Andreas Huberf9334412010-12-15 15:17:42 -0800539}
540
541void NuPlayer::Decoder::onMessageReceived(const sp<AMessage> &msg) {
Lajos Molnar1cd13982014-01-17 15:12:51 -0800542 ALOGV("[%s] onMessage: %s", mComponentName.c_str(), msg->debugString().c_str());
543
Andreas Huberf9334412010-12-15 15:17:42 -0800544 switch (msg->what()) {
Lajos Molnar1cd13982014-01-17 15:12:51 -0800545 case kWhatConfigure:
546 {
547 sp<AMessage> format;
548 CHECK(msg->findMessage("format", &format));
549 onConfigure(format);
550 break;
551 }
552
Lajos Molnar87603c02014-08-20 19:25:30 -0700553 case kWhatUpdateFormat:
554 {
555 sp<AMessage> format;
556 CHECK(msg->findMessage("format", &format));
557 rememberCodecSpecificData(format);
558 break;
559 }
560
Lajos Molnar09524832014-07-17 14:29:51 -0700561 case kWhatGetInputBuffers:
562 {
563 uint32_t replyID;
564 CHECK(msg->senderAwaitsResponse(&replyID));
565
566 Vector<sp<ABuffer> > *dstBuffers;
567 CHECK(msg->findPointer("buffers", (void **)&dstBuffers));
568
569 dstBuffers->clear();
570 for (size_t i = 0; i < mInputBuffers.size(); i++) {
571 dstBuffers->push(mInputBuffers[i]);
572 }
573
574 (new AMessage)->postReply(replyID);
575 break;
576 }
577
Andreas Huberf9334412010-12-15 15:17:42 -0800578 case kWhatCodecNotify:
579 {
Lajos Molnar1cd13982014-01-17 15:12:51 -0800580 if (!isStaleReply(msg)) {
Wei Jia704e7262014-06-04 16:21:56 -0700581 if (!mPaused) {
582 while (handleAnInputBuffer()) {
583 }
Lajos Molnar1cd13982014-01-17 15:12:51 -0800584 }
Andreas Huberf9334412010-12-15 15:17:42 -0800585
Lajos Molnar1cd13982014-01-17 15:12:51 -0800586 while (handleAnOutputBuffer()) {
587 }
Andreas Huberf9334412010-12-15 15:17:42 -0800588 }
Lajos Molnar1cd13982014-01-17 15:12:51 -0800589
590 requestCodecNotification();
591 break;
592 }
593
594 case kWhatInputBufferFilled:
595 {
596 if (!isStaleReply(msg)) {
597 onInputBufferFilled(msg);
598 }
599 break;
600 }
601
602 case kWhatRenderBuffer:
603 {
604 if (!isStaleReply(msg)) {
605 onRenderBuffer(msg);
606 }
607 break;
608 }
609
610 case kWhatFlush:
611 {
Lajos Molnar87603c02014-08-20 19:25:30 -0700612 sp<AMessage> format;
613 if (msg->findMessage("new-format", &format)) {
614 rememberCodecSpecificData(format);
615 }
Lajos Molnar1cd13982014-01-17 15:12:51 -0800616 onFlush();
617 break;
618 }
619
Wei Jia704e7262014-06-04 16:21:56 -0700620 case kWhatResume:
621 {
622 onResume();
623 break;
624 }
625
Lajos Molnar1cd13982014-01-17 15:12:51 -0800626 case kWhatShutdown:
627 {
628 onShutdown();
Andreas Huberf9334412010-12-15 15:17:42 -0800629 break;
630 }
631
632 default:
633 TRESPASS();
634 break;
635 }
636}
637
Lajos Molnar87603c02014-08-20 19:25:30 -0700638void NuPlayer::Decoder::signalFlush(const sp<AMessage> &format) {
639 sp<AMessage> msg = new AMessage(kWhatFlush, id());
640 if (format != NULL) {
641 msg->setMessage("new-format", format);
642 }
643 msg->post();
Andreas Huberf9334412010-12-15 15:17:42 -0800644}
645
646void NuPlayer::Decoder::signalResume() {
Wei Jia704e7262014-06-04 16:21:56 -0700647 (new AMessage(kWhatResume, id()))->post();
Andreas Huberf9334412010-12-15 15:17:42 -0800648}
649
Andreas Huber3831a062010-12-21 10:22:33 -0800650void NuPlayer::Decoder::initiateShutdown() {
Lajos Molnar1cd13982014-01-17 15:12:51 -0800651 (new AMessage(kWhatShutdown, id()))->post();
Andreas Huber3831a062010-12-21 10:22:33 -0800652}
653
Robert Shih6d0a94e2014-01-23 16:18:22 -0800654bool NuPlayer::Decoder::supportsSeamlessAudioFormatChange(const sp<AMessage> &targetFormat) const {
655 if (targetFormat == NULL) {
656 return true;
657 }
658
659 AString mime;
660 if (!targetFormat->findString("mime", &mime)) {
661 return false;
662 }
663
664 if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_AUDIO_AAC)) {
665 // field-by-field comparison
666 const char * keys[] = { "channel-count", "sample-rate", "is-adts" };
667 for (unsigned int i = 0; i < sizeof(keys) / sizeof(keys[0]); i++) {
668 int32_t oldVal, newVal;
Lajos Molnar1cd13982014-01-17 15:12:51 -0800669 if (!mOutputFormat->findInt32(keys[i], &oldVal) ||
670 !targetFormat->findInt32(keys[i], &newVal) ||
671 oldVal != newVal) {
Robert Shih6d0a94e2014-01-23 16:18:22 -0800672 return false;
673 }
674 }
675
676 sp<ABuffer> oldBuf, newBuf;
Lajos Molnar1cd13982014-01-17 15:12:51 -0800677 if (mOutputFormat->findBuffer("csd-0", &oldBuf) &&
678 targetFormat->findBuffer("csd-0", &newBuf)) {
Robert Shih6d0a94e2014-01-23 16:18:22 -0800679 if (oldBuf->size() != newBuf->size()) {
680 return false;
681 }
682 return !memcmp(oldBuf->data(), newBuf->data(), oldBuf->size());
683 }
684 }
685 return false;
686}
687
688bool NuPlayer::Decoder::supportsSeamlessFormatChange(const sp<AMessage> &targetFormat) const {
Lajos Molnar1cd13982014-01-17 15:12:51 -0800689 if (mOutputFormat == NULL) {
Robert Shih6d0a94e2014-01-23 16:18:22 -0800690 return false;
691 }
692
693 if (targetFormat == NULL) {
694 return true;
695 }
696
697 AString oldMime, newMime;
Lajos Molnar1cd13982014-01-17 15:12:51 -0800698 if (!mOutputFormat->findString("mime", &oldMime)
Robert Shih6d0a94e2014-01-23 16:18:22 -0800699 || !targetFormat->findString("mime", &newMime)
700 || !(oldMime == newMime)) {
701 return false;
702 }
703
704 bool audio = !strncasecmp(oldMime.c_str(), "audio/", strlen("audio/"));
705 bool seamless;
706 if (audio) {
707 seamless = supportsSeamlessAudioFormatChange(targetFormat);
708 } else {
Lajos Molnar1cd13982014-01-17 15:12:51 -0800709 int32_t isAdaptive;
710 seamless = (mCodec != NULL &&
711 mInputFormat->findInt32("adaptive-playback", &isAdaptive) &&
712 isAdaptive);
Robert Shih6d0a94e2014-01-23 16:18:22 -0800713 }
714
715 ALOGV("%s seamless support for %s", seamless ? "yes" : "no", oldMime.c_str());
716 return seamless;
717}
718
Chong Zhanga7fa1d92014-06-11 14:49:23 -0700719struct NuPlayer::CCDecoder::CCData {
720 CCData(uint8_t type, uint8_t data1, uint8_t data2)
721 : mType(type), mData1(data1), mData2(data2) {
722 }
723
724 uint8_t mType;
725 uint8_t mData1;
726 uint8_t mData2;
727};
728
729NuPlayer::CCDecoder::CCDecoder(const sp<AMessage> &notify)
730 : mNotify(notify),
731 mTrackCount(0),
732 mSelectedTrack(-1) {
733}
734
735size_t NuPlayer::CCDecoder::getTrackCount() const {
736 return mTrackCount;
737}
738
739sp<AMessage> NuPlayer::CCDecoder::getTrackInfo(size_t index) const {
740 CHECK(index == 0);
741
742 sp<AMessage> format = new AMessage();
743
744 format->setInt32("type", MEDIA_TRACK_TYPE_SUBTITLE);
745 format->setString("language", "und");
746 format->setString("mime", MEDIA_MIMETYPE_TEXT_CEA_608);
747 format->setInt32("auto", 1);
748 format->setInt32("default", 1);
749 format->setInt32("forced", 0);
750
751 return format;
752}
753
754status_t NuPlayer::CCDecoder::selectTrack(size_t index, bool select) {
755 CHECK(index < mTrackCount);
756
757 if (select) {
758 if (mSelectedTrack == (ssize_t)index) {
759 ALOGE("track %zu already selected", index);
760 return BAD_VALUE;
761 }
762 ALOGV("selected track %zu", index);
763 mSelectedTrack = index;
764 } else {
765 if (mSelectedTrack != (ssize_t)index) {
766 ALOGE("track %zu is not selected", index);
767 return BAD_VALUE;
768 }
769 ALOGV("unselected track %zu", index);
770 mSelectedTrack = -1;
771 }
772
773 return OK;
774}
775
776bool NuPlayer::CCDecoder::isSelected() const {
777 return mSelectedTrack >= 0 && mSelectedTrack < (int32_t)mTrackCount;
778}
779
780bool NuPlayer::CCDecoder::isNullPad(CCData *cc) const {
781 return cc->mData1 < 0x10 && cc->mData2 < 0x10;
782}
783
784void NuPlayer::CCDecoder::dumpBytePair(const sp<ABuffer> &ccBuf) const {
785 size_t offset = 0;
786 AString out;
787
788 while (offset < ccBuf->size()) {
789 char tmp[128];
790
791 CCData *cc = (CCData *) (ccBuf->data() + offset);
792
793 if (isNullPad(cc)) {
794 // 1 null pad or XDS metadata, ignore
795 offset += sizeof(CCData);
796 continue;
797 }
798
799 if (cc->mData1 >= 0x20 && cc->mData1 <= 0x7f) {
800 // 2 basic chars
801 sprintf(tmp, "[%d]Basic: %c %c", cc->mType, cc->mData1, cc->mData2);
802 } else if ((cc->mData1 == 0x11 || cc->mData1 == 0x19)
803 && cc->mData2 >= 0x30 && cc->mData2 <= 0x3f) {
804 // 1 special char
805 sprintf(tmp, "[%d]Special: %02x %02x", cc->mType, cc->mData1, cc->mData2);
806 } else if ((cc->mData1 == 0x12 || cc->mData1 == 0x1A)
807 && cc->mData2 >= 0x20 && cc->mData2 <= 0x3f){
808 // 1 Spanish/French char
809 sprintf(tmp, "[%d]Spanish: %02x %02x", cc->mType, cc->mData1, cc->mData2);
810 } else if ((cc->mData1 == 0x13 || cc->mData1 == 0x1B)
811 && cc->mData2 >= 0x20 && cc->mData2 <= 0x3f){
812 // 1 Portuguese/German/Danish char
813 sprintf(tmp, "[%d]German: %02x %02x", cc->mType, cc->mData1, cc->mData2);
814 } else if ((cc->mData1 == 0x11 || cc->mData1 == 0x19)
815 && cc->mData2 >= 0x20 && cc->mData2 <= 0x2f){
816 // Mid-Row Codes (Table 69)
817 sprintf(tmp, "[%d]Mid-row: %02x %02x", cc->mType, cc->mData1, cc->mData2);
818 } else if (((cc->mData1 == 0x14 || cc->mData1 == 0x1c)
819 && cc->mData2 >= 0x20 && cc->mData2 <= 0x2f)
820 ||
821 ((cc->mData1 == 0x17 || cc->mData1 == 0x1f)
822 && cc->mData2 >= 0x21 && cc->mData2 <= 0x23)){
823 // Misc Control Codes (Table 70)
824 sprintf(tmp, "[%d]Ctrl: %02x %02x", cc->mType, cc->mData1, cc->mData2);
825 } else if ((cc->mData1 & 0x70) == 0x10
826 && (cc->mData2 & 0x40) == 0x40
827 && ((cc->mData1 & 0x07) || !(cc->mData2 & 0x20)) ) {
828 // Preamble Address Codes (Table 71)
829 sprintf(tmp, "[%d]PAC: %02x %02x", cc->mType, cc->mData1, cc->mData2);
830 } else {
831 sprintf(tmp, "[%d]Invalid: %02x %02x", cc->mType, cc->mData1, cc->mData2);
832 }
833
834 if (out.size() > 0) {
835 out.append(", ");
836 }
837
838 out.append(tmp);
839
840 offset += sizeof(CCData);
841 }
842
843 ALOGI("%s", out.c_str());
844}
845
846bool NuPlayer::CCDecoder::extractFromSEI(const sp<ABuffer> &accessUnit) {
847 int64_t timeUs;
848 CHECK(accessUnit->meta()->findInt64("timeUs", &timeUs));
849
850 sp<ABuffer> sei;
851 if (!accessUnit->meta()->findBuffer("sei", &sei) || sei == NULL) {
852 return false;
853 }
854
855 bool hasCC = false;
856
Chong Zhang862f8452014-06-26 19:55:23 -0700857 NALBitReader br(sei->data() + 1, sei->size() - 1);
Chong Zhanga7fa1d92014-06-11 14:49:23 -0700858 // sei_message()
Chong Zhang862f8452014-06-26 19:55:23 -0700859 while (br.atLeastNumBitsLeft(16)) { // at least 16-bit for sei_message()
Chong Zhanga7fa1d92014-06-11 14:49:23 -0700860 uint32_t payload_type = 0;
861 size_t payload_size = 0;
862 uint8_t last_byte;
863
864 do {
865 last_byte = br.getBits(8);
866 payload_type += last_byte;
867 } while (last_byte == 0xFF);
868
869 do {
870 last_byte = br.getBits(8);
871 payload_size += last_byte;
872 } while (last_byte == 0xFF);
873
874 // sei_payload()
875 if (payload_type == 4) {
876 // user_data_registered_itu_t_t35()
877
878 // ATSC A/72: 6.4.2
879 uint8_t itu_t_t35_country_code = br.getBits(8);
880 uint16_t itu_t_t35_provider_code = br.getBits(16);
881 uint32_t user_identifier = br.getBits(32);
882 uint8_t user_data_type_code = br.getBits(8);
883
884 payload_size -= 1 + 2 + 4 + 1;
885
886 if (itu_t_t35_country_code == 0xB5
887 && itu_t_t35_provider_code == 0x0031
888 && user_identifier == 'GA94'
889 && user_data_type_code == 0x3) {
890 hasCC = true;
891
892 // MPEG_cc_data()
893 // ATSC A/53 Part 4: 6.2.3.1
894 br.skipBits(1); //process_em_data_flag
895 bool process_cc_data_flag = br.getBits(1);
896 br.skipBits(1); //additional_data_flag
897 size_t cc_count = br.getBits(5);
898 br.skipBits(8); // em_data;
899 payload_size -= 2;
900
901 if (process_cc_data_flag) {
902 AString out;
903
904 sp<ABuffer> ccBuf = new ABuffer(cc_count * sizeof(CCData));
905 ccBuf->setRange(0, 0);
906
907 for (size_t i = 0; i < cc_count; i++) {
908 uint8_t marker = br.getBits(5);
909 CHECK_EQ(marker, 0x1f);
910
911 bool cc_valid = br.getBits(1);
912 uint8_t cc_type = br.getBits(2);
913 // remove odd parity bit
914 uint8_t cc_data_1 = br.getBits(8) & 0x7f;
915 uint8_t cc_data_2 = br.getBits(8) & 0x7f;
916
917 if (cc_valid
918 && (cc_type == 0 || cc_type == 1)) {
919 CCData cc(cc_type, cc_data_1, cc_data_2);
920 if (!isNullPad(&cc)) {
921 memcpy(ccBuf->data() + ccBuf->size(),
922 (void *)&cc, sizeof(cc));
923 ccBuf->setRange(0, ccBuf->size() + sizeof(CCData));
924 }
925 }
926 }
927 payload_size -= cc_count * 3;
928
929 mCCMap.add(timeUs, ccBuf);
930 break;
931 }
932 } else {
933 ALOGV("Malformed SEI payload type 4");
934 }
935 } else {
936 ALOGV("Unsupported SEI payload type %d", payload_type);
937 }
938
939 // skipping remaining bits of this payload
940 br.skipBits(payload_size * 8);
941 }
942
943 return hasCC;
944}
945
946void NuPlayer::CCDecoder::decode(const sp<ABuffer> &accessUnit) {
947 if (extractFromSEI(accessUnit) && mTrackCount == 0) {
948 mTrackCount++;
949
950 ALOGI("Found CEA-608 track");
951 sp<AMessage> msg = mNotify->dup();
952 msg->setInt32("what", kWhatTrackAdded);
953 msg->post();
954 }
955 // TODO: extract CC from other sources
956}
957
958void NuPlayer::CCDecoder::display(int64_t timeUs) {
959 ssize_t index = mCCMap.indexOfKey(timeUs);
960 if (index < 0) {
961 ALOGV("cc for timestamp %" PRId64 " not found", timeUs);
962 return;
963 }
964
965 sp<ABuffer> &ccBuf = mCCMap.editValueAt(index);
966
967 if (ccBuf->size() > 0) {
968#if 0
969 dumpBytePair(ccBuf);
970#endif
971
972 ccBuf->meta()->setInt32("trackIndex", mSelectedTrack);
973 ccBuf->meta()->setInt64("timeUs", timeUs);
974 ccBuf->meta()->setInt64("durationUs", 0ll);
975
976 sp<AMessage> msg = mNotify->dup();
977 msg->setInt32("what", kWhatClosedCaptionData);
978 msg->setBuffer("buffer", ccBuf);
979 msg->post();
980 }
981
982 // remove all entries before timeUs
983 mCCMap.removeItemsAt(0, index + 1);
984}
985
Andreas Huberf9334412010-12-15 15:17:42 -0800986} // namespace android
987