CCodec.cpp revision 7a702c9f08c57f64121149e3e233cbe8fcf4dc36
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 <cutils/properties.h>
20033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include <utils/Log.h>
21033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
22033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include <thread>
23033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
24277b7295f317c6597fadb116b6aee5ca3be106c1Wonsik Kim#include <C2Config.h>
25069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim#include <C2ParamInternal.h>
26033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include <C2PlatformSupport.h>
27033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include <C2V4l2Support.h>
28033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
29033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include <android/IOMXBufferSource.h>
301c421ef3ded7c7dd25a44ea0d90db1ec46f5c1fbWonsik Kim#include <android/IGraphicBufferSource.h>
312bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa#include <cutils/properties.h>
32033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include <gui/bufferqueue/1.0/H2BGraphicBufferProducer.h>
331c421ef3ded7c7dd25a44ea0d90db1ec46f5c1fbWonsik Kim#include <gui/IGraphicBufferProducer.h>
34033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include <gui/Surface.h>
351c421ef3ded7c7dd25a44ea0d90db1ec46f5c1fbWonsik Kim#include <media/omx/1.0/WOmx.h>
36033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include <media/stagefright/codec2/1.0/InputSurface.h>
37033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include <media/stagefright/BufferProducerWrapper.h>
38033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include <media/stagefright/PersistentSurface.h>
39033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
40033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include "C2OMXNode.h"
41033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include "CCodec.h"
42033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include "CCodecBufferChannel.h"
43033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include "InputSurfaceWrapper.h"
44033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
45033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimnamespace android {
46033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
47033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimusing namespace std::chrono_literals;
48033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimusing ::android::hardware::graphics::bufferqueue::V1_0::utils::H2BGraphicBufferProducer;
491c421ef3ded7c7dd25a44ea0d90db1ec46f5c1fbWonsik Kimusing BGraphicBufferSource = ::android::IGraphicBufferSource;
50033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
51033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimnamespace {
52033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
53033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimclass CCodecWatchdog : public AHandler {
54033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimprivate:
55033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    enum {
56033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        kWhatRegister,
57033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        kWhatWatch,
58033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    };
59033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    constexpr static int64_t kWatchIntervalUs = 3000000;  // 3 secs
60033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
61033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimpublic:
62033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    static sp<CCodecWatchdog> getInstance() {
63033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<sp<CCodecWatchdog>>::Locked instance(sInstance);
64033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (*instance == nullptr) {
65033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            *instance = new CCodecWatchdog;
66033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            (*instance)->init();
67033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
68033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return *instance;
69033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
70033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
71033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    ~CCodecWatchdog() = default;
72033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
73033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    void registerCodec(CCodec *codec) {
74033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        sp<AMessage> msg = new AMessage(kWhatRegister, this);
75033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        msg->setPointer("codec", codec);
76033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        msg->post();
77033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
78033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
79033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimprotected:
80033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    void onMessageReceived(const sp<AMessage> &msg) {
81033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        switch (msg->what()) {
82033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            case kWhatRegister: {
83033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                void *ptr = nullptr;
84033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                CHECK(msg->findPointer("codec", &ptr));
85033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                Mutexed<std::list<wp<CCodec>>>::Locked codecs(mCodecs);
86033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                codecs->emplace_back((CCodec *)ptr);
87033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                break;
88033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            }
89033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
90033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            case kWhatWatch: {
91033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                Mutexed<std::list<wp<CCodec>>>::Locked codecs(mCodecs);
92033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                for (auto it = codecs->begin(); it != codecs->end(); ) {
93033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                    sp<CCodec> codec = it->promote();
94033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                    if (codec == nullptr) {
95033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                        it = codecs->erase(it);
96033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                        continue;
97033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                    }
98033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                    codec->initiateReleaseIfStuck();
99033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                    ++it;
100033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                }
101033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                msg->post(kWatchIntervalUs);
102033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                break;
103033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            }
104033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
105033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            default: {
106033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                TRESPASS("CCodecWatchdog: unrecognized message");
107033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            }
108033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
109033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
110033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
111033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimprivate:
112033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    CCodecWatchdog() : mLooper(new ALooper) {}
113033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
114033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    void init() {
115033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mLooper->setName("CCodecWatchdog");
116033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mLooper->registerHandler(this);
117033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mLooper->start();
118033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        (new AMessage(kWhatWatch, this))->post(kWatchIntervalUs);
119033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
120033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
121033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    static Mutexed<sp<CCodecWatchdog>> sInstance;
122033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
123033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<ALooper> mLooper;
124033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    Mutexed<std::list<wp<CCodec>>> mCodecs;
125033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim};
126033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
127033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik KimMutexed<sp<CCodecWatchdog>> CCodecWatchdog::sInstance;
128033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
129033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimclass C2InputSurfaceWrapper : public InputSurfaceWrapper {
130033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimpublic:
1310f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    explicit C2InputSurfaceWrapper(
1320f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa            const std::shared_ptr<Codec2Client::InputSurface> &surface) :
1330f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa        mSurface(surface) {
1340f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    }
1350f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa
136033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    ~C2InputSurfaceWrapper() override = default;
137033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1380f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    status_t connect(const std::shared_ptr<Codec2Client::Component> &comp) override {
139033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (mConnection != nullptr) {
140033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return ALREADY_EXISTS;
141033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
1420f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa        return static_cast<status_t>(
1430f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa                mSurface->connectToComponent(comp, &mConnection));
144033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
145033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
146033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    void disconnect() override {
147033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (mConnection != nullptr) {
148033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            mConnection->disconnect();
1490f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa            mConnection = nullptr;
150033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
151033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
152033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1537a702c9f08c57f64121149e3e233cbe8fcf4dc36Wonsik Kim    status_t signalEndOfInputStream() override {
1547a702c9f08c57f64121149e3e233cbe8fcf4dc36Wonsik Kim        C2InputSurfaceEosTuning eos(true);
1557a702c9f08c57f64121149e3e233cbe8fcf4dc36Wonsik Kim        std::vector<std::unique_ptr<C2SettingResult>> failures;
1567a702c9f08c57f64121149e3e233cbe8fcf4dc36Wonsik Kim        c2_status_t err = mSurface->getConfigurable()->config({&eos}, C2_MAY_BLOCK, &failures);
1577a702c9f08c57f64121149e3e233cbe8fcf4dc36Wonsik Kim        if (err != C2_OK) {
1587a702c9f08c57f64121149e3e233cbe8fcf4dc36Wonsik Kim            return UNKNOWN_ERROR;
1597a702c9f08c57f64121149e3e233cbe8fcf4dc36Wonsik Kim        }
1607a702c9f08c57f64121149e3e233cbe8fcf4dc36Wonsik Kim        return OK;
1617a702c9f08c57f64121149e3e233cbe8fcf4dc36Wonsik Kim    }
1627a702c9f08c57f64121149e3e233cbe8fcf4dc36Wonsik Kim
163033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimprivate:
1640f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    std::shared_ptr<Codec2Client::InputSurface> mSurface;
1650f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    std::shared_ptr<Codec2Client::InputSurfaceConnection> mConnection;
166033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim};
167033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
168033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimclass GraphicBufferSourceWrapper : public InputSurfaceWrapper {
169033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimpublic:
170ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim//    explicit GraphicBufferSourceWrapper(const sp<BGraphicBufferSource> &source) : mSource(source) {}
171ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim    GraphicBufferSourceWrapper(
172ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim            const sp<BGraphicBufferSource> &source,
173ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim            uint32_t width,
174ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim            uint32_t height)
175ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim        : mSource(source), mWidth(width), mHeight(height) {}
176033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    ~GraphicBufferSourceWrapper() override = default;
177033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1780f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    status_t connect(const std::shared_ptr<Codec2Client::Component> &comp) override {
179033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        // TODO: proper color aspect & dataspace
180033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        android_dataspace dataSpace = HAL_DATASPACE_BT709;
181033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
182033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mNode = new C2OMXNode(comp);
183ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim        mNode->setFrameSize(mWidth, mHeight);
184033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mSource->configure(mNode, dataSpace);
185033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
186033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        // TODO: configure according to intf().
187033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
188033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        sp<IOMXBufferSource> source = mNode->getSource();
189033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (source == nullptr) {
190033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return NO_INIT;
191033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
192033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        constexpr size_t kNumSlots = 16;
193033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        for (size_t i = 0; i < kNumSlots; ++i) {
194033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            source->onInputBufferAdded(i);
195033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
196033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        source->onOmxExecuting();
197033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return OK;
198033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
199033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
200033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    void disconnect() override {
201033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (mNode == nullptr) {
202033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return;
203033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
204033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        sp<IOMXBufferSource> source = mNode->getSource();
205033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (source == nullptr) {
206033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            ALOGD("GBSWrapper::disconnect: node is not configured with OMXBufferSource.");
207033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return;
208033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
209033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        source->onOmxIdle();
210033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        source->onOmxLoaded();
211033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mNode.clear();
212033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
213033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
2147a702c9f08c57f64121149e3e233cbe8fcf4dc36Wonsik Kim    status_t signalEndOfInputStream() override {
2157a702c9f08c57f64121149e3e233cbe8fcf4dc36Wonsik Kim        binder::Status status = mSource->signalEndOfInputStream();
2167a702c9f08c57f64121149e3e233cbe8fcf4dc36Wonsik Kim        status_t err = OK;
2177a702c9f08c57f64121149e3e233cbe8fcf4dc36Wonsik Kim        if (status.isOk()) {
2187a702c9f08c57f64121149e3e233cbe8fcf4dc36Wonsik Kim            return OK;
2197a702c9f08c57f64121149e3e233cbe8fcf4dc36Wonsik Kim        } else if ((err = status.serviceSpecificErrorCode()) != OK) {
2207a702c9f08c57f64121149e3e233cbe8fcf4dc36Wonsik Kim            return err;
2217a702c9f08c57f64121149e3e233cbe8fcf4dc36Wonsik Kim        } else if ((err = status.transactionError()) != OK) {
2227a702c9f08c57f64121149e3e233cbe8fcf4dc36Wonsik Kim            return err;
2237a702c9f08c57f64121149e3e233cbe8fcf4dc36Wonsik Kim        } else {
2247a702c9f08c57f64121149e3e233cbe8fcf4dc36Wonsik Kim            return UNKNOWN_ERROR;
2257a702c9f08c57f64121149e3e233cbe8fcf4dc36Wonsik Kim        }
2267a702c9f08c57f64121149e3e233cbe8fcf4dc36Wonsik Kim    }
2277a702c9f08c57f64121149e3e233cbe8fcf4dc36Wonsik Kim
228033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimprivate:
2291c421ef3ded7c7dd25a44ea0d90db1ec46f5c1fbWonsik Kim    sp<BGraphicBufferSource> mSource;
230033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<C2OMXNode> mNode;
231ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim    uint32_t mWidth;
232ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim    uint32_t mHeight;
233033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim};
234033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
235033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}  // namespace
236033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
2370f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa// CCodec::ClientListener
2380f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa
2390f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasastruct CCodec::ClientListener : public Codec2Client::Listener {
2400f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa
2410f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa    explicit ClientListener(const wp<CCodec> &codec) : mCodec(codec) {}
2420f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa
2430f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa    virtual void onWorkDone(
2440f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa            const std::weak_ptr<Codec2Client::Component>& component,
2450f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa            std::list<std::unique_ptr<C2Work>>& workItems) override {
2460f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa        (void)component;
2470f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa        sp<CCodec> codec(mCodec.promote());
2480f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa        if (!codec) {
2490f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa            return;
2500f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa        }
2510f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa        codec->onWorkDone(workItems);
2520f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa    }
2530f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa
2540f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa    virtual void onTripped(
2550f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa            const std::weak_ptr<Codec2Client::Component>& component,
2560f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa            const std::vector<std::shared_ptr<C2SettingResult>>& settingResult
2570f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa            ) override {
2580f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa        // TODO
2590f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa        (void)component;
2600f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa        (void)settingResult;
2610f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa    }
2620f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa
2630f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa    virtual void onError(
2640f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa            const std::weak_ptr<Codec2Client::Component>& component,
2650f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa            uint32_t errorCode) override {
2660f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa        // TODO
2670f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa        (void)component;
2680f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa        (void)errorCode;
2690f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa    }
2700f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa
2710f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa    virtual void onDeath(
2720f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa            const std::weak_ptr<Codec2Client::Component>& component) override {
2730f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa        { // Log the death of the component.
2740f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa            std::shared_ptr<Codec2Client::Component> comp = component.lock();
2750f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa            if (!comp) {
2760f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa                ALOGE("Codec2 component died.");
2770f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa            } else {
2780f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa                ALOGE("Codec2 component \"%s\" died.", comp->getName().c_str());
2790f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa            }
2800f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa        }
2810f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa
2820f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa        // Report to MediaCodec.
2830f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa        sp<CCodec> codec(mCodec.promote());
2840f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa        if (!codec || !codec->mCallback) {
2850f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa            return;
2860f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa        }
2870f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa        codec->mCallback->onError(DEAD_OBJECT, ACTION_CODE_FATAL);
2880f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa    }
2890f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa
2900f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasaprivate:
2910f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa    wp<CCodec> mCodec;
2920f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa};
2930f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa
2940f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa// CCodec
2950f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa
296033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik KimCCodec::CCodec()
297033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    : mChannel(new CCodecBufferChannel([this] (status_t err, enum ActionCode actionCode) {
298033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim          mCallback->onError(err, actionCode);
299033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim      })) {
300033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    CCodecWatchdog::getInstance()->registerCodec(this);
3019bb43191636ff973c9e7592a623b58528f55a6f5Lajos Molnar    initializeStandardParams();
302033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
303033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
304033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik KimCCodec::~CCodec() {
305033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
306033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
307033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimstd::shared_ptr<BufferChannelBase> CCodec::getBufferChannel() {
308033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    return mChannel;
309033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
310033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
311033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimstatus_t CCodec::tryAndReportOnError(std::function<status_t()> job) {
312033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    status_t err = job();
313033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (err != C2_OK) {
314033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mCallback->onError(err, ACTION_CODE_FATAL);
315033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
316033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    return err;
317033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
318033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
319033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::initiateAllocateComponent(const sp<AMessage> &msg) {
320033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    auto setAllocating = [this] {
321033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
322033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() != RELEASED) {
323033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return INVALID_OPERATION;
324033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
325033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state->set(ALLOCATING);
326033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return OK;
327033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    };
328033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (tryAndReportOnError(setAllocating) != OK) {
329033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
330033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
331033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
332033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<RefBase> codecInfo;
333033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    CHECK(msg->findObject("codecInfo", &codecInfo));
334033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    // For Codec 2.0 components, componentName == codecInfo->getCodecName().
335033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
336033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<AMessage> allocMsg(new AMessage(kWhatAllocate, this));
337033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    allocMsg->setObject("codecInfo", codecInfo);
338033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    allocMsg->post();
339033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
340033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
341033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::allocate(const sp<MediaCodecInfo> &codecInfo) {
342033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (codecInfo == nullptr) {
343033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL);
344033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
345033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
346033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    ALOGV("allocate(%s)", codecInfo->getCodecName());
3470f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa    mClientListener.reset(new ClientListener(this));
348033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
349033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    AString componentName = codecInfo->getCodecName();
3500f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    std::shared_ptr<Codec2Client> client;
3510f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    std::shared_ptr<Codec2Client::Component> comp =
3520f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa            Codec2Client::CreateComponentByName(
3530f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa            componentName.c_str(),
3540f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa            mClientListener,
3550f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa            &client);
3560f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    if (!comp) {
357033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        ALOGE("Failed Create component: %s", componentName.c_str());
358033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
359033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state->set(RELEASED);
360033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state.unlock();
3610f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa        mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL);
362033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state.lock();
363033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
364033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
365033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    ALOGV("Success Create component: %s", componentName.c_str());
366033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mChannel->setComponent(comp);
3670f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    auto setAllocated = [this, comp, client] {
368033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
369033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() != ALLOCATING) {
370033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            state->set(RELEASED);
371033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return UNKNOWN_ERROR;
372033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
373033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state->set(ALLOCATED);
374033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state->comp = comp;
3750f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa        mClient = client;
376033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return OK;
377033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    };
378033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (tryAndReportOnError(setAllocated) != OK) {
379033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
380033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
3810f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    mCallback->onComponentAllocated(comp->getName().c_str());
382033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
383033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
384033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::initiateConfigureComponent(const sp<AMessage> &format) {
385033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    auto checkAllocated = [this] {
386033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
387033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return (state->get() != ALLOCATED) ? UNKNOWN_ERROR : OK;
388033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    };
389033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (tryAndReportOnError(checkAllocated) != OK) {
390033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
391033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
392033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
393033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<AMessage> msg(new AMessage(kWhatConfigure, this));
394033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    msg->setMessage("format", format);
395033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    msg->post();
396033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
397033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
398033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::configure(const sp<AMessage> &msg) {
3990f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    std::shared_ptr<Codec2Client::Component> comp;
4000f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    auto checkAllocated = [this, &comp] {
401033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
402033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() != ALLOCATED) {
403033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            state->set(RELEASED);
404033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return UNKNOWN_ERROR;
405033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
4060f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa        comp = state->comp;
407033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return OK;
408033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    };
409033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (tryAndReportOnError(checkAllocated) != OK) {
410033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
411033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
412033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
413033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<AMessage> inputFormat(new AMessage);
414033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<AMessage> outputFormat(new AMessage);
415069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim    std::vector<std::shared_ptr<C2ParamDescriptor>> paramDescs;
416069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim
417069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim    auto doConfig = [=, paramDescsPtr = &paramDescs] {
418069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        c2_status_t c2err = comp->querySupportedParams(paramDescsPtr);
419069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        if (c2err != C2_OK) {
420069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim            ALOGD("Failed to query supported params");
421069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim            // TODO: return error once we complete implementation.
422069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim            // return UNKNOWN_ERROR;
423069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        }
424069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim
425033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        AString mime;
426033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (!msg->findString("mime", &mime)) {
427033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return BAD_VALUE;
428033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
429033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
430033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        int32_t encoder;
431033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (!msg->findInt32("encoder", &encoder)) {
432033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            encoder = false;
433033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
434033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
435033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        // TODO: read from intf()
4360f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa        if ((!encoder) != (comp->getName().find("encoder") == std::string::npos)) {
437033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return UNKNOWN_ERROR;
438033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
439033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
440033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        sp<RefBase> obj;
441033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (msg->findObject("native-window", &obj)) {
442033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            sp<Surface> surface = static_cast<Surface *>(obj.get());
443033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            setSurface(surface);
444033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
445033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
446033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        std::vector<std::unique_ptr<C2Param>> params;
447033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        std::initializer_list<C2Param::Index> indices {
448033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            C2PortMimeConfig::input::PARAM_TYPE,
449033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            C2PortMimeConfig::output::PARAM_TYPE,
450033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        };
451069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        c2err = comp->query(
452033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                {},
453033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                indices,
454033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                C2_DONT_BLOCK,
455033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                &params);
456033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (c2err != C2_OK) {
457033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            ALOGE("Failed to query component interface: %d", c2err);
458033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return UNKNOWN_ERROR;
459033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
460033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (params.size() != indices.size()) {
461033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            ALOGE("Component returns wrong number of params");
462033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return UNKNOWN_ERROR;
463033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
464033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (!params[0] || !params[1]) {
465033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            ALOGE("Component returns null params");
466033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return UNKNOWN_ERROR;
467033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
468033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        inputFormat->setString("mime", ((C2PortMimeConfig *)params[0].get())->m.value);
469033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        outputFormat->setString("mime", ((C2PortMimeConfig *)params[1].get())->m.value);
470033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
471033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        // XXX: hack
472033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        bool audio = mime.startsWithIgnoreCase("audio/");
473ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim        if (!audio) {
474ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim            int32_t tmp;
475ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim            if (msg->findInt32("width", &tmp)) {
476f6cf85003c1e03fa86373baa345eaec1880d80f6Wonsik Kim                inputFormat->setInt32("width", tmp);
477ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim                outputFormat->setInt32("width", tmp);
478ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim            }
479ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim            if (msg->findInt32("height", &tmp)) {
480f6cf85003c1e03fa86373baa345eaec1880d80f6Wonsik Kim                inputFormat->setInt32("height", tmp);
481ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim                outputFormat->setInt32("height", tmp);
482ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim            }
483ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim        } else {
484ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim            if (encoder) {
485033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                inputFormat->setInt32("channel-count", 1);
486033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                inputFormat->setInt32("sample-rate", 44100);
487033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                outputFormat->setInt32("channel-count", 1);
488033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                outputFormat->setInt32("sample-rate", 44100);
489033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            } else {
490033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                outputFormat->setInt32("channel-count", 2);
491033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                outputFormat->setInt32("sample-rate", 44100);
492033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            }
493033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
494033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
495a00de0de4f172b294f286460292dc4a99f9dda67Lajos Molnar        // TODO: do this based on component requiring linear allocator for input
496a00de0de4f172b294f286460292dc4a99f9dda67Lajos Molnar        if (!encoder || audio) {
497a00de0de4f172b294f286460292dc4a99f9dda67Lajos Molnar            int32_t tmp;
498a00de0de4f172b294f286460292dc4a99f9dda67Lajos Molnar            if (msg->findInt32("max-input-size", &tmp)) {
499a00de0de4f172b294f286460292dc4a99f9dda67Lajos Molnar                inputFormat->setInt32(C2_NAME_STREAM_MAX_BUFFER_SIZE_SETTING, tmp);
500a00de0de4f172b294f286460292dc4a99f9dda67Lajos Molnar            }
501a00de0de4f172b294f286460292dc4a99f9dda67Lajos Molnar        }
502a00de0de4f172b294f286460292dc4a99f9dda67Lajos Molnar
503033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        // TODO
504033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
505033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return OK;
506033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    };
507033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (tryAndReportOnError(doConfig) != OK) {
508033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
509033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
510033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
511033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    {
512033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<Formats>::Locked formats(mFormats);
513033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        formats->inputFormat = inputFormat;
514033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        formats->outputFormat = outputFormat;
515033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
516069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim    std::shared_ptr<C2ParamReflector> reflector = mClient->getParamReflector();
517069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim    if (reflector != nullptr) {
518069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        Mutexed<ReflectedParamUpdater>::Locked paramUpdater(mParamUpdater);
519069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        paramUpdater->clear();
520069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        paramUpdater->addParamDesc(reflector, paramDescs);
521069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim    } else {
522069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        ALOGE("Failed to get param reflector");
523069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        // TODO: report error once we complete implementation.
524069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim    }
525033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mCallback->onComponentConfigured(inputFormat, outputFormat);
526033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
527033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
528033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::initiateCreateInputSurface() {
529033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    status_t err = [this] {
530033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
531033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() != ALLOCATED) {
532033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return UNKNOWN_ERROR;
533033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
534033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        // TODO: read it from intf() properly.
5350f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa        if (state->comp->getName().find("encoder") == std::string::npos) {
536033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return INVALID_OPERATION;
537033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
538033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return OK;
539033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }();
540033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (err != OK) {
541033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mCallback->onInputSurfaceCreationFailed(err);
542033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
543033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
544033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
545033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    (new AMessage(kWhatCreateInputSurface, this))->post();
546033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
547033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
548033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::createInputSurface() {
5492bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa    status_t err;
5501c421ef3ded7c7dd25a44ea0d90db1ec46f5c1fbWonsik Kim    sp<IGraphicBufferProducer> bufferProducer;
551033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
552033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<AMessage> inputFormat;
553033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<AMessage> outputFormat;
554033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    {
555033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<Formats>::Locked formats(mFormats);
556033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        inputFormat = formats->inputFormat;
557033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        outputFormat = formats->outputFormat;
558033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
5592bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa
5602bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa    // TODO: Remove this property check and assume it's always true.
5612bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa    if (property_get_bool("debug.stagefright.c2inputsurface", false)) {
5622bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa        std::shared_ptr<Codec2Client::InputSurface> surface;
5632bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa
5642bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa        err = static_cast<status_t>(mClient->createInputSurface(&surface));
5652bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa        if (err != OK) {
5662bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa            ALOGE("Failed to create input surface: %d", static_cast<int>(err));
5672bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa            mCallback->onInputSurfaceCreationFailed(err);
5682bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa            return;
5692bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa        }
5702bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa        if (!surface) {
5712bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa            ALOGE("Failed to create input surface: null input surface");
5722bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa            mCallback->onInputSurfaceCreationFailed(UNKNOWN_ERROR);
5732bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa            return;
5742bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa        }
5752bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa        bufferProducer = surface->getGraphicBufferProducer();
5762bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa        err = setupInputSurface(std::make_shared<C2InputSurfaceWrapper>(surface));
5772bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa    } else { // TODO: Remove this block.
5782bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa        using namespace ::android::hardware::media::omx::V1_0;
5792bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa        sp<IOmx> tOmx = IOmx::getService("default");
5802bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa        if (tOmx == nullptr) {
5812bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa            ALOGE("Failed to create input surface");
5822bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa            mCallback->onInputSurfaceCreationFailed(UNKNOWN_ERROR);
5832bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa            return;
5842bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa        }
5852bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa        sp<IOMX> omx = new utils::LWOmx(tOmx);
5862bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa
5872bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa        sp<BGraphicBufferSource> bufferSource;
5882bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa        err = omx->createInputSurface(&bufferProducer, &bufferSource);
5892bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa
5902bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa        if (err != OK) {
5912bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa            ALOGE("Failed to create input surface: %d", err);
5922bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa            mCallback->onInputSurfaceCreationFailed(err);
5932bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa            return;
5942bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa        }
5952bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa        int32_t width = 0;
5962bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa        (void)outputFormat->findInt32("width", &width);
5972bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa        int32_t height = 0;
5982bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa        (void)outputFormat->findInt32("height", &height);
5992bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa        err = setupInputSurface(std::make_shared<GraphicBufferSourceWrapper>(
6002bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa                bufferSource, width, height));
6012bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa    }
6022bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa
603ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim    if (err != OK) {
604ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim        ALOGE("Failed to set up input surface: %d", err);
605ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim        mCallback->onInputSurfaceCreationFailed(err);
606ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim        return;
607ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim    }
608033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mCallback->onInputSurfaceCreated(
609033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            inputFormat,
610033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            outputFormat,
6111c421ef3ded7c7dd25a44ea0d90db1ec46f5c1fbWonsik Kim            new BufferProducerWrapper(bufferProducer));
612033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
613033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
614033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimstatus_t CCodec::setupInputSurface(const std::shared_ptr<InputSurfaceWrapper> &surface) {
615033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    status_t err = mChannel->setInputSurface(surface);
616033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (err != OK) {
617033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return err;
618033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
619033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
620033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    // TODO: configure |surface| with other settings.
621033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    return OK;
622033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
623033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
624033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::initiateSetInputSurface(const sp<PersistentSurface> &surface) {
625033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<AMessage> msg = new AMessage(kWhatSetInputSurface, this);
626033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    msg->setObject("surface", surface);
627033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    msg->post();
628033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
629033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
630033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::setInputSurface(const sp<PersistentSurface> &surface) {
631033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<AMessage> inputFormat;
632033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<AMessage> outputFormat;
633033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    {
634033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<Formats>::Locked formats(mFormats);
635033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        inputFormat = formats->inputFormat;
636033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        outputFormat = formats->outputFormat;
637033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
638ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim    int32_t width = 0;
639ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim    (void)outputFormat->findInt32("width", &width);
640ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim    int32_t height = 0;
641ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim    (void)outputFormat->findInt32("height", &height);
642ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim    status_t err = setupInputSurface(std::make_shared<GraphicBufferSourceWrapper>(
643ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim            surface->getBufferSource(), width, height));
644ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim    if (err != OK) {
645ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim        ALOGE("Failed to set up input surface: %d", err);
646ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim        mCallback->onInputSurfaceDeclined(err);
647ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim        return;
648ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim    }
649033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mCallback->onInputSurfaceAccepted(inputFormat, outputFormat);
650033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
651033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
652033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::initiateStart() {
653033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    auto setStarting = [this] {
654033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
655033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() != ALLOCATED) {
656033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return UNKNOWN_ERROR;
657033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
658033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state->set(STARTING);
659033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return OK;
660033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    };
661033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (tryAndReportOnError(setStarting) != OK) {
662033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
663033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
664033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
665033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    (new AMessage(kWhatStart, this))->post();
666033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
667033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
668033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::start() {
6690f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    std::shared_ptr<Codec2Client::Component> comp;
670033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    auto checkStarting = [this, &comp] {
671033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
672033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() != STARTING) {
673033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return UNKNOWN_ERROR;
674033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
675033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        comp = state->comp;
676033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return OK;
677033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    };
678033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (tryAndReportOnError(checkStarting) != OK) {
679033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
680033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
681033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
682033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    c2_status_t err = comp->start();
683033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (err != C2_OK) {
684033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        // TODO: convert err into status_t
685033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL);
686033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
687033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
688033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<AMessage> inputFormat;
689033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<AMessage> outputFormat;
690033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    {
691033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<Formats>::Locked formats(mFormats);
692033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        inputFormat = formats->inputFormat;
693033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        outputFormat = formats->outputFormat;
694033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
695033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    status_t err2 = mChannel->start(inputFormat, outputFormat);
696033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (err2 != OK) {
697033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mCallback->onError(err2, ACTION_CODE_FATAL);
698033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
699033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
700033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
701033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    auto setRunning = [this] {
702033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
703033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() != STARTING) {
704033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return UNKNOWN_ERROR;
705033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
706033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state->set(RUNNING);
707033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return OK;
708033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    };
709033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (tryAndReportOnError(setRunning) != OK) {
710033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
711033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
712033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mCallback->onStartCompleted();
713033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
714033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
715033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::initiateShutdown(bool keepComponentAllocated) {
716033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (keepComponentAllocated) {
717033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        initiateStop();
718033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    } else {
719033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        initiateRelease();
720033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
721033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
722033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
723033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::initiateStop() {
724033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    {
725033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
726033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() == ALLOCATED
727033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                || state->get()  == RELEASED
728033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                || state->get() == STOPPING
729033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                || state->get() == RELEASING) {
730033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            // We're already stopped, released, or doing it right now.
731033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            state.unlock();
732033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            mCallback->onStopCompleted();
733033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            state.lock();
734033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return;
735033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
736033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state->set(STOPPING);
737033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
738033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
739033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    (new AMessage(kWhatStop, this))->post();
740033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
741033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
742033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::stop() {
7430f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    std::shared_ptr<Codec2Client::Component> comp;
744033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    {
745033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
746033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() == RELEASING) {
747033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            state.unlock();
748033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            // We're already stopped or release is in progress.
749033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            mCallback->onStopCompleted();
750033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            state.lock();
751033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return;
752033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        } else if (state->get() != STOPPING) {
753033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            state.unlock();
754033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL);
755033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            state.lock();
756033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return;
757033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
758033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        comp = state->comp;
759033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
760033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mChannel->stop();
761033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    status_t err = comp->stop();
762033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (err != C2_OK) {
763033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        // TODO: convert err into status_t
764033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL);
765033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
766033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
767033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    {
768033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
769033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() == STOPPING) {
770033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            state->set(ALLOCATED);
771033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
772033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
773033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mCallback->onStopCompleted();
774033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
775033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
776033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::initiateRelease(bool sendCallback /* = true */) {
777033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    {
778033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
779033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() == RELEASED || state->get() == RELEASING) {
780033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            // We're already released or doing it right now.
781033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            if (sendCallback) {
782033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                state.unlock();
783033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                mCallback->onReleaseCompleted();
784033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                state.lock();
785033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            }
786033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return;
787033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
788033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() == ALLOCATING) {
789033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            state->set(RELEASING);
790033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            // With the altered state allocate() would fail and clean up.
791033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            if (sendCallback) {
792033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                state.unlock();
793033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                mCallback->onReleaseCompleted();
794033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                state.lock();
795033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            }
796033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return;
797033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
798033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state->set(RELEASING);
799033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
800033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
801033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    std::thread([this, sendCallback] { release(sendCallback); }).detach();
802033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
803033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
804033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::release(bool sendCallback) {
8050f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    std::shared_ptr<Codec2Client::Component> comp;
806033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    {
807033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
808033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() == RELEASED) {
809033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            if (sendCallback) {
810033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                state.unlock();
811033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                mCallback->onReleaseCompleted();
812033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                state.lock();
813033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            }
814033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return;
815033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
816033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        comp = state->comp;
817033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
818033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mChannel->stop();
819033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    comp->release();
820033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
821033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    {
822033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
823033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state->set(RELEASED);
824033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state->comp.reset();
825033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
826033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (sendCallback) {
827033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mCallback->onReleaseCompleted();
828033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
829033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
830033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
831033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimstatus_t CCodec::setSurface(const sp<Surface> &surface) {
832033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    return mChannel->setSurface(surface);
833033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
834033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
835033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::signalFlush() {
836033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    status_t err = [this] {
837033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
838033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() == FLUSHED) {
839033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return ALREADY_EXISTS;
840033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
841033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() != RUNNING) {
842033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return UNKNOWN_ERROR;
843033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
844033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state->set(FLUSHING);
845033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return OK;
846033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }();
847033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    switch (err) {
848033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        case ALREADY_EXISTS:
849033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            mCallback->onFlushCompleted();
850033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return;
851033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        case OK:
852033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            break;
853033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        default:
854033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            mCallback->onError(err, ACTION_CODE_FATAL);
855033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return;
856033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
857033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
858033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    (new AMessage(kWhatFlush, this))->post();
859033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
860033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
861033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::flush() {
8620f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    std::shared_ptr<Codec2Client::Component> comp;
863033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    auto checkFlushing = [this, &comp] {
864033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
865033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() != FLUSHING) {
866033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return UNKNOWN_ERROR;
867033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
868033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        comp = state->comp;
869033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return OK;
870033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    };
871033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (tryAndReportOnError(checkFlushing) != OK) {
872033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
873033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
874033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
875033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mChannel->stop();
876033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
877033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    std::list<std::unique_ptr<C2Work>> flushedWork;
8780f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    c2_status_t err = comp->flush(C2Component::FLUSH_COMPONENT, &flushedWork);
879033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (err != C2_OK) {
880033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        // TODO: convert err into status_t
881033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL);
882033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
883033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
884033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mChannel->flush(flushedWork);
885033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
886033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    {
887033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
888033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state->set(FLUSHED);
889033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
890033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mCallback->onFlushCompleted();
891033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
892033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
893033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::signalResume() {
894033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    auto setResuming = [this] {
895033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
896033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() != FLUSHED) {
897033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return UNKNOWN_ERROR;
898033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
899033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state->set(RESUMING);
900033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return OK;
901033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    };
902033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (tryAndReportOnError(setResuming) != OK) {
903033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
904033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
905033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
906033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    (void)mChannel->start(nullptr, nullptr);
907033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
908033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    {
909033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
910033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() != RESUMING) {
911033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            state.unlock();
912033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL);
913033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            state.lock();
914033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return;
915033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
916033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state->set(RUNNING);
917033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
918033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
919033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
920069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kimvoid CCodec::signalSetParameters(const sp<AMessage> &params) {
921069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim    sp<AMessage> msg = new AMessage(kWhatSetParameters, this);
922069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim    msg->setMessage("params", params);
923069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim    msg->post();
924069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim}
925069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim
9269bb43191636ff973c9e7592a623b58528f55a6f5Lajos Molnarvoid CCodec::initializeStandardParams() {
9279bb43191636ff973c9e7592a623b58528f55a6f5Lajos Molnar    mStandardParams.emplace("bitrate",          "coded.bitrate.value");
9289bb43191636ff973c9e7592a623b58528f55a6f5Lajos Molnar    mStandardParams.emplace("video-bitrate",    "coded.bitrate.value");
9299bb43191636ff973c9e7592a623b58528f55a6f5Lajos Molnar    mStandardParams.emplace("bitrate-mode",     "coded.bitrate-mode.value");
9309bb43191636ff973c9e7592a623b58528f55a6f5Lajos Molnar    mStandardParams.emplace("frame-rate",       "coded.frame-rate.value");
9319bb43191636ff973c9e7592a623b58528f55a6f5Lajos Molnar    mStandardParams.emplace("max-input-size",   "coded.max-frame-size.value");
9329bb43191636ff973c9e7592a623b58528f55a6f5Lajos Molnar    mStandardParams.emplace("rotation-degrees", "coded.vui.rotation.value");
9339bb43191636ff973c9e7592a623b58528f55a6f5Lajos Molnar
9349bb43191636ff973c9e7592a623b58528f55a6f5Lajos Molnar    mStandardParams.emplace("prepend-sps-pps-to-idr-frames", "coding.add-csd-to-sync-frames.value");
9359bb43191636ff973c9e7592a623b58528f55a6f5Lajos Molnar    mStandardParams.emplace("i-frame-period",   "coding.gop.intra-period");
9369bb43191636ff973c9e7592a623b58528f55a6f5Lajos Molnar    mStandardParams.emplace("intra-refresh-period", "coding.intra-refresh.period");
9379bb43191636ff973c9e7592a623b58528f55a6f5Lajos Molnar    mStandardParams.emplace("quality",          "coding.quality.value");
9389bb43191636ff973c9e7592a623b58528f55a6f5Lajos Molnar    mStandardParams.emplace("request-sync",     "coding.request-sync.value");
9399bb43191636ff973c9e7592a623b58528f55a6f5Lajos Molnar
9409bb43191636ff973c9e7592a623b58528f55a6f5Lajos Molnar    mStandardParams.emplace("operating-rate",   "ctrl.operating-rate.value");
9419bb43191636ff973c9e7592a623b58528f55a6f5Lajos Molnar    mStandardParams.emplace("priority",         "ctrl.priority.value");
9429bb43191636ff973c9e7592a623b58528f55a6f5Lajos Molnar
9439bb43191636ff973c9e7592a623b58528f55a6f5Lajos Molnar    mStandardParams.emplace("channel-count",    "raw.channel-count.value");
9449bb43191636ff973c9e7592a623b58528f55a6f5Lajos Molnar    mStandardParams.emplace("max-width",        "raw.max-size.width");
9459bb43191636ff973c9e7592a623b58528f55a6f5Lajos Molnar    mStandardParams.emplace("max-height",       "raw.max-size.height");
9469bb43191636ff973c9e7592a623b58528f55a6f5Lajos Molnar    mStandardParams.emplace("pcm-encoding",     "raw.pcm-encoding.value");
9479bb43191636ff973c9e7592a623b58528f55a6f5Lajos Molnar    mStandardParams.emplace("color-format",     "raw.pixel-format.value");
9489bb43191636ff973c9e7592a623b58528f55a6f5Lajos Molnar    mStandardParams.emplace("sample-rate",      "raw.sample-rate.value");
9499bb43191636ff973c9e7592a623b58528f55a6f5Lajos Molnar    mStandardParams.emplace("width",            "raw.size.width");
9509bb43191636ff973c9e7592a623b58528f55a6f5Lajos Molnar    mStandardParams.emplace("height",           "raw.size.height");
9519bb43191636ff973c9e7592a623b58528f55a6f5Lajos Molnar
952277b7295f317c6597fadb116b6aee5ca3be106c1Wonsik Kim    mStandardParams.emplace("is-adts",          "coded.aac-stream-format.value");
953277b7295f317c6597fadb116b6aee5ca3be106c1Wonsik Kim
9549bb43191636ff973c9e7592a623b58528f55a6f5Lajos Molnar    // mStandardParams.emplace("stride", "raw.??");
9559bb43191636ff973c9e7592a623b58528f55a6f5Lajos Molnar    // mStandardParams.emplace("slice-height", "raw.??");
9569bb43191636ff973c9e7592a623b58528f55a6f5Lajos Molnar}
9579bb43191636ff973c9e7592a623b58528f55a6f5Lajos Molnar
9589bb43191636ff973c9e7592a623b58528f55a6f5Lajos Molnarsp<AMessage> CCodec::filterParameters(const sp<AMessage> &params) const {
9599bb43191636ff973c9e7592a623b58528f55a6f5Lajos Molnar    sp<AMessage> filtered = params->dup();
9609bb43191636ff973c9e7592a623b58528f55a6f5Lajos Molnar
9619bb43191636ff973c9e7592a623b58528f55a6f5Lajos Molnar    // TODO: some params may require recalculation or a type fix
9629bb43191636ff973c9e7592a623b58528f55a6f5Lajos Molnar    // e.g. i-frame-interval here
9639bb43191636ff973c9e7592a623b58528f55a6f5Lajos Molnar    {
9649bb43191636ff973c9e7592a623b58528f55a6f5Lajos Molnar        int32_t frameRateInt;
9659bb43191636ff973c9e7592a623b58528f55a6f5Lajos Molnar        if (filtered->findInt32("frame-rate", &frameRateInt)) {
9669bb43191636ff973c9e7592a623b58528f55a6f5Lajos Molnar            filtered->removeEntryAt(filtered->findEntryByName("frame-rate"));
9679bb43191636ff973c9e7592a623b58528f55a6f5Lajos Molnar            filtered->setFloat("frame-rate", frameRateInt);
9689bb43191636ff973c9e7592a623b58528f55a6f5Lajos Molnar        }
9699bb43191636ff973c9e7592a623b58528f55a6f5Lajos Molnar    }
9709bb43191636ff973c9e7592a623b58528f55a6f5Lajos Molnar
9719bb43191636ff973c9e7592a623b58528f55a6f5Lajos Molnar    {
9729bb43191636ff973c9e7592a623b58528f55a6f5Lajos Molnar        float frameRate;
9739bb43191636ff973c9e7592a623b58528f55a6f5Lajos Molnar        int32_t iFrameInterval;
9749bb43191636ff973c9e7592a623b58528f55a6f5Lajos Molnar        if (filtered->findInt32("i-frame-interval", &iFrameInterval)
9759bb43191636ff973c9e7592a623b58528f55a6f5Lajos Molnar                && filtered->findFloat("frame-rate", &frameRate)) {
9769bb43191636ff973c9e7592a623b58528f55a6f5Lajos Molnar            filtered->setInt32("i-frame-period", iFrameInterval * frameRate + 0.5);
9779bb43191636ff973c9e7592a623b58528f55a6f5Lajos Molnar        }
9789bb43191636ff973c9e7592a623b58528f55a6f5Lajos Molnar    }
9799bb43191636ff973c9e7592a623b58528f55a6f5Lajos Molnar
980277b7295f317c6597fadb116b6aee5ca3be106c1Wonsik Kim    {
981277b7295f317c6597fadb116b6aee5ca3be106c1Wonsik Kim        int32_t isAdts;
982277b7295f317c6597fadb116b6aee5ca3be106c1Wonsik Kim        if (filtered->findInt32("is-adts", &isAdts)) {
983277b7295f317c6597fadb116b6aee5ca3be106c1Wonsik Kim            filtered->setInt32(
984277b7295f317c6597fadb116b6aee5ca3be106c1Wonsik Kim                    "is-adts",
985277b7295f317c6597fadb116b6aee5ca3be106c1Wonsik Kim                    isAdts ? C2AacStreamFormatAdts : C2AacStreamFormatRaw);
986277b7295f317c6597fadb116b6aee5ca3be106c1Wonsik Kim        }
987277b7295f317c6597fadb116b6aee5ca3be106c1Wonsik Kim    }
988277b7295f317c6597fadb116b6aee5ca3be106c1Wonsik Kim
9899bb43191636ff973c9e7592a623b58528f55a6f5Lajos Molnar    for (size_t ix = 0; ix < filtered->countEntries();) {
9909bb43191636ff973c9e7592a623b58528f55a6f5Lajos Molnar        AMessage::Type type;
9919bb43191636ff973c9e7592a623b58528f55a6f5Lajos Molnar        AString name = filtered->getEntryNameAt(ix, &type);
9929bb43191636ff973c9e7592a623b58528f55a6f5Lajos Molnar        if (name.startsWith("vendor.")) {
9939bb43191636ff973c9e7592a623b58528f55a6f5Lajos Molnar            // vendor params pass through as is
9949bb43191636ff973c9e7592a623b58528f55a6f5Lajos Molnar            ++ix;
9959bb43191636ff973c9e7592a623b58528f55a6f5Lajos Molnar            continue;
9969bb43191636ff973c9e7592a623b58528f55a6f5Lajos Molnar        }
9979bb43191636ff973c9e7592a623b58528f55a6f5Lajos Molnar        auto it = mStandardParams.find(name.c_str());
9989bb43191636ff973c9e7592a623b58528f55a6f5Lajos Molnar        if (it == mStandardParams.end()) {
9999bb43191636ff973c9e7592a623b58528f55a6f5Lajos Molnar            // non-standard parameters are filtered out
10009bb43191636ff973c9e7592a623b58528f55a6f5Lajos Molnar            filtered->removeEntryAt(ix);
10019bb43191636ff973c9e7592a623b58528f55a6f5Lajos Molnar            continue;
10029bb43191636ff973c9e7592a623b58528f55a6f5Lajos Molnar        }
10039bb43191636ff973c9e7592a623b58528f55a6f5Lajos Molnar        filtered->setEntryNameAt(ix++, it->second.c_str());
10049bb43191636ff973c9e7592a623b58528f55a6f5Lajos Molnar    }
10059bb43191636ff973c9e7592a623b58528f55a6f5Lajos Molnar    ALOGV("filtered %s to %s", params->debugString(4).c_str(), filtered->debugString(4).c_str());
10069bb43191636ff973c9e7592a623b58528f55a6f5Lajos Molnar    return filtered;
10079bb43191636ff973c9e7592a623b58528f55a6f5Lajos Molnar}
1008069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim
10099bb43191636ff973c9e7592a623b58528f55a6f5Lajos Molnarvoid CCodec::setParameters(const sp<AMessage> &unfiltered) {
1010069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim    std::shared_ptr<Codec2Client::Component> comp;
1011069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim    auto checkState = [this, &comp] {
1012069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        Mutexed<State>::Locked state(mState);
1013069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        if (state->get() == RELEASED) {
1014069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim            return INVALID_OPERATION;
1015069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        }
1016069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        comp = state->comp;
1017069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        return OK;
1018069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim    };
1019069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim    if (tryAndReportOnError(checkState) != OK) {
1020069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        return;
1021069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim    }
1022069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim
10239bb43191636ff973c9e7592a623b58528f55a6f5Lajos Molnar    sp<AMessage> params = filterParameters(unfiltered);
1024069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim
1025069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim    c2_status_t err = C2_OK;
1026069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim    std::vector<std::unique_ptr<C2Param>> vec;
1027069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim    {
1028069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        Mutexed<ReflectedParamUpdater>::Locked paramUpdater(mParamUpdater);
1029069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        std::vector<C2Param::Index> indices;
1030069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        paramUpdater->getParamIndicesFromMessage(params, &indices);
1031069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim
1032069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        paramUpdater.unlock();
1033069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        if (indices.empty()) {
1034069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim            ALOGD("no recognized params in: %s", params->debugString().c_str());
1035069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim            return;
1036069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        }
1037069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        err = comp->query({}, indices, C2_MAY_BLOCK, &vec);
1038069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        if (err != C2_OK) {
1039069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim            ALOGD("query failed with %d", err);
1040069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim            // This is non-fatal.
1041069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim            return;
1042069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        }
1043069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        paramUpdater.lock();
1044069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim
1045069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        paramUpdater->updateParamsFromMessage(params, &vec);
1046069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim    }
1047069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim
1048069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim    std::vector<C2Param *> paramVector;
1049069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim    for (const std::unique_ptr<C2Param> &param : vec) {
1050069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        paramVector.push_back(param.get());
1051069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim    }
1052069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim    std::vector<std::unique_ptr<C2SettingResult>> failures;
1053069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim    err = comp->config(paramVector, C2_MAY_BLOCK, &failures);
1054069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim    if (err != C2_OK) {
1055069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        ALOGD("config failed with %d", err);
1056069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        // This is non-fatal.
1057069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim    }
1058033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
1059033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1060033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::signalEndOfInputStream() {
10617a702c9f08c57f64121149e3e233cbe8fcf4dc36Wonsik Kim    mCallback->onSignaledInputEOS(mChannel->signalEndOfInputStream());
1062033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
1063033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1064033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::signalRequestIDRFrame() {
1065033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    // TODO
1066033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
1067033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1068033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::onWorkDone(std::list<std::unique_ptr<C2Work>> &workItems) {
1069033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    Mutexed<std::list<std::unique_ptr<C2Work>>>::Locked queue(mWorkDoneQueue);
1070033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    queue->splice(queue->end(), workItems);
1071033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    (new AMessage(kWhatWorkDone, this))->post();
1072033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
1073033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1074033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::onMessageReceived(const sp<AMessage> &msg) {
1075033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    TimePoint now = std::chrono::steady_clock::now();
1076033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    switch (msg->what()) {
1077033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        case kWhatAllocate: {
1078033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            // C2ComponentStore::createComponent() should return within 100ms.
1079033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            setDeadline(now + 150ms, "allocate");
1080033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            sp<RefBase> obj;
1081033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            CHECK(msg->findObject("codecInfo", &obj));
1082033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            allocate((MediaCodecInfo *)obj.get());
1083033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            break;
1084033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
1085033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        case kWhatConfigure: {
1086033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            // C2Component::commit_sm() should return within 5ms.
1087033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            setDeadline(now + 50ms, "configure");
1088033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            sp<AMessage> format;
1089033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            CHECK(msg->findMessage("format", &format));
1090033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            configure(format);
1091069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim            setParameters(format);
1092033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            break;
1093033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
1094033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        case kWhatStart: {
1095033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            // C2Component::start() should return within 500ms.
1096033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            setDeadline(now + 550ms, "start");
1097033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            start();
1098033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            break;
1099033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
1100033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        case kWhatStop: {
1101033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            // C2Component::stop() should return within 500ms.
1102033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            setDeadline(now + 550ms, "stop");
1103033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            stop();
1104033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            break;
1105033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
1106033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        case kWhatFlush: {
1107033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            // C2Component::flush_sm() should return within 5ms.
1108033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            setDeadline(now + 50ms, "flush");
1109033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            flush();
1110033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            break;
1111033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
1112033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        case kWhatCreateInputSurface: {
1113033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            // Surface operations may be briefly blocking.
1114033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            setDeadline(now + 100ms, "createInputSurface");
1115033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            createInputSurface();
1116033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            break;
1117033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
1118033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        case kWhatSetInputSurface: {
1119033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            // Surface operations may be briefly blocking.
1120033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            setDeadline(now + 100ms, "setInputSurface");
1121033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            sp<RefBase> obj;
1122033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            CHECK(msg->findObject("surface", &obj));
1123033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            sp<PersistentSurface> surface(static_cast<PersistentSurface *>(obj.get()));
1124033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            setInputSurface(surface);
1125033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            break;
1126033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
1127069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        case kWhatSetParameters: {
1128069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim            setDeadline(now + 50ms, "setParameters");
1129069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim            sp<AMessage> params;
1130069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim            CHECK(msg->findMessage("params", &params));
1131069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim            setParameters(params);
1132069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim            break;
1133069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        }
1134033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        case kWhatWorkDone: {
1135033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            std::unique_ptr<C2Work> work;
1136033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            {
1137033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                Mutexed<std::list<std::unique_ptr<C2Work>>>::Locked queue(mWorkDoneQueue);
1138033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                if (queue->empty()) {
1139033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                    break;
1140033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                }
1141033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                work.swap(queue->front());
1142033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                queue->pop_front();
1143033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                if (!queue->empty()) {
1144033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                    (new AMessage(kWhatWorkDone, this))->post();
1145033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                }
1146033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            }
1147033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            mChannel->onWorkDone(work);
1148033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            break;
1149033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
1150033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        default: {
1151033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            ALOGE("unrecognized message");
1152033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            break;
1153033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
1154033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
1155033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    setDeadline(TimePoint::max(), "none");
1156033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
1157033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1158033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::setDeadline(const TimePoint &newDeadline, const char *name) {
1159033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    Mutexed<NamedTimePoint>::Locked deadline(mDeadline);
1160033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    deadline->set(newDeadline, name);
1161033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
1162033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1163033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::initiateReleaseIfStuck() {
1164033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    std::string name;
1165033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    {
1166033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<NamedTimePoint>::Locked deadline(mDeadline);
1167033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (deadline->get() >= std::chrono::steady_clock::now()) {
1168033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            // We're not stuck.
1169033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return;
1170033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
1171033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        name = deadline->getName();
1172033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
1173033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1174033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    ALOGW("previous call to %s exceeded timeout", name.c_str());
1175033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    initiateRelease(false);
1176033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL);
1177033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
1178033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1179033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}  // namespace android
1180033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1181033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimextern "C" android::CodecBase *CreateCodec() {
1182033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    return new android::CCodec;
1183033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
11840f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa
1185