MediaCodecSource.cpp revision e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049
172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang/* 272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang * Copyright 2014, The Android Open Source Project 372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang * 472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang * Licensed under the Apache License, Version 2.0 (the "License"); 572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang * you may not use this file except in compliance with the License. 672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang * You may obtain a copy of the License at 772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang * 872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang * http://www.apache.org/licenses/LICENSE-2.0 972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang * 1072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang * Unless required by applicable law or agreed to in writing, software 1172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang * distributed under the License is distributed on an "AS IS" BASIS, 1272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang * See the License for the specific language governing permissions and 1472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang * limitations under the License. 1572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang */ 1672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 1772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang//#define LOG_NDEBUG 0 1872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#define LOG_TAG "MediaCodecSource" 1972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#define DEBUG_DRIFT_TIME 0 20a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn 21a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn#include <inttypes.h> 22a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn 23e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang#include <gui/IGraphicBufferConsumer.h> 2472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <gui/IGraphicBufferProducer.h> 2572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <gui/Surface.h> 2672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/ICrypto.h> 2772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/foundation/ABuffer.h> 2872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/foundation/ADebug.h> 2972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/foundation/ALooper.h> 3072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/foundation/AMessage.h> 3172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/MediaBuffer.h> 3272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/MediaCodec.h> 33e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang#include <media/stagefright/MediaCodecSource.h> 3472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/MediaErrors.h> 3572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/MediaSource.h> 36e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang#include <media/stagefright/MetaData.h> 37e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang#include <media/stagefright/PersistentSurface.h> 3872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/Utils.h> 3972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 4072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangnamespace android { 4172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 4272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstruct MediaCodecSource::Puller : public AHandler { 4372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang Puller(const sp<MediaSource> &source); 4472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 4572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang status_t start(const sp<MetaData> &meta, const sp<AMessage> ¬ify); 4616e79115e497386eaf010af388627f94314a55a3Chong Zhang void stop(); 4772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 4872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang void pause(); 4972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang void resume(); 5072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 5172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangprotected: 5272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang virtual void onMessageReceived(const sp<AMessage> &msg); 5372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang virtual ~Puller(); 5472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 5572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangprivate: 5672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang enum { 5772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang kWhatStart = 'msta', 5872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang kWhatStop, 5972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang kWhatPull, 6072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang kWhatPause, 6172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang kWhatResume, 6272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang }; 6372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 6472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang sp<MediaSource> mSource; 6572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang sp<AMessage> mNotify; 6672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang sp<ALooper> mLooper; 6772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang int32_t mPullGeneration; 6872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang bool mIsAudio; 6972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang bool mPaused; 7072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang bool mReachedEOS; 7172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 7272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang status_t postSynchronouslyAndReturnError(const sp<AMessage> &msg); 7372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang void schedulePull(); 7472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang void handleEOS(); 7572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 7672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang DISALLOW_EVIL_CONSTRUCTORS(Puller); 7772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}; 7872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 7972cecca17d735db6532c45f0a7e10c47ee6f065aChong ZhangMediaCodecSource::Puller::Puller(const sp<MediaSource> &source) 8072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang : mSource(source), 8172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mLooper(new ALooper()), 8272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mPullGeneration(0), 8372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mIsAudio(false), 8472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mPaused(false), 8572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mReachedEOS(false) { 8672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang sp<MetaData> meta = source->getFormat(); 8772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang const char *mime; 8872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(meta->findCString(kKeyMIMEType, &mime)); 8972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 9072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mIsAudio = !strncasecmp(mime, "audio/", 6); 9172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 9272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mLooper->setName("pull_looper"); 9372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 9472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 9572cecca17d735db6532c45f0a7e10c47ee6f065aChong ZhangMediaCodecSource::Puller::~Puller() { 9672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mLooper->unregisterHandler(id()); 9772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mLooper->stop(); 9872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 9972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 10072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::Puller::postSynchronouslyAndReturnError( 10172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang const sp<AMessage> &msg) { 10272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang sp<AMessage> response; 10372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang status_t err = msg->postAndAwaitResponse(&response); 10472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 10572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (err != OK) { 10672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return err; 10772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 10872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 10972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (!response->findInt32("err", &err)) { 11072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang err = OK; 11172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 11272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 11372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return err; 11472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 11572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 11672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::Puller::start(const sp<MetaData> &meta, 11772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang const sp<AMessage> ¬ify) { 11872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang ALOGV("puller (%s) start", mIsAudio ? "audio" : "video"); 11972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mLooper->start( 12072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang false /* runOnCallingThread */, 12172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang false /* canCallJava */, 12272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang PRIORITY_AUDIO); 12372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mLooper->registerHandler(this); 12472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mNotify = notify; 12572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 1261d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar sp<AMessage> msg = new AMessage(kWhatStart, this); 12772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang msg->setObject("meta", meta); 12872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return postSynchronouslyAndReturnError(msg); 12972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 13072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 13116e79115e497386eaf010af388627f94314a55a3Chong Zhangvoid MediaCodecSource::Puller::stop() { 13216e79115e497386eaf010af388627f94314a55a3Chong Zhang // Stop source from caller's thread instead of puller's looper. 13316e79115e497386eaf010af388627f94314a55a3Chong Zhang // mSource->stop() is thread-safe, doing it outside the puller's 13416e79115e497386eaf010af388627f94314a55a3Chong Zhang // looper allows us to at least stop if source gets stuck. 13516e79115e497386eaf010af388627f94314a55a3Chong Zhang // If source gets stuck in read(), the looper would never 13616e79115e497386eaf010af388627f94314a55a3Chong Zhang // be able to process the stop(), which could lead to ANR. 13716e79115e497386eaf010af388627f94314a55a3Chong Zhang 13816e79115e497386eaf010af388627f94314a55a3Chong Zhang ALOGV("source (%s) stopping", mIsAudio ? "audio" : "video"); 13916e79115e497386eaf010af388627f94314a55a3Chong Zhang mSource->stop(); 14016e79115e497386eaf010af388627f94314a55a3Chong Zhang ALOGV("source (%s) stopped", mIsAudio ? "audio" : "video"); 14116e79115e497386eaf010af388627f94314a55a3Chong Zhang 1421d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar (new AMessage(kWhatStop, this))->post(); 14372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 14472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 14572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::Puller::pause() { 1461d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar (new AMessage(kWhatPause, this))->post(); 14772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 14872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 14972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::Puller::resume() { 1501d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar (new AMessage(kWhatResume, this))->post(); 15172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 15272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 15372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::Puller::schedulePull() { 1541d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar sp<AMessage> msg = new AMessage(kWhatPull, this); 15572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang msg->setInt32("generation", mPullGeneration); 15672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang msg->post(); 15772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 15872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 15972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::Puller::handleEOS() { 16072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (!mReachedEOS) { 16172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang ALOGV("puller (%s) posting EOS", mIsAudio ? "audio" : "video"); 16272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mReachedEOS = true; 16372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang sp<AMessage> notify = mNotify->dup(); 16472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang notify->setPointer("accessUnit", NULL); 16572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang notify->post(); 16672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 16772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 16872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 16972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::Puller::onMessageReceived(const sp<AMessage> &msg) { 17072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang switch (msg->what()) { 17172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang case kWhatStart: 17272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang { 17372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang sp<RefBase> obj; 17472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(msg->findObject("meta", &obj)); 17572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 17672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mReachedEOS = false; 17772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 17872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang status_t err = mSource->start(static_cast<MetaData *>(obj.get())); 17972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 18072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (err == OK) { 18172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang schedulePull(); 18272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 18372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 18472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang sp<AMessage> response = new AMessage; 18572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang response->setInt32("err", err); 18672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 1873f27436a9346f043f52265da1e6a74cde2bffd4dLajos Molnar sp<AReplyToken> replyID; 18872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(msg->senderAwaitsResponse(&replyID)); 18972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang response->postReply(replyID); 19072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang break; 19172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 19272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 19372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang case kWhatStop: 19472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang { 19572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang ++mPullGeneration; 19672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 19772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang handleEOS(); 19872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang break; 19972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 20072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 20172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang case kWhatPull: 20272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang { 20372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang int32_t generation; 20472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(msg->findInt32("generation", &generation)); 20572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 20672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (generation != mPullGeneration) { 20772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang break; 20872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 20972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 21072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang MediaBuffer *mbuf; 21172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang status_t err = mSource->read(&mbuf); 21272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 21372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mPaused) { 21472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (err == OK) { 21572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mbuf->release(); 21672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mbuf = NULL; 21772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 21872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 21972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang msg->post(); 22072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang break; 22172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 22272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 22372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (err != OK) { 22472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (err == ERROR_END_OF_STREAM) { 22572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang ALOGV("stream ended, mbuf %p", mbuf); 22672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } else { 22772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang ALOGE("error %d reading stream.", err); 22872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 22972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang handleEOS(); 23072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } else { 23172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang sp<AMessage> notify = mNotify->dup(); 23272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 23372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang notify->setPointer("accessUnit", mbuf); 23472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang notify->post(); 23572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 23672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang msg->post(); 23772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 23872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang break; 23972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 24072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 24172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang case kWhatPause: 24272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang { 24372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mPaused = true; 24472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang break; 24572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 24672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 24772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang case kWhatResume: 24872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang { 24972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mPaused = false; 25072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang break; 25172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 25272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 25372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang default: 25472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang TRESPASS(); 25572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 25672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 25772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 25872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang// static 25972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangsp<MediaCodecSource> MediaCodecSource::Create( 26072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang const sp<ALooper> &looper, 26172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang const sp<AMessage> &format, 26272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang const sp<MediaSource> &source, 263e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang const sp<IGraphicBufferConsumer> &consumer, 26472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang uint32_t flags) { 26572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang sp<MediaCodecSource> mediaSource = 266e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang new MediaCodecSource(looper, format, source, consumer, flags); 26772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 26872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mediaSource->init() == OK) { 26972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return mediaSource; 27072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 27172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return NULL; 27272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 27372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 27472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::start(MetaData* params) { 2751d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar sp<AMessage> msg = new AMessage(kWhatStart, mReflector); 27672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang msg->setObject("meta", params); 27772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return postSynchronouslyAndReturnError(msg); 27872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 27972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 28072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::stop() { 2811d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar sp<AMessage> msg = new AMessage(kWhatStop, mReflector); 28216e79115e497386eaf010af388627f94314a55a3Chong Zhang status_t err = postSynchronouslyAndReturnError(msg); 28316e79115e497386eaf010af388627f94314a55a3Chong Zhang 28416e79115e497386eaf010af388627f94314a55a3Chong Zhang // mPuller->stop() needs to be done outside MediaCodecSource's looper, 28516e79115e497386eaf010af388627f94314a55a3Chong Zhang // as it contains a synchronous call to stop the underlying MediaSource, 28616e79115e497386eaf010af388627f94314a55a3Chong Zhang // which often waits for all outstanding MediaBuffers to return, but 28716e79115e497386eaf010af388627f94314a55a3Chong Zhang // MediaBuffers are only returned when MediaCodecSource looper gets 28816e79115e497386eaf010af388627f94314a55a3Chong Zhang // to process them. 28916e79115e497386eaf010af388627f94314a55a3Chong Zhang 29016e79115e497386eaf010af388627f94314a55a3Chong Zhang if (mPuller != NULL) { 29116e79115e497386eaf010af388627f94314a55a3Chong Zhang ALOGI("puller (%s) stopping", mIsVideo ? "video" : "audio"); 29216e79115e497386eaf010af388627f94314a55a3Chong Zhang mPuller->stop(); 29316e79115e497386eaf010af388627f94314a55a3Chong Zhang ALOGI("puller (%s) stopped", mIsVideo ? "video" : "audio"); 29416e79115e497386eaf010af388627f94314a55a3Chong Zhang } 29516e79115e497386eaf010af388627f94314a55a3Chong Zhang 29616e79115e497386eaf010af388627f94314a55a3Chong Zhang return err; 29772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 29872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 29972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::pause() { 3001d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar (new AMessage(kWhatPause, mReflector))->post(); 30172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return OK; 30272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 30372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 30472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangsp<IGraphicBufferProducer> MediaCodecSource::getGraphicBufferProducer() { 30572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(mFlags & FLAG_USE_SURFACE_INPUT); 30672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return mGraphicBufferProducer; 30772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 30872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 30984333e0475bc911adc16417f4ca327c975cf6c36Andreas Huberstatus_t MediaCodecSource::read( 31084333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber MediaBuffer** buffer, const ReadOptions* /* options */) { 31172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang Mutex::Autolock autolock(mOutputBufferLock); 31272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 31372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang *buffer = NULL; 31416e79115e497386eaf010af388627f94314a55a3Chong Zhang while (mOutputBufferQueue.size() == 0 && !mEncoderReachedEOS) { 31572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mOutputBufferCond.wait(mOutputBufferLock); 31672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 31716e79115e497386eaf010af388627f94314a55a3Chong Zhang if (!mEncoderReachedEOS) { 31872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang *buffer = *mOutputBufferQueue.begin(); 31972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mOutputBufferQueue.erase(mOutputBufferQueue.begin()); 32072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return OK; 32172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 32272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return mErrorCode; 32372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 32472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 32572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::signalBufferReturned(MediaBuffer *buffer) { 32672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang buffer->setObserver(0); 32772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang buffer->release(); 32872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 32972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 33072cecca17d735db6532c45f0a7e10c47ee6f065aChong ZhangMediaCodecSource::MediaCodecSource( 33172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang const sp<ALooper> &looper, 33272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang const sp<AMessage> &outputFormat, 33372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang const sp<MediaSource> &source, 334e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang const sp<IGraphicBufferConsumer> &consumer, 33572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang uint32_t flags) 33672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang : mLooper(looper), 33772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mOutputFormat(outputFormat), 33872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mMeta(new MetaData), 33972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mFlags(flags), 34072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mIsVideo(false), 34172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mStarted(false), 34272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mStopping(false), 34372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mDoMoreWorkPending(false), 344e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang mGraphicBufferConsumer(consumer), 34572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mFirstSampleTimeUs(-1ll), 34616e79115e497386eaf010af388627f94314a55a3Chong Zhang mEncoderReachedEOS(false), 34772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mErrorCode(OK) { 34872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(mLooper != NULL); 34972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 35072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang AString mime; 35172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(mOutputFormat->findString("mime", &mime)); 35272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 35372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (!strncasecmp("video/", mime.c_str(), 6)) { 35472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mIsVideo = true; 35572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 35672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 35772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (!(mFlags & FLAG_USE_SURFACE_INPUT)) { 35872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mPuller = new Puller(source); 35972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 36072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 36172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 36272cecca17d735db6532c45f0a7e10c47ee6f065aChong ZhangMediaCodecSource::~MediaCodecSource() { 36372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang releaseEncoder(); 36472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 36572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mCodecLooper->stop(); 36672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mLooper->unregisterHandler(mReflector->id()); 36772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 36872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 36972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::init() { 37072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang status_t err = initEncoder(); 37172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 37272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (err != OK) { 37372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang releaseEncoder(); 37472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 37572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 37672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return err; 37772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 37872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 37972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::initEncoder() { 38072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mReflector = new AHandlerReflector<MediaCodecSource>(this); 38172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mLooper->registerHandler(mReflector); 38272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 38372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mCodecLooper = new ALooper; 38472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mCodecLooper->setName("codec_looper"); 38572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mCodecLooper->start(); 38672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 38772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mFlags & FLAG_USE_METADATA_INPUT) { 38872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mOutputFormat->setInt32("store-metadata-in-buffers", 1); 38972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 39072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 39172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mFlags & FLAG_USE_SURFACE_INPUT) { 39272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mOutputFormat->setInt32("create-input-buffers-suspended", 1); 39372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 39472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 39572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang AString outputMIME; 39672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(mOutputFormat->findString("mime", &outputMIME)); 39772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 39872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mEncoder = MediaCodec::CreateByType( 39972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mCodecLooper, outputMIME.c_str(), true /* encoder */); 40072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 40172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mEncoder == NULL) { 40272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return NO_INIT; 40372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 40472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 40572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang ALOGV("output format is '%s'", mOutputFormat->debugString(0).c_str()); 40672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 407421f47ca9c2dcc78584b2bb609c3755483b55155Marco Nelissen mEncoderActivityNotify = new AMessage(kWhatEncoderActivity, mReflector); 408421f47ca9c2dcc78584b2bb609c3755483b55155Marco Nelissen mEncoder->setCallback(mEncoderActivityNotify); 409421f47ca9c2dcc78584b2bb609c3755483b55155Marco Nelissen 41072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang status_t err = mEncoder->configure( 41172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mOutputFormat, 41272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang NULL /* nativeWindow */, 41372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang NULL /* crypto */, 41472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang MediaCodec::CONFIGURE_FLAG_ENCODE); 41572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 41672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (err != OK) { 41772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return err; 41872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 41972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 42072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mEncoder->getOutputFormat(&mOutputFormat); 42172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang convertMessageToMetaData(mOutputFormat, mMeta); 42272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 42372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mFlags & FLAG_USE_SURFACE_INPUT) { 42472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(mIsVideo); 42572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 426e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang if (mGraphicBufferConsumer != NULL) { 427e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang // When using persistent surface, we are only interested in the 428e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang // consumer, but have to use PersistentSurface as a wrapper to 429e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang // pass consumer over messages (similar to BufferProducerWrapper) 430e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang err = mEncoder->usePersistentInputSurface( 431e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang new PersistentSurface(NULL, mGraphicBufferConsumer)); 432e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang } else { 433e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang err = mEncoder->createInputSurface(&mGraphicBufferProducer); 434e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang } 43572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 43672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (err != OK) { 43772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return err; 43872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 43972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 44072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 4411099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan err = mEncoder->start(); 44272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 44372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (err != OK) { 44472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return err; 44572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 44672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 44716e79115e497386eaf010af388627f94314a55a3Chong Zhang mEncoderReachedEOS = false; 44872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mErrorCode = OK; 44972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 45072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return OK; 45172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 45272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 45372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::releaseEncoder() { 45472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mEncoder == NULL) { 45572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return; 45672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 45772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 45872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mEncoder->release(); 45972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mEncoder.clear(); 46072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 46172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang while (!mInputBufferQueue.empty()) { 46272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang MediaBuffer *mbuf = *mInputBufferQueue.begin(); 46372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mInputBufferQueue.erase(mInputBufferQueue.begin()); 46472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mbuf != NULL) { 46572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mbuf->release(); 46672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 46772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 46872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 46972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 47072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::postSynchronouslyAndReturnError( 47172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang const sp<AMessage> &msg) { 47272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang sp<AMessage> response; 47372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang status_t err = msg->postAndAwaitResponse(&response); 47472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 47572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (err != OK) { 47672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return err; 47772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 47872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 47972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (!response->findInt32("err", &err)) { 48072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang err = OK; 48172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 48272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 48372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return err; 48472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 48572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 48672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::signalEOS(status_t err) { 48716e79115e497386eaf010af388627f94314a55a3Chong Zhang if (!mEncoderReachedEOS) { 48816e79115e497386eaf010af388627f94314a55a3Chong Zhang ALOGV("encoder (%s) reached EOS", mIsVideo ? "video" : "audio"); 48972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang { 49072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang Mutex::Autolock autoLock(mOutputBufferLock); 49172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang // release all unread media buffers 49272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang for (List<MediaBuffer*>::iterator it = mOutputBufferQueue.begin(); 49372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang it != mOutputBufferQueue.end(); it++) { 49472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang (*it)->release(); 49572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 49672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mOutputBufferQueue.clear(); 49716e79115e497386eaf010af388627f94314a55a3Chong Zhang mEncoderReachedEOS = true; 49872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mErrorCode = err; 49972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mOutputBufferCond.signal(); 50072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 50172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 50272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang releaseEncoder(); 50372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 50416e79115e497386eaf010af388627f94314a55a3Chong Zhang if (mStopping && mEncoderReachedEOS) { 50516e79115e497386eaf010af388627f94314a55a3Chong Zhang ALOGI("encoder (%s) stopped", mIsVideo ? "video" : "audio"); 50672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang // posting reply to everyone that's waiting 5073f27436a9346f043f52265da1e6a74cde2bffd4dLajos Molnar List<sp<AReplyToken>>::iterator it; 50872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang for (it = mStopReplyIDQueue.begin(); 50972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang it != mStopReplyIDQueue.end(); it++) { 51072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang (new AMessage)->postReply(*it); 51172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 51272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mStopReplyIDQueue.clear(); 51372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mStopping = false; 51472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 51572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 51672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 51772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::suspend() { 51872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(mFlags & FLAG_USE_SURFACE_INPUT); 51972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mEncoder != NULL) { 52072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang sp<AMessage> params = new AMessage; 52172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang params->setInt32("drop-input-frames", true); 52272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mEncoder->setParameters(params); 52372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 52472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 52572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 52672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::resume(int64_t skipFramesBeforeUs) { 52772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(mFlags & FLAG_USE_SURFACE_INPUT); 52872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mEncoder != NULL) { 52972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang sp<AMessage> params = new AMessage; 53072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang params->setInt32("drop-input-frames", false); 53172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (skipFramesBeforeUs > 0) { 53272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang params->setInt64("skip-frames-before", skipFramesBeforeUs); 53372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 53472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mEncoder->setParameters(params); 53572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 53672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 53772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 53872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::feedEncoderInputBuffers() { 53972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang while (!mInputBufferQueue.empty() 54072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang && !mAvailEncoderInputIndices.empty()) { 54172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang MediaBuffer* mbuf = *mInputBufferQueue.begin(); 54272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mInputBufferQueue.erase(mInputBufferQueue.begin()); 54372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 54472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang size_t bufferIndex = *mAvailEncoderInputIndices.begin(); 54572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mAvailEncoderInputIndices.erase(mAvailEncoderInputIndices.begin()); 54672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 54772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang int64_t timeUs = 0ll; 54872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang uint32_t flags = 0; 54972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang size_t size = 0; 55072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 55172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mbuf != NULL) { 55272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(mbuf->meta_data()->findInt64(kKeyTime, &timeUs)); 55372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 55472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang // push decoding time for video, or drift time for audio 55572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mIsVideo) { 55672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mDecodingTimeQueue.push_back(timeUs); 55772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } else { 55872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#if DEBUG_DRIFT_TIME 55972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mFirstSampleTimeUs < 0ll) { 56072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mFirstSampleTimeUs = timeUs; 56172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 56272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 56372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang int64_t driftTimeUs = 0; 56472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mbuf->meta_data()->findInt64(kKeyDriftTime, &driftTimeUs) 56572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang && driftTimeUs) { 56672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang driftTimeUs = timeUs - mFirstSampleTimeUs - driftTimeUs; 56772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 56872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mDriftTimeQueue.push_back(driftTimeUs); 56972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#endif // DEBUG_DRIFT_TIME 57072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 57172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 5721099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan sp<ABuffer> inbuf; 5731099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan status_t err = mEncoder->getInputBuffer(bufferIndex, &inbuf); 5741099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan if (err != OK || inbuf == NULL) { 5751099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan mbuf->release(); 5761099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan signalEOS(); 5771099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan break; 5781099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan } 5791099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan 58072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang size = mbuf->size(); 58172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 5821099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan memcpy(inbuf->data(), mbuf->data(), size); 58372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 58472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mIsVideo) { 58572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang // video encoder will release MediaBuffer when done 58672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang // with underlying data. 5871099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan inbuf->setMediaBufferBase(mbuf); 58872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } else { 58972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mbuf->release(); 59072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 59172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } else { 59272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang flags = MediaCodec::BUFFER_FLAG_EOS; 59372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 59472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 59572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang status_t err = mEncoder->queueInputBuffer( 59672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang bufferIndex, 0, size, timeUs, flags); 59772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 59872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (err != OK) { 59972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return err; 60072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 60172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 60272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 60372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return OK; 60472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 60572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 60672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::onStart(MetaData *params) { 60772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mStopping) { 60872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang ALOGE("Failed to start while we're stopping"); 60972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return INVALID_OPERATION; 61072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 61172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 61272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mStarted) { 61372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang ALOGI("MediaCodecSource (%s) resuming", mIsVideo ? "video" : "audio"); 61472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mFlags & FLAG_USE_SURFACE_INPUT) { 61572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang resume(); 61672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } else { 61772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(mPuller != NULL); 61872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mPuller->resume(); 61972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 62072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return OK; 62172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 62272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 62372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang ALOGI("MediaCodecSource (%s) starting", mIsVideo ? "video" : "audio"); 62472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 62572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang status_t err = OK; 62672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 62772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mFlags & FLAG_USE_SURFACE_INPUT) { 62872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang int64_t startTimeUs; 62972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (!params || !params->findInt64(kKeyTime, &startTimeUs)) { 63072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang startTimeUs = -1ll; 63172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 63272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang resume(startTimeUs); 63372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } else { 63472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(mPuller != NULL); 6351d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar sp<AMessage> notify = new AMessage(kWhatPullerNotify, mReflector); 63672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang err = mPuller->start(params, notify); 63772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (err != OK) { 63872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return err; 63972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 64072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 64172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 64272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang ALOGI("MediaCodecSource (%s) started", mIsVideo ? "video" : "audio"); 64372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 64472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mStarted = true; 64572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return OK; 64672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 64772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 64872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::onMessageReceived(const sp<AMessage> &msg) { 64972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang switch (msg->what()) { 65072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang case kWhatPullerNotify: 65172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang { 65272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang MediaBuffer *mbuf; 65372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(msg->findPointer("accessUnit", (void**)&mbuf)); 65472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 65572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mbuf == NULL) { 65616e79115e497386eaf010af388627f94314a55a3Chong Zhang ALOGV("puller (%s) reached EOS", 65772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mIsVideo ? "video" : "audio"); 65816e79115e497386eaf010af388627f94314a55a3Chong Zhang signalEOS(); 65972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 66072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 66172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mEncoder == NULL) { 66272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang ALOGV("got msg '%s' after encoder shutdown.", 66372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang msg->debugString().c_str()); 66472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 66572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mbuf != NULL) { 66672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mbuf->release(); 66772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 66816e79115e497386eaf010af388627f94314a55a3Chong Zhang 66972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang break; 67072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 67172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 67272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mInputBufferQueue.push_back(mbuf); 67372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 67472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang feedEncoderInputBuffers(); 67572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 67672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang break; 67772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 67872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang case kWhatEncoderActivity: 67972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang { 68072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mEncoder == NULL) { 68172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang break; 68272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 68372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 6841099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan int32_t cbID; 6851099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan CHECK(msg->findInt32("callbackID", &cbID)); 6861099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan if (cbID == MediaCodec::CB_INPUT_AVAILABLE) { 6871099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan int32_t index; 6881099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan CHECK(msg->findInt32("index", &index)); 6891099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan 6901099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan mAvailEncoderInputIndices.push_back(index); 6911099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan feedEncoderInputBuffers(); 6921099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan } else if (cbID == MediaCodec::CB_OUTPUT_AVAILABLE) { 6931099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan int32_t index; 6941099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan size_t offset; 6951099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan size_t size; 6961099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan int64_t timeUs; 6971099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan int32_t flags; 6981099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan 6991099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan CHECK(msg->findInt32("index", &index)); 7001099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan CHECK(msg->findSize("offset", &offset)); 7011099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan CHECK(msg->findSize("size", &size)); 7021099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan CHECK(msg->findInt64("timeUs", &timeUs)); 7031099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan CHECK(msg->findInt32("flags", &flags)); 7041099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan 7051099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan if (flags & MediaCodec::BUFFER_FLAG_EOS) { 7061099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan mEncoder->releaseOutputBuffer(index); 7071099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan signalEOS(); 7081099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan break; 7091099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan } 710f2a64852a4a48c5a3d8a08ffcda20d6884586672Chong Zhang 7111099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan sp<ABuffer> outbuf; 7121099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan status_t err = mEncoder->getOutputBuffer(index, &outbuf); 7131099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan if (err != OK || outbuf == NULL) { 7141099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan signalEOS(); 7151099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan break; 7161099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan } 717f2a64852a4a48c5a3d8a08ffcda20d6884586672Chong Zhang 7181099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan MediaBuffer *mbuf = new MediaBuffer(outbuf->size()); 7191099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan memcpy(mbuf->data(), outbuf->data(), outbuf->size()); 72072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 7211099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan if (!(flags & MediaCodec::BUFFER_FLAG_CODECCONFIG)) { 7221099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan if (mIsVideo) { 7231099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan int64_t decodingTimeUs; 7241099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan if (mFlags & FLAG_USE_SURFACE_INPUT) { 7251099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan // GraphicBufferSource is supposed to discard samples 7261099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan // queued before start, and offset timeUs by start time 7271099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan CHECK_GE(timeUs, 0ll); 7281099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan // TODO: 7291099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan // Decoding time for surface source is unavailable, 7301099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan // use presentation time for now. May need to move 7311099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan // this logic into MediaCodec. 7321099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan decodingTimeUs = timeUs; 7331099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan } else { 7341099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan CHECK(!mDecodingTimeQueue.empty()); 7351099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan decodingTimeUs = *(mDecodingTimeQueue.begin()); 7361099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan mDecodingTimeQueue.erase(mDecodingTimeQueue.begin()); 7371099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan } 7381099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan mbuf->meta_data()->setInt64(kKeyDecodingTime, decodingTimeUs); 73972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 7401099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan ALOGV("[video] time %" PRId64 " us (%.2f secs), dts/pts diff %" PRId64, 7411099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan timeUs, timeUs / 1E6, decodingTimeUs - timeUs); 7421099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan } else { 7431099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan int64_t driftTimeUs = 0; 7441099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan#if DEBUG_DRIFT_TIME 7451099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan CHECK(!mDriftTimeQueue.empty()); 7461099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan driftTimeUs = *(mDriftTimeQueue.begin()); 7471099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan mDriftTimeQueue.erase(mDriftTimeQueue.begin()); 7481099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan mbuf->meta_data()->setInt64(kKeyDriftTime, driftTimeUs); 7491099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan#endif // DEBUG_DRIFT_TIME 7501099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan ALOGV("[audio] time %" PRId64 " us (%.2f secs), drift %" PRId64, 7511099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan timeUs, timeUs / 1E6, driftTimeUs); 7521099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan } 7531099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan mbuf->meta_data()->setInt64(kKeyTime, timeUs); 7541099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan } else { 7551099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan mbuf->meta_data()->setInt32(kKeyIsCodecConfig, true); 7561099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan } 7571099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan if (flags & MediaCodec::BUFFER_FLAG_SYNCFRAME) { 7581099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan mbuf->meta_data()->setInt32(kKeyIsSyncFrame, true); 7591099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan } 7601099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan mbuf->setObserver(this); 7611099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan mbuf->add_ref(); 7621099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan 7631099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan { 7641099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan Mutex::Autolock autoLock(mOutputBufferLock); 7651099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan mOutputBufferQueue.push_back(mbuf); 7661099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan mOutputBufferCond.signal(); 7671099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan } 7681099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan 7691099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan mEncoder->releaseOutputBuffer(index); 7701099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan } else if (cbID == MediaCodec::CB_ERROR) { 7711099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan status_t err; 7721099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan CHECK(msg->findInt32("err", &err)); 7731099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan ALOGE("Encoder (%s) reported error : 0x%x", 7741099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan mIsVideo ? "video" : "audio", err); 7751099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan signalEOS(); 7761099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan } 7771099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan break; 77872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 77972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang case kWhatStart: 78072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang { 7813f27436a9346f043f52265da1e6a74cde2bffd4dLajos Molnar sp<AReplyToken> replyID; 78272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(msg->senderAwaitsResponse(&replyID)); 78372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 78472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang sp<RefBase> obj; 78572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(msg->findObject("meta", &obj)); 78672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang MetaData *params = static_cast<MetaData *>(obj.get()); 78772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 78872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang sp<AMessage> response = new AMessage; 78972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang response->setInt32("err", onStart(params)); 79072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang response->postReply(replyID); 79172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang break; 79272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 79372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang case kWhatStop: 79472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang { 79516e79115e497386eaf010af388627f94314a55a3Chong Zhang ALOGI("encoder (%s) stopping", mIsVideo ? "video" : "audio"); 79672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 7973f27436a9346f043f52265da1e6a74cde2bffd4dLajos Molnar sp<AReplyToken> replyID; 79872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(msg->senderAwaitsResponse(&replyID)); 79972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 80016e79115e497386eaf010af388627f94314a55a3Chong Zhang if (mEncoderReachedEOS) { 80172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang // if we already reached EOS, reply and return now 80216e79115e497386eaf010af388627f94314a55a3Chong Zhang ALOGI("encoder (%s) already stopped", 80372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mIsVideo ? "video" : "audio"); 80472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang (new AMessage)->postReply(replyID); 80572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang break; 80672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 80772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 80872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mStopReplyIDQueue.push_back(replyID); 80972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mStopping) { 81072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang // nothing to do if we're already stopping, reply will be posted 81172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang // to all when we're stopped. 81272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang break; 81372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 81472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 81572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mStopping = true; 81672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 81772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang // if using surface, signal source EOS and wait for EOS to come back. 81872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang // otherwise, release encoder and post EOS if haven't done already 81972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mFlags & FLAG_USE_SURFACE_INPUT) { 82072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mEncoder->signalEndOfInputStream(); 82172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } else { 82272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang signalEOS(); 82372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 82472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang break; 82572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 82672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang case kWhatPause: 82772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang { 82872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mFlags && FLAG_USE_SURFACE_INPUT) { 82972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang suspend(); 83072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } else { 83172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(mPuller != NULL); 83272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mPuller->pause(); 83372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 83472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang break; 83572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 83672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang default: 83772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang TRESPASS(); 83872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 83972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 84072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 84172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} // namespace android 842