MediaCodec.cpp revision 671160ffe81592efa376dc1ff0fc3f4ddcdebc35
120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber/* 220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Copyright 2012, The Android Open Source Project 320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * 420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License"); 520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * you may not use this file except in compliance with the License. 620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * You may obtain a copy of the License at 720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * 820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * http://www.apache.org/licenses/LICENSE-2.0 920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * 1020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Unless required by applicable law or agreed to in writing, software 1120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS, 1220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * See the License for the specific language governing permissions and 1420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * limitations under the License. 1520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber */ 1620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber//#define LOG_NDEBUG 0 18c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber#define LOG_TAG "MediaCodec" 1920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <utils/Log.h> 2020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <inttypes.h> 2189e69da4d86348409994c9dafbbb2634ccd7c196Andreas Huber 22c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber#include <media/stagefright/MediaCodec.h> 2389e69da4d86348409994c9dafbbb2634ccd7c196Andreas Huber 2420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include "include/SoftwareRenderer.h" 2520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <gui/Surface.h> 270c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber#include <media/ICrypto.h> 2820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/foundation/ABuffer.h> 2920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/foundation/ADebug.h> 3020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/foundation/AMessage.h> 3120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/foundation/AString.h> 32c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber#include <media/stagefright/foundation/hexdump.h> 33c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber#include <media/stagefright/ACodec.h> 34c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber#include <media/stagefright/BufferProducerWrapper.h> 35c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber#include <media/stagefright/MediaCodecList.h> 36c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber#include <media/stagefright/MediaDefs.h> 37c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber#include <media/stagefright/MediaErrors.h> 38c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber#include <media/stagefright/MetaData.h> 39c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber#include <media/stagefright/NativeWindowWrapper.h> 40c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber 41c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber#include "include/avc_utils.h" 4220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 43693d271e62a3726689ff68f4505ba49228eb94b2Andreas Hubernamespace android { 4420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 4520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber// static 4620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubersp<MediaCodec> MediaCodec::CreateByType( 4720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber const sp<ALooper> &looper, const char *mime, bool encoder) { 4820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber sp<MediaCodec> codec = new MediaCodec(looper); 4920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (codec->init(mime, true /* nameIsType */, encoder) != OK) { 5020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return NULL; 5120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 5220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 5320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return codec; 5420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 5520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 564678a6dc5f09008481524949a9667af5a6190374Andreas Huber// static 574931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Hubersp<MediaCodec> MediaCodec::CreateByComponentName( 584931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber const sp<ALooper> &looper, const char *name) { 5920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber sp<MediaCodec> codec = new MediaCodec(looper); 60c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber if (codec->init(name, false /* nameIsType */, false /* encoder */) != OK) { 618bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber return NULL; 628bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber } 63c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber 64c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber return codec; 6520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 6620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 6720111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMediaCodec::MediaCodec(const sp<ALooper> &looper) 68c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber : mState(UNINITIALIZED), 69c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber mLooper(looper), 70c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber mCodec(NULL), 718bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber mReplyID(0), 728bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber mFlags(0), 738bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber mSoftRenderer(NULL), 744931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber mDequeueInputTimeoutGeneration(0), 754931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber mDequeueInputReplyID(0), 764931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber mDequeueOutputTimeoutGeneration(0), 774678a6dc5f09008481524949a9667af5a6190374Andreas Huber mDequeueOutputReplyID(0), 784678a6dc5f09008481524949a9667af5a6190374Andreas Huber mHaveInputSurface(false) { 794678a6dc5f09008481524949a9667af5a6190374Andreas Huber} 8020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 8120111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMediaCodec::~MediaCodec() { 82c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber CHECK_EQ(mState, UNINITIALIZED); 83c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber} 84c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber 8520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber// static 8620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MediaCodec::PostAndAwaitResponse( 8720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber const sp<AMessage> &msg, sp<AMessage> *response) { 88c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong status_t err = msg->postAndAwaitResponse(response); 8920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 9020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (err != OK) { 9120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return err; 9220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 930c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber 9420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (!(*response)->findInt32("err", &err)) { 9520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber err = OK; 9620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 9720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 9820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return err; 9920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 10020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 10120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber// static 10220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MediaCodec::PostReplyWithError(int32_t replyID, int32_t err) { 10334769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber sp<AMessage> response = new AMessage; 10420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber response->setInt32("err", err); 10520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber response->postReply(replyID); 10620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 10720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 10820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MediaCodec::init(const char *name, bool nameIsType, bool encoder) { 10920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // save init parameters for reset 11020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mInitName = name; 11120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mInitNameIsType = nameIsType; 11220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mInitIsEncoder = encoder; 11320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 11420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // Current video decoders do not return from OMX_FillThisBuffer 11520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // quickly, violating the OpenMAX specs, until that is remedied 11620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // we need to invest in an extra looper to free the main event 11720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // queue. 11820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCodec = new ACodec; 11920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber bool needDedicatedLooper = false; 12020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (nameIsType && !strncasecmp(name, "video/", 6)) { 12120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber needDedicatedLooper = true; 12220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else { 12320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber AString tmp = name; 12420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (tmp.endsWith(".secure")) { 12520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber tmp.erase(tmp.size() - 7, 7); 12620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 12720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber const MediaCodecList *mcl = MediaCodecList::getInstance(); 12820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber ssize_t codecIdx = mcl->findCodecByName(tmp.c_str()); 129c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong if (codecIdx >= 0) { 13020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Vector<AString> types; 13120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mcl->getSupportedTypes(codecIdx, &types) == OK) { 13220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber for (size_t i = 0; i < types.size(); i++) { 13320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (types[i].startsWith("video/")) { 13420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber needDedicatedLooper = true; 13520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 13620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 13720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 13820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 13920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 14020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 14134769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber 14220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (needDedicatedLooper) { 14320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mCodecLooper == NULL) { 14420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCodecLooper = new ALooper; 14520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCodecLooper->setName("CodecLooper"); 14620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCodecLooper->start(false, false, ANDROID_PRIORITY_AUDIO); 14720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 14820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 14920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCodecLooper->registerHandler(mCodec); 15020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else { 15120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mLooper->registerHandler(mCodec); 15220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 15320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 15420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mLooper->registerHandler(this); 15520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 15620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCodec->setNotificationMessage(new AMessage(kWhatCodecNotify, id())); 157c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber 158c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber sp<AMessage> msg = new AMessage(kWhatInit, id()); 159c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber msg->setString("name", name); 160c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber msg->setInt32("nameIsType", nameIsType); 161c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber 162c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber if (nameIsType) { 163c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber msg->setInt32("encoder", encoder); 164c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber } 165c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber 166c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber sp<AMessage> response; 167c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber return PostAndAwaitResponse(msg, &response); 168c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber} 169c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber 170c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huberstatus_t MediaCodec::setCallback(const sp<AMessage> &callback) { 171c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber sp<AMessage> msg = new AMessage(kWhatSetCallback, id()); 172c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber msg->setMessage("callback", callback); 173c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber 174c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber sp<AMessage> response; 175c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber return PostAndAwaitResponse(msg, &response); 17620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 17720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 17820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MediaCodec::configure( 17920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber const sp<AMessage> &format, 180c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong const sp<Surface> &nativeWindow, 18120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber const sp<ICrypto> &crypto, 18220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint32_t flags) { 18320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber sp<AMessage> msg = new AMessage(kWhatConfigure, id()); 18420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1850c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber msg->setMessage("format", format); 18620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber msg->setInt32("flags", flags); 18720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 18820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (nativeWindow != NULL) { 18920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber msg->setObject( 19020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber "native-window", 19120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber new NativeWindowWrapper(nativeWindow)); 19220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 19320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 19434769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber if (crypto != NULL) { 19520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber msg->setPointer("crypto", crypto.get()); 19620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 19720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 19820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber sp<AMessage> response; 19920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return PostAndAwaitResponse(msg, &response); 20020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 20120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 20220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MediaCodec::createInputSurface( 20320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber sp<IGraphicBufferProducer>* bufferProducer) { 20420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber sp<AMessage> msg = new AMessage(kWhatCreateInputSurface, id()); 20520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 20620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber sp<AMessage> response; 20720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber status_t err = PostAndAwaitResponse(msg, &response); 20820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (err == NO_ERROR) { 20920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // unwrap the sp<IGraphicBufferProducer> 21020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber sp<RefBase> obj; 21120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber bool found = response->findObject("input-surface", &obj); 21220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber CHECK(found); 21320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber sp<BufferProducerWrapper> wrapper( 21420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber static_cast<BufferProducerWrapper*>(obj.get())); 21520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *bufferProducer = wrapper->getBufferProducer(); 21620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else { 21720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber ALOGW("createInputSurface failed, err=%d", err); 21820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 21920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return err; 22020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 22120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 22220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MediaCodec::start() { 2239f753df58a70f20db220af31cb202bbd21b30f36Andreas Huber sp<AMessage> msg = new AMessage(kWhatStart, id()); 22420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 22520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber sp<AMessage> response; 22620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return PostAndAwaitResponse(msg, &response); 22720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 22820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 22920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MediaCodec::stop() { 23020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber sp<AMessage> msg = new AMessage(kWhatStop, id()); 23120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 23220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber sp<AMessage> response; 23320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return PostAndAwaitResponse(msg, &response); 23420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 23520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 23620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MediaCodec::release() { 23720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber sp<AMessage> msg = new AMessage(kWhatRelease, id()); 23820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 23920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber sp<AMessage> response; 240c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong return PostAndAwaitResponse(msg, &response); 24120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 24220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 24320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MediaCodec::reset() { 24420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber /* When external-facing MediaCodec object is created, 24520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber it is already initialized. Thus, reset is essentially 24634769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber release() followed by init(), plus clearing the state */ 24720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 24820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber status_t err = release(); 24920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 25020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // unregister handlers 25120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mCodec != NULL) { 25220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mCodecLooper != NULL) { 25320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCodecLooper->unregisterHandler(mCodec->id()); 25420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else { 25520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mLooper->unregisterHandler(mCodec->id()); 25620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 25720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCodec = NULL; 25820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 25920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mLooper->unregisterHandler(id()); 26034769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber 26120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mFlags = 0; // clear all flags 26220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 26320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // reset state not reset by setState(UNINITIALIZED) 26420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mReplyID = 0; 26520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDequeueInputReplyID = 0; 26620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDequeueOutputReplyID = 0; 26720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDequeueInputTimeoutGeneration = 0; 26820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDequeueOutputTimeoutGeneration = 0; 26920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mHaveInputSurface = false; 27020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 27120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (err == OK) { 2724931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber err = init(mInitName.c_str(), mInitNameIsType, mInitIsEncoder); 2734931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber } 2744931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber return err; 2754931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber} 2764931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber 2774931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huberstatus_t MediaCodec::queueInputBuffer( 2784931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber size_t index, 2794931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber size_t offset, 2804931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber size_t size, 2814931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber int64_t presentationTimeUs, 2824931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber uint32_t flags, 2834931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber AString *errorDetailMsg) { 2844931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber if (errorDetailMsg != NULL) { 2854931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber errorDetailMsg->clear(); 2864931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber } 2874931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber 2884931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber sp<AMessage> msg = new AMessage(kWhatQueueInputBuffer, id()); 2894931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber msg->setSize("index", index); 2904931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber msg->setSize("offset", offset); 2914931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber msg->setSize("size", size); 2924931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber msg->setInt64("timeUs", presentationTimeUs); 2934931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber msg->setInt32("flags", flags); 2944931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber msg->setPointer("errorDetailMsg", errorDetailMsg); 2954931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber 2964931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber sp<AMessage> response; 2974931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber return PostAndAwaitResponse(msg, &response); 2984931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber} 2994931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber 3004931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huberstatus_t MediaCodec::queueSecureInputBuffer( 3014931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber size_t index, 3024931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber size_t offset, 3034931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber const CryptoPlugin::SubSample *subSamples, 3044931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber size_t numSubSamples, 3054931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber const uint8_t key[16], 3064931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber const uint8_t iv[16], 3074931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber CryptoPlugin::Mode mode, 3084931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber int64_t presentationTimeUs, 3094931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber uint32_t flags, 3104931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber AString *errorDetailMsg) { 3114931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber if (errorDetailMsg != NULL) { 3124931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber errorDetailMsg->clear(); 3134931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber } 3144931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber 3154931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber sp<AMessage> msg = new AMessage(kWhatQueueInputBuffer, id()); 3164931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber msg->setSize("index", index); 317c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong msg->setSize("offset", offset); 31820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber msg->setPointer("subSamples", (void *)subSamples); 31920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber msg->setSize("numSubSamples", numSubSamples); 32020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber msg->setPointer("key", (void *)key); 32120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber msg->setPointer("iv", (void *)iv); 32220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber msg->setInt32("mode", mode); 32320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber msg->setInt64("timeUs", presentationTimeUs); 32420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber msg->setInt32("flags", flags); 32534769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber msg->setPointer("errorDetailMsg", errorDetailMsg); 32620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 32720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber sp<AMessage> response; 32820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber status_t err = PostAndAwaitResponse(msg, &response); 32920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 33020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return err; 33120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 33220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 33320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MediaCodec::dequeueInputBuffer(size_t *index, int64_t timeoutUs) { 33420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber sp<AMessage> msg = new AMessage(kWhatDequeueInputBuffer, id()); 33520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber msg->setInt64("timeoutUs", timeoutUs); 33620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 33720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber sp<AMessage> response; 33875fc7654280ac2a72fa8124b88e616219a3e61e2Andreas Huber status_t err; 33920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if ((err = PostAndAwaitResponse(msg, &response)) != OK) { 3408bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber return err; 3418bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber } 3428bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber 3438bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber CHECK(response->findSize("index", index)); 3448bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber 3458bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber return OK; 3468bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber} 3478bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber 3488bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huberstatus_t MediaCodec::dequeueOutputBuffer( 3498bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber size_t *index, 3508bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber size_t *offset, 3518bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber size_t *size, 35220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int64_t *presentationTimeUs, 35320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint32_t *flags, 35420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int64_t timeoutUs) { 35520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber sp<AMessage> msg = new AMessage(kWhatDequeueOutputBuffer, id()); 35620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber msg->setInt64("timeoutUs", timeoutUs); 35720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 35820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber sp<AMessage> response; 35920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber status_t err; 36020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if ((err = PostAndAwaitResponse(msg, &response)) != OK) { 36120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return err; 36220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 36320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 36420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber CHECK(response->findSize("index", index)); 36520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber CHECK(response->findSize("offset", offset)); 36620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber CHECK(response->findSize("size", size)); 36720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber CHECK(response->findInt64("timeUs", presentationTimeUs)); 36820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber CHECK(response->findInt32("flags", (int32_t *)flags)); 36920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 370c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber return OK; 371da76c64dee7d95c967e2841302300cfb081e67b2Andreas Huber} 37220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 37320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MediaCodec::renderOutputBufferAndRelease(size_t index) { 37420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber sp<AMessage> msg = new AMessage(kWhatReleaseOutputBuffer, id()); 37520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber msg->setSize("index", index); 37620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber msg->setInt32("render", true); 37720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 37820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber sp<AMessage> response; 37920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return PostAndAwaitResponse(msg, &response); 38020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 38120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 38220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MediaCodec::renderOutputBufferAndRelease(size_t index, int64_t timestampNs) { 38320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber sp<AMessage> msg = new AMessage(kWhatReleaseOutputBuffer, id()); 384da76c64dee7d95c967e2841302300cfb081e67b2Andreas Huber msg->setSize("index", index); 385da76c64dee7d95c967e2841302300cfb081e67b2Andreas Huber msg->setInt32("render", true); 386da76c64dee7d95c967e2841302300cfb081e67b2Andreas Huber msg->setInt64("timestampNs", timestampNs); 387da76c64dee7d95c967e2841302300cfb081e67b2Andreas Huber 3884678a6dc5f09008481524949a9667af5a6190374Andreas Huber sp<AMessage> response; 3894678a6dc5f09008481524949a9667af5a6190374Andreas Huber return PostAndAwaitResponse(msg, &response); 3904678a6dc5f09008481524949a9667af5a6190374Andreas Huber} 3914678a6dc5f09008481524949a9667af5a6190374Andreas Huber 3924931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huberstatus_t MediaCodec::releaseOutputBuffer(size_t index) { 3934678a6dc5f09008481524949a9667af5a6190374Andreas Huber sp<AMessage> msg = new AMessage(kWhatReleaseOutputBuffer, id()); 3944678a6dc5f09008481524949a9667af5a6190374Andreas Huber msg->setSize("index", index); 3954678a6dc5f09008481524949a9667af5a6190374Andreas Huber 3964678a6dc5f09008481524949a9667af5a6190374Andreas Huber sp<AMessage> response; 3974678a6dc5f09008481524949a9667af5a6190374Andreas Huber return PostAndAwaitResponse(msg, &response); 398abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber} 3994678a6dc5f09008481524949a9667af5a6190374Andreas Huber 4004678a6dc5f09008481524949a9667af5a6190374Andreas Huberstatus_t MediaCodec::signalEndOfInputStream() { 4014678a6dc5f09008481524949a9667af5a6190374Andreas Huber sp<AMessage> msg = new AMessage(kWhatSignalEndOfInputStream, id()); 4024678a6dc5f09008481524949a9667af5a6190374Andreas Huber 40320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber sp<AMessage> response; 40420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return PostAndAwaitResponse(msg, &response); 4054678a6dc5f09008481524949a9667af5a6190374Andreas Huber} 4064678a6dc5f09008481524949a9667af5a6190374Andreas Huber 4074678a6dc5f09008481524949a9667af5a6190374Andreas Huberstatus_t MediaCodec::getOutputFormat(sp<AMessage> *format) const { 4084678a6dc5f09008481524949a9667af5a6190374Andreas Huber sp<AMessage> msg = new AMessage(kWhatGetOutputFormat, id()); 4094678a6dc5f09008481524949a9667af5a6190374Andreas Huber 4104678a6dc5f09008481524949a9667af5a6190374Andreas Huber sp<AMessage> response; 4114678a6dc5f09008481524949a9667af5a6190374Andreas Huber status_t err; 4124678a6dc5f09008481524949a9667af5a6190374Andreas Huber if ((err = PostAndAwaitResponse(msg, &response)) != OK) { 4134678a6dc5f09008481524949a9667af5a6190374Andreas Huber return err; 41420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 41520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 41620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber CHECK(response->findMessage("format", format)); 41720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 4184678a6dc5f09008481524949a9667af5a6190374Andreas Huber return OK; 4194678a6dc5f09008481524949a9667af5a6190374Andreas Huber} 42020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 4214678a6dc5f09008481524949a9667af5a6190374Andreas Huberstatus_t MediaCodec::getInputFormat(sp<AMessage> *format) const { 422abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber sp<AMessage> msg = new AMessage(kWhatGetInputFormat, id()); 4234678a6dc5f09008481524949a9667af5a6190374Andreas Huber 4244678a6dc5f09008481524949a9667af5a6190374Andreas Huber sp<AMessage> response; 4254678a6dc5f09008481524949a9667af5a6190374Andreas Huber status_t err; 4264678a6dc5f09008481524949a9667af5a6190374Andreas Huber if ((err = PostAndAwaitResponse(msg, &response)) != OK) { 4274678a6dc5f09008481524949a9667af5a6190374Andreas Huber return err; 4284678a6dc5f09008481524949a9667af5a6190374Andreas Huber } 4294678a6dc5f09008481524949a9667af5a6190374Andreas Huber 4304678a6dc5f09008481524949a9667af5a6190374Andreas Huber CHECK(response->findMessage("format", format)); 4314678a6dc5f09008481524949a9667af5a6190374Andreas Huber 4324678a6dc5f09008481524949a9667af5a6190374Andreas Huber return OK; 4334678a6dc5f09008481524949a9667af5a6190374Andreas Huber} 4344678a6dc5f09008481524949a9667af5a6190374Andreas Huber 4354678a6dc5f09008481524949a9667af5a6190374Andreas Huberstatus_t MediaCodec::getName(AString *name) const { 4364678a6dc5f09008481524949a9667af5a6190374Andreas Huber sp<AMessage> msg = new AMessage(kWhatGetName, id()); 4374678a6dc5f09008481524949a9667af5a6190374Andreas Huber 4384678a6dc5f09008481524949a9667af5a6190374Andreas Huber sp<AMessage> response; 4394678a6dc5f09008481524949a9667af5a6190374Andreas Huber status_t err; 4404678a6dc5f09008481524949a9667af5a6190374Andreas Huber if ((err = PostAndAwaitResponse(msg, &response)) != OK) { 4414678a6dc5f09008481524949a9667af5a6190374Andreas Huber return err; 4424678a6dc5f09008481524949a9667af5a6190374Andreas Huber } 4434678a6dc5f09008481524949a9667af5a6190374Andreas Huber 4444678a6dc5f09008481524949a9667af5a6190374Andreas Huber CHECK(response->findString("name", name)); 4454678a6dc5f09008481524949a9667af5a6190374Andreas Huber 4464678a6dc5f09008481524949a9667af5a6190374Andreas Huber return OK; 4474678a6dc5f09008481524949a9667af5a6190374Andreas Huber} 4484678a6dc5f09008481524949a9667af5a6190374Andreas Huber 4494678a6dc5f09008481524949a9667af5a6190374Andreas Huberstatus_t MediaCodec::getInputBuffers(Vector<sp<ABuffer> > *buffers) const { 4504678a6dc5f09008481524949a9667af5a6190374Andreas Huber sp<AMessage> msg = new AMessage(kWhatGetBuffers, id()); 4514678a6dc5f09008481524949a9667af5a6190374Andreas Huber msg->setInt32("portIndex", kPortIndexInput); 4524678a6dc5f09008481524949a9667af5a6190374Andreas Huber msg->setPointer("buffers", buffers); 4534678a6dc5f09008481524949a9667af5a6190374Andreas Huber 4544678a6dc5f09008481524949a9667af5a6190374Andreas Huber sp<AMessage> response; 4554678a6dc5f09008481524949a9667af5a6190374Andreas Huber return PostAndAwaitResponse(msg, &response); 456a488c7daf91357611fcdbff7a32e5a73ec630070Andreas Huber} 457a488c7daf91357611fcdbff7a32e5a73ec630070Andreas Huber 458a488c7daf91357611fcdbff7a32e5a73ec630070Andreas Huberstatus_t MediaCodec::getOutputBuffers(Vector<sp<ABuffer> > *buffers) const { 459a488c7daf91357611fcdbff7a32e5a73ec630070Andreas Huber sp<AMessage> msg = new AMessage(kWhatGetBuffers, id()); 4604678a6dc5f09008481524949a9667af5a6190374Andreas Huber msg->setInt32("portIndex", kPortIndexOutput); 4614678a6dc5f09008481524949a9667af5a6190374Andreas Huber msg->setPointer("buffers", buffers); 4624678a6dc5f09008481524949a9667af5a6190374Andreas Huber 4634678a6dc5f09008481524949a9667af5a6190374Andreas Huber sp<AMessage> response; 464abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber return PostAndAwaitResponse(msg, &response); 4654678a6dc5f09008481524949a9667af5a6190374Andreas Huber} 4664678a6dc5f09008481524949a9667af5a6190374Andreas Huber 4674678a6dc5f09008481524949a9667af5a6190374Andreas Huberstatus_t MediaCodec::getOutputBuffer(size_t index, sp<ABuffer> *buffer) { 4684678a6dc5f09008481524949a9667af5a6190374Andreas Huber sp<AMessage> format; 4694678a6dc5f09008481524949a9667af5a6190374Andreas Huber return getBufferAndFormat(kPortIndexOutput, index, buffer, &format); 4704678a6dc5f09008481524949a9667af5a6190374Andreas Huber} 4714678a6dc5f09008481524949a9667af5a6190374Andreas Huber 47220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MediaCodec::getOutputFormat(size_t index, sp<AMessage> *format) { 4734678a6dc5f09008481524949a9667af5a6190374Andreas Huber sp<ABuffer> buffer; 4744678a6dc5f09008481524949a9667af5a6190374Andreas Huber return getBufferAndFormat(kPortIndexOutput, index, &buffer, format); 47520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 4764678a6dc5f09008481524949a9667af5a6190374Andreas Huber 4774678a6dc5f09008481524949a9667af5a6190374Andreas Huberstatus_t MediaCodec::getInputBuffer(size_t index, sp<ABuffer> *buffer) { 4784678a6dc5f09008481524949a9667af5a6190374Andreas Huber sp<AMessage> format; 4794678a6dc5f09008481524949a9667af5a6190374Andreas Huber return getBufferAndFormat(kPortIndexInput, index, buffer, &format); 4804678a6dc5f09008481524949a9667af5a6190374Andreas Huber} 4814678a6dc5f09008481524949a9667af5a6190374Andreas Huber 4824678a6dc5f09008481524949a9667af5a6190374Andreas Huberstatus_t MediaCodec::getBufferAndFormat( 4834678a6dc5f09008481524949a9667af5a6190374Andreas Huber size_t portIndex, size_t index, 48420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber sp<ABuffer> *buffer, sp<AMessage> *format) { 48520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // use mutex instead of a context switch 4864678a6dc5f09008481524949a9667af5a6190374Andreas Huber 4874678a6dc5f09008481524949a9667af5a6190374Andreas Huber buffer->clear(); 4884678a6dc5f09008481524949a9667af5a6190374Andreas Huber format->clear(); 4894678a6dc5f09008481524949a9667af5a6190374Andreas Huber if (mState != STARTED) { 4904678a6dc5f09008481524949a9667af5a6190374Andreas Huber return INVALID_OPERATION; 4914678a6dc5f09008481524949a9667af5a6190374Andreas Huber } 4924678a6dc5f09008481524949a9667af5a6190374Andreas Huber 4934678a6dc5f09008481524949a9667af5a6190374Andreas Huber // we do not want mPortBuffers to change during this section 4944678a6dc5f09008481524949a9667af5a6190374Andreas Huber // we also don't want mOwnedByClient to change during this 4954678a6dc5f09008481524949a9667af5a6190374Andreas Huber Mutex::Autolock al(mBufferLock); 4964678a6dc5f09008481524949a9667af5a6190374Andreas Huber Vector<BufferInfo> *buffers = &mPortBuffers[portIndex]; 4974678a6dc5f09008481524949a9667af5a6190374Andreas Huber if (index < buffers->size()) { 4984678a6dc5f09008481524949a9667af5a6190374Andreas Huber const BufferInfo &info = buffers->itemAt(index); 4994678a6dc5f09008481524949a9667af5a6190374Andreas Huber if (info.mOwnedByClient) { 5004678a6dc5f09008481524949a9667af5a6190374Andreas Huber *buffer = info.mData; 5014678a6dc5f09008481524949a9667af5a6190374Andreas Huber *format = info.mFormat; 5024678a6dc5f09008481524949a9667af5a6190374Andreas Huber } 5034678a6dc5f09008481524949a9667af5a6190374Andreas Huber } 5044678a6dc5f09008481524949a9667af5a6190374Andreas Huber return OK; 5054678a6dc5f09008481524949a9667af5a6190374Andreas Huber} 5064678a6dc5f09008481524949a9667af5a6190374Andreas Huber 5074678a6dc5f09008481524949a9667af5a6190374Andreas Huberstatus_t MediaCodec::flush() { 5084678a6dc5f09008481524949a9667af5a6190374Andreas Huber sp<AMessage> msg = new AMessage(kWhatFlush, id()); 50920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 51020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber sp<AMessage> response; 5114678a6dc5f09008481524949a9667af5a6190374Andreas Huber return PostAndAwaitResponse(msg, &response); 5124678a6dc5f09008481524949a9667af5a6190374Andreas Huber} 5134678a6dc5f09008481524949a9667af5a6190374Andreas Huber 51420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MediaCodec::requestIDRFrame() { 51520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber (new AMessage(kWhatRequestIDRFrame, id()))->post(); 516abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber 517abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber return OK; 518abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber} 519abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber 52020111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MediaCodec::requestActivityNotification(const sp<AMessage> ¬ify) { 52120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber sp<AMessage> msg = new AMessage(kWhatRequestActivityNotification, id()); 52220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber msg->setMessage("notify", notify); 52320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber msg->post(); 52420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 52520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 52620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber//////////////////////////////////////////////////////////////////////////////// 52720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 528abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Hubervoid MediaCodec::cancelPendingDequeueOperations() { 529abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber if (mFlags & kFlagDequeueInputPending) { 530abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber PostReplyWithError(mDequeueInputReplyID, INVALID_OPERATION); 531abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber 532da76c64dee7d95c967e2841302300cfb081e67b2Andreas Huber ++mDequeueInputTimeoutGeneration; 533abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber mDequeueInputReplyID = 0; 534abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber mFlags &= ~kFlagDequeueInputPending; 5358bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber } 53620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 537abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber if (mFlags & kFlagDequeueOutputPending) { 53820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber PostReplyWithError(mDequeueOutputReplyID, INVALID_OPERATION); 53920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 540abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber ++mDequeueOutputTimeoutGeneration; 541abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber mDequeueOutputReplyID = 0; 542abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber mFlags &= ~kFlagDequeueOutputPending; 543f53263a7d580fb550dbc6c8d4f104119beb82ad7James Dong } 544f53263a7d580fb550dbc6c8d4f104119beb82ad7James Dong} 545f53263a7d580fb550dbc6c8d4f104119beb82ad7James Dong 546abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huberbool MediaCodec::handleDequeueInputBuffer(uint32_t replyID, bool newRequest) { 547abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber if (mState != STARTED 548abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber || (mFlags & kFlagStickyError) 549abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber || (newRequest && (mFlags & kFlagDequeueInputPending))) { 550abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber PostReplyWithError(replyID, INVALID_OPERATION); 551abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber return true; 552abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber } 553abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber 554abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber ssize_t index = dequeuePortBuffer(kPortIndexInput); 555abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber 556abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber if (index < 0) { 5578bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber CHECK_EQ(index, -EAGAIN); 558abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber return false; 559abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber } 560abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber 561abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber sp<AMessage> response = new AMessage; 562abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber response->setSize("index", index); 563abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber response->postReply(replyID); 564abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber 565abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber return true; 566abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber} 567abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber 568abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huberbool MediaCodec::handleDequeueOutputBuffer(uint32_t replyID, bool newRequest) { 569abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber sp<AMessage> response = new AMessage; 570abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber 571abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber if (mState != STARTED 572abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber || (mFlags & kFlagStickyError) 573abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber || (newRequest && (mFlags & kFlagDequeueOutputPending))) { 574abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber response->setInt32("err", INVALID_OPERATION); 575abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber } else if (mFlags & kFlagOutputBuffersChanged) { 576abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber response->setInt32("err", INFO_OUTPUT_BUFFERS_CHANGED); 577abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber mFlags &= ~kFlagOutputBuffersChanged; 578abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber } else if (mFlags & kFlagOutputFormatChanged) { 579abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber response->setInt32("err", INFO_FORMAT_CHANGED); 580abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber mFlags &= ~kFlagOutputFormatChanged; 581abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber } else { 582abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber ssize_t index = dequeuePortBuffer(kPortIndexOutput); 583abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber 584abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber if (index < 0) { 585abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber CHECK_EQ(index, -EAGAIN); 586abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber return false; 587abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber } 588abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber 589abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber const sp<ABuffer> &buffer = 590abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber mPortBuffers[kPortIndexOutput].itemAt(index).mData; 591abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber 592abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber response->setSize("index", index); 593abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber response->setSize("offset", buffer->offset()); 594abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber response->setSize("size", buffer->size()); 595abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber 596abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber int64_t timeUs; 597abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber CHECK(buffer->meta()->findInt64("timeUs", &timeUs)); 598abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber 599abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber response->setInt64("timeUs", timeUs); 600abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber 601abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber int32_t omxFlags; 602abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber CHECK(buffer->meta()->findInt32("omxFlags", &omxFlags)); 603abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber 604abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber uint32_t flags = 0; 605abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber if (omxFlags & OMX_BUFFERFLAG_SYNCFRAME) { 606abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber flags |= BUFFER_FLAG_SYNCFRAME; 607abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber } 608abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber if (omxFlags & OMX_BUFFERFLAG_CODECCONFIG) { 609abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber flags |= BUFFER_FLAG_CODECCONFIG; 610abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber } 611abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber if (omxFlags & OMX_BUFFERFLAG_EOS) { 612abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber flags |= BUFFER_FLAG_EOS; 613abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber } 614abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber 6158bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber response->setInt32("flags", flags); 616abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber } 617abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber 618abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber response->postReply(replyID); 619abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber 620abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber return true; 621abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber} 622abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber 623abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Hubervoid MediaCodec::onMessageReceived(const sp<AMessage> &msg) { 624abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber switch (msg->what()) { 62520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case kWhatCodecNotify: 62620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber { 627abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber int32_t what; 62820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber CHECK(msg->findInt32("what", &what)); 62920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 63020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber switch (what) { 63120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case CodecBase::kWhatError: 6327e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber { 633c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber int32_t omxError, internalError; 634c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber CHECK(msg->findInt32("omx-error", &omxError)); 6357e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber CHECK(msg->findInt32("err", &internalError)); 6367e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber 6377e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber ALOGE("Codec reported an error. " 6387e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber "(omx error 0x%08x, internalError %d)", 6397e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber omxError, internalError); 6407e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber 6417e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber if (omxError == OMX_ErrorResourcesLost 6427e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber && internalError == DEAD_OBJECT) { 6437e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber mFlags |= kFlagSawMediaServerDie; 6447e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber } 6457e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber 6467e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber bool sendErrorReponse = true; 6477e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber 6487e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber switch (mState) { 6497e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber case INITIALIZING: 6507e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber { 6517e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber setState(UNINITIALIZED); 6527e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber break; 6537e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber } 6547e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber 6558bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber case CONFIGURING: 6567e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber { 6577e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber setState(INITIALIZED); 6587e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber break; 659c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber } 6607e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber 6617e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber case STARTING: 6627e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber { 6637e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber setState(CONFIGURED); 6647e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber break; 6657e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber } 6667e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber 6677e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber case STOPPING: 6687e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber case RELEASING: 6697e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber { 6707e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber // Ignore the error, assuming we'll still get 6717e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber // the shutdown complete notification. 6727e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber 6737e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber sendErrorReponse = false; 6747e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber 675c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber if (mFlags & kFlagSawMediaServerDie) { 676c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber // MediaServer died, there definitely won't 677c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber // be a shutdown complete notification after 678c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber // all. 679c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber 680c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber // note that we're directly going from 681c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber // STOPPING->UNINITIALIZED, instead of the 682c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber // usual STOPPING->INITIALIZED state. 683c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong setState(UNINITIALIZED); 684c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber 6854678a6dc5f09008481524949a9667af5a6190374Andreas Huber (new AMessage)->postReply(mReplyID); 6868bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber } 687c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber break; 688c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber } 689c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber 690c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber case FLUSHING: 691c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber { 692c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber setState(STARTED); 693c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber break; 694c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber } 695c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber 696c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber case STARTED: 697c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber { 698c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber sendErrorReponse = false; 699c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber 700c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber mFlags |= kFlagStickyError; 701c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber postActivityNotificationIfPossible(); 7024678a6dc5f09008481524949a9667af5a6190374Andreas Huber 7034678a6dc5f09008481524949a9667af5a6190374Andreas Huber cancelPendingDequeueOperations(); 704c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber 705c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber if (mFlags & kFlagIsAsync) { 7068bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber onError(omxError, 0); 7078bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber } 7088bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber setState(UNINITIALIZED); 7098bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber break; 7108bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber } 7118bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber 7128bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber default: 7138bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber { 7148bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber sendErrorReponse = false; 7158bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber 7168bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber mFlags |= kFlagStickyError; 7178bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber postActivityNotificationIfPossible(); 7188bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber 7198bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber if (mFlags & kFlagIsAsync) { 7208bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber onError(omxError, 0); 7218bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber } 7228bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber setState(UNINITIALIZED); 7238bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber break; 7248bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber } 7258bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber } 7268bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber 7278bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber if (sendErrorReponse) { 728c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber PostReplyWithError(mReplyID, UNKNOWN_ERROR); 729c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber } 730c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber break; 7314931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber } 7324931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber 7334931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber case CodecBase::kWhatComponentAllocated: 7344931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber { 7354931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber CHECK_EQ(mState, INITIALIZING); 7364931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber setState(INITIALIZED); 7374931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber 7384931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber CHECK(msg->findString("componentName", &mComponentName)); 7394931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber 7404931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber if (mComponentName.startsWith("OMX.google.")) { 7414931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber mFlags |= kFlagIsSoftwareCodec; 7424931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber } else { 7434931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber mFlags &= ~kFlagIsSoftwareCodec; 7444931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber } 7454931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber 7464931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber if (mComponentName.endsWith(".secure")) { 7474931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber mFlags |= kFlagIsSecure; 7484931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber } else { 7494931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber mFlags &= ~kFlagIsSecure; 7504931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber } 7514931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber 75220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber (new AMessage)->postReply(mReplyID); 75320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 754 } 755 756 case CodecBase::kWhatComponentConfigured: 757 { 758 CHECK_EQ(mState, CONFIGURING); 759 setState(CONFIGURED); 760 761 // reset input surface flag 762 mHaveInputSurface = false; 763 764 CHECK(msg->findMessage("input-format", &mInputFormat)); 765 CHECK(msg->findMessage("output-format", &mOutputFormat)); 766 767 (new AMessage)->postReply(mReplyID); 768 break; 769 } 770 771 case CodecBase::kWhatInputSurfaceCreated: 772 { 773 // response to initiateCreateInputSurface() 774 status_t err = NO_ERROR; 775 sp<AMessage> response = new AMessage(); 776 if (!msg->findInt32("err", &err)) { 777 sp<RefBase> obj; 778 msg->findObject("input-surface", &obj); 779 CHECK(obj != NULL); 780 response->setObject("input-surface", obj); 781 mHaveInputSurface = true; 782 } else { 783 response->setInt32("err", err); 784 } 785 response->postReply(mReplyID); 786 break; 787 } 788 789 case CodecBase::kWhatSignaledInputEOS: 790 { 791 // response to signalEndOfInputStream() 792 sp<AMessage> response = new AMessage(); 793 status_t err; 794 if (msg->findInt32("err", &err)) { 795 response->setInt32("err", err); 796 } 797 response->postReply(mReplyID); 798 break; 799 } 800 801 802 case CodecBase::kWhatBuffersAllocated: 803 { 804 Mutex::Autolock al(mBufferLock); 805 int32_t portIndex; 806 CHECK(msg->findInt32("portIndex", &portIndex)); 807 808 ALOGV("%s buffers allocated", 809 portIndex == kPortIndexInput ? "input" : "output"); 810 811 CHECK(portIndex == kPortIndexInput 812 || portIndex == kPortIndexOutput); 813 814 mPortBuffers[portIndex].clear(); 815 816 Vector<BufferInfo> *buffers = &mPortBuffers[portIndex]; 817 818 sp<RefBase> obj; 819 CHECK(msg->findObject("portDesc", &obj)); 820 821 sp<CodecBase::PortDescription> portDesc = 822 static_cast<CodecBase::PortDescription *>(obj.get()); 823 824 size_t numBuffers = portDesc->countBuffers(); 825 826 for (size_t i = 0; i < numBuffers; ++i) { 827 BufferInfo info; 828 info.mBufferID = portDesc->bufferIDAt(i); 829 info.mOwnedByClient = false; 830 info.mData = portDesc->bufferAt(i); 831 832 if (portIndex == kPortIndexInput && mCrypto != NULL) { 833 info.mEncryptedData = 834 new ABuffer(info.mData->capacity()); 835 } 836 837 buffers->push_back(info); 838 } 839 840 if (portIndex == kPortIndexOutput) { 841 if (mState == STARTING) { 842 // We're always allocating output buffers after 843 // allocating input buffers, so this is a good 844 // indication that now all buffers are allocated. 845 setState(STARTED); 846 (new AMessage)->postReply(mReplyID); 847 } else { 848 mFlags |= kFlagOutputBuffersChanged; 849 postActivityNotificationIfPossible(); 850 } 851 } 852 break; 853 } 854 855 case CodecBase::kWhatOutputFormatChanged: 856 { 857 ALOGV("codec output format changed"); 858 859 if ((mFlags & kFlagIsSoftwareCodec) 860 && mNativeWindow != NULL) { 861 AString mime; 862 CHECK(msg->findString("mime", &mime)); 863 864 if (!strncasecmp("video/", mime.c_str(), 6)) { 865 delete mSoftRenderer; 866 mSoftRenderer = NULL; 867 868 int32_t width, height; 869 CHECK(msg->findInt32("width", &width)); 870 CHECK(msg->findInt32("height", &height)); 871 872 int32_t cropLeft, cropTop, cropRight, cropBottom; 873 CHECK(msg->findRect("crop", 874 &cropLeft, &cropTop, &cropRight, &cropBottom)); 875 876 int32_t colorFormat; 877 CHECK(msg->findInt32( 878 "color-format", &colorFormat)); 879 880 sp<MetaData> meta = new MetaData; 881 meta->setInt32(kKeyWidth, width); 882 meta->setInt32(kKeyHeight, height); 883 meta->setRect(kKeyCropRect, 884 cropLeft, cropTop, cropRight, cropBottom); 885 meta->setInt32(kKeyColorFormat, colorFormat); 886 887 mSoftRenderer = 888 new SoftwareRenderer(mNativeWindow, meta); 889 } 890 } 891 892 mOutputFormat = msg; 893 894 if (mFlags & kFlagIsEncoder) { 895 // Before we announce the format change we should 896 // collect codec specific data and amend the output 897 // format as necessary. 898 mFlags |= kFlagGatherCodecSpecificData; 899 } else if (mFlags & kFlagIsAsync) { 900 onOutputFormatChanged(); 901 } else { 902 mFlags |= kFlagOutputFormatChanged; 903 postActivityNotificationIfPossible(); 904 } 905 break; 906 } 907 908 case CodecBase::kWhatFillThisBuffer: 909 { 910 /* size_t index = */updateBuffers(kPortIndexInput, msg); 911 912 if (mState == FLUSHING 913 || mState == STOPPING 914 || mState == RELEASING) { 915 returnBuffersToCodecOnPort(kPortIndexInput); 916 break; 917 } 918 919 if (!mCSD.empty()) { 920 ssize_t index = dequeuePortBuffer(kPortIndexInput); 921 CHECK_GE(index, 0); 922 923 // If codec specific data had been specified as 924 // part of the format in the call to configure and 925 // if there's more csd left, we submit it here 926 // clients only get access to input buffers once 927 // this data has been exhausted. 928 929 status_t err = queueCSDInputBuffer(index); 930 931 if (err != OK) { 932 ALOGE("queueCSDInputBuffer failed w/ error %d", 933 err); 934 935 mFlags |= kFlagStickyError; 936 postActivityNotificationIfPossible(); 937 938 cancelPendingDequeueOperations(); 939 } 940 break; 941 } 942 943 if (mFlags & kFlagIsAsync) { 944 onInputBufferAvailable(); 945 } else if (mFlags & kFlagDequeueInputPending) { 946 CHECK(handleDequeueInputBuffer(mDequeueInputReplyID)); 947 948 ++mDequeueInputTimeoutGeneration; 949 mFlags &= ~kFlagDequeueInputPending; 950 mDequeueInputReplyID = 0; 951 } else { 952 postActivityNotificationIfPossible(); 953 } 954 break; 955 } 956 957 case CodecBase::kWhatDrainThisBuffer: 958 { 959 /* size_t index = */updateBuffers(kPortIndexOutput, msg); 960 961 if (mState == FLUSHING 962 || mState == STOPPING 963 || mState == RELEASING) { 964 returnBuffersToCodecOnPort(kPortIndexOutput); 965 break; 966 } 967 968 sp<ABuffer> buffer; 969 CHECK(msg->findBuffer("buffer", &buffer)); 970 971 int32_t omxFlags; 972 CHECK(msg->findInt32("flags", &omxFlags)); 973 974 buffer->meta()->setInt32("omxFlags", omxFlags); 975 976 if (mFlags & kFlagGatherCodecSpecificData) { 977 // This is the very first output buffer after a 978 // format change was signalled, it'll either contain 979 // the one piece of codec specific data we can expect 980 // or there won't be codec specific data. 981 if (omxFlags & OMX_BUFFERFLAG_CODECCONFIG) { 982 status_t err = 983 amendOutputFormatWithCodecSpecificData(buffer); 984 985 if (err != OK) { 986 ALOGE("Codec spit out malformed codec " 987 "specific data!"); 988 } 989 } 990 991 mFlags &= ~kFlagGatherCodecSpecificData; 992 if (mFlags & kFlagIsAsync) { 993 onOutputFormatChanged(); 994 } else { 995 mFlags |= kFlagOutputFormatChanged; 996 } 997 } 998 999 if (mFlags & kFlagIsAsync) { 1000 onOutputBufferAvailable(); 1001 } else if (mFlags & kFlagDequeueOutputPending) { 1002 CHECK(handleDequeueOutputBuffer(mDequeueOutputReplyID)); 1003 1004 ++mDequeueOutputTimeoutGeneration; 1005 mFlags &= ~kFlagDequeueOutputPending; 1006 mDequeueOutputReplyID = 0; 1007 } else { 1008 postActivityNotificationIfPossible(); 1009 } 1010 1011 break; 1012 } 1013 1014 case CodecBase::kWhatEOS: 1015 { 1016 // We already notify the client of this by using the 1017 // corresponding flag in "onOutputBufferReady". 1018 break; 1019 } 1020 1021 case CodecBase::kWhatShutdownCompleted: 1022 { 1023 if (mState == STOPPING) { 1024 setState(INITIALIZED); 1025 } else { 1026 CHECK_EQ(mState, RELEASING); 1027 setState(UNINITIALIZED); 1028 } 1029 1030 (new AMessage)->postReply(mReplyID); 1031 break; 1032 } 1033 1034 case CodecBase::kWhatFlushCompleted: 1035 { 1036 CHECK_EQ(mState, FLUSHING); 1037 setState(STARTED); 1038 1039 mCodec->signalResume(); 1040 1041 (new AMessage)->postReply(mReplyID); 1042 break; 1043 } 1044 1045 default: 1046 TRESPASS(); 1047 } 1048 break; 1049 } 1050 1051 case kWhatInit: 1052 { 1053 uint32_t replyID; 1054 CHECK(msg->senderAwaitsResponse(&replyID)); 1055 1056 if (mState != UNINITIALIZED) { 1057 PostReplyWithError(replyID, INVALID_OPERATION); 1058 break; 1059 } 1060 1061 mReplyID = replyID; 1062 setState(INITIALIZING); 1063 1064 AString name; 1065 CHECK(msg->findString("name", &name)); 1066 1067 int32_t nameIsType; 1068 int32_t encoder = false; 1069 CHECK(msg->findInt32("nameIsType", &nameIsType)); 1070 if (nameIsType) { 1071 CHECK(msg->findInt32("encoder", &encoder)); 1072 } 1073 1074 sp<AMessage> format = new AMessage; 1075 1076 if (nameIsType) { 1077 format->setString("mime", name.c_str()); 1078 format->setInt32("encoder", encoder); 1079 } else { 1080 format->setString("componentName", name.c_str()); 1081 } 1082 1083 mCodec->initiateAllocateComponent(format); 1084 break; 1085 } 1086 1087 case kWhatSetCallback: 1088 { 1089 uint32_t replyID; 1090 CHECK(msg->senderAwaitsResponse(&replyID)); 1091 1092 if (mState == UNINITIALIZED 1093 || mState == INITIALIZING 1094 || mState == STARTED) { 1095 // callback can't be set after codec is started, 1096 // or before it's initialized (as the callback 1097 // will be cleared when it goes to INITIALIZED) 1098 PostReplyWithError(replyID, INVALID_OPERATION); 1099 break; 1100 } 1101 1102 sp<AMessage> callback; 1103 CHECK(msg->findMessage("callback", &callback)); 1104 1105 mCallback = callback; 1106 1107 if (mCallback != NULL) { 1108 ALOGI("MediaCodec will operate in async mode"); 1109 mFlags |= kFlagIsAsync; 1110 } else { 1111 mFlags &= ~kFlagIsAsync; 1112 } 1113 1114 sp<AMessage> response = new AMessage; 1115 response->postReply(replyID); 1116 break; 1117 } 1118 1119 case kWhatConfigure: 1120 { 1121 uint32_t replyID; 1122 CHECK(msg->senderAwaitsResponse(&replyID)); 1123 1124 if (mState != INITIALIZED) { 1125 PostReplyWithError(replyID, INVALID_OPERATION); 1126 break; 1127 } 1128 1129 sp<RefBase> obj; 1130 if (!msg->findObject("native-window", &obj)) { 1131 obj.clear(); 1132 } 1133 1134 sp<AMessage> format; 1135 CHECK(msg->findMessage("format", &format)); 1136 1137 if (obj != NULL) { 1138 format->setObject("native-window", obj); 1139 1140 status_t err = setNativeWindow( 1141 static_cast<NativeWindowWrapper *>(obj.get()) 1142 ->getSurfaceTextureClient()); 1143 1144 if (err != OK) { 1145 PostReplyWithError(replyID, err); 1146 break; 1147 } 1148 } else { 1149 setNativeWindow(NULL); 1150 } 1151 1152 mReplyID = replyID; 1153 setState(CONFIGURING); 1154 1155 void *crypto; 1156 if (!msg->findPointer("crypto", &crypto)) { 1157 crypto = NULL; 1158 } 1159 1160 mCrypto = static_cast<ICrypto *>(crypto); 1161 1162 uint32_t flags; 1163 CHECK(msg->findInt32("flags", (int32_t *)&flags)); 1164 1165 if (flags & CONFIGURE_FLAG_ENCODE) { 1166 format->setInt32("encoder", true); 1167 mFlags |= kFlagIsEncoder; 1168 } 1169 1170 extractCSD(format); 1171 1172 mCodec->initiateConfigureComponent(format); 1173 break; 1174 } 1175 1176 case kWhatCreateInputSurface: 1177 { 1178 uint32_t replyID; 1179 CHECK(msg->senderAwaitsResponse(&replyID)); 1180 1181 // Must be configured, but can't have been started yet. 1182 if (mState != CONFIGURED) { 1183 PostReplyWithError(replyID, INVALID_OPERATION); 1184 break; 1185 } 1186 1187 mReplyID = replyID; 1188 mCodec->initiateCreateInputSurface(); 1189 break; 1190 } 1191 1192 case kWhatStart: 1193 { 1194 uint32_t replyID; 1195 CHECK(msg->senderAwaitsResponse(&replyID)); 1196 1197 if (mState != CONFIGURED) { 1198 PostReplyWithError(replyID, INVALID_OPERATION); 1199 break; 1200 } 1201 1202 mReplyID = replyID; 1203 setState(STARTING); 1204 1205 mCodec->initiateStart(); 1206 break; 1207 } 1208 1209 case kWhatStop: 1210 case kWhatRelease: 1211 { 1212 State targetState = 1213 (msg->what() == kWhatStop) ? INITIALIZED : UNINITIALIZED; 1214 1215 uint32_t replyID; 1216 CHECK(msg->senderAwaitsResponse(&replyID)); 1217 1218 if (mState != INITIALIZED 1219 && mState != CONFIGURED && mState != STARTED) { 1220 // We may be in "UNINITIALIZED" state already without the 1221 // client being aware of this if media server died while 1222 // we were being stopped. The client would assume that 1223 // after stop() returned, it would be safe to call release() 1224 // and it should be in this case, no harm to allow a release() 1225 // if we're already uninitialized. 1226 // Similarly stopping a stopped MediaCodec should be benign. 1227 sp<AMessage> response = new AMessage; 1228 response->setInt32( 1229 "err", 1230 mState == targetState ? OK : INVALID_OPERATION); 1231 1232 response->postReply(replyID); 1233 break; 1234 } 1235 1236 if (mFlags & kFlagSawMediaServerDie) { 1237 // It's dead, Jim. Don't expect initiateShutdown to yield 1238 // any useful results now... 1239 setState(UNINITIALIZED); 1240 (new AMessage)->postReply(replyID); 1241 break; 1242 } 1243 1244 mReplyID = replyID; 1245 setState(msg->what() == kWhatStop ? STOPPING : RELEASING); 1246 1247 mCodec->initiateShutdown( 1248 msg->what() == kWhatStop /* keepComponentAllocated */); 1249 1250 returnBuffersToCodec(); 1251 break; 1252 } 1253 1254 case kWhatDequeueInputBuffer: 1255 { 1256 uint32_t replyID; 1257 CHECK(msg->senderAwaitsResponse(&replyID)); 1258 1259 if (mFlags & kFlagIsAsync) { 1260 ALOGE("dequeueOutputBuffer can't be used in async mode"); 1261 PostReplyWithError(replyID, INVALID_OPERATION); 1262 break; 1263 } 1264 1265 if (mHaveInputSurface) { 1266 ALOGE("dequeueInputBuffer can't be used with input surface"); 1267 PostReplyWithError(replyID, INVALID_OPERATION); 1268 break; 1269 } 1270 1271 if (handleDequeueInputBuffer(replyID, true /* new request */)) { 1272 break; 1273 } 1274 1275 int64_t timeoutUs; 1276 CHECK(msg->findInt64("timeoutUs", &timeoutUs)); 1277 1278 if (timeoutUs == 0ll) { 1279 PostReplyWithError(replyID, -EAGAIN); 1280 break; 1281 } 1282 1283 mFlags |= kFlagDequeueInputPending; 1284 mDequeueInputReplyID = replyID; 1285 1286 if (timeoutUs > 0ll) { 1287 sp<AMessage> timeoutMsg = 1288 new AMessage(kWhatDequeueInputTimedOut, id()); 1289 timeoutMsg->setInt32( 1290 "generation", ++mDequeueInputTimeoutGeneration); 1291 timeoutMsg->post(timeoutUs); 1292 } 1293 break; 1294 } 1295 1296 case kWhatDequeueInputTimedOut: 1297 { 1298 int32_t generation; 1299 CHECK(msg->findInt32("generation", &generation)); 1300 1301 if (generation != mDequeueInputTimeoutGeneration) { 1302 // Obsolete 1303 break; 1304 } 1305 1306 CHECK(mFlags & kFlagDequeueInputPending); 1307 1308 PostReplyWithError(mDequeueInputReplyID, -EAGAIN); 1309 1310 mFlags &= ~kFlagDequeueInputPending; 1311 mDequeueInputReplyID = 0; 1312 break; 1313 } 1314 1315 case kWhatQueueInputBuffer: 1316 { 1317 uint32_t replyID; 1318 CHECK(msg->senderAwaitsResponse(&replyID)); 1319 1320 if (mState != STARTED || (mFlags & kFlagStickyError)) { 1321 PostReplyWithError(replyID, INVALID_OPERATION); 1322 break; 1323 } 1324 1325 status_t err = onQueueInputBuffer(msg); 1326 1327 PostReplyWithError(replyID, err); 1328 break; 1329 } 1330 1331 case kWhatDequeueOutputBuffer: 1332 { 1333 uint32_t replyID; 1334 CHECK(msg->senderAwaitsResponse(&replyID)); 1335 1336 if (mFlags & kFlagIsAsync) { 1337 ALOGE("dequeueOutputBuffer can't be used in async mode"); 1338 PostReplyWithError(replyID, INVALID_OPERATION); 1339 break; 1340 } 1341 1342 if (handleDequeueOutputBuffer(replyID, true /* new request */)) { 1343 break; 1344 } 1345 1346 int64_t timeoutUs; 1347 CHECK(msg->findInt64("timeoutUs", &timeoutUs)); 1348 1349 if (timeoutUs == 0ll) { 1350 PostReplyWithError(replyID, -EAGAIN); 1351 break; 1352 } 1353 1354 mFlags |= kFlagDequeueOutputPending; 1355 mDequeueOutputReplyID = replyID; 1356 1357 if (timeoutUs > 0ll) { 1358 sp<AMessage> timeoutMsg = 1359 new AMessage(kWhatDequeueOutputTimedOut, id()); 1360 timeoutMsg->setInt32( 1361 "generation", ++mDequeueOutputTimeoutGeneration); 1362 timeoutMsg->post(timeoutUs); 1363 } 1364 break; 1365 } 1366 1367 case kWhatDequeueOutputTimedOut: 1368 { 1369 int32_t generation; 1370 CHECK(msg->findInt32("generation", &generation)); 1371 1372 if (generation != mDequeueOutputTimeoutGeneration) { 1373 // Obsolete 1374 break; 1375 } 1376 1377 CHECK(mFlags & kFlagDequeueOutputPending); 1378 1379 PostReplyWithError(mDequeueOutputReplyID, -EAGAIN); 1380 1381 mFlags &= ~kFlagDequeueOutputPending; 1382 mDequeueOutputReplyID = 0; 1383 break; 1384 } 1385 1386 case kWhatReleaseOutputBuffer: 1387 { 1388 uint32_t replyID; 1389 CHECK(msg->senderAwaitsResponse(&replyID)); 1390 1391 if (mState != STARTED || (mFlags & kFlagStickyError)) { 1392 PostReplyWithError(replyID, INVALID_OPERATION); 1393 break; 1394 } 1395 1396 status_t err = onReleaseOutputBuffer(msg); 1397 1398 PostReplyWithError(replyID, err); 1399 break; 1400 } 1401 1402 case kWhatSignalEndOfInputStream: 1403 { 1404 uint32_t replyID; 1405 CHECK(msg->senderAwaitsResponse(&replyID)); 1406 1407 if (mState != STARTED || (mFlags & kFlagStickyError)) { 1408 PostReplyWithError(replyID, INVALID_OPERATION); 1409 break; 1410 } 1411 1412 mReplyID = replyID; 1413 mCodec->signalEndOfInputStream(); 1414 break; 1415 } 1416 1417 case kWhatGetBuffers: 1418 { 1419 uint32_t replyID; 1420 CHECK(msg->senderAwaitsResponse(&replyID)); 1421 1422 if (mState != STARTED || (mFlags & kFlagStickyError)) { 1423 PostReplyWithError(replyID, INVALID_OPERATION); 1424 break; 1425 } 1426 1427 int32_t portIndex; 1428 CHECK(msg->findInt32("portIndex", &portIndex)); 1429 1430 Vector<sp<ABuffer> > *dstBuffers; 1431 CHECK(msg->findPointer("buffers", (void **)&dstBuffers)); 1432 1433 dstBuffers->clear(); 1434 const Vector<BufferInfo> &srcBuffers = mPortBuffers[portIndex]; 1435 1436 for (size_t i = 0; i < srcBuffers.size(); ++i) { 1437 const BufferInfo &info = srcBuffers.itemAt(i); 1438 1439 dstBuffers->push_back( 1440 (portIndex == kPortIndexInput && mCrypto != NULL) 1441 ? info.mEncryptedData : info.mData); 1442 } 1443 1444 (new AMessage)->postReply(replyID); 1445 break; 1446 } 1447 1448 case kWhatFlush: 1449 { 1450 uint32_t replyID; 1451 CHECK(msg->senderAwaitsResponse(&replyID)); 1452 1453 if (mState != STARTED || (mFlags & kFlagStickyError)) { 1454 PostReplyWithError(replyID, INVALID_OPERATION); 1455 break; 1456 } 1457 1458 mReplyID = replyID; 1459 setState(FLUSHING); 1460 1461 mCodec->signalFlush(); 1462 returnBuffersToCodec(); 1463 break; 1464 } 1465 1466 case kWhatGetInputFormat: 1467 case kWhatGetOutputFormat: 1468 { 1469 sp<AMessage> format = 1470 (msg->what() == kWhatGetOutputFormat ? mOutputFormat : mInputFormat); 1471 1472 uint32_t replyID; 1473 CHECK(msg->senderAwaitsResponse(&replyID)); 1474 1475 if ((mState != CONFIGURED && mState != STARTING && 1476 mState != STARTED && mState != FLUSHING) 1477 || (mFlags & kFlagStickyError) 1478 || format == NULL) { 1479 PostReplyWithError(replyID, INVALID_OPERATION); 1480 break; 1481 } 1482 1483 sp<AMessage> response = new AMessage; 1484 response->setMessage("format", format); 1485 response->postReply(replyID); 1486 break; 1487 } 1488 1489 case kWhatRequestIDRFrame: 1490 { 1491 mCodec->signalRequestIDRFrame(); 1492 break; 1493 } 1494 1495 case kWhatRequestActivityNotification: 1496 { 1497 CHECK(mActivityNotify == NULL); 1498 CHECK(msg->findMessage("notify", &mActivityNotify)); 1499 1500 postActivityNotificationIfPossible(); 1501 break; 1502 } 1503 1504 case kWhatGetName: 1505 { 1506 uint32_t replyID; 1507 CHECK(msg->senderAwaitsResponse(&replyID)); 1508 1509 if (mComponentName.empty()) { 1510 PostReplyWithError(replyID, INVALID_OPERATION); 1511 break; 1512 } 1513 1514 sp<AMessage> response = new AMessage; 1515 response->setString("name", mComponentName.c_str()); 1516 response->postReply(replyID); 1517 break; 1518 } 1519 1520 case kWhatSetParameters: 1521 { 1522 uint32_t replyID; 1523 CHECK(msg->senderAwaitsResponse(&replyID)); 1524 1525 sp<AMessage> params; 1526 CHECK(msg->findMessage("params", ¶ms)); 1527 1528 status_t err = onSetParameters(params); 1529 1530 PostReplyWithError(replyID, err); 1531 break; 1532 } 1533 1534 default: 1535 TRESPASS(); 1536 } 1537} 1538 1539void MediaCodec::extractCSD(const sp<AMessage> &format) { 1540 mCSD.clear(); 1541 1542 size_t i = 0; 1543 for (;;) { 1544 sp<ABuffer> csd; 1545 if (!format->findBuffer(StringPrintf("csd-%u", i).c_str(), &csd)) { 1546 break; 1547 } 1548 1549 mCSD.push_back(csd); 1550 ++i; 1551 } 1552 1553 ALOGV("Found %zu pieces of codec specific data.", mCSD.size()); 1554} 1555 1556status_t MediaCodec::queueCSDInputBuffer(size_t bufferIndex) { 1557 CHECK(!mCSD.empty()); 1558 1559 const BufferInfo *info = 1560 &mPortBuffers[kPortIndexInput].itemAt(bufferIndex); 1561 1562 sp<ABuffer> csd = *mCSD.begin(); 1563 mCSD.erase(mCSD.begin()); 1564 1565 const sp<ABuffer> &codecInputData = 1566 (mCrypto != NULL) ? info->mEncryptedData : info->mData; 1567 1568 if (csd->size() > codecInputData->capacity()) { 1569 return -EINVAL; 1570 } 1571 1572 memcpy(codecInputData->data(), csd->data(), csd->size()); 1573 1574 AString errorDetailMsg; 1575 1576 sp<AMessage> msg = new AMessage(kWhatQueueInputBuffer, id()); 1577 msg->setSize("index", bufferIndex); 1578 msg->setSize("offset", 0); 1579 msg->setSize("size", csd->size()); 1580 msg->setInt64("timeUs", 0ll); 1581 msg->setInt32("flags", BUFFER_FLAG_CODECCONFIG); 1582 msg->setPointer("errorDetailMsg", &errorDetailMsg); 1583 1584 return onQueueInputBuffer(msg); 1585} 1586 1587void MediaCodec::setState(State newState) { 1588 if (newState == INITIALIZED || newState == UNINITIALIZED) { 1589 delete mSoftRenderer; 1590 mSoftRenderer = NULL; 1591 1592 mCrypto.clear(); 1593 setNativeWindow(NULL); 1594 1595 mInputFormat.clear(); 1596 mOutputFormat.clear(); 1597 mFlags &= ~kFlagOutputFormatChanged; 1598 mFlags &= ~kFlagOutputBuffersChanged; 1599 mFlags &= ~kFlagStickyError; 1600 mFlags &= ~kFlagIsEncoder; 1601 mFlags &= ~kFlagGatherCodecSpecificData; 1602 mFlags &= ~kFlagIsAsync; 1603 1604 mActivityNotify.clear(); 1605 mCallback.clear(); 1606 } 1607 1608 if (newState == UNINITIALIZED) { 1609 // return any straggling buffers, e.g. if we got here on an error 1610 returnBuffersToCodec(); 1611 1612 mComponentName.clear(); 1613 1614 // The component is gone, mediaserver's probably back up already 1615 // but should definitely be back up should we try to instantiate 1616 // another component.. and the cycle continues. 1617 mFlags &= ~kFlagSawMediaServerDie; 1618 } 1619 1620 mState = newState; 1621 1622 cancelPendingDequeueOperations(); 1623} 1624 1625void MediaCodec::returnBuffersToCodec() { 1626 returnBuffersToCodecOnPort(kPortIndexInput); 1627 returnBuffersToCodecOnPort(kPortIndexOutput); 1628} 1629 1630void MediaCodec::returnBuffersToCodecOnPort(int32_t portIndex) { 1631 CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput); 1632 Mutex::Autolock al(mBufferLock); 1633 1634 Vector<BufferInfo> *buffers = &mPortBuffers[portIndex]; 1635 1636 for (size_t i = 0; i < buffers->size(); ++i) { 1637 BufferInfo *info = &buffers->editItemAt(i); 1638 1639 if (info->mNotify != NULL) { 1640 sp<AMessage> msg = info->mNotify; 1641 info->mNotify = NULL; 1642 info->mOwnedByClient = false; 1643 1644 if (portIndex == kPortIndexInput) { 1645 /* no error, just returning buffers */ 1646 msg->setInt32("err", OK); 1647 } 1648 msg->post(); 1649 } 1650 } 1651 1652 mAvailPortBuffers[portIndex].clear(); 1653} 1654 1655size_t MediaCodec::updateBuffers( 1656 int32_t portIndex, const sp<AMessage> &msg) { 1657 CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput); 1658 1659 uint32_t bufferID; 1660 CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID)); 1661 1662 Vector<BufferInfo> *buffers = &mPortBuffers[portIndex]; 1663 1664 for (size_t i = 0; i < buffers->size(); ++i) { 1665 BufferInfo *info = &buffers->editItemAt(i); 1666 1667 if (info->mBufferID == bufferID) { 1668 CHECK(info->mNotify == NULL); 1669 CHECK(msg->findMessage("reply", &info->mNotify)); 1670 1671 mAvailPortBuffers[portIndex].push_back(i); 1672 1673 return i; 1674 } 1675 } 1676 1677 TRESPASS(); 1678 1679 return 0; 1680} 1681 1682status_t MediaCodec::onQueueInputBuffer(const sp<AMessage> &msg) { 1683 size_t index; 1684 size_t offset; 1685 size_t size; 1686 int64_t timeUs; 1687 uint32_t flags; 1688 CHECK(msg->findSize("index", &index)); 1689 CHECK(msg->findSize("offset", &offset)); 1690 CHECK(msg->findInt64("timeUs", &timeUs)); 1691 CHECK(msg->findInt32("flags", (int32_t *)&flags)); 1692 1693 const CryptoPlugin::SubSample *subSamples; 1694 size_t numSubSamples; 1695 const uint8_t *key; 1696 const uint8_t *iv; 1697 CryptoPlugin::Mode mode = CryptoPlugin::kMode_Unencrypted; 1698 1699 // We allow the simpler queueInputBuffer API to be used even in 1700 // secure mode, by fabricating a single unencrypted subSample. 1701 CryptoPlugin::SubSample ss; 1702 1703 if (msg->findSize("size", &size)) { 1704 if (mCrypto != NULL) { 1705 ss.mNumBytesOfClearData = size; 1706 ss.mNumBytesOfEncryptedData = 0; 1707 1708 subSamples = &ss; 1709 numSubSamples = 1; 1710 key = NULL; 1711 iv = NULL; 1712 } 1713 } else { 1714 if (mCrypto == NULL) { 1715 return -EINVAL; 1716 } 1717 1718 CHECK(msg->findPointer("subSamples", (void **)&subSamples)); 1719 CHECK(msg->findSize("numSubSamples", &numSubSamples)); 1720 CHECK(msg->findPointer("key", (void **)&key)); 1721 CHECK(msg->findPointer("iv", (void **)&iv)); 1722 1723 int32_t tmp; 1724 CHECK(msg->findInt32("mode", &tmp)); 1725 1726 mode = (CryptoPlugin::Mode)tmp; 1727 1728 size = 0; 1729 for (size_t i = 0; i < numSubSamples; ++i) { 1730 size += subSamples[i].mNumBytesOfClearData; 1731 size += subSamples[i].mNumBytesOfEncryptedData; 1732 } 1733 } 1734 1735 if (index >= mPortBuffers[kPortIndexInput].size()) { 1736 return -ERANGE; 1737 } 1738 1739 BufferInfo *info = &mPortBuffers[kPortIndexInput].editItemAt(index); 1740 1741 if (info->mNotify == NULL || !info->mOwnedByClient) { 1742 return -EACCES; 1743 } 1744 1745 if (offset + size > info->mData->capacity()) { 1746 return -EINVAL; 1747 } 1748 1749 sp<AMessage> reply = info->mNotify; 1750 info->mData->setRange(offset, size); 1751 info->mData->meta()->setInt64("timeUs", timeUs); 1752 1753 if (flags & BUFFER_FLAG_EOS) { 1754 info->mData->meta()->setInt32("eos", true); 1755 } 1756 1757 if (flags & BUFFER_FLAG_CODECCONFIG) { 1758 info->mData->meta()->setInt32("csd", true); 1759 } 1760 1761 if (mCrypto != NULL) { 1762 if (size > info->mEncryptedData->capacity()) { 1763 return -ERANGE; 1764 } 1765 1766 AString *errorDetailMsg; 1767 CHECK(msg->findPointer("errorDetailMsg", (void **)&errorDetailMsg)); 1768 1769 ssize_t result = mCrypto->decrypt( 1770 (mFlags & kFlagIsSecure) != 0, 1771 key, 1772 iv, 1773 mode, 1774 info->mEncryptedData->base() + offset, 1775 subSamples, 1776 numSubSamples, 1777 info->mData->base(), 1778 errorDetailMsg); 1779 1780 if (result < 0) { 1781 return result; 1782 } 1783 1784 info->mData->setRange(0, result); 1785 } 1786 1787 // synchronization boundary for getBufferAndFormat 1788 { 1789 Mutex::Autolock al(mBufferLock); 1790 info->mOwnedByClient = false; 1791 } 1792 reply->setBuffer("buffer", info->mData); 1793 reply->post(); 1794 1795 info->mNotify = NULL; 1796 1797 return OK; 1798} 1799 1800status_t MediaCodec::onReleaseOutputBuffer(const sp<AMessage> &msg) { 1801 size_t index; 1802 CHECK(msg->findSize("index", &index)); 1803 1804 int32_t render; 1805 if (!msg->findInt32("render", &render)) { 1806 render = 0; 1807 } 1808 1809 if (mState != STARTED) { 1810 return -EINVAL; 1811 } 1812 1813 if (index >= mPortBuffers[kPortIndexOutput].size()) { 1814 return -ERANGE; 1815 } 1816 1817 BufferInfo *info = &mPortBuffers[kPortIndexOutput].editItemAt(index); 1818 1819 if (info->mNotify == NULL || !info->mOwnedByClient) { 1820 return -EACCES; 1821 } 1822 1823 // synchronization boundary for getBufferAndFormat 1824 { 1825 Mutex::Autolock al(mBufferLock); 1826 info->mOwnedByClient = false; 1827 } 1828 1829 if (render && info->mData != NULL && info->mData->size() != 0) { 1830 info->mNotify->setInt32("render", true); 1831 1832 int64_t timestampNs = 0; 1833 if (msg->findInt64("timestampNs", ×tampNs)) { 1834 info->mNotify->setInt64("timestampNs", timestampNs); 1835 } else { 1836 // TODO: it seems like we should use the timestamp 1837 // in the (media)buffer as it potentially came from 1838 // an input surface, but we did not propagate it prior to 1839 // API 20. Perhaps check for target SDK version. 1840#if 0 1841 if (info->mData->meta()->findInt64("timeUs", ×tampNs)) { 1842 ALOGV("using buffer PTS of %" PRId64, timestampNs); 1843 timestampNs *= 1000; 1844 } 1845#endif 1846 } 1847 1848 if (mSoftRenderer != NULL) { 1849 mSoftRenderer->render( 1850 info->mData->data(), info->mData->size(), timestampNs, NULL); 1851 } 1852 } 1853 1854 info->mNotify->post(); 1855 info->mNotify = NULL; 1856 1857 return OK; 1858} 1859 1860ssize_t MediaCodec::dequeuePortBuffer(int32_t portIndex) { 1861 CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput); 1862 1863 List<size_t> *availBuffers = &mAvailPortBuffers[portIndex]; 1864 1865 if (availBuffers->empty()) { 1866 return -EAGAIN; 1867 } 1868 1869 size_t index = *availBuffers->begin(); 1870 availBuffers->erase(availBuffers->begin()); 1871 1872 BufferInfo *info = &mPortBuffers[portIndex].editItemAt(index); 1873 CHECK(!info->mOwnedByClient); 1874 { 1875 Mutex::Autolock al(mBufferLock); 1876 info->mFormat = portIndex == kPortIndexInput ? mInputFormat : mOutputFormat; 1877 info->mOwnedByClient = true; 1878 } 1879 1880 return index; 1881} 1882 1883status_t MediaCodec::setNativeWindow( 1884 const sp<Surface> &surfaceTextureClient) { 1885 status_t err; 1886 1887 if (mNativeWindow != NULL) { 1888 err = native_window_api_disconnect( 1889 mNativeWindow.get(), NATIVE_WINDOW_API_MEDIA); 1890 1891 if (err != OK) { 1892 ALOGW("native_window_api_disconnect returned an error: %s (%d)", 1893 strerror(-err), err); 1894 } 1895 1896 mNativeWindow.clear(); 1897 } 1898 1899 if (surfaceTextureClient != NULL) { 1900 err = native_window_api_connect( 1901 surfaceTextureClient.get(), NATIVE_WINDOW_API_MEDIA); 1902 1903 if (err != OK) { 1904 ALOGE("native_window_api_connect returned an error: %s (%d)", 1905 strerror(-err), err); 1906 1907 return err; 1908 } 1909 1910 mNativeWindow = surfaceTextureClient; 1911 } 1912 1913 return OK; 1914} 1915 1916void MediaCodec::onInputBufferAvailable() { 1917 int32_t index; 1918 while ((index = dequeuePortBuffer(kPortIndexInput)) >= 0) { 1919 sp<AMessage> msg = mCallback->dup(); 1920 msg->setInt32("callbackID", CB_INPUT_AVAILABLE); 1921 msg->setInt32("index", index); 1922 msg->post(); 1923 } 1924} 1925 1926void MediaCodec::onOutputBufferAvailable() { 1927 int32_t index; 1928 while ((index = dequeuePortBuffer(kPortIndexOutput)) >= 0) { 1929 const sp<ABuffer> &buffer = 1930 mPortBuffers[kPortIndexOutput].itemAt(index).mData; 1931 sp<AMessage> msg = mCallback->dup(); 1932 msg->setInt32("callbackID", CB_OUTPUT_AVAILABLE); 1933 msg->setInt32("index", index); 1934 msg->setSize("offset", buffer->offset()); 1935 msg->setSize("size", buffer->size()); 1936 1937 int64_t timeUs; 1938 CHECK(buffer->meta()->findInt64("timeUs", &timeUs)); 1939 1940 msg->setInt64("timeUs", timeUs); 1941 1942 int32_t omxFlags; 1943 CHECK(buffer->meta()->findInt32("omxFlags", &omxFlags)); 1944 1945 uint32_t flags = 0; 1946 if (omxFlags & OMX_BUFFERFLAG_SYNCFRAME) { 1947 flags |= BUFFER_FLAG_SYNCFRAME; 1948 } 1949 if (omxFlags & OMX_BUFFERFLAG_CODECCONFIG) { 1950 flags |= BUFFER_FLAG_CODECCONFIG; 1951 } 1952 if (omxFlags & OMX_BUFFERFLAG_EOS) { 1953 flags |= BUFFER_FLAG_EOS; 1954 } 1955 1956 msg->setInt32("flags", flags); 1957 1958 msg->post(); 1959 } 1960} 1961 1962void MediaCodec::onError(status_t err, int32_t actionCode, const char *detail) { 1963 if (mCallback != NULL) { 1964 sp<AMessage> msg = mCallback->dup(); 1965 msg->setInt32("callbackID", CB_ERROR); 1966 msg->setInt32("err", err); 1967 msg->setInt32("actionCode", actionCode); 1968 1969 if (detail != NULL) { 1970 msg->setString("detail", detail); 1971 } 1972 1973 msg->post(); 1974 } 1975} 1976 1977void MediaCodec::onOutputFormatChanged() { 1978 if (mCallback != NULL) { 1979 sp<AMessage> msg = mCallback->dup(); 1980 msg->setInt32("callbackID", CB_OUTPUT_FORMAT_CHANGED); 1981 msg->setMessage("format", mOutputFormat); 1982 msg->post(); 1983 } 1984} 1985 1986 1987void MediaCodec::postActivityNotificationIfPossible() { 1988 if (mActivityNotify == NULL) { 1989 return; 1990 } 1991 1992 if ((mFlags & (kFlagStickyError 1993 | kFlagOutputBuffersChanged 1994 | kFlagOutputFormatChanged)) 1995 || !mAvailPortBuffers[kPortIndexInput].empty() 1996 || !mAvailPortBuffers[kPortIndexOutput].empty()) { 1997 mActivityNotify->post(); 1998 mActivityNotify.clear(); 1999 } 2000} 2001 2002status_t MediaCodec::setParameters(const sp<AMessage> ¶ms) { 2003 sp<AMessage> msg = new AMessage(kWhatSetParameters, id()); 2004 msg->setMessage("params", params); 2005 2006 sp<AMessage> response; 2007 return PostAndAwaitResponse(msg, &response); 2008} 2009 2010status_t MediaCodec::onSetParameters(const sp<AMessage> ¶ms) { 2011 mCodec->signalSetParameters(params); 2012 2013 return OK; 2014} 2015 2016status_t MediaCodec::amendOutputFormatWithCodecSpecificData( 2017 const sp<ABuffer> &buffer) { 2018 AString mime; 2019 CHECK(mOutputFormat->findString("mime", &mime)); 2020 2021 if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_AVC)) { 2022 // Codec specific data should be SPS and PPS in a single buffer, 2023 // each prefixed by a startcode (0x00 0x00 0x00 0x01). 2024 // We separate the two and put them into the output format 2025 // under the keys "csd-0" and "csd-1". 2026 2027 unsigned csdIndex = 0; 2028 2029 const uint8_t *data = buffer->data(); 2030 size_t size = buffer->size(); 2031 2032 const uint8_t *nalStart; 2033 size_t nalSize; 2034 while (getNextNALUnit(&data, &size, &nalStart, &nalSize, true) == OK) { 2035 sp<ABuffer> csd = new ABuffer(nalSize + 4); 2036 memcpy(csd->data(), "\x00\x00\x00\x01", 4); 2037 memcpy(csd->data() + 4, nalStart, nalSize); 2038 2039 mOutputFormat->setBuffer( 2040 StringPrintf("csd-%u", csdIndex).c_str(), csd); 2041 2042 ++csdIndex; 2043 } 2044 2045 if (csdIndex != 2) { 2046 return ERROR_MALFORMED; 2047 } 2048 } else { 2049 // For everything else we just stash the codec specific data into 2050 // the output format as a single piece of csd under "csd-0". 2051 mOutputFormat->setBuffer("csd-0", buffer); 2052 } 2053 2054 return OK; 2055} 2056 2057} // namespace android 2058