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 2372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <gui/IGraphicBufferProducer.h> 2472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <gui/Surface.h> 2572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/ICrypto.h> 2672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/foundation/ABuffer.h> 2772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/foundation/ADebug.h> 2872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/foundation/ALooper.h> 2972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/foundation/AMessage.h> 3072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/MediaBuffer.h> 3172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/MediaCodec.h> 3272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/MetaData.h> 3372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/MediaErrors.h> 3472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/MediaSource.h> 3572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/MediaCodecSource.h> 3672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/Utils.h> 3772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 3872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangnamespace android { 3972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 4072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstruct MediaCodecSource::Puller : public AHandler { 4172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang Puller(const sp<MediaSource> &source); 4272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 4372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang status_t start(const sp<MetaData> &meta, const sp<AMessage> ¬ify); 4416e79115e497386eaf010af388627f94314a55a3Chong Zhang void stop(); 4572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 4672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang void pause(); 4772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang void resume(); 4872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 4972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangprotected: 5072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang virtual void onMessageReceived(const sp<AMessage> &msg); 5172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang virtual ~Puller(); 5272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 5372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangprivate: 5472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang enum { 5572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang kWhatStart = 'msta', 5672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang kWhatStop, 5772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang kWhatPull, 5872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang kWhatPause, 5972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang kWhatResume, 6072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang }; 6172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 6272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang sp<MediaSource> mSource; 6372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang sp<AMessage> mNotify; 6472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang sp<ALooper> mLooper; 6572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang int32_t mPullGeneration; 6672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang bool mIsAudio; 6772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang bool mPaused; 6872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang bool mReachedEOS; 6972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 7072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang status_t postSynchronouslyAndReturnError(const sp<AMessage> &msg); 7172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang void schedulePull(); 7272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang void handleEOS(); 7372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 7472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang DISALLOW_EVIL_CONSTRUCTORS(Puller); 7572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}; 7672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 7772cecca17d735db6532c45f0a7e10c47ee6f065aChong ZhangMediaCodecSource::Puller::Puller(const sp<MediaSource> &source) 7872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang : mSource(source), 7972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mLooper(new ALooper()), 8072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mPullGeneration(0), 8172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mIsAudio(false), 8272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mPaused(false), 8372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mReachedEOS(false) { 8472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang sp<MetaData> meta = source->getFormat(); 8572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang const char *mime; 8672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(meta->findCString(kKeyMIMEType, &mime)); 8772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 8872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mIsAudio = !strncasecmp(mime, "audio/", 6); 8972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 9072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mLooper->setName("pull_looper"); 9172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 9272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 9372cecca17d735db6532c45f0a7e10c47ee6f065aChong ZhangMediaCodecSource::Puller::~Puller() { 9472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mLooper->unregisterHandler(id()); 9572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mLooper->stop(); 9672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 9772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 9872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::Puller::postSynchronouslyAndReturnError( 9972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang const sp<AMessage> &msg) { 10072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang sp<AMessage> response; 10172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang status_t err = msg->postAndAwaitResponse(&response); 10272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 10372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (err != OK) { 10472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return err; 10572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 10672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 10772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (!response->findInt32("err", &err)) { 10872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang err = OK; 10972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 11072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 11172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return err; 11272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 11372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 11472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::Puller::start(const sp<MetaData> &meta, 11572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang const sp<AMessage> ¬ify) { 11672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang ALOGV("puller (%s) start", mIsAudio ? "audio" : "video"); 11772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mLooper->start( 11872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang false /* runOnCallingThread */, 11972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang false /* canCallJava */, 12072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang PRIORITY_AUDIO); 12172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mLooper->registerHandler(this); 12272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mNotify = notify; 12372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 12472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang sp<AMessage> msg = new AMessage(kWhatStart, id()); 12572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang msg->setObject("meta", meta); 12672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return postSynchronouslyAndReturnError(msg); 12772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 12872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 12916e79115e497386eaf010af388627f94314a55a3Chong Zhangvoid MediaCodecSource::Puller::stop() { 13016e79115e497386eaf010af388627f94314a55a3Chong Zhang // Stop source from caller's thread instead of puller's looper. 13116e79115e497386eaf010af388627f94314a55a3Chong Zhang // mSource->stop() is thread-safe, doing it outside the puller's 13216e79115e497386eaf010af388627f94314a55a3Chong Zhang // looper allows us to at least stop if source gets stuck. 13316e79115e497386eaf010af388627f94314a55a3Chong Zhang // If source gets stuck in read(), the looper would never 13416e79115e497386eaf010af388627f94314a55a3Chong Zhang // be able to process the stop(), which could lead to ANR. 13516e79115e497386eaf010af388627f94314a55a3Chong Zhang 13616e79115e497386eaf010af388627f94314a55a3Chong Zhang ALOGV("source (%s) stopping", mIsAudio ? "audio" : "video"); 13716e79115e497386eaf010af388627f94314a55a3Chong Zhang mSource->stop(); 13816e79115e497386eaf010af388627f94314a55a3Chong Zhang ALOGV("source (%s) stopped", mIsAudio ? "audio" : "video"); 13916e79115e497386eaf010af388627f94314a55a3Chong Zhang 14072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang (new AMessage(kWhatStop, id()))->post(); 14172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 14272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 14372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::Puller::pause() { 14472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang (new AMessage(kWhatPause, id()))->post(); 14572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 14672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 14772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::Puller::resume() { 14872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang (new AMessage(kWhatResume, id()))->post(); 14972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 15072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 15172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::Puller::schedulePull() { 15272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang sp<AMessage> msg = new AMessage(kWhatPull, id()); 15372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang msg->setInt32("generation", mPullGeneration); 15472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang msg->post(); 15572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 15672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 15772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::Puller::handleEOS() { 15872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (!mReachedEOS) { 15972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang ALOGV("puller (%s) posting EOS", mIsAudio ? "audio" : "video"); 16072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mReachedEOS = true; 16172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang sp<AMessage> notify = mNotify->dup(); 16272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang notify->setPointer("accessUnit", NULL); 16372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang notify->post(); 16472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 16572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 16672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 16772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::Puller::onMessageReceived(const sp<AMessage> &msg) { 16872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang switch (msg->what()) { 16972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang case kWhatStart: 17072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang { 17172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang sp<RefBase> obj; 17272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(msg->findObject("meta", &obj)); 17372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 17472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mReachedEOS = false; 17572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 17672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang status_t err = mSource->start(static_cast<MetaData *>(obj.get())); 17772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 17872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (err == OK) { 17972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang schedulePull(); 18072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 18172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 18272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang sp<AMessage> response = new AMessage; 18372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang response->setInt32("err", err); 18472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 18572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang uint32_t replyID; 18672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(msg->senderAwaitsResponse(&replyID)); 18772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang response->postReply(replyID); 18872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang break; 18972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 19072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 19172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang case kWhatStop: 19272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang { 19372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang ++mPullGeneration; 19472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 19572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang handleEOS(); 19672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang break; 19772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 19872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 19972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang case kWhatPull: 20072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang { 20172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang int32_t generation; 20272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(msg->findInt32("generation", &generation)); 20372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 20472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (generation != mPullGeneration) { 20572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang break; 20672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 20772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 20872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang MediaBuffer *mbuf; 20972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang status_t err = mSource->read(&mbuf); 21072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 21172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mPaused) { 21272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (err == OK) { 21372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mbuf->release(); 21472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mbuf = NULL; 21572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 21672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 21772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang msg->post(); 21872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang break; 21972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 22072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 22172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (err != OK) { 22272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (err == ERROR_END_OF_STREAM) { 22372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang ALOGV("stream ended, mbuf %p", mbuf); 22472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } else { 22572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang ALOGE("error %d reading stream.", err); 22672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 22772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang handleEOS(); 22872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } else { 22972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang sp<AMessage> notify = mNotify->dup(); 23072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 23172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang notify->setPointer("accessUnit", mbuf); 23272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang notify->post(); 23372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 23472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang msg->post(); 23572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 23672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang break; 23772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 23872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 23972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang case kWhatPause: 24072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang { 24172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mPaused = true; 24272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang break; 24372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 24472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 24572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang case kWhatResume: 24672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang { 24772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mPaused = false; 24872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang break; 24972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 25072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 25172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang default: 25272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang TRESPASS(); 25372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 25472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 25572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 25672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang// static 25772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangsp<MediaCodecSource> MediaCodecSource::Create( 25872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang const sp<ALooper> &looper, 25972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang const sp<AMessage> &format, 26072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang const sp<MediaSource> &source, 26172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang uint32_t flags) { 26272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang sp<MediaCodecSource> mediaSource = 26372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang new MediaCodecSource(looper, format, source, flags); 26472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 26572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mediaSource->init() == OK) { 26672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return mediaSource; 26772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 26872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return NULL; 26972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 27072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 27172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::start(MetaData* params) { 27272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang sp<AMessage> msg = new AMessage(kWhatStart, mReflector->id()); 27372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang msg->setObject("meta", params); 27472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return postSynchronouslyAndReturnError(msg); 27572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 27672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 27772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::stop() { 27872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang sp<AMessage> msg = new AMessage(kWhatStop, mReflector->id()); 27916e79115e497386eaf010af388627f94314a55a3Chong Zhang status_t err = postSynchronouslyAndReturnError(msg); 28016e79115e497386eaf010af388627f94314a55a3Chong Zhang 28116e79115e497386eaf010af388627f94314a55a3Chong Zhang // mPuller->stop() needs to be done outside MediaCodecSource's looper, 28216e79115e497386eaf010af388627f94314a55a3Chong Zhang // as it contains a synchronous call to stop the underlying MediaSource, 28316e79115e497386eaf010af388627f94314a55a3Chong Zhang // which often waits for all outstanding MediaBuffers to return, but 28416e79115e497386eaf010af388627f94314a55a3Chong Zhang // MediaBuffers are only returned when MediaCodecSource looper gets 28516e79115e497386eaf010af388627f94314a55a3Chong Zhang // to process them. 28616e79115e497386eaf010af388627f94314a55a3Chong Zhang 28716e79115e497386eaf010af388627f94314a55a3Chong Zhang if (mPuller != NULL) { 28816e79115e497386eaf010af388627f94314a55a3Chong Zhang ALOGI("puller (%s) stopping", mIsVideo ? "video" : "audio"); 28916e79115e497386eaf010af388627f94314a55a3Chong Zhang mPuller->stop(); 29016e79115e497386eaf010af388627f94314a55a3Chong Zhang ALOGI("puller (%s) stopped", mIsVideo ? "video" : "audio"); 29116e79115e497386eaf010af388627f94314a55a3Chong Zhang } 29216e79115e497386eaf010af388627f94314a55a3Chong Zhang 29316e79115e497386eaf010af388627f94314a55a3Chong Zhang return err; 29472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 29572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 29672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::pause() { 29772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang (new AMessage(kWhatPause, mReflector->id()))->post(); 29872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return OK; 29972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 30072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 30172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangsp<IGraphicBufferProducer> MediaCodecSource::getGraphicBufferProducer() { 30272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(mFlags & FLAG_USE_SURFACE_INPUT); 30372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return mGraphicBufferProducer; 30472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 30572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 30684333e0475bc911adc16417f4ca327c975cf6c36Andreas Huberstatus_t MediaCodecSource::read( 30784333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber MediaBuffer** buffer, const ReadOptions* /* options */) { 30872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang Mutex::Autolock autolock(mOutputBufferLock); 30972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 31072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang *buffer = NULL; 31116e79115e497386eaf010af388627f94314a55a3Chong Zhang while (mOutputBufferQueue.size() == 0 && !mEncoderReachedEOS) { 31272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mOutputBufferCond.wait(mOutputBufferLock); 31372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 31416e79115e497386eaf010af388627f94314a55a3Chong Zhang if (!mEncoderReachedEOS) { 31572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang *buffer = *mOutputBufferQueue.begin(); 31672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mOutputBufferQueue.erase(mOutputBufferQueue.begin()); 31772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return OK; 31872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 31972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return mErrorCode; 32072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 32172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 32272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::signalBufferReturned(MediaBuffer *buffer) { 32372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang buffer->setObserver(0); 32472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang buffer->release(); 32572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 32672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 32772cecca17d735db6532c45f0a7e10c47ee6f065aChong ZhangMediaCodecSource::MediaCodecSource( 32872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang const sp<ALooper> &looper, 32972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang const sp<AMessage> &outputFormat, 33072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang const sp<MediaSource> &source, 33172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang uint32_t flags) 33272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang : mLooper(looper), 33372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mOutputFormat(outputFormat), 33472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mMeta(new MetaData), 33572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mFlags(flags), 33672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mIsVideo(false), 33772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mStarted(false), 33872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mStopping(false), 33972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mDoMoreWorkPending(false), 34072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mFirstSampleTimeUs(-1ll), 34116e79115e497386eaf010af388627f94314a55a3Chong Zhang mEncoderReachedEOS(false), 34272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mErrorCode(OK) { 34372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(mLooper != NULL); 34472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 34572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang AString mime; 34672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(mOutputFormat->findString("mime", &mime)); 34772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 34872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (!strncasecmp("video/", mime.c_str(), 6)) { 34972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mIsVideo = true; 35072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 35172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 35272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (!(mFlags & FLAG_USE_SURFACE_INPUT)) { 35372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mPuller = new Puller(source); 35472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 35572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 35672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 35772cecca17d735db6532c45f0a7e10c47ee6f065aChong ZhangMediaCodecSource::~MediaCodecSource() { 35872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang releaseEncoder(); 35972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 36072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mCodecLooper->stop(); 36172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mLooper->unregisterHandler(mReflector->id()); 36272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 36372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 36472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::init() { 36572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang status_t err = initEncoder(); 36672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 36772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (err != OK) { 36872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang releaseEncoder(); 36972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 37072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 37172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return err; 37272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 37372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 37472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::initEncoder() { 37572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mReflector = new AHandlerReflector<MediaCodecSource>(this); 37672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mLooper->registerHandler(mReflector); 37772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 37872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mCodecLooper = new ALooper; 37972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mCodecLooper->setName("codec_looper"); 38072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mCodecLooper->start(); 38172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 38272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mFlags & FLAG_USE_METADATA_INPUT) { 38372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mOutputFormat->setInt32("store-metadata-in-buffers", 1); 38472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 38572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 38672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mFlags & FLAG_USE_SURFACE_INPUT) { 38772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mOutputFormat->setInt32("create-input-buffers-suspended", 1); 38872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 38972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 39072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang AString outputMIME; 39172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(mOutputFormat->findString("mime", &outputMIME)); 39272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 39372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mEncoder = MediaCodec::CreateByType( 39472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mCodecLooper, outputMIME.c_str(), true /* encoder */); 39572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 39672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mEncoder == NULL) { 39772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return NO_INIT; 39872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 39972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 40072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang ALOGV("output format is '%s'", mOutputFormat->debugString(0).c_str()); 40172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 40272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang status_t err = mEncoder->configure( 40372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mOutputFormat, 40472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang NULL /* nativeWindow */, 40572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang NULL /* crypto */, 40672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang MediaCodec::CONFIGURE_FLAG_ENCODE); 40772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 40872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (err != OK) { 40972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return err; 41072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 41172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 41272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mEncoder->getOutputFormat(&mOutputFormat); 41372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang convertMessageToMetaData(mOutputFormat, mMeta); 41472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 41572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mFlags & FLAG_USE_SURFACE_INPUT) { 41672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(mIsVideo); 41772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 41872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang err = mEncoder->createInputSurface(&mGraphicBufferProducer); 41972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 42072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (err != OK) { 42172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return err; 42272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 42372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 42472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 4251099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan mEncoderActivityNotify = new AMessage( 4261099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan kWhatEncoderActivity, mReflector->id()); 4271099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan mEncoder->setCallback(mEncoderActivityNotify); 42872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 4291099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan err = mEncoder->start(); 43072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 43172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (err != OK) { 43272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return err; 43372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 43472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 43516e79115e497386eaf010af388627f94314a55a3Chong Zhang mEncoderReachedEOS = false; 43672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mErrorCode = OK; 43772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 43872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return OK; 43972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 44072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 44172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::releaseEncoder() { 44272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mEncoder == NULL) { 44372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return; 44472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 44572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 44672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mEncoder->release(); 44772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mEncoder.clear(); 44872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 44972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang while (!mInputBufferQueue.empty()) { 45072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang MediaBuffer *mbuf = *mInputBufferQueue.begin(); 45172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mInputBufferQueue.erase(mInputBufferQueue.begin()); 45272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mbuf != NULL) { 45372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mbuf->release(); 45472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 45572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 45672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 45772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 45872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::postSynchronouslyAndReturnError( 45972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang const sp<AMessage> &msg) { 46072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang sp<AMessage> response; 46172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang status_t err = msg->postAndAwaitResponse(&response); 46272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 46372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (err != OK) { 46472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return err; 46572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 46672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 46772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (!response->findInt32("err", &err)) { 46872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang err = OK; 46972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 47072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 47172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return err; 47272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 47372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 47472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::signalEOS(status_t err) { 47516e79115e497386eaf010af388627f94314a55a3Chong Zhang if (!mEncoderReachedEOS) { 47616e79115e497386eaf010af388627f94314a55a3Chong Zhang ALOGV("encoder (%s) reached EOS", mIsVideo ? "video" : "audio"); 47772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang { 47872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang Mutex::Autolock autoLock(mOutputBufferLock); 47972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang // release all unread media buffers 48072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang for (List<MediaBuffer*>::iterator it = mOutputBufferQueue.begin(); 48172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang it != mOutputBufferQueue.end(); it++) { 48272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang (*it)->release(); 48372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 48472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mOutputBufferQueue.clear(); 48516e79115e497386eaf010af388627f94314a55a3Chong Zhang mEncoderReachedEOS = true; 48672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mErrorCode = err; 48772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mOutputBufferCond.signal(); 48872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 48972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 49072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang releaseEncoder(); 49172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 49216e79115e497386eaf010af388627f94314a55a3Chong Zhang if (mStopping && mEncoderReachedEOS) { 49316e79115e497386eaf010af388627f94314a55a3Chong Zhang ALOGI("encoder (%s) stopped", mIsVideo ? "video" : "audio"); 49472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang // posting reply to everyone that's waiting 49572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang List<uint32_t>::iterator it; 49672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang for (it = mStopReplyIDQueue.begin(); 49772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang it != mStopReplyIDQueue.end(); it++) { 49872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang (new AMessage)->postReply(*it); 49972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 50072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mStopReplyIDQueue.clear(); 50172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mStopping = false; 50272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 50372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 50472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 50572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::suspend() { 50672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(mFlags & FLAG_USE_SURFACE_INPUT); 50772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mEncoder != NULL) { 50872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang sp<AMessage> params = new AMessage; 50972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang params->setInt32("drop-input-frames", true); 51072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mEncoder->setParameters(params); 51172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 51272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 51372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 51472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::resume(int64_t skipFramesBeforeUs) { 51572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(mFlags & FLAG_USE_SURFACE_INPUT); 51672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mEncoder != NULL) { 51772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang sp<AMessage> params = new AMessage; 51872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang params->setInt32("drop-input-frames", false); 51972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (skipFramesBeforeUs > 0) { 52072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang params->setInt64("skip-frames-before", skipFramesBeforeUs); 52172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 52272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mEncoder->setParameters(params); 52372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 52472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 52572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 52672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::feedEncoderInputBuffers() { 52772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang while (!mInputBufferQueue.empty() 52872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang && !mAvailEncoderInputIndices.empty()) { 52972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang MediaBuffer* mbuf = *mInputBufferQueue.begin(); 53072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mInputBufferQueue.erase(mInputBufferQueue.begin()); 53172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 53272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang size_t bufferIndex = *mAvailEncoderInputIndices.begin(); 53372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mAvailEncoderInputIndices.erase(mAvailEncoderInputIndices.begin()); 53472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 53572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang int64_t timeUs = 0ll; 53672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang uint32_t flags = 0; 53772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang size_t size = 0; 53872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 53972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mbuf != NULL) { 54072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(mbuf->meta_data()->findInt64(kKeyTime, &timeUs)); 54172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 54272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang // push decoding time for video, or drift time for audio 54372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mIsVideo) { 54472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mDecodingTimeQueue.push_back(timeUs); 54572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } else { 54672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#if DEBUG_DRIFT_TIME 54772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mFirstSampleTimeUs < 0ll) { 54872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mFirstSampleTimeUs = timeUs; 54972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 55072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 55172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang int64_t driftTimeUs = 0; 55272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mbuf->meta_data()->findInt64(kKeyDriftTime, &driftTimeUs) 55372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang && driftTimeUs) { 55472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang driftTimeUs = timeUs - mFirstSampleTimeUs - driftTimeUs; 55572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 55672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mDriftTimeQueue.push_back(driftTimeUs); 55772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#endif // DEBUG_DRIFT_TIME 55872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 55972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 5601099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan sp<ABuffer> inbuf; 5611099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan status_t err = mEncoder->getInputBuffer(bufferIndex, &inbuf); 5621099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan if (err != OK || inbuf == NULL) { 5631099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan mbuf->release(); 5641099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan signalEOS(); 5651099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan break; 5661099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan } 5671099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan 56872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang size = mbuf->size(); 56972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 5701099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan memcpy(inbuf->data(), mbuf->data(), size); 57172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 57272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mIsVideo) { 57372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang // video encoder will release MediaBuffer when done 57472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang // with underlying data. 5751099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan inbuf->setMediaBufferBase(mbuf); 57672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } else { 57772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mbuf->release(); 57872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 57972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } else { 58072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang flags = MediaCodec::BUFFER_FLAG_EOS; 58172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 58272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 58372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang status_t err = mEncoder->queueInputBuffer( 58472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang bufferIndex, 0, size, timeUs, flags); 58572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 58672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (err != OK) { 58772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return err; 58872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 58972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 59072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 59172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return OK; 59272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 59372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 59472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::onStart(MetaData *params) { 59572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mStopping) { 59672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang ALOGE("Failed to start while we're stopping"); 59772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return INVALID_OPERATION; 59872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 59972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 60072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mStarted) { 60172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang ALOGI("MediaCodecSource (%s) resuming", mIsVideo ? "video" : "audio"); 60272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mFlags & FLAG_USE_SURFACE_INPUT) { 60372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang resume(); 60472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } else { 60572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(mPuller != NULL); 60672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mPuller->resume(); 60772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 60872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return OK; 60972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 61072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 61172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang ALOGI("MediaCodecSource (%s) starting", mIsVideo ? "video" : "audio"); 61272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 61372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang status_t err = OK; 61472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 61572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mFlags & FLAG_USE_SURFACE_INPUT) { 61672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang int64_t startTimeUs; 61772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (!params || !params->findInt64(kKeyTime, &startTimeUs)) { 61872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang startTimeUs = -1ll; 61972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 62072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang resume(startTimeUs); 62172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } else { 62272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(mPuller != NULL); 62372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang sp<AMessage> notify = new AMessage( 62472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang kWhatPullerNotify, mReflector->id()); 62572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang err = mPuller->start(params, notify); 62672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (err != OK) { 62772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return err; 62872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 62972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 63072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 63172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang ALOGI("MediaCodecSource (%s) started", mIsVideo ? "video" : "audio"); 63272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 63372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mStarted = true; 63472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return OK; 63572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 63672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 63772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::onMessageReceived(const sp<AMessage> &msg) { 63872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang switch (msg->what()) { 63972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang case kWhatPullerNotify: 64072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang { 64172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang MediaBuffer *mbuf; 64272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(msg->findPointer("accessUnit", (void**)&mbuf)); 64372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 64472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mbuf == NULL) { 64516e79115e497386eaf010af388627f94314a55a3Chong Zhang ALOGV("puller (%s) reached EOS", 64672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mIsVideo ? "video" : "audio"); 64716e79115e497386eaf010af388627f94314a55a3Chong Zhang signalEOS(); 64872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 64972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 65072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mEncoder == NULL) { 65172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang ALOGV("got msg '%s' after encoder shutdown.", 65272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang msg->debugString().c_str()); 65372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 65472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mbuf != NULL) { 65572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mbuf->release(); 65672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 65716e79115e497386eaf010af388627f94314a55a3Chong Zhang 65872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang break; 65972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 66072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 66172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mInputBufferQueue.push_back(mbuf); 66272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 66372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang feedEncoderInputBuffers(); 66472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 66572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang break; 66672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 66772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang case kWhatEncoderActivity: 66872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang { 66972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mEncoder == NULL) { 67072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang break; 67172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 67272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 6731099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan int32_t cbID; 6741099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan CHECK(msg->findInt32("callbackID", &cbID)); 6751099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan if (cbID == MediaCodec::CB_INPUT_AVAILABLE) { 6761099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan int32_t index; 6771099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan CHECK(msg->findInt32("index", &index)); 6781099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan 6791099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan mAvailEncoderInputIndices.push_back(index); 6801099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan feedEncoderInputBuffers(); 6811099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan } else if (cbID == MediaCodec::CB_OUTPUT_AVAILABLE) { 6821099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan int32_t index; 6831099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan size_t offset; 6841099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan size_t size; 6851099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan int64_t timeUs; 6861099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan int32_t flags; 6871099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan native_handle_t* handle = NULL; 6881099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan 6891099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan CHECK(msg->findInt32("index", &index)); 6901099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan CHECK(msg->findSize("offset", &offset)); 6911099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan CHECK(msg->findSize("size", &size)); 6921099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan CHECK(msg->findInt64("timeUs", &timeUs)); 6931099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan CHECK(msg->findInt32("flags", &flags)); 6941099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan 6951099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan if (flags & MediaCodec::BUFFER_FLAG_EOS) { 6961099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan mEncoder->releaseOutputBuffer(index); 6971099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan signalEOS(); 6981099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan break; 6991099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan } 700f2a64852a4a48c5a3d8a08ffcda20d6884586672Chong Zhang 7011099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan sp<ABuffer> outbuf; 7021099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan status_t err = mEncoder->getOutputBuffer(index, &outbuf); 7031099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan if (err != OK || outbuf == NULL) { 7041099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan signalEOS(); 7051099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan break; 7061099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan } 707f2a64852a4a48c5a3d8a08ffcda20d6884586672Chong Zhang 7081099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan MediaBuffer *mbuf = new MediaBuffer(outbuf->size()); 7091099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan memcpy(mbuf->data(), outbuf->data(), outbuf->size()); 71072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 7111099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan if (!(flags & MediaCodec::BUFFER_FLAG_CODECCONFIG)) { 7121099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan if (mIsVideo) { 7131099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan int64_t decodingTimeUs; 7141099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan if (mFlags & FLAG_USE_SURFACE_INPUT) { 7151099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan // GraphicBufferSource is supposed to discard samples 7161099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan // queued before start, and offset timeUs by start time 7171099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan CHECK_GE(timeUs, 0ll); 7181099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan // TODO: 7191099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan // Decoding time for surface source is unavailable, 7201099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan // use presentation time for now. May need to move 7211099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan // this logic into MediaCodec. 7221099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan decodingTimeUs = timeUs; 7231099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan } else { 7241099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan CHECK(!mDecodingTimeQueue.empty()); 7251099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan decodingTimeUs = *(mDecodingTimeQueue.begin()); 7261099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan mDecodingTimeQueue.erase(mDecodingTimeQueue.begin()); 7271099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan } 7281099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan mbuf->meta_data()->setInt64(kKeyDecodingTime, decodingTimeUs); 72972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 7301099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan ALOGV("[video] time %" PRId64 " us (%.2f secs), dts/pts diff %" PRId64, 7311099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan timeUs, timeUs / 1E6, decodingTimeUs - timeUs); 7321099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan } else { 7331099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan int64_t driftTimeUs = 0; 7341099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan#if DEBUG_DRIFT_TIME 7351099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan CHECK(!mDriftTimeQueue.empty()); 7361099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan driftTimeUs = *(mDriftTimeQueue.begin()); 7371099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan mDriftTimeQueue.erase(mDriftTimeQueue.begin()); 7381099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan mbuf->meta_data()->setInt64(kKeyDriftTime, driftTimeUs); 7391099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan#endif // DEBUG_DRIFT_TIME 7401099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan ALOGV("[audio] time %" PRId64 " us (%.2f secs), drift %" PRId64, 7411099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan timeUs, timeUs / 1E6, driftTimeUs); 7421099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan } 7431099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan mbuf->meta_data()->setInt64(kKeyTime, timeUs); 7441099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan } else { 7451099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan mbuf->meta_data()->setInt32(kKeyIsCodecConfig, true); 7461099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan } 7471099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan if (flags & MediaCodec::BUFFER_FLAG_SYNCFRAME) { 7481099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan mbuf->meta_data()->setInt32(kKeyIsSyncFrame, true); 7491099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan } 7501099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan mbuf->setObserver(this); 7511099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan mbuf->add_ref(); 7521099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan 7531099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan { 7541099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan Mutex::Autolock autoLock(mOutputBufferLock); 7551099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan mOutputBufferQueue.push_back(mbuf); 7561099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan mOutputBufferCond.signal(); 7571099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan } 7581099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan 7591099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan mEncoder->releaseOutputBuffer(index); 7601099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan } else if (cbID == MediaCodec::CB_ERROR) { 7611099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan status_t err; 7621099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan CHECK(msg->findInt32("err", &err)); 7631099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan ALOGE("Encoder (%s) reported error : 0x%x", 7641099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan mIsVideo ? "video" : "audio", err); 7651099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan signalEOS(); 7661099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan } 7671099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan break; 76872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 76972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang case kWhatStart: 77072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang { 77172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang uint32_t replyID; 77272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(msg->senderAwaitsResponse(&replyID)); 77372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 77472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang sp<RefBase> obj; 77572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(msg->findObject("meta", &obj)); 77672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang MetaData *params = static_cast<MetaData *>(obj.get()); 77772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 77872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang sp<AMessage> response = new AMessage; 77972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang response->setInt32("err", onStart(params)); 78072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang response->postReply(replyID); 78172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang break; 78272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 78372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang case kWhatStop: 78472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang { 78516e79115e497386eaf010af388627f94314a55a3Chong Zhang ALOGI("encoder (%s) stopping", mIsVideo ? "video" : "audio"); 78672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 78772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang uint32_t replyID; 78872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(msg->senderAwaitsResponse(&replyID)); 78972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 79016e79115e497386eaf010af388627f94314a55a3Chong Zhang if (mEncoderReachedEOS) { 79172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang // if we already reached EOS, reply and return now 79216e79115e497386eaf010af388627f94314a55a3Chong Zhang ALOGI("encoder (%s) already stopped", 79372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mIsVideo ? "video" : "audio"); 79472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang (new AMessage)->postReply(replyID); 79572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang break; 79672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 79772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 79872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mStopReplyIDQueue.push_back(replyID); 79972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mStopping) { 80072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang // nothing to do if we're already stopping, reply will be posted 80172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang // to all when we're stopped. 80272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang break; 80372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 80472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 80572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mStopping = true; 80672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 80772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang // if using surface, signal source EOS and wait for EOS to come back. 80872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang // otherwise, release encoder and post EOS if haven't done already 80972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mFlags & FLAG_USE_SURFACE_INPUT) { 81072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mEncoder->signalEndOfInputStream(); 81172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } else { 81272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang signalEOS(); 81372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 81472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang break; 81572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 81672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang case kWhatPause: 81772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang { 81872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mFlags && FLAG_USE_SURFACE_INPUT) { 81972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang suspend(); 82072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } else { 82172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(mPuller != NULL); 82272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mPuller->pause(); 82372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 82472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang break; 82572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 82672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang default: 82772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang TRESPASS(); 82872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 82972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 83072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 83172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} // namespace android 832