CCodec.cpp revision 384b6a0bcf56a6cdc81fad923fc4695027fa42dd
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>
253bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar#include <C2Debug.h>
26069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim#include <C2ParamInternal.h>
27033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include <C2PlatformSupport.h>
28033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include <C2V4l2Support.h>
29033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
30033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include <android/IOMXBufferSource.h>
311c421ef3ded7c7dd25a44ea0d90db1ec46f5c1fbWonsik Kim#include <android/IGraphicBufferSource.h>
322bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa#include <cutils/properties.h>
33033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include <gui/bufferqueue/1.0/H2BGraphicBufferProducer.h>
341c421ef3ded7c7dd25a44ea0d90db1ec46f5c1fbWonsik Kim#include <gui/IGraphicBufferProducer.h>
35033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include <gui/Surface.h>
361c421ef3ded7c7dd25a44ea0d90db1ec46f5c1fbWonsik Kim#include <media/omx/1.0/WOmx.h>
37033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include <media/stagefright/codec2/1.0/InputSurface.h>
38033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include <media/stagefright/BufferProducerWrapper.h>
393bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar#include <media/stagefright/MediaCodecConstants.h>
40033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include <media/stagefright/PersistentSurface.h>
41033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
42033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include "C2OMXNode.h"
43033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include "CCodec.h"
44033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include "CCodecBufferChannel.h"
45033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include "InputSurfaceWrapper.h"
46033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
47033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimnamespace android {
48033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
49033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimusing namespace std::chrono_literals;
50033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimusing ::android::hardware::graphics::bufferqueue::V1_0::utils::H2BGraphicBufferProducer;
511c421ef3ded7c7dd25a44ea0d90db1ec46f5c1fbWonsik Kimusing BGraphicBufferSource = ::android::IGraphicBufferSource;
52033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
53033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimnamespace {
54033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
55033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimclass CCodecWatchdog : public AHandler {
56033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimprivate:
57033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    enum {
58033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        kWhatRegister,
59033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        kWhatWatch,
60033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    };
61033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    constexpr static int64_t kWatchIntervalUs = 3000000;  // 3 secs
62033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
63033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimpublic:
64033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    static sp<CCodecWatchdog> getInstance() {
65033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<sp<CCodecWatchdog>>::Locked instance(sInstance);
66033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (*instance == nullptr) {
67033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            *instance = new CCodecWatchdog;
68033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            (*instance)->init();
69033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
70033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return *instance;
71033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
72033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
73033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    ~CCodecWatchdog() = default;
74033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
75033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    void registerCodec(CCodec *codec) {
76033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        sp<AMessage> msg = new AMessage(kWhatRegister, this);
77033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        msg->setPointer("codec", codec);
78033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        msg->post();
79033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
80033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
81033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimprotected:
82033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    void onMessageReceived(const sp<AMessage> &msg) {
83033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        switch (msg->what()) {
84033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            case kWhatRegister: {
85033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                void *ptr = nullptr;
86033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                CHECK(msg->findPointer("codec", &ptr));
87033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                Mutexed<std::list<wp<CCodec>>>::Locked codecs(mCodecs);
88033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                codecs->emplace_back((CCodec *)ptr);
89033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                break;
90033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            }
91033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
92033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            case kWhatWatch: {
93033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                Mutexed<std::list<wp<CCodec>>>::Locked codecs(mCodecs);
94033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                for (auto it = codecs->begin(); it != codecs->end(); ) {
95033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                    sp<CCodec> codec = it->promote();
96033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                    if (codec == nullptr) {
97033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                        it = codecs->erase(it);
98033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                        continue;
99033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                    }
100033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                    codec->initiateReleaseIfStuck();
101033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                    ++it;
102033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                }
103033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                msg->post(kWatchIntervalUs);
104033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                break;
105033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            }
106033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
107033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            default: {
108033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                TRESPASS("CCodecWatchdog: unrecognized message");
109033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            }
110033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
111033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
112033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
113033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimprivate:
114033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    CCodecWatchdog() : mLooper(new ALooper) {}
115033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
116033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    void init() {
117033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mLooper->setName("CCodecWatchdog");
118033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mLooper->registerHandler(this);
119033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mLooper->start();
120033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        (new AMessage(kWhatWatch, this))->post(kWatchIntervalUs);
121033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
122033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
123033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    static Mutexed<sp<CCodecWatchdog>> sInstance;
124033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
125033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<ALooper> mLooper;
126033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    Mutexed<std::list<wp<CCodec>>> mCodecs;
127033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim};
128033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
129033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik KimMutexed<sp<CCodecWatchdog>> CCodecWatchdog::sInstance;
130033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
131033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimclass C2InputSurfaceWrapper : public InputSurfaceWrapper {
132033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimpublic:
1330f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    explicit C2InputSurfaceWrapper(
1340f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa            const std::shared_ptr<Codec2Client::InputSurface> &surface) :
1350f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa        mSurface(surface) {
1360f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    }
1370f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa
138033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    ~C2InputSurfaceWrapper() override = default;
139033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1400f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    status_t connect(const std::shared_ptr<Codec2Client::Component> &comp) override {
141033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (mConnection != nullptr) {
142033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return ALREADY_EXISTS;
143033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
1440f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa        return static_cast<status_t>(
1450f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa                mSurface->connectToComponent(comp, &mConnection));
146033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
147033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
148033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    void disconnect() override {
149033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (mConnection != nullptr) {
150033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            mConnection->disconnect();
1510f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa            mConnection = nullptr;
152033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
153033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
154033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1557a702c9f08c57f64121149e3e233cbe8fcf4dc36Wonsik Kim    status_t signalEndOfInputStream() override {
1567a702c9f08c57f64121149e3e233cbe8fcf4dc36Wonsik Kim        C2InputSurfaceEosTuning eos(true);
1577a702c9f08c57f64121149e3e233cbe8fcf4dc36Wonsik Kim        std::vector<std::unique_ptr<C2SettingResult>> failures;
1587a702c9f08c57f64121149e3e233cbe8fcf4dc36Wonsik Kim        c2_status_t err = mSurface->getConfigurable()->config({&eos}, C2_MAY_BLOCK, &failures);
1597a702c9f08c57f64121149e3e233cbe8fcf4dc36Wonsik Kim        if (err != C2_OK) {
1607a702c9f08c57f64121149e3e233cbe8fcf4dc36Wonsik Kim            return UNKNOWN_ERROR;
1617a702c9f08c57f64121149e3e233cbe8fcf4dc36Wonsik Kim        }
1627a702c9f08c57f64121149e3e233cbe8fcf4dc36Wonsik Kim        return OK;
1637a702c9f08c57f64121149e3e233cbe8fcf4dc36Wonsik Kim    }
1647a702c9f08c57f64121149e3e233cbe8fcf4dc36Wonsik Kim
165033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimprivate:
1660f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    std::shared_ptr<Codec2Client::InputSurface> mSurface;
1670f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    std::shared_ptr<Codec2Client::InputSurfaceConnection> mConnection;
168033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim};
169033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
170033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimclass GraphicBufferSourceWrapper : public InputSurfaceWrapper {
171033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimpublic:
172ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim//    explicit GraphicBufferSourceWrapper(const sp<BGraphicBufferSource> &source) : mSource(source) {}
173ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim    GraphicBufferSourceWrapper(
174ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim            const sp<BGraphicBufferSource> &source,
175ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim            uint32_t width,
176ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim            uint32_t height)
177ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim        : mSource(source), mWidth(width), mHeight(height) {}
178033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    ~GraphicBufferSourceWrapper() override = default;
179033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1800f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    status_t connect(const std::shared_ptr<Codec2Client::Component> &comp) override {
181033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        // TODO: proper color aspect & dataspace
182033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        android_dataspace dataSpace = HAL_DATASPACE_BT709;
183033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
184033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mNode = new C2OMXNode(comp);
185ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim        mNode->setFrameSize(mWidth, mHeight);
186033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mSource->configure(mNode, dataSpace);
187033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
188033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        // TODO: configure according to intf().
189033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
190033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        sp<IOMXBufferSource> source = mNode->getSource();
191033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (source == nullptr) {
192033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return NO_INIT;
193033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
194033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        constexpr size_t kNumSlots = 16;
195033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        for (size_t i = 0; i < kNumSlots; ++i) {
196033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            source->onInputBufferAdded(i);
197033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
198033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        source->onOmxExecuting();
199033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return OK;
200033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
201033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
202033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    void disconnect() override {
203033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (mNode == nullptr) {
204033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return;
205033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
206033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        sp<IOMXBufferSource> source = mNode->getSource();
207033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (source == nullptr) {
208033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            ALOGD("GBSWrapper::disconnect: node is not configured with OMXBufferSource.");
209033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return;
210033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
211033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        source->onOmxIdle();
212033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        source->onOmxLoaded();
213033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mNode.clear();
214033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
215033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
2167a702c9f08c57f64121149e3e233cbe8fcf4dc36Wonsik Kim    status_t signalEndOfInputStream() override {
2177a702c9f08c57f64121149e3e233cbe8fcf4dc36Wonsik Kim        binder::Status status = mSource->signalEndOfInputStream();
2187a702c9f08c57f64121149e3e233cbe8fcf4dc36Wonsik Kim        status_t err = OK;
2197a702c9f08c57f64121149e3e233cbe8fcf4dc36Wonsik Kim        if (status.isOk()) {
2207a702c9f08c57f64121149e3e233cbe8fcf4dc36Wonsik Kim            return OK;
2217a702c9f08c57f64121149e3e233cbe8fcf4dc36Wonsik Kim        } else if ((err = status.serviceSpecificErrorCode()) != OK) {
2227a702c9f08c57f64121149e3e233cbe8fcf4dc36Wonsik Kim            return err;
2237a702c9f08c57f64121149e3e233cbe8fcf4dc36Wonsik Kim        } else if ((err = status.transactionError()) != OK) {
2247a702c9f08c57f64121149e3e233cbe8fcf4dc36Wonsik Kim            return err;
2257a702c9f08c57f64121149e3e233cbe8fcf4dc36Wonsik Kim        } else {
2267a702c9f08c57f64121149e3e233cbe8fcf4dc36Wonsik Kim            return UNKNOWN_ERROR;
2277a702c9f08c57f64121149e3e233cbe8fcf4dc36Wonsik Kim        }
2287a702c9f08c57f64121149e3e233cbe8fcf4dc36Wonsik Kim    }
2297a702c9f08c57f64121149e3e233cbe8fcf4dc36Wonsik Kim
230033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimprivate:
2311c421ef3ded7c7dd25a44ea0d90db1ec46f5c1fbWonsik Kim    sp<BGraphicBufferSource> mSource;
232033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<C2OMXNode> mNode;
233ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim    uint32_t mWidth;
234ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim    uint32_t mHeight;
235033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim};
236033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
237033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}  // namespace
238033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
2390f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa// CCodec::ClientListener
2400f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa
2410f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasastruct CCodec::ClientListener : public Codec2Client::Listener {
2420f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa
2430f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa    explicit ClientListener(const wp<CCodec> &codec) : mCodec(codec) {}
2440f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa
2450f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa    virtual void onWorkDone(
2460f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa            const std::weak_ptr<Codec2Client::Component>& component,
2470f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa            std::list<std::unique_ptr<C2Work>>& workItems) override {
2480f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa        (void)component;
2490f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa        sp<CCodec> codec(mCodec.promote());
2500f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa        if (!codec) {
2510f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa            return;
2520f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa        }
2530f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa        codec->onWorkDone(workItems);
2540f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa    }
2550f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa
2560f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa    virtual void onTripped(
2570f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa            const std::weak_ptr<Codec2Client::Component>& component,
2580f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa            const std::vector<std::shared_ptr<C2SettingResult>>& settingResult
2590f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa            ) override {
2600f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa        // TODO
2610f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa        (void)component;
2620f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa        (void)settingResult;
2630f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa    }
2640f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa
2650f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa    virtual void onError(
2660f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa            const std::weak_ptr<Codec2Client::Component>& component,
2670f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa            uint32_t errorCode) override {
2680f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa        // TODO
2690f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa        (void)component;
2700f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa        (void)errorCode;
2710f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa    }
2720f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa
2730f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa    virtual void onDeath(
2740f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa            const std::weak_ptr<Codec2Client::Component>& component) override {
2750f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa        { // Log the death of the component.
2760f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa            std::shared_ptr<Codec2Client::Component> comp = component.lock();
2770f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa            if (!comp) {
2780f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa                ALOGE("Codec2 component died.");
2790f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa            } else {
2800f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa                ALOGE("Codec2 component \"%s\" died.", comp->getName().c_str());
2810f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa            }
2820f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa        }
2830f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa
2840f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa        // Report to MediaCodec.
2850f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa        sp<CCodec> codec(mCodec.promote());
2860f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa        if (!codec || !codec->mCallback) {
2870f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa            return;
2880f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa        }
2890f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa        codec->mCallback->onError(DEAD_OBJECT, ACTION_CODE_FATAL);
2900f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa    }
2910f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa
292c3d20aa9415c8f02e568f203560685eaf12c3e2dPawin Vongmasa    virtual void onFramesRendered(
293c3d20aa9415c8f02e568f203560685eaf12c3e2dPawin Vongmasa            const std::vector<RenderedFrame>& renderedFrames) override {
294c3d20aa9415c8f02e568f203560685eaf12c3e2dPawin Vongmasa        // TODO
295c3d20aa9415c8f02e568f203560685eaf12c3e2dPawin Vongmasa        (void)renderedFrames;
296c3d20aa9415c8f02e568f203560685eaf12c3e2dPawin Vongmasa    }
297c3d20aa9415c8f02e568f203560685eaf12c3e2dPawin Vongmasa
2980f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasaprivate:
2990f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa    wp<CCodec> mCodec;
3000f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa};
3010f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa
302384b6a0bcf56a6cdc81fad923fc4695027fa42ddWonsik Kim// CCodecCallbackImpl
303384b6a0bcf56a6cdc81fad923fc4695027fa42ddWonsik Kim
304384b6a0bcf56a6cdc81fad923fc4695027fa42ddWonsik Kimclass CCodecCallbackImpl : public CCodecCallback {
305384b6a0bcf56a6cdc81fad923fc4695027fa42ddWonsik Kimpublic:
306384b6a0bcf56a6cdc81fad923fc4695027fa42ddWonsik Kim    explicit CCodecCallbackImpl(CCodec *codec) : mCodec(codec) {}
307384b6a0bcf56a6cdc81fad923fc4695027fa42ddWonsik Kim    ~CCodecCallbackImpl() override = default;
308384b6a0bcf56a6cdc81fad923fc4695027fa42ddWonsik Kim
309384b6a0bcf56a6cdc81fad923fc4695027fa42ddWonsik Kim    void onError(status_t err, enum ActionCode actionCode) override {
310384b6a0bcf56a6cdc81fad923fc4695027fa42ddWonsik Kim        mCodec->mCallback->onError(err, actionCode);
311384b6a0bcf56a6cdc81fad923fc4695027fa42ddWonsik Kim    }
312384b6a0bcf56a6cdc81fad923fc4695027fa42ddWonsik Kim
313384b6a0bcf56a6cdc81fad923fc4695027fa42ddWonsik Kim    void onOutputFramesRendered(int64_t mediaTimeUs, nsecs_t renderTimeNs) override {
314384b6a0bcf56a6cdc81fad923fc4695027fa42ddWonsik Kim        mCodec->mCallback->onOutputFramesRendered(
315384b6a0bcf56a6cdc81fad923fc4695027fa42ddWonsik Kim                {RenderedFrameInfo(mediaTimeUs, renderTimeNs)});
316384b6a0bcf56a6cdc81fad923fc4695027fa42ddWonsik Kim    }
317384b6a0bcf56a6cdc81fad923fc4695027fa42ddWonsik Kim
318384b6a0bcf56a6cdc81fad923fc4695027fa42ddWonsik Kimprivate:
319384b6a0bcf56a6cdc81fad923fc4695027fa42ddWonsik Kim    CCodec *mCodec;
320384b6a0bcf56a6cdc81fad923fc4695027fa42ddWonsik Kim};
321384b6a0bcf56a6cdc81fad923fc4695027fa42ddWonsik Kim
3220f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa// CCodec
3230f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa
324033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik KimCCodec::CCodec()
325384b6a0bcf56a6cdc81fad923fc4695027fa42ddWonsik Kim    : mChannel(new CCodecBufferChannel(std::make_shared<CCodecCallbackImpl>(this))) {
326033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    CCodecWatchdog::getInstance()->registerCodec(this);
327033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
328033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
329033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik KimCCodec::~CCodec() {
330033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
331033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
332033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimstd::shared_ptr<BufferChannelBase> CCodec::getBufferChannel() {
333033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    return mChannel;
334033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
335033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
336033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimstatus_t CCodec::tryAndReportOnError(std::function<status_t()> job) {
337033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    status_t err = job();
338033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (err != C2_OK) {
339033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mCallback->onError(err, ACTION_CODE_FATAL);
340033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
341033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    return err;
342033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
343033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
344033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::initiateAllocateComponent(const sp<AMessage> &msg) {
345033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    auto setAllocating = [this] {
346033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
347033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() != RELEASED) {
348033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return INVALID_OPERATION;
349033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
350033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state->set(ALLOCATING);
351033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return OK;
352033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    };
353033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (tryAndReportOnError(setAllocating) != OK) {
354033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
355033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
356033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
357033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<RefBase> codecInfo;
358033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    CHECK(msg->findObject("codecInfo", &codecInfo));
359033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    // For Codec 2.0 components, componentName == codecInfo->getCodecName().
360033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
361033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<AMessage> allocMsg(new AMessage(kWhatAllocate, this));
362033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    allocMsg->setObject("codecInfo", codecInfo);
363033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    allocMsg->post();
364033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
365033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
366033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::allocate(const sp<MediaCodecInfo> &codecInfo) {
367033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (codecInfo == nullptr) {
368033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL);
369033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
370033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
371033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    ALOGV("allocate(%s)", codecInfo->getCodecName());
3720f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa    mClientListener.reset(new ClientListener(this));
373033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
374033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    AString componentName = codecInfo->getCodecName();
3750f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    std::shared_ptr<Codec2Client> client;
3760f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    std::shared_ptr<Codec2Client::Component> comp =
3770f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa            Codec2Client::CreateComponentByName(
3780f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa            componentName.c_str(),
3790f9da7a2c27625c1ebbd7910d3749494bc78d58aPawin Vongmasa            mClientListener,
3800f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa            &client);
3810f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    if (!comp) {
382033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        ALOGE("Failed Create component: %s", componentName.c_str());
383033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
384033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state->set(RELEASED);
385033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state.unlock();
3860f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa        mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL);
387033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state.lock();
388033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
389033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
3903bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar    ALOGI("Created component [%s]", componentName.c_str());
391033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mChannel->setComponent(comp);
3920f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    auto setAllocated = [this, comp, client] {
393033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
394033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() != ALLOCATING) {
395033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            state->set(RELEASED);
396033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return UNKNOWN_ERROR;
397033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
398033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state->set(ALLOCATED);
399033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state->comp = comp;
4000f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa        mClient = client;
401033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return OK;
402033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    };
403033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (tryAndReportOnError(setAllocated) != OK) {
404033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
405033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
4063bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar
4073bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar    // initialize config here in case setParameters is called prior to configure
4083bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar    Mutexed<Config>::Locked config(mConfig);
4093bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar    status_t err = config->initialize(mClient, comp);
4103bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar    if (err != OK) {
4113bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar        ALOGW("Failed to initialize configuration support");
4123bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar        // TODO: report error once we complete implementation.
4133bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar    }
4143bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar    config->queryConfiguration(comp);
4153bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar
4160f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    mCallback->onComponentAllocated(comp->getName().c_str());
417033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
418033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
419033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::initiateConfigureComponent(const sp<AMessage> &format) {
420033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    auto checkAllocated = [this] {
421033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
422033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return (state->get() != ALLOCATED) ? UNKNOWN_ERROR : OK;
423033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    };
424033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (tryAndReportOnError(checkAllocated) != OK) {
425033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
426033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
427033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
428033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<AMessage> msg(new AMessage(kWhatConfigure, this));
429033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    msg->setMessage("format", format);
430033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    msg->post();
431033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
432033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
433033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::configure(const sp<AMessage> &msg) {
4340f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    std::shared_ptr<Codec2Client::Component> comp;
4350f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    auto checkAllocated = [this, &comp] {
436033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
437033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() != ALLOCATED) {
438033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            state->set(RELEASED);
439033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return UNKNOWN_ERROR;
440033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
4410f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa        comp = state->comp;
442033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return OK;
443033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    };
444033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (tryAndReportOnError(checkAllocated) != OK) {
445033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
446033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
447033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
4483bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar    auto doConfig = [msg, comp, this] {
449033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        AString mime;
450033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (!msg->findString("mime", &mime)) {
451033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return BAD_VALUE;
452033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
453033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
454033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        int32_t encoder;
455033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (!msg->findInt32("encoder", &encoder)) {
456033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            encoder = false;
457033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
458033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
4593bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar        // TODO: read from intf()
4603bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar        if ((!encoder) != (comp->getName().find("encoder") == std::string::npos)) {
4613bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar            return UNKNOWN_ERROR;
4623bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar        }
4633bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar
464f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim        int32_t storeMeta;
465f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim        if (encoder
466f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim                && msg->findInt32("android._input-metadata-buffer-type", &storeMeta)
467f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim                && storeMeta != kMetadataBufferTypeInvalid) {
468f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim            if (storeMeta != kMetadataBufferTypeANWBuffer) {
469f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim                ALOGD("Only ANW buffers are supported for legacy metadata mode");
470f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim                return BAD_VALUE;
471f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim            }
472f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim            mChannel->setMetaMode(CCodecBufferChannel::MODE_ANW);
473f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim        }
474f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim
475033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        sp<RefBase> obj;
476033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (msg->findObject("native-window", &obj)) {
477033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            sp<Surface> surface = static_cast<Surface *>(obj.get());
478033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            setSurface(surface);
479033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
480033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
4813bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar        Mutexed<Config>::Locked config(mConfig);
4823bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar        std::vector<std::unique_ptr<C2Param>> configUpdate;
4833bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar        status_t err = config->getConfigUpdateFromSdkParams(
4843bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar                comp, msg, Config::CONFIG, C2_DONT_BLOCK, &configUpdate);
4853bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar        if (err != OK) {
4863bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar            ALOGW("failed to convert configuration to c2 params");
4873bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar        }
4883bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar        err = config->setParameters(comp, configUpdate, C2_DONT_BLOCK);
4893bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar        if (err != OK) {
4903bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar            ALOGW("failed to configure c2 params");
4913bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar        }
4923bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar
493033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        std::vector<std::unique_ptr<C2Param>> params;
4943bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar        C2StreamUsageTuning::input usage(0u, 0u);
4953bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar        C2StreamMaxBufferSizeInfo::input maxInputSize(0u, 0u);
4963bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar        // TEMP: get max input size from format (in case component is not exposing this)
4973bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar        (void)msg->findInt32(KEY_MAX_INPUT_SIZE, (int32_t*)&maxInputSize.value);
4983bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar
499033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        std::initializer_list<C2Param::Index> indices {
500033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        };
5013bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar        c2_status_t c2err = comp->query(
5023bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar                { &usage, &maxInputSize },
503033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                indices,
504033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                C2_DONT_BLOCK,
505033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                &params);
506f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim        if (c2err != C2_OK && c2err != C2_BAD_INDEX) {
507033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            ALOGE("Failed to query component interface: %d", c2err);
508033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return UNKNOWN_ERROR;
509033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
510033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (params.size() != indices.size()) {
511f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim            ALOGE("Component returns wrong number of params: expected %zu actual %zu",
512f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim                    indices.size(), params.size());
513033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return UNKNOWN_ERROR;
514033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
515f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim        if (usage && (usage.value & C2MemoryUsage::CPU_READ)) {
5163bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar            config->mInputFormat->setInt32("using-sw-read-often", true);
517f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim        }
518033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
5193bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar        // TEMP: enforce minimum buffer size of 1MB for video decoders
5203bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar        if (!encoder && !(config->mDomain & Config::IS_AUDIO)) {
5213bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar            maxInputSize.value = c2_max(1048576u, maxInputSize.value);
522033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
523033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
524a00de0de4f172b294f286460292dc4a99f9dda67Lajos Molnar        // TODO: do this based on component requiring linear allocator for input
5253bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar        if ((config->mDomain & Config::IS_DECODER) || (config->mDomain & Config::IS_AUDIO)) {
5263bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar            // Pass max input size on input format to the buffer channel
5273bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar            config->mInputFormat->setInt32(
5283bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar                    KEY_MAX_INPUT_SIZE, (int32_t)(c2_min(maxInputSize.value, uint32_t(INT32_MAX))));
529a00de0de4f172b294f286460292dc4a99f9dda67Lajos Molnar        }
530a00de0de4f172b294f286460292dc4a99f9dda67Lajos Molnar
5313bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar        ALOGD("setup formats input: %s and output: %s",
5323bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar                config->mInputFormat->debugString().c_str(),
5333bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar                config->mOutputFormat->debugString().c_str());
534033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return OK;
535033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    };
536033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (tryAndReportOnError(doConfig) != OK) {
537033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
538033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
539033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
5403bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar    Mutexed<Config>::Locked config(mConfig);
5413bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar
5423bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar    mCallback->onComponentConfigured(config->mInputFormat, config->mOutputFormat);
543033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
544033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
545033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::initiateCreateInputSurface() {
546033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    status_t err = [this] {
547033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
548033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() != ALLOCATED) {
549033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return UNKNOWN_ERROR;
550033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
551033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        // TODO: read it from intf() properly.
5520f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa        if (state->comp->getName().find("encoder") == std::string::npos) {
553033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return INVALID_OPERATION;
554033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
555033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return OK;
556033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }();
557033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (err != OK) {
558033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mCallback->onInputSurfaceCreationFailed(err);
559033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
560033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
561033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
562033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    (new AMessage(kWhatCreateInputSurface, this))->post();
563033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
564033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
565033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::createInputSurface() {
5662bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa    status_t err;
5671c421ef3ded7c7dd25a44ea0d90db1ec46f5c1fbWonsik Kim    sp<IGraphicBufferProducer> bufferProducer;
568033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
569033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<AMessage> inputFormat;
570033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<AMessage> outputFormat;
571033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    {
5723bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar        Mutexed<Config>::Locked config(mConfig);
5733bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar        inputFormat = config->mInputFormat;
5743bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar        outputFormat = config->mOutputFormat;
575033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
5762bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa
5772bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa    // TODO: Remove this property check and assume it's always true.
5782bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa    if (property_get_bool("debug.stagefright.c2inputsurface", false)) {
5792bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa        std::shared_ptr<Codec2Client::InputSurface> surface;
5802bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa
5812bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa        err = static_cast<status_t>(mClient->createInputSurface(&surface));
5822bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa        if (err != OK) {
5832bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa            ALOGE("Failed to create input surface: %d", static_cast<int>(err));
5842bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa            mCallback->onInputSurfaceCreationFailed(err);
5852bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa            return;
5862bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa        }
5872bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa        if (!surface) {
5882bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa            ALOGE("Failed to create input surface: null input surface");
5892bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa            mCallback->onInputSurfaceCreationFailed(UNKNOWN_ERROR);
5902bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa            return;
5912bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa        }
5922bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa        bufferProducer = surface->getGraphicBufferProducer();
5932bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa        err = setupInputSurface(std::make_shared<C2InputSurfaceWrapper>(surface));
5942bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa    } else { // TODO: Remove this block.
5952bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa        using namespace ::android::hardware::media::omx::V1_0;
5962bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa        sp<IOmx> tOmx = IOmx::getService("default");
5972bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa        if (tOmx == nullptr) {
5982bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa            ALOGE("Failed to create input surface");
5992bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa            mCallback->onInputSurfaceCreationFailed(UNKNOWN_ERROR);
6002bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa            return;
6012bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa        }
6022bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa        sp<IOMX> omx = new utils::LWOmx(tOmx);
6032bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa
6042bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa        sp<BGraphicBufferSource> bufferSource;
6052bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa        err = omx->createInputSurface(&bufferProducer, &bufferSource);
6062bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa
6072bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa        if (err != OK) {
6082bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa            ALOGE("Failed to create input surface: %d", err);
6092bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa            mCallback->onInputSurfaceCreationFailed(err);
6102bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa            return;
6112bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa        }
6122bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa        int32_t width = 0;
6132bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa        (void)outputFormat->findInt32("width", &width);
6142bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa        int32_t height = 0;
6152bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa        (void)outputFormat->findInt32("height", &height);
6162bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa        err = setupInputSurface(std::make_shared<GraphicBufferSourceWrapper>(
6172bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa                bufferSource, width, height));
6182bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa    }
6192bc4356b1c43e24210c9bb2d2b7afeef419fa2e7Pawin Vongmasa
620ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim    if (err != OK) {
621ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim        ALOGE("Failed to set up input surface: %d", err);
622ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim        mCallback->onInputSurfaceCreationFailed(err);
623ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim        return;
624ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim    }
625033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mCallback->onInputSurfaceCreated(
626033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            inputFormat,
627033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            outputFormat,
6281c421ef3ded7c7dd25a44ea0d90db1ec46f5c1fbWonsik Kim            new BufferProducerWrapper(bufferProducer));
629033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
630033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
631033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimstatus_t CCodec::setupInputSurface(const std::shared_ptr<InputSurfaceWrapper> &surface) {
632033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    status_t err = mChannel->setInputSurface(surface);
633033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (err != OK) {
634033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return err;
635033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
636033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
637033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    // TODO: configure |surface| with other settings.
638033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    return OK;
639033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
640033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
641033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::initiateSetInputSurface(const sp<PersistentSurface> &surface) {
642033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<AMessage> msg = new AMessage(kWhatSetInputSurface, this);
643033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    msg->setObject("surface", surface);
644033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    msg->post();
645033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
646033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
647033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::setInputSurface(const sp<PersistentSurface> &surface) {
648033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<AMessage> inputFormat;
649033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<AMessage> outputFormat;
650033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    {
6513bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar        Mutexed<Config>::Locked config(mConfig);
6523bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar        inputFormat = config->mInputFormat;
6533bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar        outputFormat = config->mOutputFormat;
654033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
655ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim    int32_t width = 0;
656ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim    (void)outputFormat->findInt32("width", &width);
657ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim    int32_t height = 0;
658ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim    (void)outputFormat->findInt32("height", &height);
659ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim    status_t err = setupInputSurface(std::make_shared<GraphicBufferSourceWrapper>(
660ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim            surface->getBufferSource(), width, height));
661ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim    if (err != OK) {
662ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim        ALOGE("Failed to set up input surface: %d", err);
663ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim        mCallback->onInputSurfaceDeclined(err);
664ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim        return;
665ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim    }
666033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mCallback->onInputSurfaceAccepted(inputFormat, outputFormat);
667033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
668033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
669033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::initiateStart() {
670033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    auto setStarting = [this] {
671033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
672033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() != ALLOCATED) {
673033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return UNKNOWN_ERROR;
674033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
675033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state->set(STARTING);
676033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return OK;
677033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    };
678033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (tryAndReportOnError(setStarting) != OK) {
679033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
680033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
681033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
682033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    (new AMessage(kWhatStart, this))->post();
683033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
684033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
685033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::start() {
6860f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    std::shared_ptr<Codec2Client::Component> comp;
687033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    auto checkStarting = [this, &comp] {
688033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
689033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() != STARTING) {
690033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return UNKNOWN_ERROR;
691033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
692033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        comp = state->comp;
693033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return OK;
694033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    };
695033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (tryAndReportOnError(checkStarting) != OK) {
696033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
697033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
698033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
699033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    c2_status_t err = comp->start();
700033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (err != C2_OK) {
701033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        // TODO: convert err into status_t
702033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL);
703033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
704033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
705033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<AMessage> inputFormat;
706033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<AMessage> outputFormat;
707033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    {
7083bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar        Mutexed<Config>::Locked config(mConfig);
7093bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar        inputFormat = config->mInputFormat;
7103bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar        outputFormat = config->mOutputFormat;
711033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
712033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    status_t err2 = mChannel->start(inputFormat, outputFormat);
713033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (err2 != OK) {
714033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mCallback->onError(err2, ACTION_CODE_FATAL);
715033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
716033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
717033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
718033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    auto setRunning = [this] {
719033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
720033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() != STARTING) {
721033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return UNKNOWN_ERROR;
722033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
723033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state->set(RUNNING);
724033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return OK;
725033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    };
726033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (tryAndReportOnError(setRunning) != OK) {
727033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
728033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
729033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mCallback->onStartCompleted();
730033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
731033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
732033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::initiateShutdown(bool keepComponentAllocated) {
733033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (keepComponentAllocated) {
734033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        initiateStop();
735033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    } else {
736033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        initiateRelease();
737033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
738033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
739033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
740033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::initiateStop() {
741033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    {
742033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
743033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() == ALLOCATED
744033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                || state->get()  == RELEASED
745033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                || state->get() == STOPPING
746033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                || state->get() == RELEASING) {
747033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            // We're already stopped, released, or doing it right now.
748033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            state.unlock();
749033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            mCallback->onStopCompleted();
750033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            state.lock();
751033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return;
752033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
753033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state->set(STOPPING);
754033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
755033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
756033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    (new AMessage(kWhatStop, this))->post();
757033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
758033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
759033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::stop() {
7600f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    std::shared_ptr<Codec2Client::Component> comp;
761033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    {
762033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
763033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() == RELEASING) {
764033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            state.unlock();
765033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            // We're already stopped or release is in progress.
766033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            mCallback->onStopCompleted();
767033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            state.lock();
768033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return;
769033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        } else if (state->get() != STOPPING) {
770033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            state.unlock();
771033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL);
772033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            state.lock();
773033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return;
774033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
775033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        comp = state->comp;
776033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
777033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mChannel->stop();
778033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    status_t err = comp->stop();
779033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (err != C2_OK) {
780033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        // TODO: convert err into status_t
781033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL);
782033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
783033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
784033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    {
785033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
786033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() == STOPPING) {
787033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            state->set(ALLOCATED);
788033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
789033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
790033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mCallback->onStopCompleted();
791033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
792033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
793033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::initiateRelease(bool sendCallback /* = true */) {
794033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    {
795033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
796033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() == RELEASED || state->get() == RELEASING) {
797033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            // We're already released or doing it right now.
798033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            if (sendCallback) {
799033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                state.unlock();
800033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                mCallback->onReleaseCompleted();
801033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                state.lock();
802033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            }
803033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return;
804033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
805033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() == ALLOCATING) {
806033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            state->set(RELEASING);
807033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            // With the altered state allocate() would fail and clean up.
808033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            if (sendCallback) {
809033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                state.unlock();
810033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                mCallback->onReleaseCompleted();
811033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                state.lock();
812033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            }
813033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return;
814033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
815033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state->set(RELEASING);
816033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
817033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
818033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    std::thread([this, sendCallback] { release(sendCallback); }).detach();
819033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
820033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
821033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::release(bool sendCallback) {
8220f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    std::shared_ptr<Codec2Client::Component> comp;
823033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    {
824033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
825033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() == RELEASED) {
826033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            if (sendCallback) {
827033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                state.unlock();
828033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                mCallback->onReleaseCompleted();
829033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                state.lock();
830033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            }
831033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return;
832033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
833033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        comp = state->comp;
834033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
835033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mChannel->stop();
836033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    comp->release();
837033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
838033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    {
839033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
840033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state->set(RELEASED);
841033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state->comp.reset();
842033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
843033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (sendCallback) {
844033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mCallback->onReleaseCompleted();
845033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
846033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
847033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
848033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimstatus_t CCodec::setSurface(const sp<Surface> &surface) {
849033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    return mChannel->setSurface(surface);
850033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
851033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
852033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::signalFlush() {
853033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    status_t err = [this] {
854033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
855033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() == FLUSHED) {
856033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return ALREADY_EXISTS;
857033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
858033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() != RUNNING) {
859033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return UNKNOWN_ERROR;
860033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
861033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state->set(FLUSHING);
862033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return OK;
863033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }();
864033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    switch (err) {
865033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        case ALREADY_EXISTS:
866033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            mCallback->onFlushCompleted();
867033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return;
868033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        case OK:
869033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            break;
870033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        default:
871033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            mCallback->onError(err, ACTION_CODE_FATAL);
872033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return;
873033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
874033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
875033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    (new AMessage(kWhatFlush, this))->post();
876033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
877033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
878033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::flush() {
8790f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    std::shared_ptr<Codec2Client::Component> comp;
880033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    auto checkFlushing = [this, &comp] {
881033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
882033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() != FLUSHING) {
883033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return UNKNOWN_ERROR;
884033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
885033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        comp = state->comp;
886033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return OK;
887033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    };
888033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (tryAndReportOnError(checkFlushing) != OK) {
889033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
890033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
891033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
892033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mChannel->stop();
893033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
894033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    std::list<std::unique_ptr<C2Work>> flushedWork;
8950f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    c2_status_t err = comp->flush(C2Component::FLUSH_COMPONENT, &flushedWork);
896033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (err != C2_OK) {
897033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        // TODO: convert err into status_t
898033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL);
899033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
900033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
901033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mChannel->flush(flushedWork);
902033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
903033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    {
904033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
905033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state->set(FLUSHED);
906033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
907033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mCallback->onFlushCompleted();
908033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
909033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
910033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::signalResume() {
911033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    auto setResuming = [this] {
912033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
913033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() != FLUSHED) {
914033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return UNKNOWN_ERROR;
915033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
916033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state->set(RESUMING);
917033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return OK;
918033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    };
919033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (tryAndReportOnError(setResuming) != OK) {
920033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
921033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
922033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
923033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    (void)mChannel->start(nullptr, nullptr);
924033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
925033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    {
926033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
927033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() != RESUMING) {
928033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            state.unlock();
929033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL);
930033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            state.lock();
931033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return;
932033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
933033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state->set(RUNNING);
934033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
935033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
936033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
937069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kimvoid CCodec::signalSetParameters(const sp<AMessage> &params) {
938069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim    sp<AMessage> msg = new AMessage(kWhatSetParameters, this);
939069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim    msg->setMessage("params", params);
940069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim    msg->post();
941069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim}
942069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim
9433bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnarvoid CCodec::setParameters(const sp<AMessage> &params) {
944069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim    std::shared_ptr<Codec2Client::Component> comp;
945069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim    auto checkState = [this, &comp] {
946069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        Mutexed<State>::Locked state(mState);
947069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        if (state->get() == RELEASED) {
948069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim            return INVALID_OPERATION;
949069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        }
950069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        comp = state->comp;
951069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        return OK;
952069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim    };
953069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim    if (tryAndReportOnError(checkState) != OK) {
954069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        return;
955069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim    }
956069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim
9573bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar    Mutexed<Config>::Locked config(mConfig);
9583bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar    std::vector<std::unique_ptr<C2Param>> configUpdate;
9593bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar    (void)config->getConfigUpdateFromSdkParams(comp, params, Config::PARAM, C2_MAY_BLOCK, &configUpdate);
9603bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar    if (property_get_bool("debug.stagefright.ccodec_delayed_params", false)) {
9613bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar        // mChannel->queueConfigUpdate(configUpdate);
9623bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar    } else {
9633bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar        (void)config->setParameters(comp, configUpdate, C2_MAY_BLOCK);
964069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim    }
965033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
966033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
967033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::signalEndOfInputStream() {
9687a702c9f08c57f64121149e3e233cbe8fcf4dc36Wonsik Kim    mCallback->onSignaledInputEOS(mChannel->signalEndOfInputStream());
969033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
970033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
971033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::signalRequestIDRFrame() {
972033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    // TODO
973033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
974033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
975033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::onWorkDone(std::list<std::unique_ptr<C2Work>> &workItems) {
976033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    Mutexed<std::list<std::unique_ptr<C2Work>>>::Locked queue(mWorkDoneQueue);
977033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    queue->splice(queue->end(), workItems);
978033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    (new AMessage(kWhatWorkDone, this))->post();
979033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
980033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
981033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::onMessageReceived(const sp<AMessage> &msg) {
982033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    TimePoint now = std::chrono::steady_clock::now();
983033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    switch (msg->what()) {
984033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        case kWhatAllocate: {
985033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            // C2ComponentStore::createComponent() should return within 100ms.
986033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            setDeadline(now + 150ms, "allocate");
987033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            sp<RefBase> obj;
988033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            CHECK(msg->findObject("codecInfo", &obj));
989033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            allocate((MediaCodecInfo *)obj.get());
990033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            break;
991033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
992033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        case kWhatConfigure: {
993033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            // C2Component::commit_sm() should return within 5ms.
994033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            setDeadline(now + 50ms, "configure");
995033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            sp<AMessage> format;
996033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            CHECK(msg->findMessage("format", &format));
997033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            configure(format);
998033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            break;
999033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
1000033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        case kWhatStart: {
1001033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            // C2Component::start() should return within 500ms.
1002033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            setDeadline(now + 550ms, "start");
1003033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            start();
1004033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            break;
1005033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
1006033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        case kWhatStop: {
1007033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            // C2Component::stop() should return within 500ms.
1008033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            setDeadline(now + 550ms, "stop");
1009033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            stop();
1010033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            break;
1011033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
1012033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        case kWhatFlush: {
1013033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            // C2Component::flush_sm() should return within 5ms.
1014033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            setDeadline(now + 50ms, "flush");
1015033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            flush();
1016033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            break;
1017033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
1018033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        case kWhatCreateInputSurface: {
1019033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            // Surface operations may be briefly blocking.
1020033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            setDeadline(now + 100ms, "createInputSurface");
1021033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            createInputSurface();
1022033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            break;
1023033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
1024033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        case kWhatSetInputSurface: {
1025033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            // Surface operations may be briefly blocking.
1026033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            setDeadline(now + 100ms, "setInputSurface");
1027033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            sp<RefBase> obj;
1028033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            CHECK(msg->findObject("surface", &obj));
1029033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            sp<PersistentSurface> surface(static_cast<PersistentSurface *>(obj.get()));
1030033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            setInputSurface(surface);
1031033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            break;
1032033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
1033069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        case kWhatSetParameters: {
1034069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim            setDeadline(now + 50ms, "setParameters");
1035069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim            sp<AMessage> params;
1036069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim            CHECK(msg->findMessage("params", &params));
1037069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim            setParameters(params);
1038069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim            break;
1039069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        }
1040033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        case kWhatWorkDone: {
1041033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            std::unique_ptr<C2Work> work;
1042033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            {
1043033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                Mutexed<std::list<std::unique_ptr<C2Work>>>::Locked queue(mWorkDoneQueue);
1044033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                if (queue->empty()) {
1045033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                    break;
1046033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                }
1047033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                work.swap(queue->front());
1048033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                queue->pop_front();
1049033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                if (!queue->empty()) {
1050033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                    (new AMessage(kWhatWorkDone, this))->post();
1051033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                }
1052033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            }
10533bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar
10543bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar            // handle configuration changes in work done
10553bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar            Mutexed<Config>::Locked config(mConfig);
10563bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar            bool changed = false;
10573bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar            Config::Watcher<C2StreamInitDataInfo::output> initData =
10583bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar                config->watch<C2StreamInitDataInfo::output>();
10593bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar            if (!work->worklets.empty()
10603bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar                    && (work->worklets.front()->output.flags
10613bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar                            & C2FrameData::FLAG_DISCARD_FRAME) == 0) {
10623bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar                changed = config->updateConfiguration(
10633bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar                        work->worklets.front()->output.configUpdate,
10643bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar                        config->mOutputDomain);
10653bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar            }
10663bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar            mChannel->onWorkDone(
10673bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar                    std::move(work), changed ? config->mOutputFormat : nullptr,
10683bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar                    initData.hasChanged() ? initData.update().get() : nullptr);
1069033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            break;
1070033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
1071033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        default: {
1072033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            ALOGE("unrecognized message");
1073033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            break;
1074033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
1075033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
1076033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    setDeadline(TimePoint::max(), "none");
1077033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
1078033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1079033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::setDeadline(const TimePoint &newDeadline, const char *name) {
1080033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    Mutexed<NamedTimePoint>::Locked deadline(mDeadline);
1081033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    deadline->set(newDeadline, name);
1082033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
1083033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1084033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::initiateReleaseIfStuck() {
1085033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    std::string name;
1086033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    {
1087033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<NamedTimePoint>::Locked deadline(mDeadline);
1088033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (deadline->get() >= std::chrono::steady_clock::now()) {
1089033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            // We're not stuck.
1090033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return;
1091033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
1092033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        name = deadline->getName();
1093033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
1094033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1095033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    ALOGW("previous call to %s exceeded timeout", name.c_str());
1096033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    initiateRelease(false);
1097033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL);
1098033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
1099033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1100033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}  // namespace android
1101033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1102033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimextern "C" android::CodecBase *CreateCodec() {
1103033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    return new android::CCodec;
1104033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
11050f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa
1106