MediaCodecSource.cpp revision d008275796ac4cccf85fefce53cef733a49bc1fa
172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang/* 272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang * Copyright 2014, The Android Open Source Project 372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang * 472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang * Licensed under the Apache License, Version 2.0 (the "License"); 572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang * you may not use this file except in compliance with the License. 672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang * You may obtain a copy of the License at 772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang * 872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang * http://www.apache.org/licenses/LICENSE-2.0 972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang * 1072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang * Unless required by applicable law or agreed to in writing, software 1172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang * distributed under the License is distributed on an "AS IS" BASIS, 1272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang * See the License for the specific language governing permissions and 1472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang * limitations under the License. 1572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang */ 1672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 1772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang//#define LOG_NDEBUG 0 1872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#define LOG_TAG "MediaCodecSource" 1972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#define DEBUG_DRIFT_TIME 0 20a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn 21a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn#include <inttypes.h> 22a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn 23e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang#include <gui/IGraphicBufferConsumer.h> 2472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <gui/IGraphicBufferProducer.h> 2572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <gui/Surface.h> 2672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/ICrypto.h> 2772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/foundation/ABuffer.h> 2872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/foundation/ADebug.h> 2972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/foundation/ALooper.h> 3072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/foundation/AMessage.h> 3172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/MediaBuffer.h> 3272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/MediaCodec.h> 33e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang#include <media/stagefright/MediaCodecSource.h> 3472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/MediaErrors.h> 3572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/MediaSource.h> 36e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang#include <media/stagefright/MetaData.h> 37e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang#include <media/stagefright/PersistentSurface.h> 3872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/Utils.h> 3972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 4072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangnamespace android { 4172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 42c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnarconst int kDefaultSwVideoEncoderFormat = HAL_PIXEL_FORMAT_YCbCr_420_888; 43c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnarconst int kDefaultSwVideoEncoderDataSpace = HAL_DATASPACE_BT709; 44c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar 4572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstruct MediaCodecSource::Puller : public AHandler { 4672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang Puller(const sp<MediaSource> &source); 4772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 4872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang status_t start(const sp<MetaData> &meta, const sp<AMessage> ¬ify); 4916e79115e497386eaf010af388627f94314a55a3Chong Zhang void stop(); 5072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 5172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang void pause(); 5272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang void resume(); 5372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 5472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangprotected: 5572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang virtual void onMessageReceived(const sp<AMessage> &msg); 5672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang virtual ~Puller(); 5772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 5872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangprivate: 5972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang enum { 6072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang kWhatStart = 'msta', 6172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang kWhatStop, 6272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang kWhatPull, 6372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang kWhatPause, 6472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang kWhatResume, 6572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang }; 6672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 6772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang sp<MediaSource> mSource; 6872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang sp<AMessage> mNotify; 6972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang sp<ALooper> mLooper; 7072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang int32_t mPullGeneration; 7172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang bool mIsAudio; 7272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang bool mPaused; 7372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang bool mReachedEOS; 7472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 7572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang status_t postSynchronouslyAndReturnError(const sp<AMessage> &msg); 7672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang void schedulePull(); 7772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang void handleEOS(); 7872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 7972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang DISALLOW_EVIL_CONSTRUCTORS(Puller); 8072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}; 8172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 8272cecca17d735db6532c45f0a7e10c47ee6f065aChong ZhangMediaCodecSource::Puller::Puller(const sp<MediaSource> &source) 8372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang : mSource(source), 8472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mLooper(new ALooper()), 8572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mPullGeneration(0), 8672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mIsAudio(false), 8772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mPaused(false), 8872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mReachedEOS(false) { 8972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang sp<MetaData> meta = source->getFormat(); 9072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang const char *mime; 9172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(meta->findCString(kKeyMIMEType, &mime)); 9272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 9372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mIsAudio = !strncasecmp(mime, "audio/", 6); 9472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 9572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mLooper->setName("pull_looper"); 9672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 9772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 9872cecca17d735db6532c45f0a7e10c47ee6f065aChong ZhangMediaCodecSource::Puller::~Puller() { 9972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mLooper->unregisterHandler(id()); 10072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mLooper->stop(); 10172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 10272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 10372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::Puller::postSynchronouslyAndReturnError( 10472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang const sp<AMessage> &msg) { 10572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang sp<AMessage> response; 10672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang status_t err = msg->postAndAwaitResponse(&response); 10772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 10872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (err != OK) { 10972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return err; 11072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 11172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 11272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (!response->findInt32("err", &err)) { 11372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang err = OK; 11472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 11572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 11672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return err; 11772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 11872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 11972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::Puller::start(const sp<MetaData> &meta, 12072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang const sp<AMessage> ¬ify) { 12172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang ALOGV("puller (%s) start", mIsAudio ? "audio" : "video"); 12272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mLooper->start( 12372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang false /* runOnCallingThread */, 12472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang false /* canCallJava */, 12572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang PRIORITY_AUDIO); 12672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mLooper->registerHandler(this); 12772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mNotify = notify; 12872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 1291d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar sp<AMessage> msg = new AMessage(kWhatStart, this); 13072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang msg->setObject("meta", meta); 13172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return postSynchronouslyAndReturnError(msg); 13272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 13372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 13416e79115e497386eaf010af388627f94314a55a3Chong Zhangvoid MediaCodecSource::Puller::stop() { 13516e79115e497386eaf010af388627f94314a55a3Chong Zhang // Stop source from caller's thread instead of puller's looper. 13616e79115e497386eaf010af388627f94314a55a3Chong Zhang // mSource->stop() is thread-safe, doing it outside the puller's 13716e79115e497386eaf010af388627f94314a55a3Chong Zhang // looper allows us to at least stop if source gets stuck. 13816e79115e497386eaf010af388627f94314a55a3Chong Zhang // If source gets stuck in read(), the looper would never 13916e79115e497386eaf010af388627f94314a55a3Chong Zhang // be able to process the stop(), which could lead to ANR. 14016e79115e497386eaf010af388627f94314a55a3Chong Zhang 14116e79115e497386eaf010af388627f94314a55a3Chong Zhang ALOGV("source (%s) stopping", mIsAudio ? "audio" : "video"); 14216e79115e497386eaf010af388627f94314a55a3Chong Zhang mSource->stop(); 14316e79115e497386eaf010af388627f94314a55a3Chong Zhang ALOGV("source (%s) stopped", mIsAudio ? "audio" : "video"); 14416e79115e497386eaf010af388627f94314a55a3Chong Zhang 1451d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar (new AMessage(kWhatStop, this))->post(); 14672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 14772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 14872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::Puller::pause() { 1491d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar (new AMessage(kWhatPause, this))->post(); 15072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 15172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 15272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::Puller::resume() { 1531d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar (new AMessage(kWhatResume, this))->post(); 15472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 15572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 15672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::Puller::schedulePull() { 1571d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar sp<AMessage> msg = new AMessage(kWhatPull, this); 15872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang msg->setInt32("generation", mPullGeneration); 15972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang msg->post(); 16072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 16172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 16272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::Puller::handleEOS() { 16372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (!mReachedEOS) { 16472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang ALOGV("puller (%s) posting EOS", mIsAudio ? "audio" : "video"); 16572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mReachedEOS = true; 16672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang sp<AMessage> notify = mNotify->dup(); 16772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang notify->setPointer("accessUnit", NULL); 16872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang notify->post(); 16972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 17072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 17172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 17272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::Puller::onMessageReceived(const sp<AMessage> &msg) { 17372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang switch (msg->what()) { 17472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang case kWhatStart: 17572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang { 17672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang sp<RefBase> obj; 17772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(msg->findObject("meta", &obj)); 17872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 17972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mReachedEOS = false; 18072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 18172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang status_t err = mSource->start(static_cast<MetaData *>(obj.get())); 18272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 18372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (err == OK) { 18472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang schedulePull(); 18572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 18672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 18772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang sp<AMessage> response = new AMessage; 18872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang response->setInt32("err", err); 18972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 1903f27436a9346f043f52265da1e6a74cde2bffd4dLajos Molnar sp<AReplyToken> replyID; 19172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(msg->senderAwaitsResponse(&replyID)); 19272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang response->postReply(replyID); 19372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang break; 19472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 19572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 19672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang case kWhatStop: 19772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang { 19872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang ++mPullGeneration; 19972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 20072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang handleEOS(); 20172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang break; 20272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 20372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 20472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang case kWhatPull: 20572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang { 20672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang int32_t generation; 20772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(msg->findInt32("generation", &generation)); 20872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 20972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (generation != mPullGeneration) { 21072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang break; 21172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 21272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 21372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang MediaBuffer *mbuf; 21472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang status_t err = mSource->read(&mbuf); 21572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 21672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mPaused) { 21772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (err == OK) { 21872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mbuf->release(); 21972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mbuf = NULL; 22072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 22172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 22272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang msg->post(); 22372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang break; 22472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 22572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 22672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (err != OK) { 22772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (err == ERROR_END_OF_STREAM) { 22872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang ALOGV("stream ended, mbuf %p", mbuf); 22972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } else { 23072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang ALOGE("error %d reading stream.", err); 23172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 23272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang handleEOS(); 23372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } else { 23472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang sp<AMessage> notify = mNotify->dup(); 23572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 23672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang notify->setPointer("accessUnit", mbuf); 23772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang notify->post(); 23872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 23972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang msg->post(); 24072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 24172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang break; 24272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 24372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 24472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang case kWhatPause: 24572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang { 24672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mPaused = true; 24772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang break; 24872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 24972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 25072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang case kWhatResume: 25172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang { 25272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mPaused = false; 25372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang break; 25472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 25572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 25672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang default: 25772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang TRESPASS(); 25872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 25972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 26072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 26172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang// static 26272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangsp<MediaCodecSource> MediaCodecSource::Create( 26372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang const sp<ALooper> &looper, 26472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang const sp<AMessage> &format, 26572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang const sp<MediaSource> &source, 266e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang const sp<IGraphicBufferConsumer> &consumer, 26772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang uint32_t flags) { 26872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang sp<MediaCodecSource> mediaSource = 269e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang new MediaCodecSource(looper, format, source, consumer, flags); 27072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 27172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mediaSource->init() == OK) { 27272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return mediaSource; 27372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 27472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return NULL; 27572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 27672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 277d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kimvoid MediaCodecSource::setInputBufferTimeOffset(int64_t timeOffsetUs) { 278d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim sp<AMessage> msg = new AMessage(kWhatSetInputBufferTimeOffset, mReflector); 279d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim msg->setInt64("time-offset-us", timeOffsetUs); 280d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim postSynchronouslyAndReturnError(msg); 281d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim} 282d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim 28372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::start(MetaData* params) { 2841d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar sp<AMessage> msg = new AMessage(kWhatStart, mReflector); 28572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang msg->setObject("meta", params); 28672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return postSynchronouslyAndReturnError(msg); 28772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 28872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 28972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::stop() { 2901d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar sp<AMessage> msg = new AMessage(kWhatStop, mReflector); 29116e79115e497386eaf010af388627f94314a55a3Chong Zhang status_t err = postSynchronouslyAndReturnError(msg); 29216e79115e497386eaf010af388627f94314a55a3Chong Zhang 29316e79115e497386eaf010af388627f94314a55a3Chong Zhang // mPuller->stop() needs to be done outside MediaCodecSource's looper, 29416e79115e497386eaf010af388627f94314a55a3Chong Zhang // as it contains a synchronous call to stop the underlying MediaSource, 29516e79115e497386eaf010af388627f94314a55a3Chong Zhang // which often waits for all outstanding MediaBuffers to return, but 29616e79115e497386eaf010af388627f94314a55a3Chong Zhang // MediaBuffers are only returned when MediaCodecSource looper gets 29716e79115e497386eaf010af388627f94314a55a3Chong Zhang // to process them. 29816e79115e497386eaf010af388627f94314a55a3Chong Zhang 29916e79115e497386eaf010af388627f94314a55a3Chong Zhang if (mPuller != NULL) { 30016e79115e497386eaf010af388627f94314a55a3Chong Zhang ALOGI("puller (%s) stopping", mIsVideo ? "video" : "audio"); 30116e79115e497386eaf010af388627f94314a55a3Chong Zhang mPuller->stop(); 30216e79115e497386eaf010af388627f94314a55a3Chong Zhang ALOGI("puller (%s) stopped", mIsVideo ? "video" : "audio"); 30316e79115e497386eaf010af388627f94314a55a3Chong Zhang } 30416e79115e497386eaf010af388627f94314a55a3Chong Zhang 30516e79115e497386eaf010af388627f94314a55a3Chong Zhang return err; 30672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 30772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 30872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::pause() { 3091d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar (new AMessage(kWhatPause, mReflector))->post(); 31072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return OK; 31172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 31272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 31372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangsp<IGraphicBufferProducer> MediaCodecSource::getGraphicBufferProducer() { 31472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(mFlags & FLAG_USE_SURFACE_INPUT); 31572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return mGraphicBufferProducer; 31672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 31772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 31884333e0475bc911adc16417f4ca327c975cf6c36Andreas Huberstatus_t MediaCodecSource::read( 31984333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber MediaBuffer** buffer, const ReadOptions* /* options */) { 32072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang Mutex::Autolock autolock(mOutputBufferLock); 32172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 32272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang *buffer = NULL; 32316e79115e497386eaf010af388627f94314a55a3Chong Zhang while (mOutputBufferQueue.size() == 0 && !mEncoderReachedEOS) { 32472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mOutputBufferCond.wait(mOutputBufferLock); 32572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 32616e79115e497386eaf010af388627f94314a55a3Chong Zhang if (!mEncoderReachedEOS) { 32772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang *buffer = *mOutputBufferQueue.begin(); 32872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mOutputBufferQueue.erase(mOutputBufferQueue.begin()); 32972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return OK; 33072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 33172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return mErrorCode; 33272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 33372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 33472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::signalBufferReturned(MediaBuffer *buffer) { 33572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang buffer->setObserver(0); 33672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang buffer->release(); 33772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 33872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 33972cecca17d735db6532c45f0a7e10c47ee6f065aChong ZhangMediaCodecSource::MediaCodecSource( 34072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang const sp<ALooper> &looper, 34172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang const sp<AMessage> &outputFormat, 34272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang const sp<MediaSource> &source, 343e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang const sp<IGraphicBufferConsumer> &consumer, 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), 353c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar mSetEncoderFormat(false), 354c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar mEncoderFormat(0), 355c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar mEncoderDataSpace(0), 356e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang mGraphicBufferConsumer(consumer), 357d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim mInputBufferTimeOffsetUs(0), 35872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mFirstSampleTimeUs(-1ll), 35916e79115e497386eaf010af388627f94314a55a3Chong Zhang mEncoderReachedEOS(false), 36072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mErrorCode(OK) { 36172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(mLooper != NULL); 36272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 36372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang AString mime; 36472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(mOutputFormat->findString("mime", &mime)); 36572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 36672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (!strncasecmp("video/", mime.c_str(), 6)) { 36772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mIsVideo = true; 36872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 36972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 37072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (!(mFlags & FLAG_USE_SURFACE_INPUT)) { 37172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mPuller = new Puller(source); 37272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 37372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 37472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 37572cecca17d735db6532c45f0a7e10c47ee6f065aChong ZhangMediaCodecSource::~MediaCodecSource() { 37672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang releaseEncoder(); 37772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 37872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mCodecLooper->stop(); 37972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mLooper->unregisterHandler(mReflector->id()); 38072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 38172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 38272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::init() { 38372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang status_t err = initEncoder(); 38472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 38572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (err != OK) { 38672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang releaseEncoder(); 38772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 38872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 38972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return err; 39072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 39172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 39272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::initEncoder() { 39372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mReflector = new AHandlerReflector<MediaCodecSource>(this); 39472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mLooper->registerHandler(mReflector); 39572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 39672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mCodecLooper = new ALooper; 39772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mCodecLooper->setName("codec_looper"); 39872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mCodecLooper->start(); 39972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 40072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mFlags & FLAG_USE_METADATA_INPUT) { 40172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mOutputFormat->setInt32("store-metadata-in-buffers", 1); 40272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 40372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 40472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mFlags & FLAG_USE_SURFACE_INPUT) { 40572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mOutputFormat->setInt32("create-input-buffers-suspended", 1); 40672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 40772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 40872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang AString outputMIME; 40972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(mOutputFormat->findString("mime", &outputMIME)); 41072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 41172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mEncoder = MediaCodec::CreateByType( 41272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mCodecLooper, outputMIME.c_str(), true /* encoder */); 41372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 41472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mEncoder == NULL) { 41572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return NO_INIT; 41672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 41772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 41872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang ALOGV("output format is '%s'", mOutputFormat->debugString(0).c_str()); 41972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 420421f47ca9c2dcc78584b2bb609c3755483b55155Marco Nelissen mEncoderActivityNotify = new AMessage(kWhatEncoderActivity, mReflector); 421421f47ca9c2dcc78584b2bb609c3755483b55155Marco Nelissen mEncoder->setCallback(mEncoderActivityNotify); 422421f47ca9c2dcc78584b2bb609c3755483b55155Marco Nelissen 42372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang status_t err = mEncoder->configure( 42472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mOutputFormat, 42572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang NULL /* nativeWindow */, 42672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang NULL /* crypto */, 42772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang MediaCodec::CONFIGURE_FLAG_ENCODE); 42872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 42972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (err != OK) { 43072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return err; 43172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 43272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 43372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mEncoder->getOutputFormat(&mOutputFormat); 43472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang convertMessageToMetaData(mOutputFormat, mMeta); 43572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 43672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mFlags & FLAG_USE_SURFACE_INPUT) { 43772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(mIsVideo); 43872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 439e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang if (mGraphicBufferConsumer != NULL) { 440e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang // When using persistent surface, we are only interested in the 441e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang // consumer, but have to use PersistentSurface as a wrapper to 442e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang // pass consumer over messages (similar to BufferProducerWrapper) 4438f469e18c307cb9dc0d16ed9225972aa8be4516fChong Zhang err = mEncoder->setInputSurface( 444e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang new PersistentSurface(NULL, mGraphicBufferConsumer)); 445e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang } else { 446e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang err = mEncoder->createInputSurface(&mGraphicBufferProducer); 447e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang } 44872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 44972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (err != OK) { 45072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return err; 45172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 45272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 45372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 454c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar sp<AMessage> inputFormat; 455c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar int32_t usingSwReadOften; 456c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar mSetEncoderFormat = false; 457c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar if (mEncoder->getInputFormat(&inputFormat) == OK 458c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar && inputFormat->findInt32("using-sw-read-often", &usingSwReadOften) 459c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar && usingSwReadOften) { 460c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar // this is a SW encoder; signal source to allocate SW readable buffers 461c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar mSetEncoderFormat = true; 462c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar mEncoderFormat = kDefaultSwVideoEncoderFormat; 463c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar mEncoderDataSpace = kDefaultSwVideoEncoderDataSpace; 464c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar } 465c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar 4661099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan err = mEncoder->start(); 46772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 46872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (err != OK) { 46972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return err; 47072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 47172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 47216e79115e497386eaf010af388627f94314a55a3Chong Zhang mEncoderReachedEOS = false; 47372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mErrorCode = OK; 47472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 47572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return OK; 47672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 47772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 47872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::releaseEncoder() { 47972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mEncoder == NULL) { 48072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return; 48172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 48272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 48372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mEncoder->release(); 48472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mEncoder.clear(); 48572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 48672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang while (!mInputBufferQueue.empty()) { 48772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang MediaBuffer *mbuf = *mInputBufferQueue.begin(); 48872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mInputBufferQueue.erase(mInputBufferQueue.begin()); 48972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mbuf != NULL) { 49072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mbuf->release(); 49172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 49272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 49372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 49472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 49572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::postSynchronouslyAndReturnError( 49672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang const sp<AMessage> &msg) { 49772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang sp<AMessage> response; 49872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang status_t err = msg->postAndAwaitResponse(&response); 49972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 50072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (err != OK) { 50172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return err; 50272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 50372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 50472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (!response->findInt32("err", &err)) { 50572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang err = OK; 50672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 50772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 50872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return err; 50972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 51072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 51172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::signalEOS(status_t err) { 51216e79115e497386eaf010af388627f94314a55a3Chong Zhang if (!mEncoderReachedEOS) { 51316e79115e497386eaf010af388627f94314a55a3Chong Zhang ALOGV("encoder (%s) reached EOS", mIsVideo ? "video" : "audio"); 51472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang { 51572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang Mutex::Autolock autoLock(mOutputBufferLock); 51672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang // release all unread media buffers 51772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang for (List<MediaBuffer*>::iterator it = mOutputBufferQueue.begin(); 51872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang it != mOutputBufferQueue.end(); it++) { 51972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang (*it)->release(); 52072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 52172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mOutputBufferQueue.clear(); 52216e79115e497386eaf010af388627f94314a55a3Chong Zhang mEncoderReachedEOS = true; 52372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mErrorCode = err; 52472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mOutputBufferCond.signal(); 52572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 52672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 52772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang releaseEncoder(); 52872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 52916e79115e497386eaf010af388627f94314a55a3Chong Zhang if (mStopping && mEncoderReachedEOS) { 53016e79115e497386eaf010af388627f94314a55a3Chong Zhang ALOGI("encoder (%s) stopped", mIsVideo ? "video" : "audio"); 53172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang // posting reply to everyone that's waiting 5323f27436a9346f043f52265da1e6a74cde2bffd4dLajos Molnar List<sp<AReplyToken>>::iterator it; 53372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang for (it = mStopReplyIDQueue.begin(); 53472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang it != mStopReplyIDQueue.end(); it++) { 53572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang (new AMessage)->postReply(*it); 53672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 53772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mStopReplyIDQueue.clear(); 53872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mStopping = false; 53972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 54072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 54172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 54272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::suspend() { 54372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(mFlags & FLAG_USE_SURFACE_INPUT); 54472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mEncoder != NULL) { 54572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang sp<AMessage> params = new AMessage; 54672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang params->setInt32("drop-input-frames", true); 54772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mEncoder->setParameters(params); 54872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 54972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 55072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 55172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::resume(int64_t skipFramesBeforeUs) { 55272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(mFlags & FLAG_USE_SURFACE_INPUT); 55372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mEncoder != NULL) { 55472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang sp<AMessage> params = new AMessage; 55572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang params->setInt32("drop-input-frames", false); 55672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (skipFramesBeforeUs > 0) { 55772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang params->setInt64("skip-frames-before", skipFramesBeforeUs); 55872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 55972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mEncoder->setParameters(params); 56072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 56172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 56272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 56372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::feedEncoderInputBuffers() { 56472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang while (!mInputBufferQueue.empty() 56572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang && !mAvailEncoderInputIndices.empty()) { 56672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang MediaBuffer* mbuf = *mInputBufferQueue.begin(); 56772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mInputBufferQueue.erase(mInputBufferQueue.begin()); 56872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 56972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang size_t bufferIndex = *mAvailEncoderInputIndices.begin(); 57072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mAvailEncoderInputIndices.erase(mAvailEncoderInputIndices.begin()); 57172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 57272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang int64_t timeUs = 0ll; 57372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang uint32_t flags = 0; 57472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang size_t size = 0; 57572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 57672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mbuf != NULL) { 57772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(mbuf->meta_data()->findInt64(kKeyTime, &timeUs)); 578d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim timeUs += mInputBufferTimeOffsetUs; 57972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 58072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang // push decoding time for video, or drift time for audio 58172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mIsVideo) { 58272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mDecodingTimeQueue.push_back(timeUs); 58372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } else { 58472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#if DEBUG_DRIFT_TIME 58572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mFirstSampleTimeUs < 0ll) { 58672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mFirstSampleTimeUs = timeUs; 58772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 58872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 58972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang int64_t driftTimeUs = 0; 59072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mbuf->meta_data()->findInt64(kKeyDriftTime, &driftTimeUs) 59172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang && driftTimeUs) { 59272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang driftTimeUs = timeUs - mFirstSampleTimeUs - driftTimeUs; 59372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 59472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mDriftTimeQueue.push_back(driftTimeUs); 59572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#endif // DEBUG_DRIFT_TIME 59672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 59772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 5981099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan sp<ABuffer> inbuf; 5991099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan status_t err = mEncoder->getInputBuffer(bufferIndex, &inbuf); 6001099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan if (err != OK || inbuf == NULL) { 6011099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan mbuf->release(); 6021099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan signalEOS(); 6031099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan break; 6041099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan } 6051099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan 60672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang size = mbuf->size(); 60772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 6081099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan memcpy(inbuf->data(), mbuf->data(), size); 60972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 61072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mIsVideo) { 61172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang // video encoder will release MediaBuffer when done 61272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang // with underlying data. 6131099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan inbuf->setMediaBufferBase(mbuf); 61472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } else { 61572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mbuf->release(); 61672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 61772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } else { 61872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang flags = MediaCodec::BUFFER_FLAG_EOS; 61972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 62072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 62172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang status_t err = mEncoder->queueInputBuffer( 62272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang bufferIndex, 0, size, timeUs, flags); 62372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 62472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (err != OK) { 62572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return err; 62672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 62772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 62872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 62972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return OK; 63072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 63172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 63272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::onStart(MetaData *params) { 63372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mStopping) { 63472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang ALOGE("Failed to start while we're stopping"); 63572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return INVALID_OPERATION; 63672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 63772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 63872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mStarted) { 63972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang ALOGI("MediaCodecSource (%s) resuming", mIsVideo ? "video" : "audio"); 64072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mFlags & FLAG_USE_SURFACE_INPUT) { 64172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang resume(); 64272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } else { 64372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(mPuller != NULL); 64472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mPuller->resume(); 64572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 64672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return OK; 64772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 64872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 64972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang ALOGI("MediaCodecSource (%s) starting", mIsVideo ? "video" : "audio"); 65072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 65172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang status_t err = OK; 65272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 65372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mFlags & FLAG_USE_SURFACE_INPUT) { 65472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang int64_t startTimeUs; 65572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (!params || !params->findInt64(kKeyTime, &startTimeUs)) { 65672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang startTimeUs = -1ll; 65772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 65872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang resume(startTimeUs); 65972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } else { 66072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(mPuller != NULL); 661c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar sp<MetaData> meta = params; 662c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar if (mSetEncoderFormat) { 663c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar if (meta == NULL) { 664c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar meta = new MetaData; 665c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar } 666c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar meta->setInt32(kKeyPixelFormat, mEncoderFormat); 667c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar meta->setInt32(kKeyColorSpace, mEncoderDataSpace); 668c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar } 669c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar 6701d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar sp<AMessage> notify = new AMessage(kWhatPullerNotify, mReflector); 671c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar err = mPuller->start(meta.get(), notify); 67272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (err != OK) { 67372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return err; 67472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 67572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 67672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 67772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang ALOGI("MediaCodecSource (%s) started", mIsVideo ? "video" : "audio"); 67872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 67972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mStarted = true; 68072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang return OK; 68172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 68272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 68372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::onMessageReceived(const sp<AMessage> &msg) { 68472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang switch (msg->what()) { 68572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang case kWhatPullerNotify: 68672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang { 68772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang MediaBuffer *mbuf; 68872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(msg->findPointer("accessUnit", (void**)&mbuf)); 68972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 69072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mbuf == NULL) { 69116e79115e497386eaf010af388627f94314a55a3Chong Zhang ALOGV("puller (%s) reached EOS", 69272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mIsVideo ? "video" : "audio"); 69316e79115e497386eaf010af388627f94314a55a3Chong Zhang signalEOS(); 69472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 69572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 69672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mEncoder == NULL) { 69772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang ALOGV("got msg '%s' after encoder shutdown.", 69872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang msg->debugString().c_str()); 69972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 70072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mbuf != NULL) { 70172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mbuf->release(); 70272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 70316e79115e497386eaf010af388627f94314a55a3Chong Zhang 70472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang break; 70572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 70672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 70772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mInputBufferQueue.push_back(mbuf); 70872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 70972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang feedEncoderInputBuffers(); 71072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 71172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang break; 71272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 71372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang case kWhatEncoderActivity: 71472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang { 71572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mEncoder == NULL) { 71672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang break; 71772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 71872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 7191099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan int32_t cbID; 7201099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan CHECK(msg->findInt32("callbackID", &cbID)); 7211099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan if (cbID == MediaCodec::CB_INPUT_AVAILABLE) { 7221099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan int32_t index; 7231099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan CHECK(msg->findInt32("index", &index)); 7241099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan 7251099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan mAvailEncoderInputIndices.push_back(index); 7261099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan feedEncoderInputBuffers(); 7271099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan } else if (cbID == MediaCodec::CB_OUTPUT_AVAILABLE) { 7281099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan int32_t index; 7291099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan size_t offset; 7301099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan size_t size; 7311099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan int64_t timeUs; 7321099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan int32_t flags; 7331099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan 7341099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan CHECK(msg->findInt32("index", &index)); 7351099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan CHECK(msg->findSize("offset", &offset)); 7361099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan CHECK(msg->findSize("size", &size)); 7371099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan CHECK(msg->findInt64("timeUs", &timeUs)); 7381099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan CHECK(msg->findInt32("flags", &flags)); 7391099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan 7401099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan if (flags & MediaCodec::BUFFER_FLAG_EOS) { 7411099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan mEncoder->releaseOutputBuffer(index); 7421099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan signalEOS(); 7431099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan break; 7441099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan } 745f2a64852a4a48c5a3d8a08ffcda20d6884586672Chong Zhang 7461099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan sp<ABuffer> outbuf; 7471099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan status_t err = mEncoder->getOutputBuffer(index, &outbuf); 7481099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan if (err != OK || outbuf == NULL) { 7491099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan signalEOS(); 7501099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan break; 7511099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan } 752f2a64852a4a48c5a3d8a08ffcda20d6884586672Chong Zhang 7531099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan MediaBuffer *mbuf = new MediaBuffer(outbuf->size()); 7541099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan memcpy(mbuf->data(), outbuf->data(), outbuf->size()); 75572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 7561099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan if (!(flags & MediaCodec::BUFFER_FLAG_CODECCONFIG)) { 7571099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan if (mIsVideo) { 7581099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan int64_t decodingTimeUs; 7591099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan if (mFlags & FLAG_USE_SURFACE_INPUT) { 760d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim // Time offset is not applied at 761d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim // feedEncoderInputBuffer() in surface input case. 762d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim timeUs += mInputBufferTimeOffsetUs; 7631099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan // GraphicBufferSource is supposed to discard samples 7641099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan // queued before start, and offset timeUs by start time 7651099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan CHECK_GE(timeUs, 0ll); 7661099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan // TODO: 7671099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan // Decoding time for surface source is unavailable, 7681099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan // use presentation time for now. May need to move 7691099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan // this logic into MediaCodec. 7701099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan decodingTimeUs = timeUs; 7711099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan } else { 7721099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan CHECK(!mDecodingTimeQueue.empty()); 7731099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan decodingTimeUs = *(mDecodingTimeQueue.begin()); 7741099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan mDecodingTimeQueue.erase(mDecodingTimeQueue.begin()); 7751099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan } 7761099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan mbuf->meta_data()->setInt64(kKeyDecodingTime, decodingTimeUs); 77772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 7781099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan ALOGV("[video] time %" PRId64 " us (%.2f secs), dts/pts diff %" PRId64, 7791099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan timeUs, timeUs / 1E6, decodingTimeUs - timeUs); 7801099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan } else { 7811099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan int64_t driftTimeUs = 0; 7821099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan#if DEBUG_DRIFT_TIME 7831099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan CHECK(!mDriftTimeQueue.empty()); 7841099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan driftTimeUs = *(mDriftTimeQueue.begin()); 7851099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan mDriftTimeQueue.erase(mDriftTimeQueue.begin()); 7861099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan mbuf->meta_data()->setInt64(kKeyDriftTime, driftTimeUs); 7871099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan#endif // DEBUG_DRIFT_TIME 7881099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan ALOGV("[audio] time %" PRId64 " us (%.2f secs), drift %" PRId64, 7891099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan timeUs, timeUs / 1E6, driftTimeUs); 7901099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan } 7911099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan mbuf->meta_data()->setInt64(kKeyTime, timeUs); 7921099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan } else { 7931099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan mbuf->meta_data()->setInt32(kKeyIsCodecConfig, true); 7941099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan } 7951099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan if (flags & MediaCodec::BUFFER_FLAG_SYNCFRAME) { 7961099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan mbuf->meta_data()->setInt32(kKeyIsSyncFrame, true); 7971099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan } 7981099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan mbuf->setObserver(this); 7991099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan mbuf->add_ref(); 8001099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan 8011099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan { 8021099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan Mutex::Autolock autoLock(mOutputBufferLock); 8031099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan mOutputBufferQueue.push_back(mbuf); 8041099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan mOutputBufferCond.signal(); 8051099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan } 8061099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan 8071099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan mEncoder->releaseOutputBuffer(index); 8081099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan } else if (cbID == MediaCodec::CB_ERROR) { 8091099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan status_t err; 8101099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan CHECK(msg->findInt32("err", &err)); 8111099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan ALOGE("Encoder (%s) reported error : 0x%x", 8121099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan mIsVideo ? "video" : "audio", err); 8131099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan signalEOS(); 8141099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan } 8151099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan break; 81672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 81772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang case kWhatStart: 81872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang { 8193f27436a9346f043f52265da1e6a74cde2bffd4dLajos Molnar sp<AReplyToken> replyID; 82072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(msg->senderAwaitsResponse(&replyID)); 82172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 82272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang sp<RefBase> obj; 82372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(msg->findObject("meta", &obj)); 82472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang MetaData *params = static_cast<MetaData *>(obj.get()); 82572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 82672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang sp<AMessage> response = new AMessage; 82772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang response->setInt32("err", onStart(params)); 82872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang response->postReply(replyID); 82972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang break; 83072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 83172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang case kWhatStop: 83272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang { 83316e79115e497386eaf010af388627f94314a55a3Chong Zhang ALOGI("encoder (%s) stopping", mIsVideo ? "video" : "audio"); 83472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 8353f27436a9346f043f52265da1e6a74cde2bffd4dLajos Molnar sp<AReplyToken> replyID; 83672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(msg->senderAwaitsResponse(&replyID)); 83772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 83816e79115e497386eaf010af388627f94314a55a3Chong Zhang if (mEncoderReachedEOS) { 83972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang // if we already reached EOS, reply and return now 84016e79115e497386eaf010af388627f94314a55a3Chong Zhang ALOGI("encoder (%s) already stopped", 84172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mIsVideo ? "video" : "audio"); 84272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang (new AMessage)->postReply(replyID); 84372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang break; 84472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 84572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 84672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mStopReplyIDQueue.push_back(replyID); 84772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mStopping) { 84872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang // nothing to do if we're already stopping, reply will be posted 84972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang // to all when we're stopped. 85072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang break; 85172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 85272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 85372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mStopping = true; 85472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 85572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang // if using surface, signal source EOS and wait for EOS to come back. 85672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang // otherwise, release encoder and post EOS if haven't done already 85772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang if (mFlags & FLAG_USE_SURFACE_INPUT) { 85872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mEncoder->signalEndOfInputStream(); 85972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } else { 86072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang signalEOS(); 86172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 86272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang break; 86372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 86472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang case kWhatPause: 86572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang { 866d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim if (mFlags & FLAG_USE_SURFACE_INPUT) { 86772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang suspend(); 86872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } else { 86972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang CHECK(mPuller != NULL); 87072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mPuller->pause(); 87172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 87272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang break; 87372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 874d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim case kWhatSetInputBufferTimeOffset: 875d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim { 876d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim sp<AReplyToken> replyID; 877d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim CHECK(msg->senderAwaitsResponse(&replyID)); 878d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim 879d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim CHECK(msg->findInt64("time-offset-us", &mInputBufferTimeOffsetUs)); 880d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim 881d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim sp<AMessage> response = new AMessage; 882d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim response->postReply(replyID); 883d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim break; 884d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim } 88572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang default: 88672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang TRESPASS(); 88772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang } 88872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} 88972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 89072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} // namespace android 891