CCodec.cpp revision 033ea548eec7ec220082ea6b199bf6e77f67a40d
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
17033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim//#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
24033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include <C2PlatformSupport.h>
25033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include <C2V4l2Support.h>
26033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
27033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include <android/IOMXBufferSource.h>
28033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include <gui/bufferqueue/1.0/H2BGraphicBufferProducer.h>
29033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include <gui/Surface.h>
30033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include <media/stagefright/codec2/1.0/InputSurface.h>
31033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include <media/stagefright/BufferProducerWrapper.h>
32033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include <media/stagefright/PersistentSurface.h>
33033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
34033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include "C2OMXNode.h"
35033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include "CCodec.h"
36033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include "CCodecBufferChannel.h"
37033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include "InputSurfaceWrapper.h"
38033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
39033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimnamespace android {
40033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
41033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimusing namespace std::chrono_literals;
42033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimusing ::android::hardware::graphics::bufferqueue::V1_0::utils::H2BGraphicBufferProducer;
43033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
44033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimnamespace {
45033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
46033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimclass CCodecWatchdog : public AHandler {
47033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimprivate:
48033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    enum {
49033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        kWhatRegister,
50033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        kWhatWatch,
51033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    };
52033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    constexpr static int64_t kWatchIntervalUs = 3000000;  // 3 secs
53033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
54033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimpublic:
55033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    static sp<CCodecWatchdog> getInstance() {
56033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<sp<CCodecWatchdog>>::Locked instance(sInstance);
57033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (*instance == nullptr) {
58033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            *instance = new CCodecWatchdog;
59033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            (*instance)->init();
60033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
61033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return *instance;
62033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
63033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
64033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    ~CCodecWatchdog() = default;
65033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
66033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    void registerCodec(CCodec *codec) {
67033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        sp<AMessage> msg = new AMessage(kWhatRegister, this);
68033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        msg->setPointer("codec", codec);
69033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        msg->post();
70033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
71033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
72033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimprotected:
73033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    void onMessageReceived(const sp<AMessage> &msg) {
74033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        switch (msg->what()) {
75033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            case kWhatRegister: {
76033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                void *ptr = nullptr;
77033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                CHECK(msg->findPointer("codec", &ptr));
78033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                Mutexed<std::list<wp<CCodec>>>::Locked codecs(mCodecs);
79033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                codecs->emplace_back((CCodec *)ptr);
80033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                break;
81033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            }
82033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
83033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            case kWhatWatch: {
84033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                Mutexed<std::list<wp<CCodec>>>::Locked codecs(mCodecs);
85033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                for (auto it = codecs->begin(); it != codecs->end(); ) {
86033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                    sp<CCodec> codec = it->promote();
87033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                    if (codec == nullptr) {
88033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                        it = codecs->erase(it);
89033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                        continue;
90033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                    }
91033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                    codec->initiateReleaseIfStuck();
92033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                    ++it;
93033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                }
94033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                msg->post(kWatchIntervalUs);
95033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                break;
96033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            }
97033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
98033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            default: {
99033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                TRESPASS("CCodecWatchdog: unrecognized message");
100033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            }
101033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
102033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
103033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
104033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimprivate:
105033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    CCodecWatchdog() : mLooper(new ALooper) {}
106033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
107033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    void init() {
108033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mLooper->setName("CCodecWatchdog");
109033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mLooper->registerHandler(this);
110033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mLooper->start();
111033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        (new AMessage(kWhatWatch, this))->post(kWatchIntervalUs);
112033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
113033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
114033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    static Mutexed<sp<CCodecWatchdog>> sInstance;
115033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
116033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<ALooper> mLooper;
117033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    Mutexed<std::list<wp<CCodec>>> mCodecs;
118033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim};
119033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
120033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik KimMutexed<sp<CCodecWatchdog>> CCodecWatchdog::sInstance;
121033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
122033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimclass CCodecListener : public C2Component::Listener {
123033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimpublic:
124033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    explicit CCodecListener(const wp<CCodec> &codec) : mCodec(codec) {}
125033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
126033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    virtual void onWorkDone_nb(
127033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            std::weak_ptr<C2Component> component,
128033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            std::list<std::unique_ptr<C2Work>> workItems) override {
129033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        (void)component;
130033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        sp<CCodec> codec(mCodec.promote());
131033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (!codec) {
132033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return;
133033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
134033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        codec->onWorkDone(workItems);
135033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
136033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
137033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    virtual void onTripped_nb(
138033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            std::weak_ptr<C2Component> component,
139033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            std::vector<std::shared_ptr<C2SettingResult>> settingResult) override {
140033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        // TODO
141033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        (void)component;
142033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        (void)settingResult;
143033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
144033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
145033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    virtual void onError_nb(std::weak_ptr<C2Component> component, uint32_t errorCode) override {
146033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        // TODO
147033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        (void)component;
148033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        (void)errorCode;
149033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
150033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
151033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimprivate:
152033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    wp<CCodec> mCodec;
153033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim};
154033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
155033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimclass C2InputSurfaceWrapper : public InputSurfaceWrapper {
156033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimpublic:
157033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    explicit C2InputSurfaceWrapper(const sp<InputSurface> &surface) : mSurface(surface) {}
158033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    ~C2InputSurfaceWrapper() override = default;
159033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
160033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    status_t connect(const std::shared_ptr<C2Component> &comp) override {
161033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (mConnection != nullptr) {
162033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return ALREADY_EXISTS;
163033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
164033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mConnection = mSurface->connectToComponent(comp);
165033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return OK;
166033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
167033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
168033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    void disconnect() override {
169033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (mConnection != nullptr) {
170033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            mConnection->disconnect();
171033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            mConnection.clear();
172033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
173033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
174033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
175033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimprivate:
176033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<InputSurface> mSurface;
177033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<InputSurfaceConnection> mConnection;
178033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim};
179033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
180033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimclass GraphicBufferSourceWrapper : public InputSurfaceWrapper {
181033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimpublic:
182033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    explicit GraphicBufferSourceWrapper(const sp<IGraphicBufferSource> &source) : mSource(source) {}
183033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    ~GraphicBufferSourceWrapper() override = default;
184033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
185033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    status_t connect(const std::shared_ptr<C2Component> &comp) override {
186033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        // TODO: proper color aspect & dataspace
187033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        android_dataspace dataSpace = HAL_DATASPACE_BT709;
188033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
189033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mNode = new C2OMXNode(comp);
190033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mSource->configure(mNode, dataSpace);
191033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
192033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        // TODO: configure according to intf().
193033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
194033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        sp<IOMXBufferSource> source = mNode->getSource();
195033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (source == nullptr) {
196033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return NO_INIT;
197033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
198033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        constexpr size_t kNumSlots = 16;
199033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        for (size_t i = 0; i < kNumSlots; ++i) {
200033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            source->onInputBufferAdded(i);
201033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
202033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        source->onOmxExecuting();
203033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return OK;
204033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
205033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
206033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    void disconnect() override {
207033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (mNode == nullptr) {
208033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return;
209033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
210033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        sp<IOMXBufferSource> source = mNode->getSource();
211033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (source == nullptr) {
212033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            ALOGD("GBSWrapper::disconnect: node is not configured with OMXBufferSource.");
213033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return;
214033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
215033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        source->onOmxIdle();
216033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        source->onOmxLoaded();
217033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mNode.clear();
218033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
219033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
220033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimprivate:
221033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<IGraphicBufferSource> mSource;
222033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<C2OMXNode> mNode;
223033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim};
224033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
225033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}  // namespace
226033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
227033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik KimCCodec::CCodec()
228033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    : mChannel(new CCodecBufferChannel([this] (status_t err, enum ActionCode actionCode) {
229033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim          mCallback->onError(err, actionCode);
230033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim      })) {
231033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    CCodecWatchdog::getInstance()->registerCodec(this);
232033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
233033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
234033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik KimCCodec::~CCodec() {
235033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
236033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
237033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimstd::shared_ptr<BufferChannelBase> CCodec::getBufferChannel() {
238033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    return mChannel;
239033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
240033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
241033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimstatus_t CCodec::tryAndReportOnError(std::function<status_t()> job) {
242033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    status_t err = job();
243033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (err != C2_OK) {
244033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mCallback->onError(err, ACTION_CODE_FATAL);
245033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
246033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    return err;
247033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
248033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
249033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::initiateAllocateComponent(const sp<AMessage> &msg) {
250033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    auto setAllocating = [this] {
251033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
252033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() != RELEASED) {
253033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return INVALID_OPERATION;
254033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
255033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state->set(ALLOCATING);
256033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return OK;
257033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    };
258033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (tryAndReportOnError(setAllocating) != OK) {
259033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
260033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
261033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
262033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<RefBase> codecInfo;
263033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    CHECK(msg->findObject("codecInfo", &codecInfo));
264033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    // For Codec 2.0 components, componentName == codecInfo->getCodecName().
265033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
266033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<AMessage> allocMsg(new AMessage(kWhatAllocate, this));
267033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    allocMsg->setObject("codecInfo", codecInfo);
268033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    allocMsg->post();
269033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
270033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
271033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::allocate(const sp<MediaCodecInfo> &codecInfo) {
272033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (codecInfo == nullptr) {
273033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL);
274033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
275033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
276033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    ALOGV("allocate(%s)", codecInfo->getCodecName());
277033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mListener.reset(new CCodecListener(this));
278033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
279033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    AString componentName = codecInfo->getCodecName();
280033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    // TODO: use codecInfo->getOwnerName() for connecting to remote process.
281033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
282033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    std::shared_ptr<C2Component> comp;
283033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    c2_status_t err = GetCodec2PlatformComponentStore()->createComponent(
284033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            componentName.c_str(), &comp);
285033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    static bool v4l2Enabled =
286033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            property_get_bool("debug.stagefright.ccodec_v4l2", false);
287033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (err != C2_OK && v4l2Enabled) {
288033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        err = GetCodec2VDAComponentStore()->createComponent(
289033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                componentName.c_str(), &comp);
290033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
291033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (err != C2_OK) {
292033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        ALOGE("Failed Create component: %s", componentName.c_str());
293033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
294033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state->set(RELEASED);
295033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state.unlock();
296033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mCallback->onError(err, ACTION_CODE_FATAL);
297033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state.lock();
298033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
299033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
300033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    ALOGV("Success Create component: %s", componentName.c_str());
301033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    comp->setListener_vb(mListener, C2_MAY_BLOCK);
302033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mChannel->setComponent(comp);
303033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    auto setAllocated = [this, comp] {
304033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
305033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() != ALLOCATING) {
306033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            state->set(RELEASED);
307033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return UNKNOWN_ERROR;
308033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
309033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state->set(ALLOCATED);
310033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state->comp = comp;
311033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return OK;
312033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    };
313033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (tryAndReportOnError(setAllocated) != OK) {
314033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
315033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
316033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mCallback->onComponentAllocated(comp->intf()->getName().c_str());
317033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
318033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
319033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::initiateConfigureComponent(const sp<AMessage> &format) {
320033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    auto checkAllocated = [this] {
321033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
322033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return (state->get() != ALLOCATED) ? UNKNOWN_ERROR : OK;
323033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    };
324033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (tryAndReportOnError(checkAllocated) != OK) {
325033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
326033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
327033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
328033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<AMessage> msg(new AMessage(kWhatConfigure, this));
329033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    msg->setMessage("format", format);
330033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    msg->post();
331033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
332033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
333033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::configure(const sp<AMessage> &msg) {
334033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    std::shared_ptr<C2ComponentInterface> intf;
335033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    auto checkAllocated = [this, &intf] {
336033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
337033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() != ALLOCATED) {
338033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            state->set(RELEASED);
339033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return UNKNOWN_ERROR;
340033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
341033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        intf = state->comp->intf();
342033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return OK;
343033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    };
344033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (tryAndReportOnError(checkAllocated) != OK) {
345033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
346033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
347033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
348033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<AMessage> inputFormat(new AMessage);
349033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<AMessage> outputFormat(new AMessage);
350033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    auto doConfig = [=] {
351033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        AString mime;
352033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (!msg->findString("mime", &mime)) {
353033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return BAD_VALUE;
354033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
355033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
356033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        int32_t encoder;
357033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (!msg->findInt32("encoder", &encoder)) {
358033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            encoder = false;
359033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
360033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
361033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        // TODO: read from intf()
362033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if ((!encoder) != (intf->getName().find("encoder") == std::string::npos)) {
363033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return UNKNOWN_ERROR;
364033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
365033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
366033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        sp<RefBase> obj;
367033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (msg->findObject("native-window", &obj)) {
368033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            sp<Surface> surface = static_cast<Surface *>(obj.get());
369033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            setSurface(surface);
370033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
371033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
372033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        std::vector<std::unique_ptr<C2Param>> params;
373033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        std::initializer_list<C2Param::Index> indices {
374033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            C2PortMimeConfig::input::PARAM_TYPE,
375033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            C2PortMimeConfig::output::PARAM_TYPE,
376033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        };
377033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        c2_status_t c2err = intf->query_vb(
378033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                {},
379033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                indices,
380033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                C2_DONT_BLOCK,
381033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                &params);
382033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (c2err != C2_OK) {
383033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            ALOGE("Failed to query component interface: %d", c2err);
384033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return UNKNOWN_ERROR;
385033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
386033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (params.size() != indices.size()) {
387033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            ALOGE("Component returns wrong number of params");
388033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return UNKNOWN_ERROR;
389033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
390033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (!params[0] || !params[1]) {
391033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            ALOGE("Component returns null params");
392033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return UNKNOWN_ERROR;
393033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
394033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        inputFormat->setString("mime", ((C2PortMimeConfig *)params[0].get())->m.value);
395033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        outputFormat->setString("mime", ((C2PortMimeConfig *)params[1].get())->m.value);
396033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
397033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        // XXX: hack
398033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        bool audio = mime.startsWithIgnoreCase("audio/");
399033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (encoder) {
400033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            if (audio) {
401033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                inputFormat->setInt32("channel-count", 1);
402033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                inputFormat->setInt32("sample-rate", 44100);
403033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                outputFormat->setInt32("channel-count", 1);
404033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                outputFormat->setInt32("sample-rate", 44100);
405033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            } else {
406033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                outputFormat->setInt32("width", 1080);
407033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                outputFormat->setInt32("height", 1920);
408033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            }
409033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        } else {
410033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            if (audio) {
411033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                outputFormat->setInt32("channel-count", 2);
412033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                outputFormat->setInt32("sample-rate", 44100);
413033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            } else {
414033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                int32_t tmp;
415033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                if (msg->findInt32("width", &tmp)) {
416033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                    outputFormat->setInt32("width", tmp);
417033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                }
418033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                if (msg->findInt32("height", &tmp)) {
419033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                    outputFormat->setInt32("height", tmp);
420033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                }
421033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            }
422033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
423033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
424033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        // TODO
425033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
426033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return OK;
427033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    };
428033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (tryAndReportOnError(doConfig) != OK) {
429033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
430033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
431033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
432033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    {
433033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<Formats>::Locked formats(mFormats);
434033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        formats->inputFormat = inputFormat;
435033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        formats->outputFormat = outputFormat;
436033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
437033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mCallback->onComponentConfigured(inputFormat, outputFormat);
438033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
439033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
440033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::initiateCreateInputSurface() {
441033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    status_t err = [this] {
442033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
443033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() != ALLOCATED) {
444033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return UNKNOWN_ERROR;
445033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
446033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        // TODO: read it from intf() properly.
447033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->comp->intf()->getName().find("encoder") == std::string::npos) {
448033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return INVALID_OPERATION;
449033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
450033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return OK;
451033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }();
452033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (err != OK) {
453033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mCallback->onInputSurfaceCreationFailed(err);
454033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
455033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
456033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
457033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    (new AMessage(kWhatCreateInputSurface, this))->post();
458033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
459033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
460033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::createInputSurface() {
461033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    // TODO: get this from codec process
462033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<InputSurface> surface(InputSurface::Create());
463033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
464033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    // TODO: get proper error code.
465033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    status_t err = (surface == nullptr) ? UNKNOWN_ERROR : OK;
466033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (err != OK) {
467033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        ALOGE("Failed to initialize input surface: %d", err);
468033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mCallback->onInputSurfaceCreationFailed(err);
469033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
470033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
471033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
472033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    err = setupInputSurface(std::make_shared<C2InputSurfaceWrapper>(surface));
473033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (err != OK) {
474033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        ALOGE("Failed to set up input surface: %d", err);
475033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mCallback->onInputSurfaceCreationFailed(err);
476033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
477033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
478033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
479033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<AMessage> inputFormat;
480033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<AMessage> outputFormat;
481033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    {
482033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<Formats>::Locked formats(mFormats);
483033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        inputFormat = formats->inputFormat;
484033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        outputFormat = formats->outputFormat;
485033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
486033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mCallback->onInputSurfaceCreated(
487033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            inputFormat,
488033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            outputFormat,
489033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            new BufferProducerWrapper(new H2BGraphicBufferProducer(surface)));
490033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
491033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
492033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimstatus_t CCodec::setupInputSurface(const std::shared_ptr<InputSurfaceWrapper> &surface) {
493033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    status_t err = mChannel->setInputSurface(surface);
494033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (err != OK) {
495033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return err;
496033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
497033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
498033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    // TODO: configure |surface| with other settings.
499033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    return OK;
500033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
501033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
502033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::initiateSetInputSurface(const sp<PersistentSurface> &surface) {
503033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<AMessage> msg = new AMessage(kWhatSetInputSurface, this);
504033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    msg->setObject("surface", surface);
505033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    msg->post();
506033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
507033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
508033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::setInputSurface(const sp<PersistentSurface> &surface) {
509033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    status_t err = setupInputSurface(std::make_shared<GraphicBufferSourceWrapper>(
510033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            surface->getBufferSource()));
511033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (err != OK) {
512033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        ALOGE("Failed to set up input surface: %d", err);
513033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mCallback->onInputSurfaceDeclined(err);
514033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
515033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
516033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
517033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<AMessage> inputFormat;
518033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<AMessage> outputFormat;
519033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    {
520033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<Formats>::Locked formats(mFormats);
521033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        inputFormat = formats->inputFormat;
522033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        outputFormat = formats->outputFormat;
523033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
524033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mCallback->onInputSurfaceAccepted(inputFormat, outputFormat);
525033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
526033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
527033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::initiateStart() {
528033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    auto setStarting = [this] {
529033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
530033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() != ALLOCATED) {
531033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return UNKNOWN_ERROR;
532033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
533033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state->set(STARTING);
534033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return OK;
535033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    };
536033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (tryAndReportOnError(setStarting) != OK) {
537033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
538033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
539033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
540033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    (new AMessage(kWhatStart, this))->post();
541033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
542033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
543033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::start() {
544033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    std::shared_ptr<C2Component> comp;
545033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    auto checkStarting = [this, &comp] {
546033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
547033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() != STARTING) {
548033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return UNKNOWN_ERROR;
549033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
550033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        comp = state->comp;
551033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return OK;
552033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    };
553033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (tryAndReportOnError(checkStarting) != OK) {
554033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
555033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
556033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
557033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    c2_status_t err = comp->start();
558033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (err != C2_OK) {
559033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        // TODO: convert err into status_t
560033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL);
561033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
562033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
563033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<AMessage> inputFormat;
564033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<AMessage> outputFormat;
565033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    {
566033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<Formats>::Locked formats(mFormats);
567033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        inputFormat = formats->inputFormat;
568033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        outputFormat = formats->outputFormat;
569033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
570033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    status_t err2 = mChannel->start(inputFormat, outputFormat);
571033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (err2 != OK) {
572033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mCallback->onError(err2, ACTION_CODE_FATAL);
573033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
574033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
575033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
576033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    auto setRunning = [this] {
577033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
578033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() != STARTING) {
579033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return UNKNOWN_ERROR;
580033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
581033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state->set(RUNNING);
582033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return OK;
583033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    };
584033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (tryAndReportOnError(setRunning) != OK) {
585033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
586033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
587033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mCallback->onStartCompleted();
588033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
589033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
590033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::initiateShutdown(bool keepComponentAllocated) {
591033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (keepComponentAllocated) {
592033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        initiateStop();
593033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    } else {
594033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        initiateRelease();
595033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
596033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
597033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
598033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::initiateStop() {
599033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    {
600033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
601033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() == ALLOCATED
602033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                || state->get()  == RELEASED
603033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                || state->get() == STOPPING
604033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                || state->get() == RELEASING) {
605033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            // We're already stopped, released, or doing it right now.
606033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            state.unlock();
607033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            mCallback->onStopCompleted();
608033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            state.lock();
609033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return;
610033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
611033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state->set(STOPPING);
612033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
613033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
614033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    (new AMessage(kWhatStop, this))->post();
615033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
616033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
617033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::stop() {
618033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    std::shared_ptr<C2Component> comp;
619033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    {
620033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
621033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() == RELEASING) {
622033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            state.unlock();
623033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            // We're already stopped or release is in progress.
624033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            mCallback->onStopCompleted();
625033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            state.lock();
626033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return;
627033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        } else if (state->get() != STOPPING) {
628033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            state.unlock();
629033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL);
630033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            state.lock();
631033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return;
632033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
633033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        comp = state->comp;
634033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
635033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mChannel->stop();
636033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    status_t err = comp->stop();
637033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (err != C2_OK) {
638033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        // TODO: convert err into status_t
639033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL);
640033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
641033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
642033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    {
643033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
644033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() == STOPPING) {
645033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            state->set(ALLOCATED);
646033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
647033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
648033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mCallback->onStopCompleted();
649033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
650033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
651033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::initiateRelease(bool sendCallback /* = true */) {
652033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    {
653033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
654033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() == RELEASED || state->get() == RELEASING) {
655033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            // We're already released or doing it right now.
656033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            if (sendCallback) {
657033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                state.unlock();
658033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                mCallback->onReleaseCompleted();
659033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                state.lock();
660033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            }
661033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return;
662033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
663033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() == ALLOCATING) {
664033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            state->set(RELEASING);
665033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            // With the altered state allocate() would fail and clean up.
666033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            if (sendCallback) {
667033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                state.unlock();
668033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                mCallback->onReleaseCompleted();
669033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                state.lock();
670033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            }
671033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return;
672033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
673033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state->set(RELEASING);
674033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
675033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
676033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    std::thread([this, sendCallback] { release(sendCallback); }).detach();
677033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
678033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
679033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::release(bool sendCallback) {
680033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    std::shared_ptr<C2Component> comp;
681033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    {
682033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
683033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() == RELEASED) {
684033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            if (sendCallback) {
685033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                state.unlock();
686033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                mCallback->onReleaseCompleted();
687033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                state.lock();
688033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            }
689033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return;
690033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
691033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        comp = state->comp;
692033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
693033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mChannel->stop();
694033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    comp->release();
695033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
696033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    {
697033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
698033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state->set(RELEASED);
699033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state->comp.reset();
700033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
701033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (sendCallback) {
702033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mCallback->onReleaseCompleted();
703033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
704033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
705033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
706033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimstatus_t CCodec::setSurface(const sp<Surface> &surface) {
707033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    return mChannel->setSurface(surface);
708033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
709033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
710033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::signalFlush() {
711033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    status_t err = [this] {
712033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
713033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() == FLUSHED) {
714033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return ALREADY_EXISTS;
715033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
716033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() != RUNNING) {
717033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return UNKNOWN_ERROR;
718033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
719033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state->set(FLUSHING);
720033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return OK;
721033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }();
722033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    switch (err) {
723033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        case ALREADY_EXISTS:
724033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            mCallback->onFlushCompleted();
725033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return;
726033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        case OK:
727033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            break;
728033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        default:
729033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            mCallback->onError(err, ACTION_CODE_FATAL);
730033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return;
731033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
732033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
733033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    (new AMessage(kWhatFlush, this))->post();
734033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
735033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
736033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::flush() {
737033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    std::shared_ptr<C2Component> comp;
738033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    auto checkFlushing = [this, &comp] {
739033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
740033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() != FLUSHING) {
741033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return UNKNOWN_ERROR;
742033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
743033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        comp = state->comp;
744033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return OK;
745033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    };
746033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (tryAndReportOnError(checkFlushing) != OK) {
747033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
748033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
749033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
750033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mChannel->stop();
751033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
752033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    std::list<std::unique_ptr<C2Work>> flushedWork;
753033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    c2_status_t err = comp->flush_sm(C2Component::FLUSH_COMPONENT, &flushedWork);
754033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (err != C2_OK) {
755033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        // TODO: convert err into status_t
756033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL);
757033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
758033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
759033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mChannel->flush(flushedWork);
760033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
761033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    {
762033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
763033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state->set(FLUSHED);
764033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
765033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mCallback->onFlushCompleted();
766033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
767033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
768033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::signalResume() {
769033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    auto setResuming = [this] {
770033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
771033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() != FLUSHED) {
772033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return UNKNOWN_ERROR;
773033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
774033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state->set(RESUMING);
775033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return OK;
776033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    };
777033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (tryAndReportOnError(setResuming) != OK) {
778033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
779033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
780033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
781033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    (void)mChannel->start(nullptr, nullptr);
782033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
783033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    {
784033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
785033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() != RESUMING) {
786033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            state.unlock();
787033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL);
788033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            state.lock();
789033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return;
790033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
791033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state->set(RUNNING);
792033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
793033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
794033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
795033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::signalSetParameters(const sp<AMessage> &msg) {
796033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    // TODO
797033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    (void) msg;
798033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
799033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
800033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::signalEndOfInputStream() {
801033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    // TODO
802033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mCallback->onSignaledInputEOS(INVALID_OPERATION);
803033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
804033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
805033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::signalRequestIDRFrame() {
806033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    // TODO
807033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
808033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
809033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::onWorkDone(std::list<std::unique_ptr<C2Work>> &workItems) {
810033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    Mutexed<std::list<std::unique_ptr<C2Work>>>::Locked queue(mWorkDoneQueue);
811033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    queue->splice(queue->end(), workItems);
812033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    (new AMessage(kWhatWorkDone, this))->post();
813033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
814033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
815033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::onMessageReceived(const sp<AMessage> &msg) {
816033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    TimePoint now = std::chrono::steady_clock::now();
817033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    switch (msg->what()) {
818033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        case kWhatAllocate: {
819033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            // C2ComponentStore::createComponent() should return within 100ms.
820033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            setDeadline(now + 150ms, "allocate");
821033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            sp<RefBase> obj;
822033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            CHECK(msg->findObject("codecInfo", &obj));
823033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            allocate((MediaCodecInfo *)obj.get());
824033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            break;
825033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
826033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        case kWhatConfigure: {
827033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            // C2Component::commit_sm() should return within 5ms.
828033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            setDeadline(now + 50ms, "configure");
829033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            sp<AMessage> format;
830033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            CHECK(msg->findMessage("format", &format));
831033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            configure(format);
832033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            break;
833033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
834033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        case kWhatStart: {
835033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            // C2Component::start() should return within 500ms.
836033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            setDeadline(now + 550ms, "start");
837033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            start();
838033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            break;
839033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
840033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        case kWhatStop: {
841033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            // C2Component::stop() should return within 500ms.
842033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            setDeadline(now + 550ms, "stop");
843033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            stop();
844033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            break;
845033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
846033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        case kWhatFlush: {
847033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            // C2Component::flush_sm() should return within 5ms.
848033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            setDeadline(now + 50ms, "flush");
849033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            flush();
850033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            break;
851033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
852033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        case kWhatCreateInputSurface: {
853033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            // Surface operations may be briefly blocking.
854033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            setDeadline(now + 100ms, "createInputSurface");
855033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            createInputSurface();
856033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            break;
857033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
858033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        case kWhatSetInputSurface: {
859033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            // Surface operations may be briefly blocking.
860033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            setDeadline(now + 100ms, "setInputSurface");
861033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            sp<RefBase> obj;
862033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            CHECK(msg->findObject("surface", &obj));
863033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            sp<PersistentSurface> surface(static_cast<PersistentSurface *>(obj.get()));
864033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            setInputSurface(surface);
865033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            break;
866033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
867033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        case kWhatWorkDone: {
868033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            std::unique_ptr<C2Work> work;
869033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            {
870033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                Mutexed<std::list<std::unique_ptr<C2Work>>>::Locked queue(mWorkDoneQueue);
871033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                if (queue->empty()) {
872033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                    break;
873033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                }
874033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                work.swap(queue->front());
875033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                queue->pop_front();
876033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                if (!queue->empty()) {
877033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                    (new AMessage(kWhatWorkDone, this))->post();
878033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                }
879033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            }
880033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            mChannel->onWorkDone(work);
881033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            break;
882033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
883033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        default: {
884033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            ALOGE("unrecognized message");
885033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            break;
886033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
887033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
888033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    setDeadline(TimePoint::max(), "none");
889033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
890033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
891033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::setDeadline(const TimePoint &newDeadline, const char *name) {
892033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    Mutexed<NamedTimePoint>::Locked deadline(mDeadline);
893033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    deadline->set(newDeadline, name);
894033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
895033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
896033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::initiateReleaseIfStuck() {
897033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    std::string name;
898033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    {
899033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<NamedTimePoint>::Locked deadline(mDeadline);
900033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (deadline->get() >= std::chrono::steady_clock::now()) {
901033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            // We're not stuck.
902033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return;
903033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
904033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        name = deadline->getName();
905033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
906033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
907033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    ALOGW("previous call to %s exceeded timeout", name.c_str());
908033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    initiateRelease(false);
909033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL);
910033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
911033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
912033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}  // namespace android
913033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
914033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimextern "C" android::CodecBase *CreateCodec() {
915033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    return new android::CCodec;
916033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
917