MediaCodecSource.cpp revision 16e79115e497386eaf010af388627f94314a55a3
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 Zhangstatic void ReleaseMediaBufferReference(const sp<ABuffer> &accessUnit) { 4172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang void *mbuf; 4272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (accessUnit->meta()->findPointer("mediaBuffer", &mbuf) 4372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang && mbuf != NULL) { 4472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang ALOGV("releasing mbuf %p", mbuf); 4572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 4672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang accessUnit->meta()->setPointer("mediaBuffer", NULL); 4772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 4872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang static_cast<MediaBuffer *>(mbuf)->release(); 4972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mbuf = NULL; 5072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 5172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 5272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 5372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstruct MediaCodecSource::Puller : public AHandler { 5472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang Puller(const sp<MediaSource> &source); 5572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 5672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang status_t start(const sp<MetaData> &meta, const sp<AMessage> ¬ify); 5716e79115e497386eaf010af388627f94314a55a3Chong Zhang void stop(); 5872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 5972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang void pause(); 6072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang void resume(); 6172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 6272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangprotected: 6372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang virtual void onMessageReceived(const sp<AMessage> &msg); 6472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang virtual ~Puller(); 6572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 6672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangprivate: 6772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang enum { 6872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang kWhatStart = 'msta', 6972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang kWhatStop, 7072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang kWhatPull, 7172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang kWhatPause, 7272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang kWhatResume, 7372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang }; 7472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 7572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang sp<MediaSource> mSource; 7672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang sp<AMessage> mNotify; 7772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang sp<ALooper> mLooper; 7872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang int32_t mPullGeneration; 7972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang bool mIsAudio; 8072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang bool mPaused; 8172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang bool mReachedEOS; 8272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 8372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang status_t postSynchronouslyAndReturnError(const sp<AMessage> &msg); 8472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang void schedulePull(); 8572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang void handleEOS(); 8672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 8772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang DISALLOW_EVIL_CONSTRUCTORS(Puller); 8872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}; 8972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 9072cecca17d735db6532c45f0a7e10c47ee6f065aChong ZhangMediaCodecSource::Puller::Puller(const sp<MediaSource> &source) 9172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang : mSource(source), 9272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mLooper(new ALooper()), 9372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mPullGeneration(0), 9472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mIsAudio(false), 9572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mPaused(false), 9672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mReachedEOS(false) { 9772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang sp<MetaData> meta = source->getFormat(); 9872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang const char *mime; 9972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(meta->findCString(kKeyMIMEType, &mime)); 10072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 10172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mIsAudio = !strncasecmp(mime, "audio/", 6); 10272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 10372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mLooper->setName("pull_looper"); 10472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 10572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 10672cecca17d735db6532c45f0a7e10c47ee6f065aChong ZhangMediaCodecSource::Puller::~Puller() { 10772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mLooper->unregisterHandler(id()); 10872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mLooper->stop(); 10972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 11072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 11172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::Puller::postSynchronouslyAndReturnError( 11272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang const sp<AMessage> &msg) { 11372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang sp<AMessage> response; 11472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang status_t err = msg->postAndAwaitResponse(&response); 11572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 11672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (err != OK) { 11772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return err; 11872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 11972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 12072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (!response->findInt32("err", &err)) { 12172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang err = OK; 12272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 12372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 12472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return err; 12572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 12672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 12772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::Puller::start(const sp<MetaData> &meta, 12872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang const sp<AMessage> ¬ify) { 12972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang ALOGV("puller (%s) start", mIsAudio ? "audio" : "video"); 13072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mLooper->start( 13172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang false /* runOnCallingThread */, 13272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang false /* canCallJava */, 13372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang PRIORITY_AUDIO); 13472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mLooper->registerHandler(this); 13572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mNotify = notify; 13672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 13772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang sp<AMessage> msg = new AMessage(kWhatStart, id()); 13872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang msg->setObject("meta", meta); 13972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return postSynchronouslyAndReturnError(msg); 14072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 14172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 14216e79115e497386eaf010af388627f94314a55a3Chong Zhangvoid MediaCodecSource::Puller::stop() { 14316e79115e497386eaf010af388627f94314a55a3Chong Zhang // Stop source from caller's thread instead of puller's looper. 14416e79115e497386eaf010af388627f94314a55a3Chong Zhang // mSource->stop() is thread-safe, doing it outside the puller's 14516e79115e497386eaf010af388627f94314a55a3Chong Zhang // looper allows us to at least stop if source gets stuck. 14616e79115e497386eaf010af388627f94314a55a3Chong Zhang // If source gets stuck in read(), the looper would never 14716e79115e497386eaf010af388627f94314a55a3Chong Zhang // be able to process the stop(), which could lead to ANR. 14816e79115e497386eaf010af388627f94314a55a3Chong Zhang 14916e79115e497386eaf010af388627f94314a55a3Chong Zhang ALOGV("source (%s) stopping", mIsAudio ? "audio" : "video"); 15016e79115e497386eaf010af388627f94314a55a3Chong Zhang mSource->stop(); 15116e79115e497386eaf010af388627f94314a55a3Chong Zhang ALOGV("source (%s) stopped", mIsAudio ? "audio" : "video"); 15216e79115e497386eaf010af388627f94314a55a3Chong Zhang 15372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang (new AMessage(kWhatStop, id()))->post(); 15472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 15572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 15672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::Puller::pause() { 15772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang (new AMessage(kWhatPause, id()))->post(); 15872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 15972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 16072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::Puller::resume() { 16172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang (new AMessage(kWhatResume, id()))->post(); 16272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 16372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 16472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::Puller::schedulePull() { 16572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang sp<AMessage> msg = new AMessage(kWhatPull, id()); 16672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang msg->setInt32("generation", mPullGeneration); 16772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang msg->post(); 16872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 16972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 17072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::Puller::handleEOS() { 17172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (!mReachedEOS) { 17272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang ALOGV("puller (%s) posting EOS", mIsAudio ? "audio" : "video"); 17372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mReachedEOS = true; 17472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang sp<AMessage> notify = mNotify->dup(); 17572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang notify->setPointer("accessUnit", NULL); 17672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang notify->post(); 17772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 17872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 17972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 18072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::Puller::onMessageReceived(const sp<AMessage> &msg) { 18172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang switch (msg->what()) { 18272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang case kWhatStart: 18372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang { 18472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang sp<RefBase> obj; 18572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(msg->findObject("meta", &obj)); 18672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 18772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mReachedEOS = false; 18872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 18972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang status_t err = mSource->start(static_cast<MetaData *>(obj.get())); 19072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 19172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (err == OK) { 19272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang schedulePull(); 19372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 19472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 19572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang sp<AMessage> response = new AMessage; 19672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang response->setInt32("err", err); 19772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 19872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang uint32_t replyID; 19972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(msg->senderAwaitsResponse(&replyID)); 20072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang response->postReply(replyID); 20172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang break; 20272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 20372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 20472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang case kWhatStop: 20572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang { 20672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang ++mPullGeneration; 20772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 20872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang handleEOS(); 20972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang break; 21072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 21172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 21272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang case kWhatPull: 21372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang { 21472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang int32_t generation; 21572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(msg->findInt32("generation", &generation)); 21672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 21772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (generation != mPullGeneration) { 21872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang break; 21972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 22072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 22172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang MediaBuffer *mbuf; 22272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang status_t err = mSource->read(&mbuf); 22372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 22472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mPaused) { 22572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (err == OK) { 22672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mbuf->release(); 22772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mbuf = NULL; 22872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 22972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 23072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang msg->post(); 23172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang break; 23272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 23372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 23472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (err != OK) { 23572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (err == ERROR_END_OF_STREAM) { 23672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang ALOGV("stream ended, mbuf %p", mbuf); 23772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } else { 23872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang ALOGE("error %d reading stream.", err); 23972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 24072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang handleEOS(); 24172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } else { 24272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang sp<AMessage> notify = mNotify->dup(); 24372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 24472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang notify->setPointer("accessUnit", mbuf); 24572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang notify->post(); 24672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 24772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang msg->post(); 24872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 24972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang break; 25072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 25172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 25272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang case kWhatPause: 25372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang { 25472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mPaused = true; 25572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang break; 25672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 25772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 25872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang case kWhatResume: 25972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang { 26072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mPaused = false; 26172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang break; 26272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 26372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 26472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang default: 26572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang TRESPASS(); 26672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 26772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 26872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 26972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang// static 27072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangsp<MediaCodecSource> MediaCodecSource::Create( 27172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang const sp<ALooper> &looper, 27272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang const sp<AMessage> &format, 27372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang const sp<MediaSource> &source, 27472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang uint32_t flags) { 27572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang sp<MediaCodecSource> mediaSource = 27672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang new MediaCodecSource(looper, format, source, flags); 27772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 27872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mediaSource->init() == OK) { 27972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return mediaSource; 28072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 28172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return NULL; 28272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 28372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 28472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::start(MetaData* params) { 28572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang sp<AMessage> msg = new AMessage(kWhatStart, mReflector->id()); 28672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang msg->setObject("meta", params); 28772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return postSynchronouslyAndReturnError(msg); 28872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 28972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 29072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::stop() { 29172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang sp<AMessage> msg = new AMessage(kWhatStop, mReflector->id()); 29216e79115e497386eaf010af388627f94314a55a3Chong Zhang status_t err = postSynchronouslyAndReturnError(msg); 29316e79115e497386eaf010af388627f94314a55a3Chong Zhang 29416e79115e497386eaf010af388627f94314a55a3Chong Zhang // mPuller->stop() needs to be done outside MediaCodecSource's looper, 29516e79115e497386eaf010af388627f94314a55a3Chong Zhang // as it contains a synchronous call to stop the underlying MediaSource, 29616e79115e497386eaf010af388627f94314a55a3Chong Zhang // which often waits for all outstanding MediaBuffers to return, but 29716e79115e497386eaf010af388627f94314a55a3Chong Zhang // MediaBuffers are only returned when MediaCodecSource looper gets 29816e79115e497386eaf010af388627f94314a55a3Chong Zhang // to process them. 29916e79115e497386eaf010af388627f94314a55a3Chong Zhang 30016e79115e497386eaf010af388627f94314a55a3Chong Zhang if (mPuller != NULL) { 30116e79115e497386eaf010af388627f94314a55a3Chong Zhang ALOGI("puller (%s) stopping", mIsVideo ? "video" : "audio"); 30216e79115e497386eaf010af388627f94314a55a3Chong Zhang mPuller->stop(); 30316e79115e497386eaf010af388627f94314a55a3Chong Zhang ALOGI("puller (%s) stopped", mIsVideo ? "video" : "audio"); 30416e79115e497386eaf010af388627f94314a55a3Chong Zhang } 30516e79115e497386eaf010af388627f94314a55a3Chong Zhang 30616e79115e497386eaf010af388627f94314a55a3Chong Zhang return err; 30772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 30872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 30972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::pause() { 31072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang (new AMessage(kWhatPause, mReflector->id()))->post(); 31172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return OK; 31272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 31372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 31472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangsp<IGraphicBufferProducer> MediaCodecSource::getGraphicBufferProducer() { 31572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(mFlags & FLAG_USE_SURFACE_INPUT); 31672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return mGraphicBufferProducer; 31772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 31872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 31984333e0475bc911adc16417f4ca327c975cf6c36Andreas Huberstatus_t MediaCodecSource::read( 32084333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber MediaBuffer** buffer, const ReadOptions* /* options */) { 32172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang Mutex::Autolock autolock(mOutputBufferLock); 32272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 32372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang *buffer = NULL; 32416e79115e497386eaf010af388627f94314a55a3Chong Zhang while (mOutputBufferQueue.size() == 0 && !mEncoderReachedEOS) { 32572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mOutputBufferCond.wait(mOutputBufferLock); 32672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 32716e79115e497386eaf010af388627f94314a55a3Chong Zhang if (!mEncoderReachedEOS) { 32872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang *buffer = *mOutputBufferQueue.begin(); 32972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mOutputBufferQueue.erase(mOutputBufferQueue.begin()); 33072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return OK; 33172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 33272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return mErrorCode; 33372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 33472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 33572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::signalBufferReturned(MediaBuffer *buffer) { 33672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang buffer->setObserver(0); 33772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang buffer->release(); 33872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 33972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 34072cecca17d735db6532c45f0a7e10c47ee6f065aChong ZhangMediaCodecSource::MediaCodecSource( 34172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang const sp<ALooper> &looper, 34272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang const sp<AMessage> &outputFormat, 34372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang const sp<MediaSource> &source, 34472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang uint32_t flags) 34572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang : mLooper(looper), 34672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mOutputFormat(outputFormat), 34772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mMeta(new MetaData), 34872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mFlags(flags), 34972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mIsVideo(false), 35072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mStarted(false), 35172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mStopping(false), 35272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mDoMoreWorkPending(false), 35372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mFirstSampleTimeUs(-1ll), 35416e79115e497386eaf010af388627f94314a55a3Chong Zhang mEncoderReachedEOS(false), 35572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mErrorCode(OK) { 35672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(mLooper != NULL); 35772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 35872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang AString mime; 35972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(mOutputFormat->findString("mime", &mime)); 36072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 36172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (!strncasecmp("video/", mime.c_str(), 6)) { 36272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mIsVideo = true; 36372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 36472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 36572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (!(mFlags & FLAG_USE_SURFACE_INPUT)) { 36672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mPuller = new Puller(source); 36772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 36872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 36972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 37072cecca17d735db6532c45f0a7e10c47ee6f065aChong ZhangMediaCodecSource::~MediaCodecSource() { 37172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang releaseEncoder(); 37272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 37372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mCodecLooper->stop(); 37472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mLooper->unregisterHandler(mReflector->id()); 37572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 37672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 37772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::init() { 37872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang status_t err = initEncoder(); 37972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 38072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (err != OK) { 38172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang releaseEncoder(); 38272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 38372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 38472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return err; 38572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 38672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 38772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::initEncoder() { 38872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mReflector = new AHandlerReflector<MediaCodecSource>(this); 38972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mLooper->registerHandler(mReflector); 39072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 39172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mCodecLooper = new ALooper; 39272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mCodecLooper->setName("codec_looper"); 39372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mCodecLooper->start(); 39472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 39572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mFlags & FLAG_USE_METADATA_INPUT) { 39672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mOutputFormat->setInt32("store-metadata-in-buffers", 1); 39772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 39872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 39972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mFlags & FLAG_USE_SURFACE_INPUT) { 40072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mOutputFormat->setInt32("create-input-buffers-suspended", 1); 40172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 40272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 40372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang AString outputMIME; 40472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(mOutputFormat->findString("mime", &outputMIME)); 40572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 40672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mEncoder = MediaCodec::CreateByType( 40772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mCodecLooper, outputMIME.c_str(), true /* encoder */); 40872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 40972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mEncoder == NULL) { 41072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return NO_INIT; 41172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 41272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 41372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang ALOGV("output format is '%s'", mOutputFormat->debugString(0).c_str()); 41472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 41572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang status_t err = mEncoder->configure( 41672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mOutputFormat, 41772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang NULL /* nativeWindow */, 41872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang NULL /* crypto */, 41972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang MediaCodec::CONFIGURE_FLAG_ENCODE); 42072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 42172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (err != OK) { 42272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return err; 42372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 42472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 42572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mEncoder->getOutputFormat(&mOutputFormat); 42672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang convertMessageToMetaData(mOutputFormat, mMeta); 42772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 42872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mFlags & FLAG_USE_SURFACE_INPUT) { 42972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(mIsVideo); 43072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 43172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang err = mEncoder->createInputSurface(&mGraphicBufferProducer); 43272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 43372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (err != OK) { 43472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return err; 43572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 43672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 43772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 43872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang err = mEncoder->start(); 43972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 44072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (err != OK) { 44172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return err; 44272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 44372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 44472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang err = mEncoder->getInputBuffers(&mEncoderInputBuffers); 44572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 44672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (err != OK) { 44772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return err; 44872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 44972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 45072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang err = mEncoder->getOutputBuffers(&mEncoderOutputBuffers); 45172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 45272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (err != OK) { 45372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return err; 45472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 45572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 45616e79115e497386eaf010af388627f94314a55a3Chong Zhang mEncoderReachedEOS = false; 45772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mErrorCode = OK; 45872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 45972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return OK; 46072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 46172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 46272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::releaseEncoder() { 46372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mEncoder == NULL) { 46472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return; 46572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 46672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 46772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mEncoder->release(); 46872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mEncoder.clear(); 46972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 47072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang while (!mInputBufferQueue.empty()) { 47172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang MediaBuffer *mbuf = *mInputBufferQueue.begin(); 47272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mInputBufferQueue.erase(mInputBufferQueue.begin()); 47372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mbuf != NULL) { 47472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mbuf->release(); 47572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 47672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 47772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 47872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang for (size_t i = 0; i < mEncoderInputBuffers.size(); ++i) { 47972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang sp<ABuffer> accessUnit = mEncoderInputBuffers.itemAt(i); 48072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang ReleaseMediaBufferReference(accessUnit); 48172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 48272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 48372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mEncoderInputBuffers.clear(); 48472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mEncoderOutputBuffers.clear(); 48572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 48672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 48772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::postSynchronouslyAndReturnError( 48872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang const sp<AMessage> &msg) { 48972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang sp<AMessage> response; 49072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang status_t err = msg->postAndAwaitResponse(&response); 49172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 49272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (err != OK) { 49372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return err; 49472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 49572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 49672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (!response->findInt32("err", &err)) { 49772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang err = OK; 49872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 49972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 50072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return err; 50172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 50272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 50372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::signalEOS(status_t err) { 50416e79115e497386eaf010af388627f94314a55a3Chong Zhang if (!mEncoderReachedEOS) { 50516e79115e497386eaf010af388627f94314a55a3Chong Zhang ALOGV("encoder (%s) reached EOS", mIsVideo ? "video" : "audio"); 50672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang { 50772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang Mutex::Autolock autoLock(mOutputBufferLock); 50872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang // release all unread media buffers 50972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang for (List<MediaBuffer*>::iterator it = mOutputBufferQueue.begin(); 51072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang it != mOutputBufferQueue.end(); it++) { 51172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang (*it)->release(); 51272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 51372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mOutputBufferQueue.clear(); 51416e79115e497386eaf010af388627f94314a55a3Chong Zhang mEncoderReachedEOS = true; 51572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mErrorCode = err; 51672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mOutputBufferCond.signal(); 51772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 51872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 51972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang releaseEncoder(); 52072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 52116e79115e497386eaf010af388627f94314a55a3Chong Zhang if (mStopping && mEncoderReachedEOS) { 52216e79115e497386eaf010af388627f94314a55a3Chong Zhang ALOGI("encoder (%s) stopped", mIsVideo ? "video" : "audio"); 52372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang // posting reply to everyone that's waiting 52472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang List<uint32_t>::iterator it; 52572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang for (it = mStopReplyIDQueue.begin(); 52672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang it != mStopReplyIDQueue.end(); it++) { 52772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang (new AMessage)->postReply(*it); 52872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 52972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mStopReplyIDQueue.clear(); 53072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mStopping = false; 53172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 53272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 53372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 53472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::suspend() { 53572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(mFlags & FLAG_USE_SURFACE_INPUT); 53672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mEncoder != NULL) { 53772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang sp<AMessage> params = new AMessage; 53872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang params->setInt32("drop-input-frames", true); 53972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mEncoder->setParameters(params); 54072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 54172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 54272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 54372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::resume(int64_t skipFramesBeforeUs) { 54472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(mFlags & FLAG_USE_SURFACE_INPUT); 54572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mEncoder != NULL) { 54672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang sp<AMessage> params = new AMessage; 54772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang params->setInt32("drop-input-frames", false); 54872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (skipFramesBeforeUs > 0) { 54972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang params->setInt64("skip-frames-before", skipFramesBeforeUs); 55072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 55172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mEncoder->setParameters(params); 55272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 55372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 55472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 55572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::scheduleDoMoreWork() { 55672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mDoMoreWorkPending) { 55772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return; 55872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 55972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 56072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mDoMoreWorkPending = true; 56172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 56272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mEncoderActivityNotify == NULL) { 56372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mEncoderActivityNotify = new AMessage( 56472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang kWhatEncoderActivity, mReflector->id()); 56572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 56672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mEncoder->requestActivityNotification(mEncoderActivityNotify); 56772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 56872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 56972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::feedEncoderInputBuffers() { 57072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang while (!mInputBufferQueue.empty() 57172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang && !mAvailEncoderInputIndices.empty()) { 57272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang MediaBuffer* mbuf = *mInputBufferQueue.begin(); 57372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mInputBufferQueue.erase(mInputBufferQueue.begin()); 57472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 57572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang size_t bufferIndex = *mAvailEncoderInputIndices.begin(); 57672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mAvailEncoderInputIndices.erase(mAvailEncoderInputIndices.begin()); 57772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 57872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang int64_t timeUs = 0ll; 57972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang uint32_t flags = 0; 58072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang size_t size = 0; 58172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 58272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mbuf != NULL) { 58372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(mbuf->meta_data()->findInt64(kKeyTime, &timeUs)); 58472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 58572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang // push decoding time for video, or drift time for audio 58672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mIsVideo) { 58772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mDecodingTimeQueue.push_back(timeUs); 58872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } else { 58972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#if DEBUG_DRIFT_TIME 59072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mFirstSampleTimeUs < 0ll) { 59172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mFirstSampleTimeUs = timeUs; 59272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 59372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 59472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang int64_t driftTimeUs = 0; 59572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mbuf->meta_data()->findInt64(kKeyDriftTime, &driftTimeUs) 59672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang && driftTimeUs) { 59772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang driftTimeUs = timeUs - mFirstSampleTimeUs - driftTimeUs; 59872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 59972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mDriftTimeQueue.push_back(driftTimeUs); 60072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#endif // DEBUG_DRIFT_TIME 60172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 60272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 60372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang size = mbuf->size(); 60472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 60572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang memcpy(mEncoderInputBuffers.itemAt(bufferIndex)->data(), 60672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mbuf->data(), size); 60772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 60872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mIsVideo) { 60972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang // video encoder will release MediaBuffer when done 61072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang // with underlying data. 61172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mEncoderInputBuffers.itemAt(bufferIndex)->meta() 61272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang ->setPointer("mediaBuffer", mbuf); 61372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } else { 61472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mbuf->release(); 61572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 61672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } else { 61772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang flags = MediaCodec::BUFFER_FLAG_EOS; 61872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 61972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 62072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang status_t err = mEncoder->queueInputBuffer( 62172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang bufferIndex, 0, size, timeUs, flags); 62272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 62372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (err != OK) { 62472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return err; 62572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 62672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 62772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 62872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return OK; 62972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 63072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 63172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::doMoreWork() { 63272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang status_t err; 63372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 63472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (!(mFlags & FLAG_USE_SURFACE_INPUT)) { 63572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang for (;;) { 63672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang size_t bufferIndex; 63772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang err = mEncoder->dequeueInputBuffer(&bufferIndex); 63872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 63972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (err != OK) { 64072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang break; 64172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 64272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 64372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mAvailEncoderInputIndices.push_back(bufferIndex); 64472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 64572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 64672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang feedEncoderInputBuffers(); 64772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 64872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 64972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang for (;;) { 65072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang size_t bufferIndex; 65172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang size_t offset; 65272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang size_t size; 65372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang int64_t timeUs; 65472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang uint32_t flags; 65572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang native_handle_t* handle = NULL; 65672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang err = mEncoder->dequeueOutputBuffer( 65772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang &bufferIndex, &offset, &size, &timeUs, &flags); 65872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 65972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (err != OK) { 66072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (err == INFO_FORMAT_CHANGED) { 66172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang continue; 66272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } else if (err == INFO_OUTPUT_BUFFERS_CHANGED) { 66372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mEncoder->getOutputBuffers(&mEncoderOutputBuffers); 66472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang continue; 66572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 66672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 66772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (err == -EAGAIN) { 66872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang err = OK; 66972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 67072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang break; 67172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 67272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (!(flags & MediaCodec::BUFFER_FLAG_EOS)) { 67372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang sp<ABuffer> outbuf = mEncoderOutputBuffers.itemAt(bufferIndex); 67472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 67572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang MediaBuffer *mbuf = new MediaBuffer(outbuf->size()); 67672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang memcpy(mbuf->data(), outbuf->data(), outbuf->size()); 67772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 67872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (!(flags & MediaCodec::BUFFER_FLAG_CODECCONFIG)) { 67972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mIsVideo) { 68072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang int64_t decodingTimeUs; 68172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mFlags & FLAG_USE_SURFACE_INPUT) { 68272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang // GraphicBufferSource is supposed to discard samples 68372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang // queued before start, and offset timeUs by start time 68472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK_GE(timeUs, 0ll); 68572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang // TODO: 68672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang // Decoding time for surface source is unavailable, 68772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang // use presentation time for now. May need to move 68872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang // this logic into MediaCodec. 68972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang decodingTimeUs = timeUs; 69072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } else { 69172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(!mDecodingTimeQueue.empty()); 69272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang decodingTimeUs = *(mDecodingTimeQueue.begin()); 69372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mDecodingTimeQueue.erase(mDecodingTimeQueue.begin()); 69472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 69572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mbuf->meta_data()->setInt64(kKeyDecodingTime, decodingTimeUs); 69672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 697a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("[video] time %" PRId64 " us (%.2f secs), dts/pts diff %" PRId64, 69872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang timeUs, timeUs / 1E6, decodingTimeUs - timeUs); 69972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } else { 70072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang int64_t driftTimeUs = 0; 70172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#if DEBUG_DRIFT_TIME 70272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(!mDriftTimeQueue.empty()); 70372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang driftTimeUs = *(mDriftTimeQueue.begin()); 70472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mDriftTimeQueue.erase(mDriftTimeQueue.begin()); 70572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mbuf->meta_data()->setInt64(kKeyDriftTime, driftTimeUs); 70672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#endif // DEBUG_DRIFT_TIME 707a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("[audio] time %" PRId64 " us (%.2f secs), drift %" PRId64, 70872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang timeUs, timeUs / 1E6, driftTimeUs); 70972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 71072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mbuf->meta_data()->setInt64(kKeyTime, timeUs); 71172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } else { 71272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mbuf->meta_data()->setInt32(kKeyIsCodecConfig, true); 71372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 71472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (flags & MediaCodec::BUFFER_FLAG_SYNCFRAME) { 71572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mbuf->meta_data()->setInt32(kKeyIsSyncFrame, true); 71672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 71772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mbuf->setObserver(this); 71872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mbuf->add_ref(); 71972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 72072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang { 72172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang Mutex::Autolock autoLock(mOutputBufferLock); 72272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mOutputBufferQueue.push_back(mbuf); 72372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mOutputBufferCond.signal(); 72472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 72572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 72672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 72772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mEncoder->releaseOutputBuffer(bufferIndex); 72872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 72972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (flags & MediaCodec::BUFFER_FLAG_EOS) { 73072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang err = ERROR_END_OF_STREAM; 73172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang break; 73272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 73372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 73472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 73572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return err; 73672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 73772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 73872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::onStart(MetaData *params) { 73972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mStopping) { 74072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang ALOGE("Failed to start while we're stopping"); 74172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return INVALID_OPERATION; 74272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 74372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 74472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mStarted) { 74572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang ALOGI("MediaCodecSource (%s) resuming", mIsVideo ? "video" : "audio"); 74672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mFlags & FLAG_USE_SURFACE_INPUT) { 74772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang resume(); 74872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } else { 74972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(mPuller != NULL); 75072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mPuller->resume(); 75172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 75272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return OK; 75372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 75472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 75572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang ALOGI("MediaCodecSource (%s) starting", mIsVideo ? "video" : "audio"); 75672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 75772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang status_t err = OK; 75872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 75972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mFlags & FLAG_USE_SURFACE_INPUT) { 76072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang int64_t startTimeUs; 76172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (!params || !params->findInt64(kKeyTime, &startTimeUs)) { 76272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang startTimeUs = -1ll; 76372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 76472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang resume(startTimeUs); 76572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang scheduleDoMoreWork(); 76672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } else { 76772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(mPuller != NULL); 76872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang sp<AMessage> notify = new AMessage( 76972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang kWhatPullerNotify, mReflector->id()); 77072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang err = mPuller->start(params, notify); 77172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (err != OK) { 77272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return err; 77372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 77472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 77572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 77672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang ALOGI("MediaCodecSource (%s) started", mIsVideo ? "video" : "audio"); 77772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 77872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mStarted = true; 77972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return OK; 78072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 78172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 78272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::onMessageReceived(const sp<AMessage> &msg) { 78372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang switch (msg->what()) { 78472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang case kWhatPullerNotify: 78572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang { 78672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang MediaBuffer *mbuf; 78772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(msg->findPointer("accessUnit", (void**)&mbuf)); 78872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 78972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mbuf == NULL) { 79016e79115e497386eaf010af388627f94314a55a3Chong Zhang ALOGV("puller (%s) reached EOS", 79172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mIsVideo ? "video" : "audio"); 79216e79115e497386eaf010af388627f94314a55a3Chong Zhang signalEOS(); 79372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 79472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 79572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mEncoder == NULL) { 79672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang ALOGV("got msg '%s' after encoder shutdown.", 79772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang msg->debugString().c_str()); 79872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 79972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mbuf != NULL) { 80072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mbuf->release(); 80172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 80216e79115e497386eaf010af388627f94314a55a3Chong Zhang 80372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang break; 80472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 80572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 80672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mInputBufferQueue.push_back(mbuf); 80772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 80872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang feedEncoderInputBuffers(); 80972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang scheduleDoMoreWork(); 81072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 81172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang break; 81272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 81372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang case kWhatEncoderActivity: 81472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang { 81572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mDoMoreWorkPending = false; 81672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 81772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mEncoder == NULL) { 81872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang break; 81972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 82072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 82172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang status_t err = doMoreWork(); 82272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 82372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (err == OK) { 82472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang scheduleDoMoreWork(); 82572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } else { 82672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang // reached EOS, or error 82772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang signalEOS(err); 82872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 82972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 83072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang break; 83172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 83272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang case kWhatStart: 83372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang { 83472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang uint32_t replyID; 83572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(msg->senderAwaitsResponse(&replyID)); 83672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 83772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang sp<RefBase> obj; 83872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(msg->findObject("meta", &obj)); 83972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang MetaData *params = static_cast<MetaData *>(obj.get()); 84072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 84172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang sp<AMessage> response = new AMessage; 84272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang response->setInt32("err", onStart(params)); 84372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang response->postReply(replyID); 84472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang break; 84572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 84672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang case kWhatStop: 84772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang { 84816e79115e497386eaf010af388627f94314a55a3Chong Zhang ALOGI("encoder (%s) stopping", mIsVideo ? "video" : "audio"); 84972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 85072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang uint32_t replyID; 85172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(msg->senderAwaitsResponse(&replyID)); 85272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 85316e79115e497386eaf010af388627f94314a55a3Chong Zhang if (mEncoderReachedEOS) { 85472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang // if we already reached EOS, reply and return now 85516e79115e497386eaf010af388627f94314a55a3Chong Zhang ALOGI("encoder (%s) already stopped", 85672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mIsVideo ? "video" : "audio"); 85772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang (new AMessage)->postReply(replyID); 85872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang break; 85972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 86072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 86172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mStopReplyIDQueue.push_back(replyID); 86272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mStopping) { 86372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang // nothing to do if we're already stopping, reply will be posted 86472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang // to all when we're stopped. 86572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang break; 86672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 86772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 86872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mStopping = true; 86972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 87072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang // if using surface, signal source EOS and wait for EOS to come back. 87172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang // otherwise, release encoder and post EOS if haven't done already 87272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mFlags & FLAG_USE_SURFACE_INPUT) { 87372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mEncoder->signalEndOfInputStream(); 87472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } else { 87572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang signalEOS(); 87672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 87772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang break; 87872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 87972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang case kWhatPause: 88072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang { 88172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mFlags && FLAG_USE_SURFACE_INPUT) { 88272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang suspend(); 88372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } else { 88472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(mPuller != NULL); 88572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mPuller->pause(); 88672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 88772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang break; 88872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 88972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang default: 89072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang TRESPASS(); 89172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 89272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 89372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 89472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} // namespace android 895