1033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim/*
2033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim * Copyright (C) 2017 The Android Open Source Project
3033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim *
4033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim * Licensed under the Apache License, Version 2.0 (the "License");
5033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim * you may not use this file except in compliance with the License.
6033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim * You may obtain a copy of the License at
7033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim *
8033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim *      http://www.apache.org/licenses/LICENSE-2.0
9033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim *
10033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim * Unless required by applicable law or agreed to in writing, software
11033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim * distributed under the License is distributed on an "AS IS" BASIS,
12033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim * See the License for the specific language governing permissions and
14033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim * limitations under the License.
15033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim */
16033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
170f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa#define LOG_NDEBUG 0
18033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#define LOG_TAG "CCodec"
19033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include <utils/Log.h>
20033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
21cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar#include <sstream>
22033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include <thread>
23033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
24277b7295f317c6597fadb116b6aee5ca3be106c1Wonsik Kim#include <C2Config.h>
253bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar#include <C2Debug.h>
26069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim#include <C2ParamInternal.h>
27033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include <C2PlatformSupport.h>
28033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include <C2V4l2Support.h>
29033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
30033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include <android/IOMXBufferSource.h>
311c421ef3ded7c7dd25a44ea0d90db1ec46f5c1fbWonsik Kim#include <android/IGraphicBufferSource.h>
322bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa#include <cutils/properties.h>
33033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include <gui/bufferqueue/1.0/H2BGraphicBufferProducer.h>
341c421ef3ded7c7dd25a44ea0d90db1ec46f5c1fbWonsik Kim#include <gui/IGraphicBufferProducer.h>
35033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include <gui/Surface.h>
361c421ef3ded7c7dd25a44ea0d90db1ec46f5c1fbWonsik Kim#include <media/omx/1.0/WOmx.h>
37033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include <media/stagefright/codec2/1.0/InputSurface.h>
38033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include <media/stagefright/BufferProducerWrapper.h>
393bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar#include <media/stagefright/MediaCodecConstants.h>
40033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include <media/stagefright/PersistentSurface.h>
41033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
42033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include "C2OMXNode.h"
43033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include "CCodec.h"
44033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include "CCodecBufferChannel.h"
45033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include "InputSurfaceWrapper.h"
46033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
47033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimnamespace android {
48033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
49033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimusing namespace std::chrono_literals;
50033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimusing ::android::hardware::graphics::bufferqueue::V1_0::utils::H2BGraphicBufferProducer;
511c421ef3ded7c7dd25a44ea0d90db1ec46f5c1fbWonsik Kimusing BGraphicBufferSource = ::android::IGraphicBufferSource;
52033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
53033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimnamespace {
54033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
55033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimclass CCodecWatchdog : public AHandler {
56033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimprivate:
57033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    enum {
58033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        kWhatRegister,
59033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        kWhatWatch,
60033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    };
61033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    constexpr static int64_t kWatchIntervalUs = 3000000;  // 3 secs
62033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
63033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimpublic:
64033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    static sp<CCodecWatchdog> getInstance() {
65033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<sp<CCodecWatchdog>>::Locked instance(sInstance);
66033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (*instance == nullptr) {
67033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            *instance = new CCodecWatchdog;
68033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            (*instance)->init();
69033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
70033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return *instance;
71033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
72033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
73033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    ~CCodecWatchdog() = default;
74033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
75033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    void registerCodec(CCodec *codec) {
76033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        sp<AMessage> msg = new AMessage(kWhatRegister, this);
77033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        msg->setPointer("codec", codec);
78033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        msg->post();
79033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
80033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
81033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimprotected:
82033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    void onMessageReceived(const sp<AMessage> &msg) {
83033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        switch (msg->what()) {
84033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            case kWhatRegister: {
85033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                void *ptr = nullptr;
86033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                CHECK(msg->findPointer("codec", &ptr));
87033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                Mutexed<std::list<wp<CCodec>>>::Locked codecs(mCodecs);
88033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                codecs->emplace_back((CCodec *)ptr);
89033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                break;
90033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            }
91033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
92033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            case kWhatWatch: {
93033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                Mutexed<std::list<wp<CCodec>>>::Locked codecs(mCodecs);
94033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                for (auto it = codecs->begin(); it != codecs->end(); ) {
95033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                    sp<CCodec> codec = it->promote();
96033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                    if (codec == nullptr) {
97033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                        it = codecs->erase(it);
98033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                        continue;
99033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                    }
100033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                    codec->initiateReleaseIfStuck();
101033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                    ++it;
102033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                }
103033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                msg->post(kWatchIntervalUs);
104033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                break;
105033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            }
106033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
107033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            default: {
108033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                TRESPASS("CCodecWatchdog: unrecognized message");
109033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            }
110033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
111033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
112033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
113033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimprivate:
114033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    CCodecWatchdog() : mLooper(new ALooper) {}
115033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
116033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    void init() {
117033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mLooper->setName("CCodecWatchdog");
118033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mLooper->registerHandler(this);
119033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mLooper->start();
120033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        (new AMessage(kWhatWatch, this))->post(kWatchIntervalUs);
121033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
122033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
123033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    static Mutexed<sp<CCodecWatchdog>> sInstance;
124033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
125033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<ALooper> mLooper;
126033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    Mutexed<std::list<wp<CCodec>>> mCodecs;
127033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim};
128033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
129033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik KimMutexed<sp<CCodecWatchdog>> CCodecWatchdog::sInstance;
130033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
131033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimclass C2InputSurfaceWrapper : public InputSurfaceWrapper {
132033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimpublic:
1330f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    explicit C2InputSurfaceWrapper(
1340f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa            const std::shared_ptr<Codec2Client::InputSurface> &surface) :
1350f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa        mSurface(surface) {
1360f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    }
1370f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa
138033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    ~C2InputSurfaceWrapper() override = default;
139033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1400f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    status_t connect(const std::shared_ptr<Codec2Client::Component> &comp) override {
141033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (mConnection != nullptr) {
142033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return ALREADY_EXISTS;
143033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
1440f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa        return static_cast<status_t>(
1450f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa                mSurface->connectToComponent(comp, &mConnection));
146033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
147033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
148033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    void disconnect() override {
149033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (mConnection != nullptr) {
150033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            mConnection->disconnect();
1510f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa            mConnection = nullptr;
152033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
153033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
154033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1557a702c9f08c57f64121149e3e233cbe8fcf4dc36Wonsik Kim    status_t signalEndOfInputStream() override {
1567a702c9f08c57f64121149e3e233cbe8fcf4dc36Wonsik Kim        C2InputSurfaceEosTuning eos(true);
1577a702c9f08c57f64121149e3e233cbe8fcf4dc36Wonsik Kim        std::vector<std::unique_ptr<C2SettingResult>> failures;
1587a702c9f08c57f64121149e3e233cbe8fcf4dc36Wonsik Kim        c2_status_t err = mSurface->getConfigurable()->config({&eos}, C2_MAY_BLOCK, &failures);
1597a702c9f08c57f64121149e3e233cbe8fcf4dc36Wonsik Kim        if (err != C2_OK) {
1607a702c9f08c57f64121149e3e233cbe8fcf4dc36Wonsik Kim            return UNKNOWN_ERROR;
1617a702c9f08c57f64121149e3e233cbe8fcf4dc36Wonsik Kim        }
1627a702c9f08c57f64121149e3e233cbe8fcf4dc36Wonsik Kim        return OK;
1637a702c9f08c57f64121149e3e233cbe8fcf4dc36Wonsik Kim    }
1647a702c9f08c57f64121149e3e233cbe8fcf4dc36Wonsik Kim
165cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar    status_t configure(Config &config __unused) {
166cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar        // TODO
167cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar        return OK;
168cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar    }
169cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar
170033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimprivate:
1710f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    std::shared_ptr<Codec2Client::InputSurface> mSurface;
1720f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    std::shared_ptr<Codec2Client::InputSurfaceConnection> mConnection;
173033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim};
174033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
175033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimclass GraphicBufferSourceWrapper : public InputSurfaceWrapper {
176033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimpublic:
177ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim//    explicit GraphicBufferSourceWrapper(const sp<BGraphicBufferSource> &source) : mSource(source) {}
178ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim    GraphicBufferSourceWrapper(
179ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim            const sp<BGraphicBufferSource> &source,
180ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim            uint32_t width,
181ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim            uint32_t height)
182ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim        : mSource(source), mWidth(width), mHeight(height) {}
183033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    ~GraphicBufferSourceWrapper() override = default;
184033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1850f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    status_t connect(const std::shared_ptr<Codec2Client::Component> &comp) override {
186033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        // TODO: proper color aspect & dataspace
187033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        android_dataspace dataSpace = HAL_DATASPACE_BT709;
188033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
189033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mNode = new C2OMXNode(comp);
190ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim        mNode->setFrameSize(mWidth, mHeight);
191033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mSource->configure(mNode, dataSpace);
192033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
193033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        // TODO: configure according to intf().
194cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar        // TODO: initial color aspects (dataspace)
195033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
196033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        sp<IOMXBufferSource> source = mNode->getSource();
197033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (source == nullptr) {
198033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return NO_INIT;
199033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
200033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        constexpr size_t kNumSlots = 16;
201033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        for (size_t i = 0; i < kNumSlots; ++i) {
202033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            source->onInputBufferAdded(i);
203033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
204033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        source->onOmxExecuting();
205033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return OK;
206033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
207033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
208033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    void disconnect() override {
209033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (mNode == nullptr) {
210033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return;
211033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
212033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        sp<IOMXBufferSource> source = mNode->getSource();
213033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (source == nullptr) {
214033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            ALOGD("GBSWrapper::disconnect: node is not configured with OMXBufferSource.");
215033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return;
216033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
217033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        source->onOmxIdle();
218033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        source->onOmxLoaded();
219033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mNode.clear();
220033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
221033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
222cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar    status_t GetStatus(const binder::Status &status) {
223cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar        status_t err = OK;
224cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar        if (!status.isOk()) {
225cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar            err = status.serviceSpecificErrorCode();
226cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar            if (err == OK) {
227cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar                err = status.transactionError();
228cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar                if (err == OK) {
229cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar                    // binder status failed, but there is no servie or transaction error
230cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar                    err = UNKNOWN_ERROR;
231cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar                }
232cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar            }
233cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar        }
234cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar        return err;
235cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar    }
236cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar
2377a702c9f08c57f64121149e3e233cbe8fcf4dc36Wonsik Kim    status_t signalEndOfInputStream() override {
238cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar        return GetStatus(mSource->signalEndOfInputStream());
239cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar    }
240cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar
241cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar    status_t configure(Config &config) {
242cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar        std::stringstream status;
2437a702c9f08c57f64121149e3e233cbe8fcf4dc36Wonsik Kim        status_t err = OK;
244cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar
245cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar        // handle each configuration granually, in case we need to handle part of the configuration
246cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar        // elsewhere
247cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar
248cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar        // TRICKY: we do not unset frame delay repeating
249cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar        if (config.mMinFps > 0 && config.mMinFps != mConfig.mMinFps) {
250cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar            int64_t us = 1e6 / config.mMinFps + 0.5;
251cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar            status_t res = GetStatus(mSource->setRepeatPreviousFrameDelayUs(us));
252cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar            status << " minFps=" << config.mMinFps << " => repeatDelayUs=" << us;
253cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar            if (res != OK) {
254cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar                status << " (=> " << asString(res) << ")";
255cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar                err = res;
256cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar            }
257cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar            mConfig.mMinFps = config.mMinFps;
258cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar        }
259cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar
260cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar        // TODO: pts gap
261cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar
262cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar        // max fps
263cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar        // TRICKY: we do not unset max fps to 0 unless using fixed fps
264cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar        if ((config.mMaxFps > 0 || (config.mFixedAdjustedFps > 0 && config.mMaxFps == 0))
265cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar                && config.mMaxFps != mConfig.mMaxFps) {
266cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar            status_t res = GetStatus(mSource->setMaxFps(config.mMaxFps));
267cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar            status << " maxFps=" << config.mMaxFps;
268cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar            if (res != OK) {
269cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar                status << " (=> " << asString(res) << ")";
270cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar                err = res;
271cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar            }
272cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar            mConfig.mMaxFps = config.mMaxFps;
273cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar        }
274cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar
275cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar        if (config.mTimeOffsetUs != mConfig.mTimeOffsetUs) {
276cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar            status_t res = GetStatus(mSource->setTimeOffsetUs(config.mTimeOffsetUs));
277cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar            status << " timeOffset " << config.mTimeOffsetUs << "us";
278cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar            if (res != OK) {
279cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar                status << " (=> " << asString(res) << ")";
280cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar                err = res;
281cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar            }
282cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar            mConfig.mTimeOffsetUs = config.mTimeOffsetUs;
2837a702c9f08c57f64121149e3e233cbe8fcf4dc36Wonsik Kim        }
284cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar
285cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar        // TODO: time lapse config
286cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar
287cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar        if (config.mStartAtUs != mConfig.mStartAtUs
288cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar                || (config.mStopped != mConfig.mStopped && !config.mStopped)) {
289cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar            status_t res = GetStatus(mSource->setStartTimeUs(config.mStartAtUs));
290cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar            status << " start at " << config.mStartAtUs << "us";
291cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar            if (res != OK) {
292cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar                status << " (=> " << asString(res) << ")";
293cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar                err = res;
294cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar            }
295cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar            mConfig.mStartAtUs = config.mStartAtUs;
296cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar            mConfig.mStopped = config.mStopped;
297cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar        }
298cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar
299cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar        // suspend-resume
300cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar        if (config.mSuspended != mConfig.mSuspended) {
301cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar            status_t res = GetStatus(mSource->setSuspend(config.mSuspended, config.mSuspendAtUs));
302cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar            status << " " << (config.mSuspended ? "suspend" : "resume")
303cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar                    << " at " << config.mSuspendAtUs << "us";
304cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar            if (res != OK) {
305cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar                status << " (=> " << asString(res) << ")";
306cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar                err = res;
307cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar            }
308cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar            mConfig.mSuspended = config.mSuspended;
309cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar            mConfig.mSuspendAtUs = config.mSuspendAtUs;
310cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar        }
311cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar
312cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar        if (config.mStopped != mConfig.mStopped && config.mStopped) {
313cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar            status_t res = GetStatus(mSource->setStopTimeUs(config.mStopAtUs));
314cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar            status << " stop at " << config.mStopAtUs << "us";
315cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar            if (res != OK) {
316cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar                status << " (=> " << asString(res) << ")";
317cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar                err = res;
318cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar            } else {
319cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar                status << " delayUs";
320cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar                res = GetStatus(mSource->getStopTimeOffsetUs(&config.mInputDelayUs));
321cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar                if (res != OK) {
322cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar                    status << " (=> " << asString(res) << ")";
323cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar                } else {
324cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar                    status << "=" << config.mInputDelayUs << "us";
325cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar                }
326cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar                mConfig.mInputDelayUs = config.mInputDelayUs;
327cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar            }
328cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar            mConfig.mStopAtUs = config.mStopAtUs;
329cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar            mConfig.mStopped = config.mStopped;
330cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar        }
331cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar
332cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar        // color aspects (android._color-aspects)
333cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar
334cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar        // consumer usage
335cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar        ALOGD("ISConfig%s", status.str().c_str());
336cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar        return err;
3377a702c9f08c57f64121149e3e233cbe8fcf4dc36Wonsik Kim    }
3387a702c9f08c57f64121149e3e233cbe8fcf4dc36Wonsik Kim
339033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimprivate:
3401c421ef3ded7c7dd25a44ea0d90db1ec46f5c1fbWonsik Kim    sp<BGraphicBufferSource> mSource;
341033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<C2OMXNode> mNode;
342ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim    uint32_t mWidth;
343ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim    uint32_t mHeight;
344cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar    Config mConfig;
345033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim};
346033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
34778746a1fc9643659f5a50658a5c6db75955d440cLajos Molnarclass Codec2ClientInterfaceWrapper : public C2ComponentStore {
34878746a1fc9643659f5a50658a5c6db75955d440cLajos Molnar    std::shared_ptr<Codec2Client> mClient;
34978746a1fc9643659f5a50658a5c6db75955d440cLajos Molnar
35078746a1fc9643659f5a50658a5c6db75955d440cLajos Molnarpublic:
35178746a1fc9643659f5a50658a5c6db75955d440cLajos Molnar    Codec2ClientInterfaceWrapper(std::shared_ptr<Codec2Client> client)
35278746a1fc9643659f5a50658a5c6db75955d440cLajos Molnar        : mClient(client) { }
35378746a1fc9643659f5a50658a5c6db75955d440cLajos Molnar
35478746a1fc9643659f5a50658a5c6db75955d440cLajos Molnar    virtual ~Codec2ClientInterfaceWrapper() = default;
35578746a1fc9643659f5a50658a5c6db75955d440cLajos Molnar
35678746a1fc9643659f5a50658a5c6db75955d440cLajos Molnar    virtual c2_status_t config_sm(
35778746a1fc9643659f5a50658a5c6db75955d440cLajos Molnar            const std::vector<C2Param *> &params,
35878746a1fc9643659f5a50658a5c6db75955d440cLajos Molnar            std::vector<std::unique_ptr<C2SettingResult>> *const failures) {
35978746a1fc9643659f5a50658a5c6db75955d440cLajos Molnar        return mClient->config(params, C2_MAY_BLOCK, failures);
36078746a1fc9643659f5a50658a5c6db75955d440cLajos Molnar    };
36178746a1fc9643659f5a50658a5c6db75955d440cLajos Molnar
36278746a1fc9643659f5a50658a5c6db75955d440cLajos Molnar    virtual c2_status_t copyBuffer(
36378746a1fc9643659f5a50658a5c6db75955d440cLajos Molnar            std::shared_ptr<C2GraphicBuffer>,
36478746a1fc9643659f5a50658a5c6db75955d440cLajos Molnar            std::shared_ptr<C2GraphicBuffer>) {
36578746a1fc9643659f5a50658a5c6db75955d440cLajos Molnar        return C2_OMITTED;
36678746a1fc9643659f5a50658a5c6db75955d440cLajos Molnar    }
36778746a1fc9643659f5a50658a5c6db75955d440cLajos Molnar
36878746a1fc9643659f5a50658a5c6db75955d440cLajos Molnar    virtual c2_status_t createComponent(
36978746a1fc9643659f5a50658a5c6db75955d440cLajos Molnar            C2String, std::shared_ptr<C2Component> *const component) {
37078746a1fc9643659f5a50658a5c6db75955d440cLajos Molnar        component->reset();
37178746a1fc9643659f5a50658a5c6db75955d440cLajos Molnar        return C2_OMITTED;
37278746a1fc9643659f5a50658a5c6db75955d440cLajos Molnar    }
37378746a1fc9643659f5a50658a5c6db75955d440cLajos Molnar
37478746a1fc9643659f5a50658a5c6db75955d440cLajos Molnar    virtual c2_status_t createInterface(
37578746a1fc9643659f5a50658a5c6db75955d440cLajos Molnar            C2String, std::shared_ptr<C2ComponentInterface> *const interface) {
37678746a1fc9643659f5a50658a5c6db75955d440cLajos Molnar        interface->reset();
37778746a1fc9643659f5a50658a5c6db75955d440cLajos Molnar        return C2_OMITTED;
37878746a1fc9643659f5a50658a5c6db75955d440cLajos Molnar    }
37978746a1fc9643659f5a50658a5c6db75955d440cLajos Molnar
38078746a1fc9643659f5a50658a5c6db75955d440cLajos Molnar    virtual c2_status_t query_sm(
38178746a1fc9643659f5a50658a5c6db75955d440cLajos Molnar            const std::vector<C2Param *> &stackParams,
38278746a1fc9643659f5a50658a5c6db75955d440cLajos Molnar            const std::vector<C2Param::Index> &heapParamIndices,
38378746a1fc9643659f5a50658a5c6db75955d440cLajos Molnar            std::vector<std::unique_ptr<C2Param>> *const heapParams) const {
38478746a1fc9643659f5a50658a5c6db75955d440cLajos Molnar        return mClient->query(stackParams, heapParamIndices, C2_MAY_BLOCK, heapParams);
38578746a1fc9643659f5a50658a5c6db75955d440cLajos Molnar    }
38678746a1fc9643659f5a50658a5c6db75955d440cLajos Molnar
38778746a1fc9643659f5a50658a5c6db75955d440cLajos Molnar    virtual c2_status_t querySupportedParams_nb(
38878746a1fc9643659f5a50658a5c6db75955d440cLajos Molnar            std::vector<std::shared_ptr<C2ParamDescriptor>> *const params) const {
38978746a1fc9643659f5a50658a5c6db75955d440cLajos Molnar        return mClient->querySupportedParams(params);
39078746a1fc9643659f5a50658a5c6db75955d440cLajos Molnar    }
39178746a1fc9643659f5a50658a5c6db75955d440cLajos Molnar
39278746a1fc9643659f5a50658a5c6db75955d440cLajos Molnar    virtual c2_status_t querySupportedValues_sm(
39378746a1fc9643659f5a50658a5c6db75955d440cLajos Molnar            std::vector<C2FieldSupportedValuesQuery> &fields) const {
39478746a1fc9643659f5a50658a5c6db75955d440cLajos Molnar        return mClient->querySupportedValues(fields, C2_MAY_BLOCK);
39578746a1fc9643659f5a50658a5c6db75955d440cLajos Molnar    }
39678746a1fc9643659f5a50658a5c6db75955d440cLajos Molnar
39778746a1fc9643659f5a50658a5c6db75955d440cLajos Molnar    virtual C2String getName() const {
39878746a1fc9643659f5a50658a5c6db75955d440cLajos Molnar        return mClient->getName();
39978746a1fc9643659f5a50658a5c6db75955d440cLajos Molnar    }
40078746a1fc9643659f5a50658a5c6db75955d440cLajos Molnar
40178746a1fc9643659f5a50658a5c6db75955d440cLajos Molnar    virtual std::shared_ptr<C2ParamReflector> getParamReflector() const {
40278746a1fc9643659f5a50658a5c6db75955d440cLajos Molnar        return mClient->getParamReflector();
40378746a1fc9643659f5a50658a5c6db75955d440cLajos Molnar    }
40478746a1fc9643659f5a50658a5c6db75955d440cLajos Molnar
40578746a1fc9643659f5a50658a5c6db75955d440cLajos Molnar    virtual std::vector<std::shared_ptr<const C2Component::Traits>> listComponents() {
40678746a1fc9643659f5a50658a5c6db75955d440cLajos Molnar        return std::vector<std::shared_ptr<const C2Component::Traits>>();
40778746a1fc9643659f5a50658a5c6db75955d440cLajos Molnar    }
40878746a1fc9643659f5a50658a5c6db75955d440cLajos Molnar};
40978746a1fc9643659f5a50658a5c6db75955d440cLajos Molnar
410033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}  // namespace
411033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
4120f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa// CCodec::ClientListener
4130f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa
4140f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasastruct CCodec::ClientListener : public Codec2Client::Listener {
4150f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa
4160f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa    explicit ClientListener(const wp<CCodec> &codec) : mCodec(codec) {}
4170f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa
4180f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa    virtual void onWorkDone(
4190f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa            const std::weak_ptr<Codec2Client::Component>& component,
4200f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa            std::list<std::unique_ptr<C2Work>>& workItems) override {
4210f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa        (void)component;
4220f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa        sp<CCodec> codec(mCodec.promote());
4230f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa        if (!codec) {
4240f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa            return;
4250f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa        }
4260f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa        codec->onWorkDone(workItems);
4270f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa    }
4280f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa
4290f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa    virtual void onTripped(
4300f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa            const std::weak_ptr<Codec2Client::Component>& component,
4310f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa            const std::vector<std::shared_ptr<C2SettingResult>>& settingResult
4320f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa            ) override {
4330f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa        // TODO
4340f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa        (void)component;
4350f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa        (void)settingResult;
4360f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa    }
4370f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa
4380f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa    virtual void onError(
4390f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa            const std::weak_ptr<Codec2Client::Component>& component,
4400f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa            uint32_t errorCode) override {
4410f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa        // TODO
4420f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa        (void)component;
4430f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa        (void)errorCode;
4440f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa    }
4450f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa
4460f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa    virtual void onDeath(
4470f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa            const std::weak_ptr<Codec2Client::Component>& component) override {
4480f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa        { // Log the death of the component.
4490f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa            std::shared_ptr<Codec2Client::Component> comp = component.lock();
4500f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa            if (!comp) {
4510f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa                ALOGE("Codec2 component died.");
4520f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa            } else {
4530f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa                ALOGE("Codec2 component \"%s\" died.", comp->getName().c_str());
4540f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa            }
4550f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa        }
4560f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa
4570f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa        // Report to MediaCodec.
4580f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa        sp<CCodec> codec(mCodec.promote());
4590f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa        if (!codec || !codec->mCallback) {
4600f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa            return;
4610f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa        }
4620f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa        codec->mCallback->onError(DEAD_OBJECT, ACTION_CODE_FATAL);
4630f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa    }
4640f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa
465c3d20aa9415c8f02e568f203560685eaf12c3e2dPawin Vongmasa    virtual void onFramesRendered(
466c3d20aa9415c8f02e568f203560685eaf12c3e2dPawin Vongmasa            const std::vector<RenderedFrame>& renderedFrames) override {
467c3d20aa9415c8f02e568f203560685eaf12c3e2dPawin Vongmasa        // TODO
468c3d20aa9415c8f02e568f203560685eaf12c3e2dPawin Vongmasa        (void)renderedFrames;
469c3d20aa9415c8f02e568f203560685eaf12c3e2dPawin Vongmasa    }
470c3d20aa9415c8f02e568f203560685eaf12c3e2dPawin Vongmasa
4710f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasaprivate:
4720f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa    wp<CCodec> mCodec;
4730f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa};
4740f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa
475384b6a0bcf56a6cdc81fad923fc4695027fa42ddWonsik Kim// CCodecCallbackImpl
476384b6a0bcf56a6cdc81fad923fc4695027fa42ddWonsik Kim
477384b6a0bcf56a6cdc81fad923fc4695027fa42ddWonsik Kimclass CCodecCallbackImpl : public CCodecCallback {
478384b6a0bcf56a6cdc81fad923fc4695027fa42ddWonsik Kimpublic:
479384b6a0bcf56a6cdc81fad923fc4695027fa42ddWonsik Kim    explicit CCodecCallbackImpl(CCodec *codec) : mCodec(codec) {}
480384b6a0bcf56a6cdc81fad923fc4695027fa42ddWonsik Kim    ~CCodecCallbackImpl() override = default;
481384b6a0bcf56a6cdc81fad923fc4695027fa42ddWonsik Kim
482384b6a0bcf56a6cdc81fad923fc4695027fa42ddWonsik Kim    void onError(status_t err, enum ActionCode actionCode) override {
483384b6a0bcf56a6cdc81fad923fc4695027fa42ddWonsik Kim        mCodec->mCallback->onError(err, actionCode);
484384b6a0bcf56a6cdc81fad923fc4695027fa42ddWonsik Kim    }
485384b6a0bcf56a6cdc81fad923fc4695027fa42ddWonsik Kim
486384b6a0bcf56a6cdc81fad923fc4695027fa42ddWonsik Kim    void onOutputFramesRendered(int64_t mediaTimeUs, nsecs_t renderTimeNs) override {
487384b6a0bcf56a6cdc81fad923fc4695027fa42ddWonsik Kim        mCodec->mCallback->onOutputFramesRendered(
488384b6a0bcf56a6cdc81fad923fc4695027fa42ddWonsik Kim                {RenderedFrameInfo(mediaTimeUs, renderTimeNs)});
489384b6a0bcf56a6cdc81fad923fc4695027fa42ddWonsik Kim    }
490384b6a0bcf56a6cdc81fad923fc4695027fa42ddWonsik Kim
491384b6a0bcf56a6cdc81fad923fc4695027fa42ddWonsik Kimprivate:
492384b6a0bcf56a6cdc81fad923fc4695027fa42ddWonsik Kim    CCodec *mCodec;
493384b6a0bcf56a6cdc81fad923fc4695027fa42ddWonsik Kim};
494384b6a0bcf56a6cdc81fad923fc4695027fa42ddWonsik Kim
4950f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa// CCodec
4960f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa
497033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik KimCCodec::CCodec()
498384b6a0bcf56a6cdc81fad923fc4695027fa42ddWonsik Kim    : mChannel(new CCodecBufferChannel(std::make_shared<CCodecCallbackImpl>(this))) {
499033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    CCodecWatchdog::getInstance()->registerCodec(this);
500033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
501033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
502033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik KimCCodec::~CCodec() {
503033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
504033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
505033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimstd::shared_ptr<BufferChannelBase> CCodec::getBufferChannel() {
506033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    return mChannel;
507033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
508033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
509033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimstatus_t CCodec::tryAndReportOnError(std::function<status_t()> job) {
510033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    status_t err = job();
511033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (err != C2_OK) {
512033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mCallback->onError(err, ACTION_CODE_FATAL);
513033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
514033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    return err;
515033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
516033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
517033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::initiateAllocateComponent(const sp<AMessage> &msg) {
518033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    auto setAllocating = [this] {
519033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
520033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() != RELEASED) {
521033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return INVALID_OPERATION;
522033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
523033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state->set(ALLOCATING);
524033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return OK;
525033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    };
526033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (tryAndReportOnError(setAllocating) != OK) {
527033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
528033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
529033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
530033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<RefBase> codecInfo;
531033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    CHECK(msg->findObject("codecInfo", &codecInfo));
532033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    // For Codec 2.0 components, componentName == codecInfo->getCodecName().
533033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
534033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<AMessage> allocMsg(new AMessage(kWhatAllocate, this));
535033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    allocMsg->setObject("codecInfo", codecInfo);
536033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    allocMsg->post();
537033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
538033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
539033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::allocate(const sp<MediaCodecInfo> &codecInfo) {
540033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (codecInfo == nullptr) {
541033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL);
542033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
543033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
544033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    ALOGV("allocate(%s)", codecInfo->getCodecName());
5450f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa    mClientListener.reset(new ClientListener(this));
546033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
547033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    AString componentName = codecInfo->getCodecName();
5480f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    std::shared_ptr<Codec2Client> client;
54978746a1fc9643659f5a50658a5c6db75955d440cLajos Molnar
55078746a1fc9643659f5a50658a5c6db75955d440cLajos Molnar    // set up preferred component store to access vendor store parameters
55178746a1fc9643659f5a50658a5c6db75955d440cLajos Molnar    client = Codec2Client::CreateFromService("default", false);
55278746a1fc9643659f5a50658a5c6db75955d440cLajos Molnar    if (client) {
55378746a1fc9643659f5a50658a5c6db75955d440cLajos Molnar        ALOGI("setting up '%s' as default (vendor) store", client->getInstanceName().c_str());
55478746a1fc9643659f5a50658a5c6db75955d440cLajos Molnar        SetPreferredCodec2ComponentStore(
55578746a1fc9643659f5a50658a5c6db75955d440cLajos Molnar                std::make_shared<Codec2ClientInterfaceWrapper>(client));
55678746a1fc9643659f5a50658a5c6db75955d440cLajos Molnar    }
55778746a1fc9643659f5a50658a5c6db75955d440cLajos Molnar
5580f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    std::shared_ptr<Codec2Client::Component> comp =
5590f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa            Codec2Client::CreateComponentByName(
5600f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa            componentName.c_str(),
5610f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa            mClientListener,
5620f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa            &client);
5630f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    if (!comp) {
564033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        ALOGE("Failed Create component: %s", componentName.c_str());
565033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
566033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state->set(RELEASED);
567033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state.unlock();
5680f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa        mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL);
569033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state.lock();
570033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
571033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
5723bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar    ALOGI("Created component [%s]", componentName.c_str());
573033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mChannel->setComponent(comp);
5740f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    auto setAllocated = [this, comp, client] {
575033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
576033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() != ALLOCATING) {
577033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            state->set(RELEASED);
578033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return UNKNOWN_ERROR;
579033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
580033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state->set(ALLOCATED);
581033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state->comp = comp;
5820f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa        mClient = client;
583033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return OK;
584033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    };
585033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (tryAndReportOnError(setAllocated) != OK) {
586033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
587033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
5883bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar
5893bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar    // initialize config here in case setParameters is called prior to configure
5903bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar    Mutexed<Config>::Locked config(mConfig);
5913bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar    status_t err = config->initialize(mClient, comp);
5923bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar    if (err != OK) {
5933bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar        ALOGW("Failed to initialize configuration support");
5943bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar        // TODO: report error once we complete implementation.
5953bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar    }
5963bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar    config->queryConfiguration(comp);
5973bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar
5980f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    mCallback->onComponentAllocated(comp->getName().c_str());
599033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
600033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
601033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::initiateConfigureComponent(const sp<AMessage> &format) {
602033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    auto checkAllocated = [this] {
603033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
604033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return (state->get() != ALLOCATED) ? UNKNOWN_ERROR : OK;
605033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    };
606033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (tryAndReportOnError(checkAllocated) != OK) {
607033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
608033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
609033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
610033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<AMessage> msg(new AMessage(kWhatConfigure, this));
611033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    msg->setMessage("format", format);
612033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    msg->post();
613033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
614033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
615033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::configure(const sp<AMessage> &msg) {
6160f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    std::shared_ptr<Codec2Client::Component> comp;
6170f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    auto checkAllocated = [this, &comp] {
618033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
619033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() != ALLOCATED) {
620033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            state->set(RELEASED);
621033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return UNKNOWN_ERROR;
622033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
6230f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa        comp = state->comp;
624033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return OK;
625033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    };
626033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (tryAndReportOnError(checkAllocated) != OK) {
627033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
628033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
629033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
6303078c7c3136bc9546da39943f0d6abb1f7e344c8Wonsik Kim    auto doConfig = [msg, comp, this]() -> status_t {
631033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        AString mime;
632033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (!msg->findString("mime", &mime)) {
633033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return BAD_VALUE;
634033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
635033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
636033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        int32_t encoder;
637033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (!msg->findInt32("encoder", &encoder)) {
638033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            encoder = false;
639033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
640033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
6413bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar        // TODO: read from intf()
6423bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar        if ((!encoder) != (comp->getName().find("encoder") == std::string::npos)) {
6433bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar            return UNKNOWN_ERROR;
6443bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar        }
6453bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar
646f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim        int32_t storeMeta;
647f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim        if (encoder
648f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim                && msg->findInt32("android._input-metadata-buffer-type", &storeMeta)
649f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim                && storeMeta != kMetadataBufferTypeInvalid) {
650f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim            if (storeMeta != kMetadataBufferTypeANWBuffer) {
651f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim                ALOGD("Only ANW buffers are supported for legacy metadata mode");
652f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim                return BAD_VALUE;
653f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim            }
654f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim            mChannel->setMetaMode(CCodecBufferChannel::MODE_ANW);
655f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim        }
656f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim
657033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        sp<RefBase> obj;
658c3979a09c521d8aa8bf2a8e6c18a622b7701a2ceLajos Molnar        sp<Surface> surface;
659033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (msg->findObject("native-window", &obj)) {
660c3979a09c521d8aa8bf2a8e6c18a622b7701a2ceLajos Molnar            surface = static_cast<Surface *>(obj.get());
661033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            setSurface(surface);
662033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
663033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
6643bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar        Mutexed<Config>::Locked config(mConfig);
665cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar
666c3979a09c521d8aa8bf2a8e6c18a622b7701a2ceLajos Molnar        /*
667cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar         * Handle input surface configuration
668cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar         */
669cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar        if ((config->mDomain & (Config::IS_VIDEO | Config::IS_IMAGE))
670cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar                && (config->mDomain & Config::IS_ENCODER)) {
671cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar            config->mISConfig.reset(new InputSurfaceWrapper::Config{});
672cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar            {
673cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar                config->mISConfig->mMinFps = 0;
674cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar                int64_t value;
675cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar                if (msg->findInt64("repeat-previous-frame-after", &value) && value > 0) {
676cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar                    config->mISConfig->mMinFps = 1e6 / value;
677cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar                }
678cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar                (void)msg->findFloat("max-fps-to-encoder", &config->mISConfig->mMaxFps);
679cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar                config->mISConfig->mMinAdjustedFps = 0;
680cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar                config->mISConfig->mFixedAdjustedFps = 0;
681cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar                if (msg->findInt64("max-pts-gap-to-encoder", &value)) {
682cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar                    if (value < 0 && value >= INT32_MIN) {
683cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar                        config->mISConfig->mFixedAdjustedFps = -1e6 / value;
684cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar                    } else if (value > 0 && value <= INT32_MAX) {
685cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar                        config->mISConfig->mMinAdjustedFps = 1e6 / value;
686cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar                    }
687cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar                }
688cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar            }
689cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar
690cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar            {
691cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar                double value;
692cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar                if (!msg->findDouble("time-lapse-fps", &value)) {
693cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar                    config->mISConfig->mCaptureFps = value;
694cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar                }
695cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar            }
696cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar
697cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar            {
698cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar                config->mISConfig->mSuspended = false;
699cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar                config->mISConfig->mSuspendAtUs = -1;
700cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar                int32_t value;
701cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar                if (msg->findInt32("create-input-buffers-suspended", &value) && value) {
702cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar                    config->mISConfig->mSuspended = true;
703cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar                }
704cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar            }
705cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar        }
706cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar
707c3979a09c521d8aa8bf2a8e6c18a622b7701a2ceLajos Molnar        /*
708c3979a09c521d8aa8bf2a8e6c18a622b7701a2ceLajos Molnar         * Handle desired color format.
709c3979a09c521d8aa8bf2a8e6c18a622b7701a2ceLajos Molnar         */
710c3979a09c521d8aa8bf2a8e6c18a622b7701a2ceLajos Molnar        if ((config->mDomain & (Config::IS_VIDEO | Config::IS_IMAGE))) {
711c3979a09c521d8aa8bf2a8e6c18a622b7701a2ceLajos Molnar            int32_t format = -1;
712c3979a09c521d8aa8bf2a8e6c18a622b7701a2ceLajos Molnar            if (!msg->findInt32(KEY_COLOR_FORMAT, &format)) {
713c3979a09c521d8aa8bf2a8e6c18a622b7701a2ceLajos Molnar                /*
714c3979a09c521d8aa8bf2a8e6c18a622b7701a2ceLajos Molnar                 * Also handle default color format (encoders require color format, so this is only
715c3979a09c521d8aa8bf2a8e6c18a622b7701a2ceLajos Molnar                 * needed for decoders.
716c3979a09c521d8aa8bf2a8e6c18a622b7701a2ceLajos Molnar                 */
717c3979a09c521d8aa8bf2a8e6c18a622b7701a2ceLajos Molnar                if (!(config->mDomain & Config::IS_ENCODER)) {
718c3979a09c521d8aa8bf2a8e6c18a622b7701a2ceLajos Molnar                    format = (surface == nullptr) ? COLOR_FormatYUV420Planar : COLOR_FormatSurface;
719c3979a09c521d8aa8bf2a8e6c18a622b7701a2ceLajos Molnar                }
720c3979a09c521d8aa8bf2a8e6c18a622b7701a2ceLajos Molnar            }
721c3979a09c521d8aa8bf2a8e6c18a622b7701a2ceLajos Molnar
722c3979a09c521d8aa8bf2a8e6c18a622b7701a2ceLajos Molnar            if (format >= 0) {
723c3979a09c521d8aa8bf2a8e6c18a622b7701a2ceLajos Molnar                msg->setInt32("android._color-format", format);
724c3979a09c521d8aa8bf2a8e6c18a622b7701a2ceLajos Molnar            }
725c3979a09c521d8aa8bf2a8e6c18a622b7701a2ceLajos Molnar        }
726c3979a09c521d8aa8bf2a8e6c18a622b7701a2ceLajos Molnar
7273bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar        std::vector<std::unique_ptr<C2Param>> configUpdate;
7283bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar        status_t err = config->getConfigUpdateFromSdkParams(
7293bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar                comp, msg, Config::CONFIG, C2_DONT_BLOCK, &configUpdate);
7303bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar        if (err != OK) {
7313bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar            ALOGW("failed to convert configuration to c2 params");
7323bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar        }
7333bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar        err = config->setParameters(comp, configUpdate, C2_DONT_BLOCK);
7343bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar        if (err != OK) {
7353bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar            ALOGW("failed to configure c2 params");
7363078c7c3136bc9546da39943f0d6abb1f7e344c8Wonsik Kim            return err;
7373bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar        }
7383bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar
739033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        std::vector<std::unique_ptr<C2Param>> params;
7403bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar        C2StreamUsageTuning::input usage(0u, 0u);
7413bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar        C2StreamMaxBufferSizeInfo::input maxInputSize(0u, 0u);
7423bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar
743033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        std::initializer_list<C2Param::Index> indices {
744033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        };
7453bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar        c2_status_t c2err = comp->query(
7463bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar                { &usage, &maxInputSize },
747033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                indices,
748033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                C2_DONT_BLOCK,
749033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                &params);
750f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim        if (c2err != C2_OK && c2err != C2_BAD_INDEX) {
751033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            ALOGE("Failed to query component interface: %d", c2err);
752033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return UNKNOWN_ERROR;
753033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
754033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (params.size() != indices.size()) {
755f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim            ALOGE("Component returns wrong number of params: expected %zu actual %zu",
756f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim                    indices.size(), params.size());
757033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return UNKNOWN_ERROR;
758033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
759f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim        if (usage && (usage.value & C2MemoryUsage::CPU_READ)) {
7603bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar            config->mInputFormat->setInt32("using-sw-read-often", true);
761f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim        }
762033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
763e0a6b0044d208783922b0ca9553dbcd98f4aa442Lajos Molnar        // use client specified input size if specified
764e0a6b0044d208783922b0ca9553dbcd98f4aa442Lajos Molnar        bool clientInputSize = msg->findInt32(KEY_MAX_INPUT_SIZE, (int32_t*)&maxInputSize.value);
765e0a6b0044d208783922b0ca9553dbcd98f4aa442Lajos Molnar
7663bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar        // TEMP: enforce minimum buffer size of 1MB for video decoders
767e0a6b0044d208783922b0ca9553dbcd98f4aa442Lajos Molnar        if (!clientInputSize && maxInputSize.value == 0
768e0a6b0044d208783922b0ca9553dbcd98f4aa442Lajos Molnar                && !encoder && !(config->mDomain & Config::IS_AUDIO)) {
769e0a6b0044d208783922b0ca9553dbcd98f4aa442Lajos Molnar            maxInputSize.value = 1048576u;
770033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
771033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
772a00de0de4f172b294f286460292dc4a99f9dda67Lajos Molnar        // TODO: do this based on component requiring linear allocator for input
7733bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar        if ((config->mDomain & Config::IS_DECODER) || (config->mDomain & Config::IS_AUDIO)) {
7740fde62fab8b7a8802e4c8fbe8007f41af9dfcf9bLajos Molnar            // Pass max input size on input format to the buffer channel (if supplied by the
7750fde62fab8b7a8802e4c8fbe8007f41af9dfcf9bLajos Molnar            // component or by a default)
7760fde62fab8b7a8802e4c8fbe8007f41af9dfcf9bLajos Molnar            if (maxInputSize.value) {
7770fde62fab8b7a8802e4c8fbe8007f41af9dfcf9bLajos Molnar                config->mInputFormat->setInt32(
778e0a6b0044d208783922b0ca9553dbcd98f4aa442Lajos Molnar                        KEY_MAX_INPUT_SIZE,
779e0a6b0044d208783922b0ca9553dbcd98f4aa442Lajos Molnar                        (int32_t)(c2_min(maxInputSize.value, uint32_t(INT32_MAX))));
7800fde62fab8b7a8802e4c8fbe8007f41af9dfcf9bLajos Molnar            }
781a00de0de4f172b294f286460292dc4a99f9dda67Lajos Molnar        }
782a00de0de4f172b294f286460292dc4a99f9dda67Lajos Molnar
783c3979a09c521d8aa8bf2a8e6c18a622b7701a2ceLajos Molnar        if ((config->mDomain & (Config::IS_VIDEO | Config::IS_IMAGE))) {
784c3979a09c521d8aa8bf2a8e6c18a622b7701a2ceLajos Molnar            // Set desired color format from configuration parameter
785c3979a09c521d8aa8bf2a8e6c18a622b7701a2ceLajos Molnar            int32_t format;
786c3979a09c521d8aa8bf2a8e6c18a622b7701a2ceLajos Molnar            if (msg->findInt32("android._color-format", &format)) {
787c3979a09c521d8aa8bf2a8e6c18a622b7701a2ceLajos Molnar                if (config->mDomain & Config::IS_ENCODER) {
788c3979a09c521d8aa8bf2a8e6c18a622b7701a2ceLajos Molnar                    config->mInputFormat->setInt32(KEY_COLOR_FORMAT, format);
789c3979a09c521d8aa8bf2a8e6c18a622b7701a2ceLajos Molnar                } else {
790c3979a09c521d8aa8bf2a8e6c18a622b7701a2ceLajos Molnar                    config->mOutputFormat->setInt32(KEY_COLOR_FORMAT, format);
791c3979a09c521d8aa8bf2a8e6c18a622b7701a2ceLajos Molnar                }
792c3979a09c521d8aa8bf2a8e6c18a622b7701a2ceLajos Molnar            }
793c3979a09c521d8aa8bf2a8e6c18a622b7701a2ceLajos Molnar        }
794c3979a09c521d8aa8bf2a8e6c18a622b7701a2ceLajos Molnar
795c3979a09c521d8aa8bf2a8e6c18a622b7701a2ceLajos Molnar        // propagate encoder delay and padding to output format
796dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim        if ((config->mDomain & Config::IS_DECODER) && (config->mDomain & Config::IS_AUDIO)) {
797dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim            int delay = 0;
798dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim            if (msg->findInt32("encoder-delay", &delay)) {
799dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim                config->mOutputFormat->setInt32("encoder-delay", delay);
800dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim            }
801dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim            int padding = 0;
802dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim            if (msg->findInt32("encoder-padding", &padding)) {
803dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim                config->mOutputFormat->setInt32("encoder-padding", padding);
804dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim            }
805dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim        }
806dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim
8073bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar        ALOGD("setup formats input: %s and output: %s",
8083bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar                config->mInputFormat->debugString().c_str(),
8093bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar                config->mOutputFormat->debugString().c_str());
810033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return OK;
811033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    };
812033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (tryAndReportOnError(doConfig) != OK) {
813033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
814033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
815033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
8163bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar    Mutexed<Config>::Locked config(mConfig);
8173bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar
8183bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar    mCallback->onComponentConfigured(config->mInputFormat, config->mOutputFormat);
819033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
820033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
821033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::initiateCreateInputSurface() {
822033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    status_t err = [this] {
823033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
824033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() != ALLOCATED) {
825033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return UNKNOWN_ERROR;
826033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
827033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        // TODO: read it from intf() properly.
8280f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa        if (state->comp->getName().find("encoder") == std::string::npos) {
829033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return INVALID_OPERATION;
830033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
831033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return OK;
832033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }();
833033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (err != OK) {
834033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mCallback->onInputSurfaceCreationFailed(err);
835033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
836033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
837033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
838033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    (new AMessage(kWhatCreateInputSurface, this))->post();
839033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
840033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
841033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::createInputSurface() {
8422bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa    status_t err;
8431c421ef3ded7c7dd25a44ea0d90db1ec46f5c1fbWonsik Kim    sp<IGraphicBufferProducer> bufferProducer;
844033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
845033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<AMessage> inputFormat;
846033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<AMessage> outputFormat;
847033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    {
8483bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar        Mutexed<Config>::Locked config(mConfig);
8493bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar        inputFormat = config->mInputFormat;
8503bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar        outputFormat = config->mOutputFormat;
851033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
8522bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa
8532bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa    // TODO: Remove this property check and assume it's always true.
8542bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa    if (property_get_bool("debug.stagefright.c2inputsurface", false)) {
8552bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa        std::shared_ptr<Codec2Client::InputSurface> surface;
8562bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa
8572bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa        err = static_cast<status_t>(mClient->createInputSurface(&surface));
8582bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa        if (err != OK) {
8592bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa            ALOGE("Failed to create input surface: %d", static_cast<int>(err));
8602bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa            mCallback->onInputSurfaceCreationFailed(err);
8612bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa            return;
8622bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa        }
8632bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa        if (!surface) {
8642bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa            ALOGE("Failed to create input surface: null input surface");
8652bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa            mCallback->onInputSurfaceCreationFailed(UNKNOWN_ERROR);
8662bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa            return;
8672bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa        }
8682bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa        bufferProducer = surface->getGraphicBufferProducer();
8692bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa        err = setupInputSurface(std::make_shared<C2InputSurfaceWrapper>(surface));
8702bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa    } else { // TODO: Remove this block.
8712bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa        using namespace ::android::hardware::media::omx::V1_0;
8722bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa        sp<IOmx> tOmx = IOmx::getService("default");
8732bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa        if (tOmx == nullptr) {
8742bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa            ALOGE("Failed to create input surface");
8752bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa            mCallback->onInputSurfaceCreationFailed(UNKNOWN_ERROR);
8762bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa            return;
8772bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa        }
8782bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa        sp<IOMX> omx = new utils::LWOmx(tOmx);
8792bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa
8802bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa        sp<BGraphicBufferSource> bufferSource;
8812bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa        err = omx->createInputSurface(&bufferProducer, &bufferSource);
8822bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa
8832bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa        if (err != OK) {
8842bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa            ALOGE("Failed to create input surface: %d", err);
8852bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa            mCallback->onInputSurfaceCreationFailed(err);
8862bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa            return;
8872bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa        }
8882bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa        int32_t width = 0;
8892bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa        (void)outputFormat->findInt32("width", &width);
8902bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa        int32_t height = 0;
8912bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa        (void)outputFormat->findInt32("height", &height);
8922bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa        err = setupInputSurface(std::make_shared<GraphicBufferSourceWrapper>(
8932bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa                bufferSource, width, height));
8942bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa    }
8952bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa
896ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim    if (err != OK) {
897ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim        ALOGE("Failed to set up input surface: %d", err);
898ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim        mCallback->onInputSurfaceCreationFailed(err);
899ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim        return;
900ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim    }
901033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mCallback->onInputSurfaceCreated(
902033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            inputFormat,
903033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            outputFormat,
9041c421ef3ded7c7dd25a44ea0d90db1ec46f5c1fbWonsik Kim            new BufferProducerWrapper(bufferProducer));
905033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
906033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
907033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimstatus_t CCodec::setupInputSurface(const std::shared_ptr<InputSurfaceWrapper> &surface) {
908033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    status_t err = mChannel->setInputSurface(surface);
909033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (err != OK) {
910033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return err;
911033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
912033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
913cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar    Mutexed<Config>::Locked config(mConfig);
914cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar    config->mInputSurface = surface;
915cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar    if (config->mISConfig) {
916cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar        surface->configure(*config->mISConfig);
917cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar    } else {
918cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar        ALOGD("ISConfig: no configuration");
919cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar    }
920cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar
921033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    // TODO: configure |surface| with other settings.
922033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    return OK;
923033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
924033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
925033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::initiateSetInputSurface(const sp<PersistentSurface> &surface) {
926033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<AMessage> msg = new AMessage(kWhatSetInputSurface, this);
927033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    msg->setObject("surface", surface);
928033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    msg->post();
929033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
930033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
931033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::setInputSurface(const sp<PersistentSurface> &surface) {
932033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<AMessage> inputFormat;
933033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<AMessage> outputFormat;
934033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    {
9353bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar        Mutexed<Config>::Locked config(mConfig);
9363bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar        inputFormat = config->mInputFormat;
9373bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar        outputFormat = config->mOutputFormat;
938033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
939ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim    int32_t width = 0;
940ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim    (void)outputFormat->findInt32("width", &width);
941ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim    int32_t height = 0;
942ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim    (void)outputFormat->findInt32("height", &height);
943ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim    status_t err = setupInputSurface(std::make_shared<GraphicBufferSourceWrapper>(
944ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim            surface->getBufferSource(), width, height));
945ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim    if (err != OK) {
946ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim        ALOGE("Failed to set up input surface: %d", err);
947ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim        mCallback->onInputSurfaceDeclined(err);
948ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim        return;
949ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim    }
950033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mCallback->onInputSurfaceAccepted(inputFormat, outputFormat);
951033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
952033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
953033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::initiateStart() {
954033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    auto setStarting = [this] {
955033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
956033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() != ALLOCATED) {
957033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return UNKNOWN_ERROR;
958033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
959033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state->set(STARTING);
960033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return OK;
961033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    };
962033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (tryAndReportOnError(setStarting) != OK) {
963033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
964033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
965033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
966033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    (new AMessage(kWhatStart, this))->post();
967033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
968033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
969033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::start() {
9700f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    std::shared_ptr<Codec2Client::Component> comp;
971033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    auto checkStarting = [this, &comp] {
972033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
973033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() != STARTING) {
974033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return UNKNOWN_ERROR;
975033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
976033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        comp = state->comp;
977033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return OK;
978033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    };
979033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (tryAndReportOnError(checkStarting) != OK) {
980033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
981033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
982033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
983033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    c2_status_t err = comp->start();
984033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (err != C2_OK) {
985033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        // TODO: convert err into status_t
986033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL);
987033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
988033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
989033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<AMessage> inputFormat;
990033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<AMessage> outputFormat;
991033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    {
9923bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar        Mutexed<Config>::Locked config(mConfig);
9933bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar        inputFormat = config->mInputFormat;
9943bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar        outputFormat = config->mOutputFormat;
995033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
996033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    status_t err2 = mChannel->start(inputFormat, outputFormat);
997033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (err2 != OK) {
998033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mCallback->onError(err2, ACTION_CODE_FATAL);
999033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
1000033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
1001033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1002033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    auto setRunning = [this] {
1003033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
1004033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() != STARTING) {
1005033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return UNKNOWN_ERROR;
1006033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
1007033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state->set(RUNNING);
1008033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return OK;
1009033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    };
1010033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (tryAndReportOnError(setRunning) != OK) {
1011033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
1012033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
1013033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mCallback->onStartCompleted();
1014033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
1015033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1016033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::initiateShutdown(bool keepComponentAllocated) {
1017033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (keepComponentAllocated) {
1018033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        initiateStop();
1019033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    } else {
1020033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        initiateRelease();
1021033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
1022033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
1023033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1024033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::initiateStop() {
1025033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    {
1026033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
1027033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() == ALLOCATED
1028033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                || state->get()  == RELEASED
1029033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                || state->get() == STOPPING
1030033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                || state->get() == RELEASING) {
1031033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            // We're already stopped, released, or doing it right now.
1032033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            state.unlock();
1033033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            mCallback->onStopCompleted();
1034033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            state.lock();
1035033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return;
1036033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
1037033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state->set(STOPPING);
1038033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
1039033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1040c2088887496fa8627e0a2a4e713f413301065516Wonsik Kim    mChannel->stop();
1041033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    (new AMessage(kWhatStop, this))->post();
1042033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
1043033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1044033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::stop() {
10450f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    std::shared_ptr<Codec2Client::Component> comp;
1046033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    {
1047033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
1048033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() == RELEASING) {
1049033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            state.unlock();
1050033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            // We're already stopped or release is in progress.
1051033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            mCallback->onStopCompleted();
1052033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            state.lock();
1053033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return;
1054033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        } else if (state->get() != STOPPING) {
1055033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            state.unlock();
1056033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL);
1057033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            state.lock();
1058033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return;
1059033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
1060033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        comp = state->comp;
1061033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
1062033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    status_t err = comp->stop();
1063033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (err != C2_OK) {
1064033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        // TODO: convert err into status_t
1065033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL);
1066033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
1067033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1068033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    {
1069033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
1070033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() == STOPPING) {
1071033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            state->set(ALLOCATED);
1072033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
1073033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
1074033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mCallback->onStopCompleted();
1075033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
1076033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1077033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::initiateRelease(bool sendCallback /* = true */) {
1078033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    {
1079033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
1080033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() == RELEASED || state->get() == RELEASING) {
1081033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            // We're already released or doing it right now.
1082033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            if (sendCallback) {
1083033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                state.unlock();
1084033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                mCallback->onReleaseCompleted();
1085033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                state.lock();
1086033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            }
1087033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return;
1088033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
1089033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() == ALLOCATING) {
1090033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            state->set(RELEASING);
1091033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            // With the altered state allocate() would fail and clean up.
1092033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            if (sendCallback) {
1093033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                state.unlock();
1094033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                mCallback->onReleaseCompleted();
1095033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                state.lock();
1096033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            }
1097033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return;
1098033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
1099033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state->set(RELEASING);
1100033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
1101033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1102c2088887496fa8627e0a2a4e713f413301065516Wonsik Kim    mChannel->stop();
1103033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    std::thread([this, sendCallback] { release(sendCallback); }).detach();
1104033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
1105033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1106033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::release(bool sendCallback) {
11070f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    std::shared_ptr<Codec2Client::Component> comp;
1108033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    {
1109033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
1110033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() == RELEASED) {
1111033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            if (sendCallback) {
1112033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                state.unlock();
1113033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                mCallback->onReleaseCompleted();
1114033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                state.lock();
1115033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            }
1116033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return;
1117033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
1118033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        comp = state->comp;
1119033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
1120033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    comp->release();
1121033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1122033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    {
1123033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
1124033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state->set(RELEASED);
1125033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state->comp.reset();
1126033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
1127033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (sendCallback) {
1128033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mCallback->onReleaseCompleted();
1129033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
1130033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
1131033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1132033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimstatus_t CCodec::setSurface(const sp<Surface> &surface) {
1133033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    return mChannel->setSurface(surface);
1134033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
1135033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1136033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::signalFlush() {
1137033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    status_t err = [this] {
1138033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
1139033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() == FLUSHED) {
1140033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return ALREADY_EXISTS;
1141033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
1142033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() != RUNNING) {
1143033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return UNKNOWN_ERROR;
1144033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
1145033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state->set(FLUSHING);
1146033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return OK;
1147033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }();
1148033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    switch (err) {
1149033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        case ALREADY_EXISTS:
1150033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            mCallback->onFlushCompleted();
1151033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return;
1152033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        case OK:
1153033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            break;
1154033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        default:
1155033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            mCallback->onError(err, ACTION_CODE_FATAL);
1156033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return;
1157033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
1158033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1159c2088887496fa8627e0a2a4e713f413301065516Wonsik Kim    mChannel->stop();
1160033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    (new AMessage(kWhatFlush, this))->post();
1161033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
1162033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1163033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::flush() {
11640f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    std::shared_ptr<Codec2Client::Component> comp;
1165033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    auto checkFlushing = [this, &comp] {
1166033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
1167033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() != FLUSHING) {
1168033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return UNKNOWN_ERROR;
1169033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
1170033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        comp = state->comp;
1171033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return OK;
1172033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    };
1173033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (tryAndReportOnError(checkFlushing) != OK) {
1174033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
1175033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
1176033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1177033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    std::list<std::unique_ptr<C2Work>> flushedWork;
11780f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    c2_status_t err = comp->flush(C2Component::FLUSH_COMPONENT, &flushedWork);
1179033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (err != C2_OK) {
1180033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        // TODO: convert err into status_t
1181033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL);
1182033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
1183033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1184033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mChannel->flush(flushedWork);
1185033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1186033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    {
1187033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
1188033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state->set(FLUSHED);
1189033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
1190033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mCallback->onFlushCompleted();
1191033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
1192033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1193033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::signalResume() {
1194033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    auto setResuming = [this] {
1195033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
1196033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() != FLUSHED) {
1197033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return UNKNOWN_ERROR;
1198033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
1199033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state->set(RESUMING);
1200033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return OK;
1201033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    };
1202033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (tryAndReportOnError(setResuming) != OK) {
1203033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
1204033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
1205033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1206033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    (void)mChannel->start(nullptr, nullptr);
1207033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1208033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    {
1209033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
1210033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() != RESUMING) {
1211033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            state.unlock();
1212033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL);
1213033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            state.lock();
1214033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return;
1215033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
1216033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state->set(RUNNING);
1217033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
1218033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
1219033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1220069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kimvoid CCodec::signalSetParameters(const sp<AMessage> &params) {
1221069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim    sp<AMessage> msg = new AMessage(kWhatSetParameters, this);
1222069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim    msg->setMessage("params", params);
1223069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim    msg->post();
1224069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim}
1225069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim
12263bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnarvoid CCodec::setParameters(const sp<AMessage> &params) {
1227069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim    std::shared_ptr<Codec2Client::Component> comp;
1228069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim    auto checkState = [this, &comp] {
1229069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        Mutexed<State>::Locked state(mState);
1230069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        if (state->get() == RELEASED) {
1231069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim            return INVALID_OPERATION;
1232069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        }
1233069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        comp = state->comp;
1234069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        return OK;
1235069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim    };
1236069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim    if (tryAndReportOnError(checkState) != OK) {
1237069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        return;
1238069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim    }
1239069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim
12403bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar    Mutexed<Config>::Locked config(mConfig);
1241cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar
1242cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar    /**
1243cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar     * Handle input surface parameters
1244cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar     */
1245cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar    if ((config->mDomain & (Config::IS_VIDEO | Config::IS_IMAGE))
1246cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar            && (config->mDomain & Config::IS_ENCODER) && config->mInputSurface && config->mISConfig) {
1247cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar        (void)params->findInt64("time-offset-us", &config->mISConfig->mTimeOffsetUs);
1248cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar
1249cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar        if (params->findInt64("skip-frames-before", &config->mISConfig->mStartAtUs)) {
1250cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar            config->mISConfig->mStopped = false;
1251cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar        } else if (params->findInt64("stop-time-us", &config->mISConfig->mStopAtUs)) {
1252cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar            config->mISConfig->mStopped = true;
1253cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar        }
1254cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar
1255cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar        int32_t value;
1256cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar        if (params->findInt32("drop-input-frames", &value)) {
1257cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar            config->mISConfig->mSuspended = value;
1258cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar            config->mISConfig->mSuspendAtUs = -1;
1259cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar            (void)params->findInt64("drop-start-time-us", &config->mISConfig->mSuspendAtUs);
1260cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar        }
1261cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar
1262cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar        (void)config->mInputSurface->configure(*config->mISConfig);
1263cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar        if (config->mISConfig->mStopped) {
1264cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar            config->mInputFormat->setInt64(
1265cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar                    "android._stop-time-offset-us", config->mISConfig->mInputDelayUs);
1266cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar        }
1267cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar    }
1268cb27b4537d5bbf2f327b30f76b1178b73955fc06Lajos Molnar
12693bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar    std::vector<std::unique_ptr<C2Param>> configUpdate;
12703bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar    (void)config->getConfigUpdateFromSdkParams(comp, params, Config::PARAM, C2_MAY_BLOCK, &configUpdate);
12713bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar    if (property_get_bool("debug.stagefright.ccodec_delayed_params", false)) {
12723bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar        // mChannel->queueConfigUpdate(configUpdate);
12733bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar    } else {
12743bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar        (void)config->setParameters(comp, configUpdate, C2_MAY_BLOCK);
1275069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim    }
1276033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
1277033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1278033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::signalEndOfInputStream() {
12797a702c9f08c57f64121149e3e233cbe8fcf4dc36Wonsik Kim    mCallback->onSignaledInputEOS(mChannel->signalEndOfInputStream());
1280033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
1281033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1282033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::signalRequestIDRFrame() {
1283033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    // TODO
1284033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
1285033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1286033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::onWorkDone(std::list<std::unique_ptr<C2Work>> &workItems) {
1287033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    Mutexed<std::list<std::unique_ptr<C2Work>>>::Locked queue(mWorkDoneQueue);
1288033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    queue->splice(queue->end(), workItems);
1289033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    (new AMessage(kWhatWorkDone, this))->post();
1290033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
1291033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1292033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::onMessageReceived(const sp<AMessage> &msg) {
1293033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    TimePoint now = std::chrono::steady_clock::now();
1294033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    switch (msg->what()) {
1295033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        case kWhatAllocate: {
1296033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            // C2ComponentStore::createComponent() should return within 100ms.
1297033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            setDeadline(now + 150ms, "allocate");
1298033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            sp<RefBase> obj;
1299033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            CHECK(msg->findObject("codecInfo", &obj));
1300033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            allocate((MediaCodecInfo *)obj.get());
1301033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            break;
1302033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
1303033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        case kWhatConfigure: {
1304033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            // C2Component::commit_sm() should return within 5ms.
1305033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            setDeadline(now + 50ms, "configure");
1306033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            sp<AMessage> format;
1307033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            CHECK(msg->findMessage("format", &format));
1308033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            configure(format);
1309033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            break;
1310033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
1311033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        case kWhatStart: {
1312033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            // C2Component::start() should return within 500ms.
1313033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            setDeadline(now + 550ms, "start");
1314033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            start();
1315033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            break;
1316033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
1317033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        case kWhatStop: {
1318033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            // C2Component::stop() should return within 500ms.
1319033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            setDeadline(now + 550ms, "stop");
1320033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            stop();
1321033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            break;
1322033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
1323033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        case kWhatFlush: {
1324033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            // C2Component::flush_sm() should return within 5ms.
1325033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            setDeadline(now + 50ms, "flush");
1326033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            flush();
1327033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            break;
1328033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
1329033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        case kWhatCreateInputSurface: {
1330033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            // Surface operations may be briefly blocking.
1331033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            setDeadline(now + 100ms, "createInputSurface");
1332033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            createInputSurface();
1333033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            break;
1334033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
1335033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        case kWhatSetInputSurface: {
1336033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            // Surface operations may be briefly blocking.
1337033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            setDeadline(now + 100ms, "setInputSurface");
1338033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            sp<RefBase> obj;
1339033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            CHECK(msg->findObject("surface", &obj));
1340033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            sp<PersistentSurface> surface(static_cast<PersistentSurface *>(obj.get()));
1341033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            setInputSurface(surface);
1342033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            break;
1343033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
1344069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        case kWhatSetParameters: {
1345069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim            setDeadline(now + 50ms, "setParameters");
1346069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim            sp<AMessage> params;
1347069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim            CHECK(msg->findMessage("params", &params));
1348069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim            setParameters(params);
1349069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim            break;
1350069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        }
1351033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        case kWhatWorkDone: {
1352033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            std::unique_ptr<C2Work> work;
1353033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            {
1354033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                Mutexed<std::list<std::unique_ptr<C2Work>>>::Locked queue(mWorkDoneQueue);
1355033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                if (queue->empty()) {
1356033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                    break;
1357033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                }
1358033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                work.swap(queue->front());
1359033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                queue->pop_front();
1360033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                if (!queue->empty()) {
1361033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                    (new AMessage(kWhatWorkDone, this))->post();
1362033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                }
1363033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            }
13643bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar
13653bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar            // handle configuration changes in work done
13663bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar            Mutexed<Config>::Locked config(mConfig);
13673bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar            bool changed = false;
13683bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar            Config::Watcher<C2StreamInitDataInfo::output> initData =
13693bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar                config->watch<C2StreamInitDataInfo::output>();
13703bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar            if (!work->worklets.empty()
13713bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar                    && (work->worklets.front()->output.flags
13723bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar                            & C2FrameData::FLAG_DISCARD_FRAME) == 0) {
1373b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar
1374b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar                // copy buffer info to config
1375b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar                std::vector<std::unique_ptr<C2Param>> updates =
1376b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar                    std::move(work->worklets.front()->output.configUpdate);
1377b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar                unsigned stream = 0;
1378b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar                for (const std::shared_ptr<C2Buffer> &buf : work->worklets.front()->output.buffers) {
1379b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar                    for (const std::shared_ptr<const C2Info> &info : buf->info()) {
1380b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar                        // move all info into output-stream #0 domain
1381b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar                        updates.emplace_back(C2Param::CopyAsStream(*info, true /* output */, stream));
1382b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar                    }
1383b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar                    for (const C2ConstGraphicBlock &block : buf->data().graphicBlocks()) {
1384b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar                        // ALOGV("got output buffer with crop %u,%u+%u,%u and size %u,%u",
1385b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar                        //      block.crop().left, block.crop().top,
1386b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar                        //      block.crop().width, block.crop().height,
1387b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar                        //      block.width(), block.height());
1388b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar                        updates.emplace_back(new C2StreamCropRectInfo::output(stream, block.crop()));
1389b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar                        updates.emplace_back(new C2StreamPictureSizeInfo::output(
1390b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar                                stream, block.width(), block.height()));
1391b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar                        break; // for now only do the first block
1392b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar                    }
1393b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar                    ++stream;
1394b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar                }
1395b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar
13966ee7f3e4abf2e0cad1461033bb3132d337179beeLajos Molnar                changed = config->updateConfiguration(updates, config->mOutputDomain);
1397b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar
1398b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar                // copy standard infos to graphic buffers if not already present (otherwise, we
1399b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar                // may overwrite the actual intermediate value with a final value)
1400b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar                stream = 0;
1401b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar                const static std::vector<C2Param::Index> stdGfxInfos = {
1402b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar                    C2StreamRotationInfo::output::PARAM_TYPE,
1403b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar                    C2StreamColorAspectsInfo::output::PARAM_TYPE,
1404b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar                    C2StreamHdrStaticInfo::output::PARAM_TYPE,
1405b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar                    C2StreamPixelAspectRatioInfo::output::PARAM_TYPE,
1406b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar                    C2StreamSurfaceScalingInfo::output::PARAM_TYPE
1407b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar                };
1408b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar                for (const std::shared_ptr<C2Buffer> &buf : work->worklets.front()->output.buffers) {
1409b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar                    if (buf->data().graphicBlocks().size()) {
1410b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar                        for (C2Param::Index ix : stdGfxInfos) {
1411b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar                            if (!buf->hasInfo(ix)) {
1412b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar                                const C2Param *param =
1413b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar                                    config->getConfigParameterValue(ix.withStream(stream));
1414b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar                                if (param) {
1415b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar                                    std::shared_ptr<C2Param> info(C2Param::Copy(*param));
1416b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar                                    buf->setInfo(std::static_pointer_cast<C2Info>(info));
1417b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar                                }
1418b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar                            }
1419b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar                        }
1420b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar                    }
1421b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar                    ++stream;
1422b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar                }
14233bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar            }
14243bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar            mChannel->onWorkDone(
14253bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar                    std::move(work), changed ? config->mOutputFormat : nullptr,
14263bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar                    initData.hasChanged() ? initData.update().get() : nullptr);
1427033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            break;
1428033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
1429033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        default: {
1430033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            ALOGE("unrecognized message");
1431033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            break;
1432033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
1433033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
1434033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    setDeadline(TimePoint::max(), "none");
1435033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
1436033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1437033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::setDeadline(const TimePoint &newDeadline, const char *name) {
1438033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    Mutexed<NamedTimePoint>::Locked deadline(mDeadline);
1439033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    deadline->set(newDeadline, name);
1440033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
1441033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1442033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::initiateReleaseIfStuck() {
1443033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    std::string name;
1444033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    {
1445033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<NamedTimePoint>::Locked deadline(mDeadline);
1446033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (deadline->get() >= std::chrono::steady_clock::now()) {
1447033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            // We're not stuck.
1448033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return;
1449033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
1450033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        name = deadline->getName();
1451033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
1452033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1453033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    ALOGW("previous call to %s exceeded timeout", name.c_str());
1454033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    initiateRelease(false);
1455033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL);
1456033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
1457033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1458033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}  // namespace android
1459033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1460033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimextern "C" android::CodecBase *CreateCodec() {
1461033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    return new android::CCodec;
1462033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
14630f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa
1464