MediaCodec.cpp revision fc70a810d18f13bdb04be3307aa2b282b0cdc5b0
15460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/* 25460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao * Copyright 2012, The Android Open Source Project 35460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao * 45460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao * Licensed under the Apache License, Version 2.0 (the "License"); 55460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao * you may not use this file except in compliance with the License. 65460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao * You may obtain a copy of the License at 75460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao * 85460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao * http://www.apache.org/licenses/LICENSE-2.0 937b74a387bb3993387029859c2d9d051c41c724eStephen Hines * 1037b74a387bb3993387029859c2d9d051c41c724eStephen Hines * Unless required by applicable law or agreed to in writing, software 1137b74a387bb3993387029859c2d9d051c41c724eStephen Hines * distributed under the License is distributed on an "AS IS" BASIS, 1237b74a387bb3993387029859c2d9d051c41c724eStephen Hines * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao * See the License for the specific language governing permissions and 1437b74a387bb3993387029859c2d9d051c41c724eStephen Hines * limitations under the License. 155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao */ 1622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//#define LOG_NDEBUG 0 185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#define LOG_TAG "MediaCodec" 1937b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include <inttypes.h> 205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include "include/avc_utils.h" 225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include "include/SoftwareRenderer.h" 235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <binder/IBatteryStats.h> 2537b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include <binder/IServiceManager.h> 2637b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include <gui/Surface.h> 2737b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include <media/ICrypto.h> 2837b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include <media/stagefright/foundation/ABuffer.h> 295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <media/stagefright/foundation/ADebug.h> 3037b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include <media/stagefright/foundation/AMessage.h> 3137b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include <media/stagefright/foundation/AString.h> 325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <media/stagefright/foundation/hexdump.h> 3337b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include <media/stagefright/ACodec.h> 3422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <media/stagefright/BufferProducerWrapper.h> 355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <media/stagefright/MediaCodec.h> 3622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <media/stagefright/MediaCodecList.h> 375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <media/stagefright/MediaDefs.h> 385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <media/stagefright/MediaErrors.h> 395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <media/stagefright/MediaFilter.h> 405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <media/stagefright/MetaData.h> 415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <media/stagefright/NativeWindowWrapper.h> 425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <private/android_filesystem_config.h> 435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <utils/Log.h> 445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <utils/Singleton.h> 455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaonamespace android { 4737b74a387bb3993387029859c2d9d051c41c724eStephen Hines 485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostruct MediaCodec::BatteryNotifier : public Singleton<BatteryNotifier> { 4937b74a387bb3993387029859c2d9d051c41c724eStephen Hines BatteryNotifier(); 505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 5137b74a387bb3993387029859c2d9d051c41c724eStephen Hines void noteStartVideo(); 525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao void noteStopVideo(); 535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao void noteStartAudio(); 545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao void noteStopAudio(); 5537b74a387bb3993387029859c2d9d051c41c724eStephen Hines 56affc150dc44fab1911775a49636d0ce85333b634Zonr Changprivate: 5737b74a387bb3993387029859c2d9d051c41c724eStephen Hines int32_t mVideoRefCount; 58 int32_t mAudioRefCount; 59 sp<IBatteryStats> mBatteryStatService; 60}; 61 62ANDROID_SINGLETON_STATIC_INSTANCE(MediaCodec::BatteryNotifier) 63 64MediaCodec::BatteryNotifier::BatteryNotifier() : 65 mVideoRefCount(0), 66 mAudioRefCount(0) { 67 // get battery service 68 const sp<IServiceManager> sm(defaultServiceManager()); 69 if (sm != NULL) { 70 const String16 name("batterystats"); 71 mBatteryStatService = interface_cast<IBatteryStats>(sm->getService(name)); 72 if (mBatteryStatService == NULL) { 73 ALOGE("batterystats service unavailable!"); 74 } 75 } 76} 77 78void MediaCodec::BatteryNotifier::noteStartVideo() { 79 if (mVideoRefCount == 0 && mBatteryStatService != NULL) { 80 mBatteryStatService->noteStartVideo(AID_MEDIA); 81 } 82 mVideoRefCount++; 83} 84 85void MediaCodec::BatteryNotifier::noteStopVideo() { 86 if (mVideoRefCount == 0) { 87 ALOGW("BatteryNotifier::noteStop(): video refcount is broken!"); 88 return; 89 } 90 91 mVideoRefCount--; 92 if (mVideoRefCount == 0 && mBatteryStatService != NULL) { 93 mBatteryStatService->noteStopVideo(AID_MEDIA); 94 } 95} 96 97void MediaCodec::BatteryNotifier::noteStartAudio() { 98 if (mAudioRefCount == 0 && mBatteryStatService != NULL) { 99 mBatteryStatService->noteStartAudio(AID_MEDIA); 100 } 101 mAudioRefCount++; 102} 103 104void MediaCodec::BatteryNotifier::noteStopAudio() { 105 if (mAudioRefCount == 0) { 106 ALOGW("BatteryNotifier::noteStop(): audio refcount is broken!"); 107 return; 108 } 109 110 mAudioRefCount--; 111 if (mAudioRefCount == 0 && mBatteryStatService != NULL) { 112 mBatteryStatService->noteStopAudio(AID_MEDIA); 113 } 114} 115// static 116sp<MediaCodec> MediaCodec::CreateByType( 117 const sp<ALooper> &looper, const char *mime, bool encoder, status_t *err) { 118 sp<MediaCodec> codec = new MediaCodec(looper); 119 120 const status_t ret = codec->init(mime, true /* nameIsType */, encoder); 121 if (err != NULL) { 122 *err = ret; 123 } 124 return ret == OK ? codec : NULL; // NULL deallocates codec. 125} 126 127// static 128sp<MediaCodec> MediaCodec::CreateByComponentName( 129 const sp<ALooper> &looper, const char *name, status_t *err) { 130 sp<MediaCodec> codec = new MediaCodec(looper); 131 132 const status_t ret = codec->init(name, false /* nameIsType */, false /* encoder */); 133 if (err != NULL) { 134 *err = ret; 135 } 136 return ret == OK ? codec : NULL; // NULL deallocates codec. 137} 138 139MediaCodec::MediaCodec(const sp<ALooper> &looper) 140 : mState(UNINITIALIZED), 141 mLooper(looper), 142 mCodec(NULL), 143 mReplyID(0), 144 mFlags(0), 145 mStickyError(OK), 146 mSoftRenderer(NULL), 147 mBatteryStatNotified(false), 148 mIsVideo(false), 149 mDequeueInputTimeoutGeneration(0), 150 mDequeueInputReplyID(0), 151 mDequeueOutputTimeoutGeneration(0), 152 mDequeueOutputReplyID(0), 153 mHaveInputSurface(false) { 154} 155 156MediaCodec::~MediaCodec() { 157 CHECK_EQ(mState, UNINITIALIZED); 158} 159 160// static 161status_t MediaCodec::PostAndAwaitResponse( 162 const sp<AMessage> &msg, sp<AMessage> *response) { 163 status_t err = msg->postAndAwaitResponse(response); 164 165 if (err != OK) { 166 return err; 167 } 168 169 if (!(*response)->findInt32("err", &err)) { 170 err = OK; 171 } 172 173 return err; 174} 175 176// static 177void MediaCodec::PostReplyWithError(int32_t replyID, int32_t err) { 178 sp<AMessage> response = new AMessage; 179 response->setInt32("err", err); 180 response->postReply(replyID); 181} 182 183status_t MediaCodec::init(const AString &name, bool nameIsType, bool encoder) { 184 // save init parameters for reset 185 mInitName = name; 186 mInitNameIsType = nameIsType; 187 mInitIsEncoder = encoder; 188 189 // Current video decoders do not return from OMX_FillThisBuffer 190 // quickly, violating the OpenMAX specs, until that is remedied 191 // we need to invest in an extra looper to free the main event 192 // queue. 193 194 if (nameIsType || !strncasecmp(name.c_str(), "omx.", 4)) { 195 mCodec = new ACodec; 196 } else if (!nameIsType 197 && !strncasecmp(name.c_str(), "android.filter.", 15)) { 198 mCodec = new MediaFilter; 199 } else { 200 return NAME_NOT_FOUND; 201 } 202 203 bool needDedicatedLooper = false; 204 if (nameIsType && !strncasecmp(name.c_str(), "video/", 6)) { 205 needDedicatedLooper = true; 206 } else { 207 AString tmp = name; 208 if (tmp.endsWith(".secure")) { 209 tmp.erase(tmp.size() - 7, 7); 210 } 211 const sp<IMediaCodecList> mcl = MediaCodecList::getInstance(); 212 ssize_t codecIdx = mcl->findCodecByName(tmp.c_str()); 213 if (codecIdx >= 0) { 214 const sp<MediaCodecInfo> info = mcl->getCodecInfo(codecIdx); 215 Vector<AString> mimes; 216 info->getSupportedMimes(&mimes); 217 for (size_t i = 0; i < mimes.size(); i++) { 218 if (mimes[i].startsWith("video/")) { 219 needDedicatedLooper = true; 220 break; 221 } 222 } 223 } 224 } 225 226 if (needDedicatedLooper) { 227 if (mCodecLooper == NULL) { 228 mCodecLooper = new ALooper; 229 mCodecLooper->setName("CodecLooper"); 230 mCodecLooper->start(false, false, ANDROID_PRIORITY_AUDIO); 231 } 232 233 mCodecLooper->registerHandler(mCodec); 234 } else { 235 mLooper->registerHandler(mCodec); 236 } 237 238 mLooper->registerHandler(this); 239 240 mCodec->setNotificationMessage(new AMessage(kWhatCodecNotify, id())); 241 242 sp<AMessage> msg = new AMessage(kWhatInit, id()); 243 msg->setString("name", name); 244 msg->setInt32("nameIsType", nameIsType); 245 246 if (nameIsType) { 247 msg->setInt32("encoder", encoder); 248 } 249 250 sp<AMessage> response; 251 return PostAndAwaitResponse(msg, &response); 252} 253 254status_t MediaCodec::setCallback(const sp<AMessage> &callback) { 255 sp<AMessage> msg = new AMessage(kWhatSetCallback, id()); 256 msg->setMessage("callback", callback); 257 258 sp<AMessage> response; 259 return PostAndAwaitResponse(msg, &response); 260} 261 262status_t MediaCodec::configure( 263 const sp<AMessage> &format, 264 const sp<Surface> &nativeWindow, 265 const sp<ICrypto> &crypto, 266 uint32_t flags) { 267 sp<AMessage> msg = new AMessage(kWhatConfigure, id()); 268 269 msg->setMessage("format", format); 270 msg->setInt32("flags", flags); 271 272 if (nativeWindow != NULL) { 273 msg->setObject( 274 "native-window", 275 new NativeWindowWrapper(nativeWindow)); 276 } 277 278 if (crypto != NULL) { 279 msg->setPointer("crypto", crypto.get()); 280 } 281 282 sp<AMessage> response; 283 status_t err = PostAndAwaitResponse(msg, &response); 284 285 if (err != OK && err != INVALID_OPERATION) { 286 // MediaCodec now set state to UNINITIALIZED upon any fatal error. 287 // To maintain backward-compatibility, do a reset() to put codec 288 // back into INITIALIZED state. 289 // But don't reset if the err is INVALID_OPERATION, which means 290 // the configure failure is due to wrong state. 291 292 ALOGE("configure failed with err 0x%08x, resetting...", err); 293 reset(); 294 } 295 296 return err; 297} 298 299status_t MediaCodec::createInputSurface( 300 sp<IGraphicBufferProducer>* bufferProducer) { 301 sp<AMessage> msg = new AMessage(kWhatCreateInputSurface, id()); 302 303 sp<AMessage> response; 304 status_t err = PostAndAwaitResponse(msg, &response); 305 if (err == NO_ERROR) { 306 // unwrap the sp<IGraphicBufferProducer> 307 sp<RefBase> obj; 308 bool found = response->findObject("input-surface", &obj); 309 CHECK(found); 310 sp<BufferProducerWrapper> wrapper( 311 static_cast<BufferProducerWrapper*>(obj.get())); 312 *bufferProducer = wrapper->getBufferProducer(); 313 } else { 314 ALOGW("createInputSurface failed, err=%d", err); 315 } 316 return err; 317} 318 319status_t MediaCodec::start() { 320 sp<AMessage> msg = new AMessage(kWhatStart, id()); 321 322 sp<AMessage> response; 323 return PostAndAwaitResponse(msg, &response); 324} 325 326status_t MediaCodec::stop() { 327 sp<AMessage> msg = new AMessage(kWhatStop, id()); 328 329 sp<AMessage> response; 330 return PostAndAwaitResponse(msg, &response); 331} 332 333status_t MediaCodec::release() { 334 sp<AMessage> msg = new AMessage(kWhatRelease, id()); 335 336 sp<AMessage> response; 337 return PostAndAwaitResponse(msg, &response); 338} 339 340status_t MediaCodec::reset() { 341 /* When external-facing MediaCodec object is created, 342 it is already initialized. Thus, reset is essentially 343 release() followed by init(), plus clearing the state */ 344 345 status_t err = release(); 346 347 // unregister handlers 348 if (mCodec != NULL) { 349 if (mCodecLooper != NULL) { 350 mCodecLooper->unregisterHandler(mCodec->id()); 351 } else { 352 mLooper->unregisterHandler(mCodec->id()); 353 } 354 mCodec = NULL; 355 } 356 mLooper->unregisterHandler(id()); 357 358 mFlags = 0; // clear all flags 359 mStickyError = OK; 360 361 // reset state not reset by setState(UNINITIALIZED) 362 mReplyID = 0; 363 mDequeueInputReplyID = 0; 364 mDequeueOutputReplyID = 0; 365 mDequeueInputTimeoutGeneration = 0; 366 mDequeueOutputTimeoutGeneration = 0; 367 mHaveInputSurface = false; 368 369 if (err == OK) { 370 err = init(mInitName, mInitNameIsType, mInitIsEncoder); 371 } 372 return err; 373} 374 375status_t MediaCodec::queueInputBuffer( 376 size_t index, 377 size_t offset, 378 size_t size, 379 int64_t presentationTimeUs, 380 uint32_t flags, 381 AString *errorDetailMsg) { 382 if (errorDetailMsg != NULL) { 383 errorDetailMsg->clear(); 384 } 385 386 sp<AMessage> msg = new AMessage(kWhatQueueInputBuffer, id()); 387 msg->setSize("index", index); 388 msg->setSize("offset", offset); 389 msg->setSize("size", size); 390 msg->setInt64("timeUs", presentationTimeUs); 391 msg->setInt32("flags", flags); 392 msg->setPointer("errorDetailMsg", errorDetailMsg); 393 394 sp<AMessage> response; 395 return PostAndAwaitResponse(msg, &response); 396} 397 398status_t MediaCodec::queueSecureInputBuffer( 399 size_t index, 400 size_t offset, 401 const CryptoPlugin::SubSample *subSamples, 402 size_t numSubSamples, 403 const uint8_t key[16], 404 const uint8_t iv[16], 405 CryptoPlugin::Mode mode, 406 int64_t presentationTimeUs, 407 uint32_t flags, 408 AString *errorDetailMsg) { 409 if (errorDetailMsg != NULL) { 410 errorDetailMsg->clear(); 411 } 412 413 sp<AMessage> msg = new AMessage(kWhatQueueInputBuffer, id()); 414 msg->setSize("index", index); 415 msg->setSize("offset", offset); 416 msg->setPointer("subSamples", (void *)subSamples); 417 msg->setSize("numSubSamples", numSubSamples); 418 msg->setPointer("key", (void *)key); 419 msg->setPointer("iv", (void *)iv); 420 msg->setInt32("mode", mode); 421 msg->setInt64("timeUs", presentationTimeUs); 422 msg->setInt32("flags", flags); 423 msg->setPointer("errorDetailMsg", errorDetailMsg); 424 425 sp<AMessage> response; 426 status_t err = PostAndAwaitResponse(msg, &response); 427 428 return err; 429} 430 431status_t MediaCodec::dequeueInputBuffer(size_t *index, int64_t timeoutUs) { 432 sp<AMessage> msg = new AMessage(kWhatDequeueInputBuffer, id()); 433 msg->setInt64("timeoutUs", timeoutUs); 434 435 sp<AMessage> response; 436 status_t err; 437 if ((err = PostAndAwaitResponse(msg, &response)) != OK) { 438 return err; 439 } 440 441 CHECK(response->findSize("index", index)); 442 443 return OK; 444} 445 446status_t MediaCodec::dequeueOutputBuffer( 447 size_t *index, 448 size_t *offset, 449 size_t *size, 450 int64_t *presentationTimeUs, 451 uint32_t *flags, 452 int64_t timeoutUs) { 453 sp<AMessage> msg = new AMessage(kWhatDequeueOutputBuffer, id()); 454 msg->setInt64("timeoutUs", timeoutUs); 455 456 sp<AMessage> response; 457 status_t err; 458 if ((err = PostAndAwaitResponse(msg, &response)) != OK) { 459 return err; 460 } 461 462 CHECK(response->findSize("index", index)); 463 CHECK(response->findSize("offset", offset)); 464 CHECK(response->findSize("size", size)); 465 CHECK(response->findInt64("timeUs", presentationTimeUs)); 466 CHECK(response->findInt32("flags", (int32_t *)flags)); 467 468 return OK; 469} 470 471status_t MediaCodec::renderOutputBufferAndRelease(size_t index) { 472 sp<AMessage> msg = new AMessage(kWhatReleaseOutputBuffer, id()); 473 msg->setSize("index", index); 474 msg->setInt32("render", true); 475 476 sp<AMessage> response; 477 return PostAndAwaitResponse(msg, &response); 478} 479 480status_t MediaCodec::renderOutputBufferAndRelease(size_t index, int64_t timestampNs) { 481 sp<AMessage> msg = new AMessage(kWhatReleaseOutputBuffer, id()); 482 msg->setSize("index", index); 483 msg->setInt32("render", true); 484 msg->setInt64("timestampNs", timestampNs); 485 486 sp<AMessage> response; 487 return PostAndAwaitResponse(msg, &response); 488} 489 490status_t MediaCodec::releaseOutputBuffer(size_t index) { 491 sp<AMessage> msg = new AMessage(kWhatReleaseOutputBuffer, id()); 492 msg->setSize("index", index); 493 494 sp<AMessage> response; 495 return PostAndAwaitResponse(msg, &response); 496} 497 498status_t MediaCodec::signalEndOfInputStream() { 499 sp<AMessage> msg = new AMessage(kWhatSignalEndOfInputStream, id()); 500 501 sp<AMessage> response; 502 return PostAndAwaitResponse(msg, &response); 503} 504 505status_t MediaCodec::getOutputFormat(sp<AMessage> *format) const { 506 sp<AMessage> msg = new AMessage(kWhatGetOutputFormat, id()); 507 508 sp<AMessage> response; 509 status_t err; 510 if ((err = PostAndAwaitResponse(msg, &response)) != OK) { 511 return err; 512 } 513 514 CHECK(response->findMessage("format", format)); 515 516 return OK; 517} 518 519status_t MediaCodec::getInputFormat(sp<AMessage> *format) const { 520 sp<AMessage> msg = new AMessage(kWhatGetInputFormat, id()); 521 522 sp<AMessage> response; 523 status_t err; 524 if ((err = PostAndAwaitResponse(msg, &response)) != OK) { 525 return err; 526 } 527 528 CHECK(response->findMessage("format", format)); 529 530 return OK; 531} 532 533status_t MediaCodec::getName(AString *name) const { 534 sp<AMessage> msg = new AMessage(kWhatGetName, id()); 535 536 sp<AMessage> response; 537 status_t err; 538 if ((err = PostAndAwaitResponse(msg, &response)) != OK) { 539 return err; 540 } 541 542 CHECK(response->findString("name", name)); 543 544 return OK; 545} 546 547status_t MediaCodec::getInputBuffers(Vector<sp<ABuffer> > *buffers) const { 548 sp<AMessage> msg = new AMessage(kWhatGetBuffers, id()); 549 msg->setInt32("portIndex", kPortIndexInput); 550 msg->setPointer("buffers", buffers); 551 552 sp<AMessage> response; 553 return PostAndAwaitResponse(msg, &response); 554} 555 556status_t MediaCodec::getOutputBuffers(Vector<sp<ABuffer> > *buffers) const { 557 sp<AMessage> msg = new AMessage(kWhatGetBuffers, id()); 558 msg->setInt32("portIndex", kPortIndexOutput); 559 msg->setPointer("buffers", buffers); 560 561 sp<AMessage> response; 562 return PostAndAwaitResponse(msg, &response); 563} 564 565status_t MediaCodec::getOutputBuffer(size_t index, sp<ABuffer> *buffer) { 566 sp<AMessage> format; 567 return getBufferAndFormat(kPortIndexOutput, index, buffer, &format); 568} 569 570status_t MediaCodec::getOutputFormat(size_t index, sp<AMessage> *format) { 571 sp<ABuffer> buffer; 572 return getBufferAndFormat(kPortIndexOutput, index, &buffer, format); 573} 574 575status_t MediaCodec::getInputBuffer(size_t index, sp<ABuffer> *buffer) { 576 sp<AMessage> format; 577 return getBufferAndFormat(kPortIndexInput, index, buffer, &format); 578} 579 580bool MediaCodec::isExecuting() const { 581 return mState == STARTED || mState == FLUSHED; 582} 583 584status_t MediaCodec::getBufferAndFormat( 585 size_t portIndex, size_t index, 586 sp<ABuffer> *buffer, sp<AMessage> *format) { 587 // use mutex instead of a context switch 588 589 buffer->clear(); 590 format->clear(); 591 if (!isExecuting()) { 592 return INVALID_OPERATION; 593 } 594 595 // we do not want mPortBuffers to change during this section 596 // we also don't want mOwnedByClient to change during this 597 Mutex::Autolock al(mBufferLock); 598 Vector<BufferInfo> *buffers = &mPortBuffers[portIndex]; 599 if (index < buffers->size()) { 600 const BufferInfo &info = buffers->itemAt(index); 601 if (info.mOwnedByClient) { 602 // by the time buffers array is initialized, crypto is set 603 if (portIndex == kPortIndexInput && mCrypto != NULL) { 604 *buffer = info.mEncryptedData; 605 } else { 606 *buffer = info.mData; 607 } 608 *format = info.mFormat; 609 } 610 } 611 return OK; 612} 613 614status_t MediaCodec::flush() { 615 sp<AMessage> msg = new AMessage(kWhatFlush, id()); 616 617 sp<AMessage> response; 618 return PostAndAwaitResponse(msg, &response); 619} 620 621status_t MediaCodec::requestIDRFrame() { 622 (new AMessage(kWhatRequestIDRFrame, id()))->post(); 623 624 return OK; 625} 626 627void MediaCodec::requestActivityNotification(const sp<AMessage> ¬ify) { 628 sp<AMessage> msg = new AMessage(kWhatRequestActivityNotification, id()); 629 msg->setMessage("notify", notify); 630 msg->post(); 631} 632 633//////////////////////////////////////////////////////////////////////////////// 634 635void MediaCodec::cancelPendingDequeueOperations() { 636 if (mFlags & kFlagDequeueInputPending) { 637 PostReplyWithError(mDequeueInputReplyID, INVALID_OPERATION); 638 639 ++mDequeueInputTimeoutGeneration; 640 mDequeueInputReplyID = 0; 641 mFlags &= ~kFlagDequeueInputPending; 642 } 643 644 if (mFlags & kFlagDequeueOutputPending) { 645 PostReplyWithError(mDequeueOutputReplyID, INVALID_OPERATION); 646 647 ++mDequeueOutputTimeoutGeneration; 648 mDequeueOutputReplyID = 0; 649 mFlags &= ~kFlagDequeueOutputPending; 650 } 651} 652 653bool MediaCodec::handleDequeueInputBuffer(uint32_t replyID, bool newRequest) { 654 if (!isExecuting() || (mFlags & kFlagIsAsync) 655 || (newRequest && (mFlags & kFlagDequeueInputPending))) { 656 PostReplyWithError(replyID, INVALID_OPERATION); 657 return true; 658 } else if (mFlags & kFlagStickyError) { 659 PostReplyWithError(replyID, getStickyError()); 660 return true; 661 } 662 663 ssize_t index = dequeuePortBuffer(kPortIndexInput); 664 665 if (index < 0) { 666 CHECK_EQ(index, -EAGAIN); 667 return false; 668 } 669 670 sp<AMessage> response = new AMessage; 671 response->setSize("index", index); 672 response->postReply(replyID); 673 674 return true; 675} 676 677bool MediaCodec::handleDequeueOutputBuffer(uint32_t replyID, bool newRequest) { 678 sp<AMessage> response = new AMessage; 679 680 if (!isExecuting() || (mFlags & kFlagIsAsync) 681 || (newRequest && (mFlags & kFlagDequeueOutputPending))) { 682 response->setInt32("err", INVALID_OPERATION); 683 } else if (mFlags & kFlagStickyError) { 684 response->setInt32("err", getStickyError()); 685 } else if (mFlags & kFlagOutputBuffersChanged) { 686 response->setInt32("err", INFO_OUTPUT_BUFFERS_CHANGED); 687 mFlags &= ~kFlagOutputBuffersChanged; 688 } else if (mFlags & kFlagOutputFormatChanged) { 689 response->setInt32("err", INFO_FORMAT_CHANGED); 690 mFlags &= ~kFlagOutputFormatChanged; 691 } else { 692 ssize_t index = dequeuePortBuffer(kPortIndexOutput); 693 694 if (index < 0) { 695 CHECK_EQ(index, -EAGAIN); 696 return false; 697 } 698 699 const sp<ABuffer> &buffer = 700 mPortBuffers[kPortIndexOutput].itemAt(index).mData; 701 702 response->setSize("index", index); 703 response->setSize("offset", buffer->offset()); 704 response->setSize("size", buffer->size()); 705 706 int64_t timeUs; 707 CHECK(buffer->meta()->findInt64("timeUs", &timeUs)); 708 709 response->setInt64("timeUs", timeUs); 710 711 int32_t omxFlags; 712 CHECK(buffer->meta()->findInt32("omxFlags", &omxFlags)); 713 714 uint32_t flags = 0; 715 if (omxFlags & OMX_BUFFERFLAG_SYNCFRAME) { 716 flags |= BUFFER_FLAG_SYNCFRAME; 717 } 718 if (omxFlags & OMX_BUFFERFLAG_CODECCONFIG) { 719 flags |= BUFFER_FLAG_CODECCONFIG; 720 } 721 if (omxFlags & OMX_BUFFERFLAG_EOS) { 722 flags |= BUFFER_FLAG_EOS; 723 } 724 725 response->setInt32("flags", flags); 726 } 727 728 response->postReply(replyID); 729 730 return true; 731} 732 733void MediaCodec::onMessageReceived(const sp<AMessage> &msg) { 734 switch (msg->what()) { 735 case kWhatCodecNotify: 736 { 737 int32_t what; 738 CHECK(msg->findInt32("what", &what)); 739 740 switch (what) { 741 case CodecBase::kWhatError: 742 { 743 int32_t err, actionCode; 744 CHECK(msg->findInt32("err", &err)); 745 CHECK(msg->findInt32("actionCode", &actionCode)); 746 747 ALOGE("Codec reported err %#x, actionCode %d, while in state %d", 748 err, actionCode, mState); 749 if (err == DEAD_OBJECT) { 750 mFlags |= kFlagSawMediaServerDie; 751 mFlags &= ~kFlagIsComponentAllocated; 752 } 753 754 bool sendErrorResponse = true; 755 756 switch (mState) { 757 case INITIALIZING: 758 { 759 setState(UNINITIALIZED); 760 break; 761 } 762 763 case CONFIGURING: 764 { 765 setState(actionCode == ACTION_CODE_FATAL ? 766 UNINITIALIZED : INITIALIZED); 767 break; 768 } 769 770 case STARTING: 771 { 772 setState(actionCode == ACTION_CODE_FATAL ? 773 UNINITIALIZED : CONFIGURED); 774 break; 775 } 776 777 case STOPPING: 778 case RELEASING: 779 { 780 // Ignore the error, assuming we'll still get 781 // the shutdown complete notification. 782 783 sendErrorResponse = false; 784 785 if (mFlags & kFlagSawMediaServerDie) { 786 // MediaServer died, there definitely won't 787 // be a shutdown complete notification after 788 // all. 789 790 // note that we're directly going from 791 // STOPPING->UNINITIALIZED, instead of the 792 // usual STOPPING->INITIALIZED state. 793 setState(UNINITIALIZED); 794 if (mState == RELEASING) { 795 mComponentName.clear(); 796 } 797 (new AMessage)->postReply(mReplyID); 798 } 799 break; 800 } 801 802 case FLUSHING: 803 { 804 if (actionCode == ACTION_CODE_FATAL) { 805 setState(UNINITIALIZED); 806 } else { 807 setState( 808 (mFlags & kFlagIsAsync) ? FLUSHED : STARTED); 809 } 810 break; 811 } 812 813 case FLUSHED: 814 case STARTED: 815 { 816 sendErrorResponse = false; 817 818 setStickyError(err); 819 postActivityNotificationIfPossible(); 820 821 cancelPendingDequeueOperations(); 822 823 if (mFlags & kFlagIsAsync) { 824 onError(err, actionCode); 825 } 826 switch (actionCode) { 827 case ACTION_CODE_TRANSIENT: 828 break; 829 case ACTION_CODE_RECOVERABLE: 830 setState(INITIALIZED); 831 break; 832 default: 833 setState(UNINITIALIZED); 834 break; 835 } 836 break; 837 } 838 839 default: 840 { 841 sendErrorResponse = false; 842 843 setStickyError(err); 844 postActivityNotificationIfPossible(); 845 846 // actionCode in an uninitialized state is always fatal. 847 if (mState == UNINITIALIZED) { 848 actionCode = ACTION_CODE_FATAL; 849 } 850 if (mFlags & kFlagIsAsync) { 851 onError(err, actionCode); 852 } 853 switch (actionCode) { 854 case ACTION_CODE_TRANSIENT: 855 break; 856 case ACTION_CODE_RECOVERABLE: 857 setState(INITIALIZED); 858 break; 859 default: 860 setState(UNINITIALIZED); 861 break; 862 } 863 break; 864 } 865 } 866 867 if (sendErrorResponse) { 868 PostReplyWithError(mReplyID, err); 869 } 870 break; 871 } 872 873 case CodecBase::kWhatComponentAllocated: 874 { 875 CHECK_EQ(mState, INITIALIZING); 876 setState(INITIALIZED); 877 mFlags |= kFlagIsComponentAllocated; 878 879 CHECK(msg->findString("componentName", &mComponentName)); 880 881 if (mComponentName.startsWith("OMX.google.")) { 882 mFlags |= kFlagIsSoftwareCodec; 883 } else { 884 mFlags &= ~kFlagIsSoftwareCodec; 885 } 886 887 if (mComponentName.endsWith(".secure")) { 888 mFlags |= kFlagIsSecure; 889 } else { 890 mFlags &= ~kFlagIsSecure; 891 } 892 893 (new AMessage)->postReply(mReplyID); 894 break; 895 } 896 897 case CodecBase::kWhatComponentConfigured: 898 { 899 CHECK_EQ(mState, CONFIGURING); 900 901 // reset input surface flag 902 mHaveInputSurface = false; 903 904 CHECK(msg->findMessage("input-format", &mInputFormat)); 905 CHECK(msg->findMessage("output-format", &mOutputFormat)); 906 907 setState(CONFIGURED); 908 (new AMessage)->postReply(mReplyID); 909 break; 910 } 911 912 case CodecBase::kWhatInputSurfaceCreated: 913 { 914 // response to initiateCreateInputSurface() 915 status_t err = NO_ERROR; 916 sp<AMessage> response = new AMessage(); 917 if (!msg->findInt32("err", &err)) { 918 sp<RefBase> obj; 919 msg->findObject("input-surface", &obj); 920 CHECK(obj != NULL); 921 response->setObject("input-surface", obj); 922 mHaveInputSurface = true; 923 } else { 924 response->setInt32("err", err); 925 } 926 response->postReply(mReplyID); 927 break; 928 } 929 930 case CodecBase::kWhatSignaledInputEOS: 931 { 932 // response to signalEndOfInputStream() 933 sp<AMessage> response = new AMessage(); 934 status_t err; 935 if (msg->findInt32("err", &err)) { 936 response->setInt32("err", err); 937 } 938 response->postReply(mReplyID); 939 break; 940 } 941 942 943 case CodecBase::kWhatBuffersAllocated: 944 { 945 Mutex::Autolock al(mBufferLock); 946 int32_t portIndex; 947 CHECK(msg->findInt32("portIndex", &portIndex)); 948 949 ALOGV("%s buffers allocated", 950 portIndex == kPortIndexInput ? "input" : "output"); 951 952 CHECK(portIndex == kPortIndexInput 953 || portIndex == kPortIndexOutput); 954 955 mPortBuffers[portIndex].clear(); 956 957 Vector<BufferInfo> *buffers = &mPortBuffers[portIndex]; 958 959 sp<RefBase> obj; 960 CHECK(msg->findObject("portDesc", &obj)); 961 962 sp<CodecBase::PortDescription> portDesc = 963 static_cast<CodecBase::PortDescription *>(obj.get()); 964 965 size_t numBuffers = portDesc->countBuffers(); 966 967 for (size_t i = 0; i < numBuffers; ++i) { 968 BufferInfo info; 969 info.mBufferID = portDesc->bufferIDAt(i); 970 info.mOwnedByClient = false; 971 info.mData = portDesc->bufferAt(i); 972 973 if (portIndex == kPortIndexInput && mCrypto != NULL) { 974 info.mEncryptedData = 975 new ABuffer(info.mData->capacity()); 976 } 977 978 buffers->push_back(info); 979 } 980 981 if (portIndex == kPortIndexOutput) { 982 if (mState == STARTING) { 983 // We're always allocating output buffers after 984 // allocating input buffers, so this is a good 985 // indication that now all buffers are allocated. 986 setState(STARTED); 987 (new AMessage)->postReply(mReplyID); 988 } else { 989 mFlags |= kFlagOutputBuffersChanged; 990 postActivityNotificationIfPossible(); 991 } 992 } 993 break; 994 } 995 996 case CodecBase::kWhatOutputFormatChanged: 997 { 998 ALOGV("codec output format changed"); 999 1000 if (mSoftRenderer == NULL && 1001 mNativeWindow != NULL && 1002 (mFlags & kFlagIsSoftwareCodec)) { 1003 AString mime; 1004 CHECK(msg->findString("mime", &mime)); 1005 1006 if (mime.startsWithIgnoreCase("video/")) { 1007 mSoftRenderer = new SoftwareRenderer(mNativeWindow); 1008 } 1009 } 1010 1011 mOutputFormat = msg; 1012 1013 if (mFlags & kFlagIsEncoder) { 1014 // Before we announce the format change we should 1015 // collect codec specific data and amend the output 1016 // format as necessary. 1017 mFlags |= kFlagGatherCodecSpecificData; 1018 } else if (mFlags & kFlagIsAsync) { 1019 onOutputFormatChanged(); 1020 } else { 1021 mFlags |= kFlagOutputFormatChanged; 1022 postActivityNotificationIfPossible(); 1023 } 1024 1025 // Notify mCrypto of video resolution changes 1026 if (mCrypto != NULL) { 1027 int32_t height, width; 1028 if (mOutputFormat->findInt32("height", &height) && 1029 mOutputFormat->findInt32("width", &width)) { 1030 mCrypto->notifyResolution(width, height); 1031 } 1032 } 1033 1034 break; 1035 } 1036 1037 case CodecBase::kWhatFillThisBuffer: 1038 { 1039 /* size_t index = */updateBuffers(kPortIndexInput, msg); 1040 1041 if (mState == FLUSHING 1042 || mState == STOPPING 1043 || mState == RELEASING) { 1044 returnBuffersToCodecOnPort(kPortIndexInput); 1045 break; 1046 } 1047 1048 if (!mCSD.empty()) { 1049 ssize_t index = dequeuePortBuffer(kPortIndexInput); 1050 CHECK_GE(index, 0); 1051 1052 // If codec specific data had been specified as 1053 // part of the format in the call to configure and 1054 // if there's more csd left, we submit it here 1055 // clients only get access to input buffers once 1056 // this data has been exhausted. 1057 1058 status_t err = queueCSDInputBuffer(index); 1059 1060 if (err != OK) { 1061 ALOGE("queueCSDInputBuffer failed w/ error %d", 1062 err); 1063 1064 setStickyError(err); 1065 postActivityNotificationIfPossible(); 1066 1067 cancelPendingDequeueOperations(); 1068 } 1069 break; 1070 } 1071 1072 if (mFlags & kFlagIsAsync) { 1073 if (!mHaveInputSurface) { 1074 onInputBufferAvailable(); 1075 } 1076 } else if (mFlags & kFlagDequeueInputPending) { 1077 CHECK(handleDequeueInputBuffer(mDequeueInputReplyID)); 1078 1079 ++mDequeueInputTimeoutGeneration; 1080 mFlags &= ~kFlagDequeueInputPending; 1081 mDequeueInputReplyID = 0; 1082 } else { 1083 postActivityNotificationIfPossible(); 1084 } 1085 break; 1086 } 1087 1088 case CodecBase::kWhatDrainThisBuffer: 1089 { 1090 /* size_t index = */updateBuffers(kPortIndexOutput, msg); 1091 1092 if (mState == FLUSHING 1093 || mState == STOPPING 1094 || mState == RELEASING) { 1095 returnBuffersToCodecOnPort(kPortIndexOutput); 1096 break; 1097 } 1098 1099 sp<ABuffer> buffer; 1100 CHECK(msg->findBuffer("buffer", &buffer)); 1101 1102 int32_t omxFlags; 1103 CHECK(msg->findInt32("flags", &omxFlags)); 1104 1105 buffer->meta()->setInt32("omxFlags", omxFlags); 1106 1107 if (mFlags & kFlagGatherCodecSpecificData) { 1108 // This is the very first output buffer after a 1109 // format change was signalled, it'll either contain 1110 // the one piece of codec specific data we can expect 1111 // or there won't be codec specific data. 1112 if (omxFlags & OMX_BUFFERFLAG_CODECCONFIG) { 1113 status_t err = 1114 amendOutputFormatWithCodecSpecificData(buffer); 1115 1116 if (err != OK) { 1117 ALOGE("Codec spit out malformed codec " 1118 "specific data!"); 1119 } 1120 } 1121 1122 mFlags &= ~kFlagGatherCodecSpecificData; 1123 if (mFlags & kFlagIsAsync) { 1124 onOutputFormatChanged(); 1125 } else { 1126 mFlags |= kFlagOutputFormatChanged; 1127 } 1128 } 1129 1130 if (mFlags & kFlagIsAsync) { 1131 onOutputBufferAvailable(); 1132 } else if (mFlags & kFlagDequeueOutputPending) { 1133 CHECK(handleDequeueOutputBuffer(mDequeueOutputReplyID)); 1134 1135 ++mDequeueOutputTimeoutGeneration; 1136 mFlags &= ~kFlagDequeueOutputPending; 1137 mDequeueOutputReplyID = 0; 1138 } else { 1139 postActivityNotificationIfPossible(); 1140 } 1141 1142 break; 1143 } 1144 1145 case CodecBase::kWhatEOS: 1146 { 1147 // We already notify the client of this by using the 1148 // corresponding flag in "onOutputBufferReady". 1149 break; 1150 } 1151 1152 case CodecBase::kWhatShutdownCompleted: 1153 { 1154 if (mState == STOPPING) { 1155 setState(INITIALIZED); 1156 } else { 1157 CHECK_EQ(mState, RELEASING); 1158 setState(UNINITIALIZED); 1159 mComponentName.clear(); 1160 } 1161 mFlags &= ~kFlagIsComponentAllocated; 1162 1163 (new AMessage)->postReply(mReplyID); 1164 break; 1165 } 1166 1167 case CodecBase::kWhatFlushCompleted: 1168 { 1169 if (mState != FLUSHING) { 1170 ALOGW("received FlushCompleted message in state %d", 1171 mState); 1172 break; 1173 } 1174 1175 if (mFlags & kFlagIsAsync) { 1176 setState(FLUSHED); 1177 } else { 1178 setState(STARTED); 1179 mCodec->signalResume(); 1180 } 1181 1182 (new AMessage)->postReply(mReplyID); 1183 break; 1184 } 1185 1186 default: 1187 TRESPASS(); 1188 } 1189 break; 1190 } 1191 1192 case kWhatInit: 1193 { 1194 uint32_t replyID; 1195 CHECK(msg->senderAwaitsResponse(&replyID)); 1196 1197 if (mState != UNINITIALIZED) { 1198 PostReplyWithError(replyID, INVALID_OPERATION); 1199 break; 1200 } 1201 1202 mReplyID = replyID; 1203 setState(INITIALIZING); 1204 1205 AString name; 1206 CHECK(msg->findString("name", &name)); 1207 1208 int32_t nameIsType; 1209 int32_t encoder = false; 1210 CHECK(msg->findInt32("nameIsType", &nameIsType)); 1211 if (nameIsType) { 1212 CHECK(msg->findInt32("encoder", &encoder)); 1213 } 1214 1215 sp<AMessage> format = new AMessage; 1216 1217 if (nameIsType) { 1218 format->setString("mime", name.c_str()); 1219 format->setInt32("encoder", encoder); 1220 } else { 1221 format->setString("componentName", name.c_str()); 1222 } 1223 1224 mCodec->initiateAllocateComponent(format); 1225 break; 1226 } 1227 1228 case kWhatSetCallback: 1229 { 1230 uint32_t replyID; 1231 CHECK(msg->senderAwaitsResponse(&replyID)); 1232 1233 if (mState == UNINITIALIZED 1234 || mState == INITIALIZING 1235 || isExecuting()) { 1236 // callback can't be set after codec is executing, 1237 // or before it's initialized (as the callback 1238 // will be cleared when it goes to INITIALIZED) 1239 PostReplyWithError(replyID, INVALID_OPERATION); 1240 break; 1241 } 1242 1243 sp<AMessage> callback; 1244 CHECK(msg->findMessage("callback", &callback)); 1245 1246 mCallback = callback; 1247 1248 if (mCallback != NULL) { 1249 ALOGI("MediaCodec will operate in async mode"); 1250 mFlags |= kFlagIsAsync; 1251 } else { 1252 mFlags &= ~kFlagIsAsync; 1253 } 1254 1255 sp<AMessage> response = new AMessage; 1256 response->postReply(replyID); 1257 break; 1258 } 1259 1260 case kWhatConfigure: 1261 { 1262 uint32_t replyID; 1263 CHECK(msg->senderAwaitsResponse(&replyID)); 1264 1265 if (mState != INITIALIZED) { 1266 PostReplyWithError(replyID, INVALID_OPERATION); 1267 break; 1268 } 1269 1270 sp<RefBase> obj; 1271 if (!msg->findObject("native-window", &obj)) { 1272 obj.clear(); 1273 } 1274 1275 sp<AMessage> format; 1276 CHECK(msg->findMessage("format", &format)); 1277 1278 if (obj != NULL) { 1279 format->setObject("native-window", obj); 1280 1281 status_t err = setNativeWindow( 1282 static_cast<NativeWindowWrapper *>(obj.get()) 1283 ->getSurfaceTextureClient()); 1284 1285 if (err != OK) { 1286 PostReplyWithError(replyID, err); 1287 break; 1288 } 1289 } else { 1290 setNativeWindow(NULL); 1291 } 1292 1293 mReplyID = replyID; 1294 setState(CONFIGURING); 1295 1296 void *crypto; 1297 if (!msg->findPointer("crypto", &crypto)) { 1298 crypto = NULL; 1299 } 1300 1301 mCrypto = static_cast<ICrypto *>(crypto); 1302 1303 uint32_t flags; 1304 CHECK(msg->findInt32("flags", (int32_t *)&flags)); 1305 1306 if (flags & CONFIGURE_FLAG_ENCODE) { 1307 format->setInt32("encoder", true); 1308 mFlags |= kFlagIsEncoder; 1309 } 1310 1311 extractCSD(format); 1312 1313 mCodec->initiateConfigureComponent(format); 1314 break; 1315 } 1316 1317 case kWhatCreateInputSurface: 1318 { 1319 uint32_t replyID; 1320 CHECK(msg->senderAwaitsResponse(&replyID)); 1321 1322 // Must be configured, but can't have been started yet. 1323 if (mState != CONFIGURED) { 1324 PostReplyWithError(replyID, INVALID_OPERATION); 1325 break; 1326 } 1327 1328 mReplyID = replyID; 1329 mCodec->initiateCreateInputSurface(); 1330 break; 1331 } 1332 1333 case kWhatStart: 1334 { 1335 uint32_t replyID; 1336 CHECK(msg->senderAwaitsResponse(&replyID)); 1337 1338 if (mState == FLUSHED) { 1339 mCodec->signalResume(); 1340 PostReplyWithError(replyID, OK); 1341 } else if (mState != CONFIGURED) { 1342 PostReplyWithError(replyID, INVALID_OPERATION); 1343 break; 1344 } 1345 1346 mReplyID = replyID; 1347 setState(STARTING); 1348 1349 mCodec->initiateStart(); 1350 break; 1351 } 1352 1353 case kWhatStop: 1354 case kWhatRelease: 1355 { 1356 State targetState = 1357 (msg->what() == kWhatStop) ? INITIALIZED : UNINITIALIZED; 1358 1359 uint32_t replyID; 1360 CHECK(msg->senderAwaitsResponse(&replyID)); 1361 1362 if (!((mFlags & kFlagIsComponentAllocated) && targetState == UNINITIALIZED) // See 1 1363 && mState != INITIALIZED 1364 && mState != CONFIGURED && !isExecuting()) { 1365 // 1) Permit release to shut down the component if allocated. 1366 // 1367 // 2) We may be in "UNINITIALIZED" state already and 1368 // also shutdown the encoder/decoder without the 1369 // client being aware of this if media server died while 1370 // we were being stopped. The client would assume that 1371 // after stop() returned, it would be safe to call release() 1372 // and it should be in this case, no harm to allow a release() 1373 // if we're already uninitialized. 1374 sp<AMessage> response = new AMessage; 1375 status_t err = mState == targetState ? OK : INVALID_OPERATION; 1376 response->setInt32("err", err); 1377 if (err == OK && targetState == UNINITIALIZED) { 1378 mComponentName.clear(); 1379 } 1380 response->postReply(replyID); 1381 break; 1382 } 1383 1384 if (mFlags & kFlagSawMediaServerDie) { 1385 // It's dead, Jim. Don't expect initiateShutdown to yield 1386 // any useful results now... 1387 setState(UNINITIALIZED); 1388 if (targetState == UNINITIALIZED) { 1389 mComponentName.clear(); 1390 } 1391 (new AMessage)->postReply(replyID); 1392 break; 1393 } 1394 1395 mReplyID = replyID; 1396 setState(msg->what() == kWhatStop ? STOPPING : RELEASING); 1397 1398 mCodec->initiateShutdown( 1399 msg->what() == kWhatStop /* keepComponentAllocated */); 1400 1401 returnBuffersToCodec(); 1402 break; 1403 } 1404 1405 case kWhatDequeueInputBuffer: 1406 { 1407 uint32_t replyID; 1408 CHECK(msg->senderAwaitsResponse(&replyID)); 1409 1410 if (mFlags & kFlagIsAsync) { 1411 ALOGE("dequeueOutputBuffer can't be used in async mode"); 1412 PostReplyWithError(replyID, INVALID_OPERATION); 1413 break; 1414 } 1415 1416 if (mHaveInputSurface) { 1417 ALOGE("dequeueInputBuffer can't be used with input surface"); 1418 PostReplyWithError(replyID, INVALID_OPERATION); 1419 break; 1420 } 1421 1422 if (handleDequeueInputBuffer(replyID, true /* new request */)) { 1423 break; 1424 } 1425 1426 int64_t timeoutUs; 1427 CHECK(msg->findInt64("timeoutUs", &timeoutUs)); 1428 1429 if (timeoutUs == 0ll) { 1430 PostReplyWithError(replyID, -EAGAIN); 1431 break; 1432 } 1433 1434 mFlags |= kFlagDequeueInputPending; 1435 mDequeueInputReplyID = replyID; 1436 1437 if (timeoutUs > 0ll) { 1438 sp<AMessage> timeoutMsg = 1439 new AMessage(kWhatDequeueInputTimedOut, id()); 1440 timeoutMsg->setInt32( 1441 "generation", ++mDequeueInputTimeoutGeneration); 1442 timeoutMsg->post(timeoutUs); 1443 } 1444 break; 1445 } 1446 1447 case kWhatDequeueInputTimedOut: 1448 { 1449 int32_t generation; 1450 CHECK(msg->findInt32("generation", &generation)); 1451 1452 if (generation != mDequeueInputTimeoutGeneration) { 1453 // Obsolete 1454 break; 1455 } 1456 1457 CHECK(mFlags & kFlagDequeueInputPending); 1458 1459 PostReplyWithError(mDequeueInputReplyID, -EAGAIN); 1460 1461 mFlags &= ~kFlagDequeueInputPending; 1462 mDequeueInputReplyID = 0; 1463 break; 1464 } 1465 1466 case kWhatQueueInputBuffer: 1467 { 1468 uint32_t replyID; 1469 CHECK(msg->senderAwaitsResponse(&replyID)); 1470 1471 if (!isExecuting()) { 1472 PostReplyWithError(replyID, INVALID_OPERATION); 1473 break; 1474 } else if (mFlags & kFlagStickyError) { 1475 PostReplyWithError(replyID, getStickyError()); 1476 break; 1477 } 1478 1479 status_t err = onQueueInputBuffer(msg); 1480 1481 PostReplyWithError(replyID, err); 1482 break; 1483 } 1484 1485 case kWhatDequeueOutputBuffer: 1486 { 1487 uint32_t replyID; 1488 CHECK(msg->senderAwaitsResponse(&replyID)); 1489 1490 if (mFlags & kFlagIsAsync) { 1491 ALOGE("dequeueOutputBuffer can't be used in async mode"); 1492 PostReplyWithError(replyID, INVALID_OPERATION); 1493 break; 1494 } 1495 1496 if (handleDequeueOutputBuffer(replyID, true /* new request */)) { 1497 break; 1498 } 1499 1500 int64_t timeoutUs; 1501 CHECK(msg->findInt64("timeoutUs", &timeoutUs)); 1502 1503 if (timeoutUs == 0ll) { 1504 PostReplyWithError(replyID, -EAGAIN); 1505 break; 1506 } 1507 1508 mFlags |= kFlagDequeueOutputPending; 1509 mDequeueOutputReplyID = replyID; 1510 1511 if (timeoutUs > 0ll) { 1512 sp<AMessage> timeoutMsg = 1513 new AMessage(kWhatDequeueOutputTimedOut, id()); 1514 timeoutMsg->setInt32( 1515 "generation", ++mDequeueOutputTimeoutGeneration); 1516 timeoutMsg->post(timeoutUs); 1517 } 1518 break; 1519 } 1520 1521 case kWhatDequeueOutputTimedOut: 1522 { 1523 int32_t generation; 1524 CHECK(msg->findInt32("generation", &generation)); 1525 1526 if (generation != mDequeueOutputTimeoutGeneration) { 1527 // Obsolete 1528 break; 1529 } 1530 1531 CHECK(mFlags & kFlagDequeueOutputPending); 1532 1533 PostReplyWithError(mDequeueOutputReplyID, -EAGAIN); 1534 1535 mFlags &= ~kFlagDequeueOutputPending; 1536 mDequeueOutputReplyID = 0; 1537 break; 1538 } 1539 1540 case kWhatReleaseOutputBuffer: 1541 { 1542 uint32_t replyID; 1543 CHECK(msg->senderAwaitsResponse(&replyID)); 1544 1545 if (!isExecuting()) { 1546 PostReplyWithError(replyID, INVALID_OPERATION); 1547 break; 1548 } else if (mFlags & kFlagStickyError) { 1549 PostReplyWithError(replyID, getStickyError()); 1550 break; 1551 } 1552 1553 status_t err = onReleaseOutputBuffer(msg); 1554 1555 PostReplyWithError(replyID, err); 1556 break; 1557 } 1558 1559 case kWhatSignalEndOfInputStream: 1560 { 1561 uint32_t replyID; 1562 CHECK(msg->senderAwaitsResponse(&replyID)); 1563 1564 if (!isExecuting()) { 1565 PostReplyWithError(replyID, INVALID_OPERATION); 1566 break; 1567 } else if (mFlags & kFlagStickyError) { 1568 PostReplyWithError(replyID, getStickyError()); 1569 break; 1570 } 1571 1572 mReplyID = replyID; 1573 mCodec->signalEndOfInputStream(); 1574 break; 1575 } 1576 1577 case kWhatGetBuffers: 1578 { 1579 uint32_t replyID; 1580 CHECK(msg->senderAwaitsResponse(&replyID)); 1581 1582 if (!isExecuting() || (mFlags & kFlagIsAsync)) { 1583 PostReplyWithError(replyID, INVALID_OPERATION); 1584 break; 1585 } else if (mFlags & kFlagStickyError) { 1586 PostReplyWithError(replyID, getStickyError()); 1587 break; 1588 } 1589 1590 int32_t portIndex; 1591 CHECK(msg->findInt32("portIndex", &portIndex)); 1592 1593 Vector<sp<ABuffer> > *dstBuffers; 1594 CHECK(msg->findPointer("buffers", (void **)&dstBuffers)); 1595 1596 dstBuffers->clear(); 1597 const Vector<BufferInfo> &srcBuffers = mPortBuffers[portIndex]; 1598 1599 for (size_t i = 0; i < srcBuffers.size(); ++i) { 1600 const BufferInfo &info = srcBuffers.itemAt(i); 1601 1602 dstBuffers->push_back( 1603 (portIndex == kPortIndexInput && mCrypto != NULL) 1604 ? info.mEncryptedData : info.mData); 1605 } 1606 1607 (new AMessage)->postReply(replyID); 1608 break; 1609 } 1610 1611 case kWhatFlush: 1612 { 1613 uint32_t replyID; 1614 CHECK(msg->senderAwaitsResponse(&replyID)); 1615 1616 if (!isExecuting()) { 1617 PostReplyWithError(replyID, INVALID_OPERATION); 1618 break; 1619 } else if (mFlags & kFlagStickyError) { 1620 PostReplyWithError(replyID, getStickyError()); 1621 break; 1622 } 1623 1624 mReplyID = replyID; 1625 // TODO: skip flushing if already FLUSHED 1626 setState(FLUSHING); 1627 1628 mCodec->signalFlush(); 1629 returnBuffersToCodec(); 1630 break; 1631 } 1632 1633 case kWhatGetInputFormat: 1634 case kWhatGetOutputFormat: 1635 { 1636 sp<AMessage> format = 1637 (msg->what() == kWhatGetOutputFormat ? mOutputFormat : mInputFormat); 1638 1639 uint32_t replyID; 1640 CHECK(msg->senderAwaitsResponse(&replyID)); 1641 1642 if ((mState != CONFIGURED && mState != STARTING && 1643 mState != STARTED && mState != FLUSHING && 1644 mState != FLUSHED) 1645 || format == NULL) { 1646 PostReplyWithError(replyID, INVALID_OPERATION); 1647 break; 1648 } else if (mFlags & kFlagStickyError) { 1649 PostReplyWithError(replyID, getStickyError()); 1650 break; 1651 } 1652 1653 sp<AMessage> response = new AMessage; 1654 response->setMessage("format", format); 1655 response->postReply(replyID); 1656 break; 1657 } 1658 1659 case kWhatRequestIDRFrame: 1660 { 1661 mCodec->signalRequestIDRFrame(); 1662 break; 1663 } 1664 1665 case kWhatRequestActivityNotification: 1666 { 1667 CHECK(mActivityNotify == NULL); 1668 CHECK(msg->findMessage("notify", &mActivityNotify)); 1669 1670 postActivityNotificationIfPossible(); 1671 break; 1672 } 1673 1674 case kWhatGetName: 1675 { 1676 uint32_t replyID; 1677 CHECK(msg->senderAwaitsResponse(&replyID)); 1678 1679 if (mComponentName.empty()) { 1680 PostReplyWithError(replyID, INVALID_OPERATION); 1681 break; 1682 } 1683 1684 sp<AMessage> response = new AMessage; 1685 response->setString("name", mComponentName.c_str()); 1686 response->postReply(replyID); 1687 break; 1688 } 1689 1690 case kWhatSetParameters: 1691 { 1692 uint32_t replyID; 1693 CHECK(msg->senderAwaitsResponse(&replyID)); 1694 1695 sp<AMessage> params; 1696 CHECK(msg->findMessage("params", ¶ms)); 1697 1698 status_t err = onSetParameters(params); 1699 1700 PostReplyWithError(replyID, err); 1701 break; 1702 } 1703 1704 default: 1705 TRESPASS(); 1706 } 1707} 1708 1709void MediaCodec::extractCSD(const sp<AMessage> &format) { 1710 mCSD.clear(); 1711 1712 size_t i = 0; 1713 for (;;) { 1714 sp<ABuffer> csd; 1715 if (!format->findBuffer(StringPrintf("csd-%u", i).c_str(), &csd)) { 1716 break; 1717 } 1718 1719 mCSD.push_back(csd); 1720 ++i; 1721 } 1722 1723 ALOGV("Found %zu pieces of codec specific data.", mCSD.size()); 1724} 1725 1726status_t MediaCodec::queueCSDInputBuffer(size_t bufferIndex) { 1727 CHECK(!mCSD.empty()); 1728 1729 const BufferInfo *info = 1730 &mPortBuffers[kPortIndexInput].itemAt(bufferIndex); 1731 1732 sp<ABuffer> csd = *mCSD.begin(); 1733 mCSD.erase(mCSD.begin()); 1734 1735 const sp<ABuffer> &codecInputData = 1736 (mCrypto != NULL) ? info->mEncryptedData : info->mData; 1737 1738 if (csd->size() > codecInputData->capacity()) { 1739 return -EINVAL; 1740 } 1741 1742 memcpy(codecInputData->data(), csd->data(), csd->size()); 1743 1744 AString errorDetailMsg; 1745 1746 sp<AMessage> msg = new AMessage(kWhatQueueInputBuffer, id()); 1747 msg->setSize("index", bufferIndex); 1748 msg->setSize("offset", 0); 1749 msg->setSize("size", csd->size()); 1750 msg->setInt64("timeUs", 0ll); 1751 msg->setInt32("flags", BUFFER_FLAG_CODECCONFIG); 1752 msg->setPointer("errorDetailMsg", &errorDetailMsg); 1753 1754 return onQueueInputBuffer(msg); 1755} 1756 1757void MediaCodec::setState(State newState) { 1758 if (newState == INITIALIZED || newState == UNINITIALIZED) { 1759 delete mSoftRenderer; 1760 mSoftRenderer = NULL; 1761 1762 mCrypto.clear(); 1763 setNativeWindow(NULL); 1764 1765 mInputFormat.clear(); 1766 mOutputFormat.clear(); 1767 mFlags &= ~kFlagOutputFormatChanged; 1768 mFlags &= ~kFlagOutputBuffersChanged; 1769 mFlags &= ~kFlagStickyError; 1770 mFlags &= ~kFlagIsEncoder; 1771 mFlags &= ~kFlagGatherCodecSpecificData; 1772 mFlags &= ~kFlagIsAsync; 1773 mStickyError = OK; 1774 1775 mActivityNotify.clear(); 1776 mCallback.clear(); 1777 } 1778 1779 if (newState == UNINITIALIZED) { 1780 // return any straggling buffers, e.g. if we got here on an error 1781 returnBuffersToCodec(); 1782 1783 // The component is gone, mediaserver's probably back up already 1784 // but should definitely be back up should we try to instantiate 1785 // another component.. and the cycle continues. 1786 mFlags &= ~kFlagSawMediaServerDie; 1787 } 1788 1789 mState = newState; 1790 1791 cancelPendingDequeueOperations(); 1792 1793 updateBatteryStat(); 1794} 1795 1796void MediaCodec::returnBuffersToCodec() { 1797 returnBuffersToCodecOnPort(kPortIndexInput); 1798 returnBuffersToCodecOnPort(kPortIndexOutput); 1799} 1800 1801void MediaCodec::returnBuffersToCodecOnPort(int32_t portIndex) { 1802 CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput); 1803 Mutex::Autolock al(mBufferLock); 1804 1805 Vector<BufferInfo> *buffers = &mPortBuffers[portIndex]; 1806 1807 for (size_t i = 0; i < buffers->size(); ++i) { 1808 BufferInfo *info = &buffers->editItemAt(i); 1809 1810 if (info->mNotify != NULL) { 1811 sp<AMessage> msg = info->mNotify; 1812 info->mNotify = NULL; 1813 info->mOwnedByClient = false; 1814 1815 if (portIndex == kPortIndexInput) { 1816 /* no error, just returning buffers */ 1817 msg->setInt32("err", OK); 1818 } 1819 msg->post(); 1820 } 1821 } 1822 1823 mAvailPortBuffers[portIndex].clear(); 1824} 1825 1826size_t MediaCodec::updateBuffers( 1827 int32_t portIndex, const sp<AMessage> &msg) { 1828 CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput); 1829 1830 uint32_t bufferID; 1831 CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID)); 1832 1833 Vector<BufferInfo> *buffers = &mPortBuffers[portIndex]; 1834 1835 for (size_t i = 0; i < buffers->size(); ++i) { 1836 BufferInfo *info = &buffers->editItemAt(i); 1837 1838 if (info->mBufferID == bufferID) { 1839 CHECK(info->mNotify == NULL); 1840 CHECK(msg->findMessage("reply", &info->mNotify)); 1841 1842 info->mFormat = 1843 (portIndex == kPortIndexInput) ? mInputFormat : mOutputFormat; 1844 mAvailPortBuffers[portIndex].push_back(i); 1845 1846 return i; 1847 } 1848 } 1849 1850 TRESPASS(); 1851 1852 return 0; 1853} 1854 1855status_t MediaCodec::onQueueInputBuffer(const sp<AMessage> &msg) { 1856 size_t index; 1857 size_t offset; 1858 size_t size; 1859 int64_t timeUs; 1860 uint32_t flags; 1861 CHECK(msg->findSize("index", &index)); 1862 CHECK(msg->findSize("offset", &offset)); 1863 CHECK(msg->findInt64("timeUs", &timeUs)); 1864 CHECK(msg->findInt32("flags", (int32_t *)&flags)); 1865 1866 const CryptoPlugin::SubSample *subSamples; 1867 size_t numSubSamples; 1868 const uint8_t *key; 1869 const uint8_t *iv; 1870 CryptoPlugin::Mode mode = CryptoPlugin::kMode_Unencrypted; 1871 1872 // We allow the simpler queueInputBuffer API to be used even in 1873 // secure mode, by fabricating a single unencrypted subSample. 1874 CryptoPlugin::SubSample ss; 1875 1876 if (msg->findSize("size", &size)) { 1877 if (mCrypto != NULL) { 1878 ss.mNumBytesOfClearData = size; 1879 ss.mNumBytesOfEncryptedData = 0; 1880 1881 subSamples = &ss; 1882 numSubSamples = 1; 1883 key = NULL; 1884 iv = NULL; 1885 } 1886 } else { 1887 if (mCrypto == NULL) { 1888 return -EINVAL; 1889 } 1890 1891 CHECK(msg->findPointer("subSamples", (void **)&subSamples)); 1892 CHECK(msg->findSize("numSubSamples", &numSubSamples)); 1893 CHECK(msg->findPointer("key", (void **)&key)); 1894 CHECK(msg->findPointer("iv", (void **)&iv)); 1895 1896 int32_t tmp; 1897 CHECK(msg->findInt32("mode", &tmp)); 1898 1899 mode = (CryptoPlugin::Mode)tmp; 1900 1901 size = 0; 1902 for (size_t i = 0; i < numSubSamples; ++i) { 1903 size += subSamples[i].mNumBytesOfClearData; 1904 size += subSamples[i].mNumBytesOfEncryptedData; 1905 } 1906 } 1907 1908 if (index >= mPortBuffers[kPortIndexInput].size()) { 1909 return -ERANGE; 1910 } 1911 1912 BufferInfo *info = &mPortBuffers[kPortIndexInput].editItemAt(index); 1913 1914 if (info->mNotify == NULL || !info->mOwnedByClient) { 1915 return -EACCES; 1916 } 1917 1918 if (offset + size > info->mData->capacity()) { 1919 return -EINVAL; 1920 } 1921 1922 sp<AMessage> reply = info->mNotify; 1923 info->mData->setRange(offset, size); 1924 info->mData->meta()->setInt64("timeUs", timeUs); 1925 1926 if (flags & BUFFER_FLAG_EOS) { 1927 info->mData->meta()->setInt32("eos", true); 1928 } 1929 1930 if (flags & BUFFER_FLAG_CODECCONFIG) { 1931 info->mData->meta()->setInt32("csd", true); 1932 } 1933 1934 if (mCrypto != NULL) { 1935 if (size > info->mEncryptedData->capacity()) { 1936 return -ERANGE; 1937 } 1938 1939 AString *errorDetailMsg; 1940 CHECK(msg->findPointer("errorDetailMsg", (void **)&errorDetailMsg)); 1941 1942 ssize_t result = mCrypto->decrypt( 1943 (mFlags & kFlagIsSecure) != 0, 1944 key, 1945 iv, 1946 mode, 1947 info->mEncryptedData->base() + offset, 1948 subSamples, 1949 numSubSamples, 1950 info->mData->base(), 1951 errorDetailMsg); 1952 1953 if (result < 0) { 1954 return result; 1955 } 1956 1957 info->mData->setRange(0, result); 1958 } 1959 1960 // synchronization boundary for getBufferAndFormat 1961 { 1962 Mutex::Autolock al(mBufferLock); 1963 info->mOwnedByClient = false; 1964 } 1965 reply->setBuffer("buffer", info->mData); 1966 reply->post(); 1967 1968 info->mNotify = NULL; 1969 1970 return OK; 1971} 1972 1973status_t MediaCodec::onReleaseOutputBuffer(const sp<AMessage> &msg) { 1974 size_t index; 1975 CHECK(msg->findSize("index", &index)); 1976 1977 int32_t render; 1978 if (!msg->findInt32("render", &render)) { 1979 render = 0; 1980 } 1981 1982 if (!isExecuting()) { 1983 return -EINVAL; 1984 } 1985 1986 if (index >= mPortBuffers[kPortIndexOutput].size()) { 1987 return -ERANGE; 1988 } 1989 1990 BufferInfo *info = &mPortBuffers[kPortIndexOutput].editItemAt(index); 1991 1992 if (info->mNotify == NULL || !info->mOwnedByClient) { 1993 return -EACCES; 1994 } 1995 1996 // synchronization boundary for getBufferAndFormat 1997 { 1998 Mutex::Autolock al(mBufferLock); 1999 info->mOwnedByClient = false; 2000 } 2001 2002 if (render && info->mData != NULL && info->mData->size() != 0) { 2003 info->mNotify->setInt32("render", true); 2004 2005 int64_t timestampNs = 0; 2006 if (msg->findInt64("timestampNs", ×tampNs)) { 2007 info->mNotify->setInt64("timestampNs", timestampNs); 2008 } else { 2009 // TODO: it seems like we should use the timestamp 2010 // in the (media)buffer as it potentially came from 2011 // an input surface, but we did not propagate it prior to 2012 // API 20. Perhaps check for target SDK version. 2013#if 0 2014 if (info->mData->meta()->findInt64("timeUs", ×tampNs)) { 2015 ALOGV("using buffer PTS of %" PRId64, timestampNs); 2016 timestampNs *= 1000; 2017 } 2018#endif 2019 } 2020 2021 if (mSoftRenderer != NULL) { 2022 mSoftRenderer->render( 2023 info->mData->data(), info->mData->size(), 2024 timestampNs, NULL, info->mFormat); 2025 } 2026 } 2027 2028 info->mNotify->post(); 2029 info->mNotify = NULL; 2030 2031 return OK; 2032} 2033 2034ssize_t MediaCodec::dequeuePortBuffer(int32_t portIndex) { 2035 CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput); 2036 2037 List<size_t> *availBuffers = &mAvailPortBuffers[portIndex]; 2038 2039 if (availBuffers->empty()) { 2040 return -EAGAIN; 2041 } 2042 2043 size_t index = *availBuffers->begin(); 2044 availBuffers->erase(availBuffers->begin()); 2045 2046 BufferInfo *info = &mPortBuffers[portIndex].editItemAt(index); 2047 CHECK(!info->mOwnedByClient); 2048 { 2049 Mutex::Autolock al(mBufferLock); 2050 info->mOwnedByClient = true; 2051 2052 // set image-data 2053 if (info->mFormat != NULL) { 2054 sp<ABuffer> imageData; 2055 if (info->mFormat->findBuffer("image-data", &imageData)) { 2056 info->mData->meta()->setBuffer("image-data", imageData); 2057 } 2058 int32_t left, top, right, bottom; 2059 if (info->mFormat->findRect("crop", &left, &top, &right, &bottom)) { 2060 info->mData->meta()->setRect("crop-rect", left, top, right, bottom); 2061 } 2062 } 2063 } 2064 2065 return index; 2066} 2067 2068status_t MediaCodec::setNativeWindow( 2069 const sp<Surface> &surfaceTextureClient) { 2070 status_t err; 2071 2072 if (mNativeWindow != NULL) { 2073 err = native_window_api_disconnect( 2074 mNativeWindow.get(), NATIVE_WINDOW_API_MEDIA); 2075 2076 if (err != OK) { 2077 ALOGW("native_window_api_disconnect returned an error: %s (%d)", 2078 strerror(-err), err); 2079 } 2080 2081 mNativeWindow.clear(); 2082 } 2083 2084 if (surfaceTextureClient != NULL) { 2085 err = native_window_api_connect( 2086 surfaceTextureClient.get(), NATIVE_WINDOW_API_MEDIA); 2087 2088 if (err != OK) { 2089 ALOGE("native_window_api_connect returned an error: %s (%d)", 2090 strerror(-err), err); 2091 2092 return err; 2093 } 2094 2095 mNativeWindow = surfaceTextureClient; 2096 } 2097 2098 return OK; 2099} 2100 2101void MediaCodec::onInputBufferAvailable() { 2102 int32_t index; 2103 while ((index = dequeuePortBuffer(kPortIndexInput)) >= 0) { 2104 sp<AMessage> msg = mCallback->dup(); 2105 msg->setInt32("callbackID", CB_INPUT_AVAILABLE); 2106 msg->setInt32("index", index); 2107 msg->post(); 2108 } 2109} 2110 2111void MediaCodec::onOutputBufferAvailable() { 2112 int32_t index; 2113 while ((index = dequeuePortBuffer(kPortIndexOutput)) >= 0) { 2114 const sp<ABuffer> &buffer = 2115 mPortBuffers[kPortIndexOutput].itemAt(index).mData; 2116 sp<AMessage> msg = mCallback->dup(); 2117 msg->setInt32("callbackID", CB_OUTPUT_AVAILABLE); 2118 msg->setInt32("index", index); 2119 msg->setSize("offset", buffer->offset()); 2120 msg->setSize("size", buffer->size()); 2121 2122 int64_t timeUs; 2123 CHECK(buffer->meta()->findInt64("timeUs", &timeUs)); 2124 2125 msg->setInt64("timeUs", timeUs); 2126 2127 int32_t omxFlags; 2128 CHECK(buffer->meta()->findInt32("omxFlags", &omxFlags)); 2129 2130 uint32_t flags = 0; 2131 if (omxFlags & OMX_BUFFERFLAG_SYNCFRAME) { 2132 flags |= BUFFER_FLAG_SYNCFRAME; 2133 } 2134 if (omxFlags & OMX_BUFFERFLAG_CODECCONFIG) { 2135 flags |= BUFFER_FLAG_CODECCONFIG; 2136 } 2137 if (omxFlags & OMX_BUFFERFLAG_EOS) { 2138 flags |= BUFFER_FLAG_EOS; 2139 } 2140 2141 msg->setInt32("flags", flags); 2142 2143 msg->post(); 2144 } 2145} 2146 2147void MediaCodec::onError(status_t err, int32_t actionCode, const char *detail) { 2148 if (mCallback != NULL) { 2149 sp<AMessage> msg = mCallback->dup(); 2150 msg->setInt32("callbackID", CB_ERROR); 2151 msg->setInt32("err", err); 2152 msg->setInt32("actionCode", actionCode); 2153 2154 if (detail != NULL) { 2155 msg->setString("detail", detail); 2156 } 2157 2158 msg->post(); 2159 } 2160} 2161 2162void MediaCodec::onOutputFormatChanged() { 2163 if (mCallback != NULL) { 2164 sp<AMessage> msg = mCallback->dup(); 2165 msg->setInt32("callbackID", CB_OUTPUT_FORMAT_CHANGED); 2166 msg->setMessage("format", mOutputFormat); 2167 msg->post(); 2168 } 2169} 2170 2171 2172void MediaCodec::postActivityNotificationIfPossible() { 2173 if (mActivityNotify == NULL) { 2174 return; 2175 } 2176 2177 bool isErrorOrOutputChanged = 2178 (mFlags & (kFlagStickyError 2179 | kFlagOutputBuffersChanged 2180 | kFlagOutputFormatChanged)); 2181 2182 if (isErrorOrOutputChanged 2183 || !mAvailPortBuffers[kPortIndexInput].empty() 2184 || !mAvailPortBuffers[kPortIndexOutput].empty()) { 2185 mActivityNotify->setInt32("input-buffers", 2186 mAvailPortBuffers[kPortIndexInput].size()); 2187 2188 if (isErrorOrOutputChanged) { 2189 // we want consumer to dequeue as many times as it can 2190 mActivityNotify->setInt32("output-buffers", INT32_MAX); 2191 } else { 2192 mActivityNotify->setInt32("output-buffers", 2193 mAvailPortBuffers[kPortIndexOutput].size()); 2194 } 2195 mActivityNotify->post(); 2196 mActivityNotify.clear(); 2197 } 2198} 2199 2200status_t MediaCodec::setParameters(const sp<AMessage> ¶ms) { 2201 sp<AMessage> msg = new AMessage(kWhatSetParameters, id()); 2202 msg->setMessage("params", params); 2203 2204 sp<AMessage> response; 2205 return PostAndAwaitResponse(msg, &response); 2206} 2207 2208status_t MediaCodec::onSetParameters(const sp<AMessage> ¶ms) { 2209 mCodec->signalSetParameters(params); 2210 2211 return OK; 2212} 2213 2214status_t MediaCodec::amendOutputFormatWithCodecSpecificData( 2215 const sp<ABuffer> &buffer) { 2216 AString mime; 2217 CHECK(mOutputFormat->findString("mime", &mime)); 2218 2219 if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_AVC)) { 2220 // Codec specific data should be SPS and PPS in a single buffer, 2221 // each prefixed by a startcode (0x00 0x00 0x00 0x01). 2222 // We separate the two and put them into the output format 2223 // under the keys "csd-0" and "csd-1". 2224 2225 unsigned csdIndex = 0; 2226 2227 const uint8_t *data = buffer->data(); 2228 size_t size = buffer->size(); 2229 2230 const uint8_t *nalStart; 2231 size_t nalSize; 2232 while (getNextNALUnit(&data, &size, &nalStart, &nalSize, true) == OK) { 2233 sp<ABuffer> csd = new ABuffer(nalSize + 4); 2234 memcpy(csd->data(), "\x00\x00\x00\x01", 4); 2235 memcpy(csd->data() + 4, nalStart, nalSize); 2236 2237 mOutputFormat->setBuffer( 2238 StringPrintf("csd-%u", csdIndex).c_str(), csd); 2239 2240 ++csdIndex; 2241 } 2242 2243 if (csdIndex != 2) { 2244 return ERROR_MALFORMED; 2245 } 2246 } else { 2247 // For everything else we just stash the codec specific data into 2248 // the output format as a single piece of csd under "csd-0". 2249 mOutputFormat->setBuffer("csd-0", buffer); 2250 } 2251 2252 return OK; 2253} 2254 2255void MediaCodec::updateBatteryStat() { 2256 if (mState == CONFIGURED && !mBatteryStatNotified) { 2257 AString mime; 2258 CHECK(mOutputFormat != NULL && 2259 mOutputFormat->findString("mime", &mime)); 2260 2261 mIsVideo = mime.startsWithIgnoreCase("video/"); 2262 2263 BatteryNotifier& notifier(BatteryNotifier::getInstance()); 2264 2265 if (mIsVideo) { 2266 notifier.noteStartVideo(); 2267 } else { 2268 notifier.noteStartAudio(); 2269 } 2270 2271 mBatteryStatNotified = true; 2272 } else if (mState == UNINITIALIZED && mBatteryStatNotified) { 2273 BatteryNotifier& notifier(BatteryNotifier::getInstance()); 2274 2275 if (mIsVideo) { 2276 notifier.noteStopVideo(); 2277 } else { 2278 notifier.noteStopAudio(); 2279 } 2280 2281 mBatteryStatNotified = false; 2282 } 2283} 2284 2285} // namespace android 2286