CCodec.cpp revision 069f7358a56620fca51d26dfb7b1c02a5501c703
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
24069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim#include <C2ParamInternal.h>
25033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include <C2PlatformSupport.h>
26033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include <C2V4l2Support.h>
27033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
28033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include <android/IOMXBufferSource.h>
291c421ef3ded7c7dd25a44ea0d90db1ec46f5c1fbWonsik Kim#include <android/IGraphicBufferSource.h>
30033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include <gui/bufferqueue/1.0/H2BGraphicBufferProducer.h>
311c421ef3ded7c7dd25a44ea0d90db1ec46f5c1fbWonsik Kim#include <gui/IGraphicBufferProducer.h>
32033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include <gui/Surface.h>
331c421ef3ded7c7dd25a44ea0d90db1ec46f5c1fbWonsik Kim#include <media/omx/1.0/WOmx.h>
34033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include <media/stagefright/codec2/1.0/InputSurface.h>
35033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include <media/stagefright/BufferProducerWrapper.h>
36033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include <media/stagefright/PersistentSurface.h>
37033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
38033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include "C2OMXNode.h"
39033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include "CCodec.h"
40033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include "CCodecBufferChannel.h"
41033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include "InputSurfaceWrapper.h"
42033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
43033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimnamespace android {
44033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
45033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimusing namespace std::chrono_literals;
46033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimusing ::android::hardware::graphics::bufferqueue::V1_0::utils::H2BGraphicBufferProducer;
471c421ef3ded7c7dd25a44ea0d90db1ec46f5c1fbWonsik Kimusing BGraphicBufferSource = ::android::IGraphicBufferSource;
48033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
49033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimnamespace {
50033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
51033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimclass CCodecWatchdog : public AHandler {
52033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimprivate:
53033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    enum {
54033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        kWhatRegister,
55033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        kWhatWatch,
56033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    };
57033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    constexpr static int64_t kWatchIntervalUs = 3000000;  // 3 secs
58033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
59033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimpublic:
60033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    static sp<CCodecWatchdog> getInstance() {
61033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<sp<CCodecWatchdog>>::Locked instance(sInstance);
62033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (*instance == nullptr) {
63033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            *instance = new CCodecWatchdog;
64033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            (*instance)->init();
65033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
66033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return *instance;
67033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
68033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
69033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    ~CCodecWatchdog() = default;
70033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
71033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    void registerCodec(CCodec *codec) {
72033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        sp<AMessage> msg = new AMessage(kWhatRegister, this);
73033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        msg->setPointer("codec", codec);
74033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        msg->post();
75033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
76033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
77033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimprotected:
78033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    void onMessageReceived(const sp<AMessage> &msg) {
79033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        switch (msg->what()) {
80033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            case kWhatRegister: {
81033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                void *ptr = nullptr;
82033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                CHECK(msg->findPointer("codec", &ptr));
83033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                Mutexed<std::list<wp<CCodec>>>::Locked codecs(mCodecs);
84033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                codecs->emplace_back((CCodec *)ptr);
85033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                break;
86033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            }
87033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
88033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            case kWhatWatch: {
89033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                Mutexed<std::list<wp<CCodec>>>::Locked codecs(mCodecs);
90033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                for (auto it = codecs->begin(); it != codecs->end(); ) {
91033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                    sp<CCodec> codec = it->promote();
92033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                    if (codec == nullptr) {
93033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                        it = codecs->erase(it);
94033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                        continue;
95033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                    }
96033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                    codec->initiateReleaseIfStuck();
97033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                    ++it;
98033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                }
99033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                msg->post(kWatchIntervalUs);
100033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                break;
101033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            }
102033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
103033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            default: {
104033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                TRESPASS("CCodecWatchdog: unrecognized message");
105033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            }
106033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
107033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
108033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
109033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimprivate:
110033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    CCodecWatchdog() : mLooper(new ALooper) {}
111033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
112033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    void init() {
113033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mLooper->setName("CCodecWatchdog");
114033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mLooper->registerHandler(this);
115033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mLooper->start();
116033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        (new AMessage(kWhatWatch, this))->post(kWatchIntervalUs);
117033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
118033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
119033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    static Mutexed<sp<CCodecWatchdog>> sInstance;
120033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
121033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<ALooper> mLooper;
122033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    Mutexed<std::list<wp<CCodec>>> mCodecs;
123033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim};
124033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
125033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik KimMutexed<sp<CCodecWatchdog>> CCodecWatchdog::sInstance;
126033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1270f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasaclass CCodecListener : public Codec2Client::Listener {
128033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimpublic:
129033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    explicit CCodecListener(const wp<CCodec> &codec) : mCodec(codec) {}
130033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1310f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    virtual void onWorkDone(
1320f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa            const std::weak_ptr<Codec2Client::Component>& component,
1330f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa            std::list<std::unique_ptr<C2Work>>& workItems) override {
134033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        (void)component;
135033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        sp<CCodec> codec(mCodec.promote());
136033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (!codec) {
137033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return;
138033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
139033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        codec->onWorkDone(workItems);
140033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
141033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1420f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    virtual void onTripped(
1430f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa            const std::weak_ptr<Codec2Client::Component>& component,
1440f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa            const std::vector<std::shared_ptr<C2SettingResult>>& settingResult) override {
145033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        // TODO
146033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        (void)component;
147033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        (void)settingResult;
148033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
149033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1500f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    virtual void onError(
1510f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa            const std::weak_ptr<Codec2Client::Component>& component,
1520f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa            uint32_t errorCode) override {
153033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        // TODO
154033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        (void)component;
155033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        (void)errorCode;
156033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
157033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
158033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimprivate:
159033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    wp<CCodec> mCodec;
160033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim};
161033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
162033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimclass C2InputSurfaceWrapper : public InputSurfaceWrapper {
163033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimpublic:
1640f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    explicit C2InputSurfaceWrapper(
1650f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa            const std::shared_ptr<Codec2Client::InputSurface> &surface) :
1660f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa        mSurface(surface) {
1670f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    }
1680f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa
169033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    ~C2InputSurfaceWrapper() override = default;
170033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1710f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    status_t connect(const std::shared_ptr<Codec2Client::Component> &comp) override {
172033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (mConnection != nullptr) {
173033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return ALREADY_EXISTS;
174033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
1750f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa        return static_cast<status_t>(
1760f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa                mSurface->connectToComponent(comp, &mConnection));
177033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
178033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
179033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    void disconnect() override {
180033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (mConnection != nullptr) {
181033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            mConnection->disconnect();
1820f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa            mConnection = nullptr;
183033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
184033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
185033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
186033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimprivate:
1870f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    std::shared_ptr<Codec2Client::InputSurface> mSurface;
1880f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    std::shared_ptr<Codec2Client::InputSurfaceConnection> mConnection;
189033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim};
190033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
191033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimclass GraphicBufferSourceWrapper : public InputSurfaceWrapper {
192033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimpublic:
193ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim//    explicit GraphicBufferSourceWrapper(const sp<BGraphicBufferSource> &source) : mSource(source) {}
194ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim    GraphicBufferSourceWrapper(
195ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim            const sp<BGraphicBufferSource> &source,
196ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim            uint32_t width,
197ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim            uint32_t height)
198ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim        : mSource(source), mWidth(width), mHeight(height) {}
199033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    ~GraphicBufferSourceWrapper() override = default;
200033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
2010f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    status_t connect(const std::shared_ptr<Codec2Client::Component> &comp) override {
202033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        // TODO: proper color aspect & dataspace
203033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        android_dataspace dataSpace = HAL_DATASPACE_BT709;
204033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
205033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mNode = new C2OMXNode(comp);
206ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim        mNode->setFrameSize(mWidth, mHeight);
207033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mSource->configure(mNode, dataSpace);
208033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
209033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        // TODO: configure according to intf().
210033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
211033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        sp<IOMXBufferSource> source = mNode->getSource();
212033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (source == nullptr) {
213033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return NO_INIT;
214033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
215033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        constexpr size_t kNumSlots = 16;
216033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        for (size_t i = 0; i < kNumSlots; ++i) {
217033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            source->onInputBufferAdded(i);
218033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
219033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        source->onOmxExecuting();
220033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return OK;
221033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
222033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
223033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    void disconnect() override {
224033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (mNode == nullptr) {
225033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return;
226033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
227033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        sp<IOMXBufferSource> source = mNode->getSource();
228033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (source == nullptr) {
229033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            ALOGD("GBSWrapper::disconnect: node is not configured with OMXBufferSource.");
230033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return;
231033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
232033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        source->onOmxIdle();
233033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        source->onOmxLoaded();
234033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mNode.clear();
235033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
236033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
237033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimprivate:
2381c421ef3ded7c7dd25a44ea0d90db1ec46f5c1fbWonsik Kim    sp<BGraphicBufferSource> mSource;
239033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<C2OMXNode> mNode;
240ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim    uint32_t mWidth;
241ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim    uint32_t mHeight;
242033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim};
243033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
244033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}  // namespace
245033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
246033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik KimCCodec::CCodec()
247033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    : mChannel(new CCodecBufferChannel([this] (status_t err, enum ActionCode actionCode) {
248033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim          mCallback->onError(err, actionCode);
249033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim      })) {
250033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    CCodecWatchdog::getInstance()->registerCodec(this);
251033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
252033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
253033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik KimCCodec::~CCodec() {
254033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
255033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
256033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimstd::shared_ptr<BufferChannelBase> CCodec::getBufferChannel() {
257033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    return mChannel;
258033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
259033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
260033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimstatus_t CCodec::tryAndReportOnError(std::function<status_t()> job) {
261033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    status_t err = job();
262033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (err != C2_OK) {
263033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mCallback->onError(err, ACTION_CODE_FATAL);
264033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
265033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    return err;
266033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
267033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
268033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::initiateAllocateComponent(const sp<AMessage> &msg) {
269033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    auto setAllocating = [this] {
270033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
271033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() != RELEASED) {
272033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return INVALID_OPERATION;
273033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
274033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state->set(ALLOCATING);
275033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return OK;
276033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    };
277033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (tryAndReportOnError(setAllocating) != OK) {
278033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
279033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
280033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
281033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<RefBase> codecInfo;
282033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    CHECK(msg->findObject("codecInfo", &codecInfo));
283033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    // For Codec 2.0 components, componentName == codecInfo->getCodecName().
284033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
285033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<AMessage> allocMsg(new AMessage(kWhatAllocate, this));
286033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    allocMsg->setObject("codecInfo", codecInfo);
287033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    allocMsg->post();
288033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
289033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
290033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::allocate(const sp<MediaCodecInfo> &codecInfo) {
291033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (codecInfo == nullptr) {
292033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL);
293033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
294033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
295033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    ALOGV("allocate(%s)", codecInfo->getCodecName());
296033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mListener.reset(new CCodecListener(this));
297033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
298033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    AString componentName = codecInfo->getCodecName();
2990f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    std::shared_ptr<Codec2Client> client;
3000f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    std::shared_ptr<Codec2Client::Component> comp =
3010f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa            Codec2Client::CreateComponentByName(
3020f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa            componentName.c_str(),
3030f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa            mListener,
3040f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa            &client);
3050f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    if (!comp) {
306033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        ALOGE("Failed Create component: %s", componentName.c_str());
307033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
308033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state->set(RELEASED);
309033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state.unlock();
3100f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa        mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL);
311033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state.lock();
312033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
313033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
314033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    ALOGV("Success Create component: %s", componentName.c_str());
315033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mChannel->setComponent(comp);
3160f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    auto setAllocated = [this, comp, client] {
317033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
318033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() != ALLOCATING) {
319033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            state->set(RELEASED);
320033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return UNKNOWN_ERROR;
321033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
322033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state->set(ALLOCATED);
323033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state->comp = comp;
3240f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa        mClient = client;
325033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return OK;
326033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    };
327033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (tryAndReportOnError(setAllocated) != OK) {
328033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
329033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
3300f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    mCallback->onComponentAllocated(comp->getName().c_str());
331033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
332033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
333033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::initiateConfigureComponent(const sp<AMessage> &format) {
334033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    auto checkAllocated = [this] {
335033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
336033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return (state->get() != ALLOCATED) ? UNKNOWN_ERROR : OK;
337033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    };
338033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (tryAndReportOnError(checkAllocated) != OK) {
339033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
340033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
341033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
342033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<AMessage> msg(new AMessage(kWhatConfigure, this));
343033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    msg->setMessage("format", format);
344033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    msg->post();
345033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
346033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
347033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::configure(const sp<AMessage> &msg) {
3480f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    std::shared_ptr<Codec2Client::Component> comp;
3490f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    auto checkAllocated = [this, &comp] {
350033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
351033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() != ALLOCATED) {
352033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            state->set(RELEASED);
353033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return UNKNOWN_ERROR;
354033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
3550f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa        comp = state->comp;
356033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return OK;
357033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    };
358033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (tryAndReportOnError(checkAllocated) != OK) {
359033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
360033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
361033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
362033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<AMessage> inputFormat(new AMessage);
363033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<AMessage> outputFormat(new AMessage);
364069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim    std::vector<std::shared_ptr<C2ParamDescriptor>> paramDescs;
365069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim
366069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim    auto doConfig = [=, paramDescsPtr = &paramDescs] {
367069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        c2_status_t c2err = comp->querySupportedParams(paramDescsPtr);
368069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        if (c2err != C2_OK) {
369069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim            ALOGD("Failed to query supported params");
370069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim            // TODO: return error once we complete implementation.
371069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim            // return UNKNOWN_ERROR;
372069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        }
373069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim
374033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        AString mime;
375033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (!msg->findString("mime", &mime)) {
376033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return BAD_VALUE;
377033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
378033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
379033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        int32_t encoder;
380033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (!msg->findInt32("encoder", &encoder)) {
381033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            encoder = false;
382033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
383033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
384033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        // TODO: read from intf()
3850f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa        if ((!encoder) != (comp->getName().find("encoder") == std::string::npos)) {
386033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return UNKNOWN_ERROR;
387033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
388033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
389033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        sp<RefBase> obj;
390033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (msg->findObject("native-window", &obj)) {
391033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            sp<Surface> surface = static_cast<Surface *>(obj.get());
392033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            setSurface(surface);
393033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
394033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
395033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        std::vector<std::unique_ptr<C2Param>> params;
396033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        std::initializer_list<C2Param::Index> indices {
397033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            C2PortMimeConfig::input::PARAM_TYPE,
398033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            C2PortMimeConfig::output::PARAM_TYPE,
399033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        };
400069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        c2err = comp->query(
401033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                {},
402033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                indices,
403033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                C2_DONT_BLOCK,
404033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                &params);
405033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (c2err != C2_OK) {
406033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            ALOGE("Failed to query component interface: %d", c2err);
407033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return UNKNOWN_ERROR;
408033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
409033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (params.size() != indices.size()) {
410033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            ALOGE("Component returns wrong number of params");
411033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return UNKNOWN_ERROR;
412033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
413033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (!params[0] || !params[1]) {
414033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            ALOGE("Component returns null params");
415033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return UNKNOWN_ERROR;
416033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
417033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        inputFormat->setString("mime", ((C2PortMimeConfig *)params[0].get())->m.value);
418033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        outputFormat->setString("mime", ((C2PortMimeConfig *)params[1].get())->m.value);
419033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
420033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        // XXX: hack
421033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        bool audio = mime.startsWithIgnoreCase("audio/");
422ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim        if (!audio) {
423ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim            int32_t tmp;
424ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim            if (msg->findInt32("width", &tmp)) {
425ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim                outputFormat->setInt32("width", tmp);
426ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim            }
427ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim            if (msg->findInt32("height", &tmp)) {
428ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim                outputFormat->setInt32("height", tmp);
429ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim            }
430ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim        } else {
431ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim            if (encoder) {
432033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                inputFormat->setInt32("channel-count", 1);
433033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                inputFormat->setInt32("sample-rate", 44100);
434033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                outputFormat->setInt32("channel-count", 1);
435033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                outputFormat->setInt32("sample-rate", 44100);
436033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            } else {
437033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                outputFormat->setInt32("channel-count", 2);
438033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                outputFormat->setInt32("sample-rate", 44100);
439033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            }
440033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
441033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
442033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        // TODO
443033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
444033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return OK;
445033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    };
446033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (tryAndReportOnError(doConfig) != OK) {
447033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
448033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
449033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
450033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    {
451033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<Formats>::Locked formats(mFormats);
452033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        formats->inputFormat = inputFormat;
453033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        formats->outputFormat = outputFormat;
454033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
455069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim    std::shared_ptr<C2ParamReflector> reflector = mClient->getParamReflector();
456069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim    if (reflector != nullptr) {
457069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        Mutexed<ReflectedParamUpdater>::Locked paramUpdater(mParamUpdater);
458069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        paramUpdater->clear();
459069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        paramUpdater->addParamDesc(reflector, paramDescs);
460069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim    } else {
461069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        ALOGE("Failed to get param reflector");
462069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        // TODO: report error once we complete implementation.
463069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim    }
464033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mCallback->onComponentConfigured(inputFormat, outputFormat);
465033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
466033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
467033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::initiateCreateInputSurface() {
468033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    status_t err = [this] {
469033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
470033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() != ALLOCATED) {
471033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return UNKNOWN_ERROR;
472033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
473033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        // TODO: read it from intf() properly.
4740f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa        if (state->comp->getName().find("encoder") == std::string::npos) {
475033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return INVALID_OPERATION;
476033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
477033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return OK;
478033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }();
479033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (err != OK) {
480033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mCallback->onInputSurfaceCreationFailed(err);
481033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
482033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
483033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
484033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    (new AMessage(kWhatCreateInputSurface, this))->post();
485033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
486033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
487033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::createInputSurface() {
4881c421ef3ded7c7dd25a44ea0d90db1ec46f5c1fbWonsik Kim    using namespace ::android::hardware::media::omx::V1_0;
4891c421ef3ded7c7dd25a44ea0d90db1ec46f5c1fbWonsik Kim    sp<IOmx> tOmx = IOmx::getService("default");
4901c421ef3ded7c7dd25a44ea0d90db1ec46f5c1fbWonsik Kim    if (tOmx == nullptr) {
4911c421ef3ded7c7dd25a44ea0d90db1ec46f5c1fbWonsik Kim        ALOGE("Failed to create input surface");
4921c421ef3ded7c7dd25a44ea0d90db1ec46f5c1fbWonsik Kim        mCallback->onInputSurfaceCreationFailed(UNKNOWN_ERROR);
4931c421ef3ded7c7dd25a44ea0d90db1ec46f5c1fbWonsik Kim        return;
4941c421ef3ded7c7dd25a44ea0d90db1ec46f5c1fbWonsik Kim    }
4951c421ef3ded7c7dd25a44ea0d90db1ec46f5c1fbWonsik Kim    sp<IOMX> omx = new utils::LWOmx(tOmx);
4961c421ef3ded7c7dd25a44ea0d90db1ec46f5c1fbWonsik Kim
4971c421ef3ded7c7dd25a44ea0d90db1ec46f5c1fbWonsik Kim    sp<IGraphicBufferProducer> bufferProducer;
4981c421ef3ded7c7dd25a44ea0d90db1ec46f5c1fbWonsik Kim    sp<BGraphicBufferSource> bufferSource;
4991c421ef3ded7c7dd25a44ea0d90db1ec46f5c1fbWonsik Kim    status_t err = omx->createInputSurface(&bufferProducer, &bufferSource);
5001c421ef3ded7c7dd25a44ea0d90db1ec46f5c1fbWonsik Kim
5011c421ef3ded7c7dd25a44ea0d90db1ec46f5c1fbWonsik Kim    if (err != OK) {
5021c421ef3ded7c7dd25a44ea0d90db1ec46f5c1fbWonsik Kim        ALOGE("Failed to create input surface: %d", err);
5031c421ef3ded7c7dd25a44ea0d90db1ec46f5c1fbWonsik Kim        mCallback->onInputSurfaceCreationFailed(err);
5041c421ef3ded7c7dd25a44ea0d90db1ec46f5c1fbWonsik Kim        return;
5051c421ef3ded7c7dd25a44ea0d90db1ec46f5c1fbWonsik Kim    }
5061c421ef3ded7c7dd25a44ea0d90db1ec46f5c1fbWonsik Kim
5071c421ef3ded7c7dd25a44ea0d90db1ec46f5c1fbWonsik Kim#if 0
5080f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    std::shared_ptr<Codec2Client::InputSurface> surface;
509033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
5100f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    status_t err = static_cast<status_t>(mClient->createInputSurface(&surface));
511033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (err != OK) {
5120f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa        ALOGE("Failed to create input surface: %d", static_cast<int>(err));
513033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mCallback->onInputSurfaceCreationFailed(err);
514033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
515033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
5160f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    if (!surface) {
5170f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa        ALOGE("Failed to create input surface: null input surface");
5180f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa        mCallback->onInputSurfaceCreationFailed(UNKNOWN_ERROR);
5190f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa        return;
5200f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    }
5211c421ef3ded7c7dd25a44ea0d90db1ec46f5c1fbWonsik Kim#endif
522033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
5231c421ef3ded7c7dd25a44ea0d90db1ec46f5c1fbWonsik Kim//    err = setupInputSurface(std::make_shared<C2InputSurfaceWrapper>(surface));
524033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<AMessage> inputFormat;
525033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<AMessage> outputFormat;
526033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    {
527033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<Formats>::Locked formats(mFormats);
528033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        inputFormat = formats->inputFormat;
529033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        outputFormat = formats->outputFormat;
530033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
531ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim    int32_t width = 0;
532ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim    (void)outputFormat->findInt32("width", &width);
533ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim    int32_t height = 0;
534ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim    (void)outputFormat->findInt32("height", &height);
535ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim    err = setupInputSurface(std::make_shared<GraphicBufferSourceWrapper>(
536ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim            bufferSource, width, height));
537ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim    if (err != OK) {
538ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim        ALOGE("Failed to set up input surface: %d", err);
539ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim        mCallback->onInputSurfaceCreationFailed(err);
540ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim        return;
541ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim    }
542033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mCallback->onInputSurfaceCreated(
543033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            inputFormat,
544033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            outputFormat,
5451c421ef3ded7c7dd25a44ea0d90db1ec46f5c1fbWonsik Kim            new BufferProducerWrapper(bufferProducer));
546033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
547033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
548033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimstatus_t CCodec::setupInputSurface(const std::shared_ptr<InputSurfaceWrapper> &surface) {
549033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    status_t err = mChannel->setInputSurface(surface);
550033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (err != OK) {
551033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return err;
552033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
553033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
554033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    // TODO: configure |surface| with other settings.
555033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    return OK;
556033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
557033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
558033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::initiateSetInputSurface(const sp<PersistentSurface> &surface) {
559033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<AMessage> msg = new AMessage(kWhatSetInputSurface, this);
560033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    msg->setObject("surface", surface);
561033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    msg->post();
562033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
563033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
564033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::setInputSurface(const sp<PersistentSurface> &surface) {
565033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<AMessage> inputFormat;
566033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<AMessage> outputFormat;
567033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    {
568033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<Formats>::Locked formats(mFormats);
569033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        inputFormat = formats->inputFormat;
570033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        outputFormat = formats->outputFormat;
571033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
572ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim    int32_t width = 0;
573ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim    (void)outputFormat->findInt32("width", &width);
574ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim    int32_t height = 0;
575ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim    (void)outputFormat->findInt32("height", &height);
576ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim    status_t err = setupInputSurface(std::make_shared<GraphicBufferSourceWrapper>(
577ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim            surface->getBufferSource(), width, height));
578ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim    if (err != OK) {
579ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim        ALOGE("Failed to set up input surface: %d", err);
580ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim        mCallback->onInputSurfaceDeclined(err);
581ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim        return;
582ea8fb50202473df2711f12a8b31418118cd3bdaaWonsik Kim    }
583033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mCallback->onInputSurfaceAccepted(inputFormat, outputFormat);
584033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
585033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
586033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::initiateStart() {
587033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    auto setStarting = [this] {
588033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
589033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() != ALLOCATED) {
590033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return UNKNOWN_ERROR;
591033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
592033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state->set(STARTING);
593033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return OK;
594033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    };
595033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (tryAndReportOnError(setStarting) != OK) {
596033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
597033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
598033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
599033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    (new AMessage(kWhatStart, this))->post();
600033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
601033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
602033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::start() {
6030f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    std::shared_ptr<Codec2Client::Component> comp;
604033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    auto checkStarting = [this, &comp] {
605033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
606033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() != STARTING) {
607033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return UNKNOWN_ERROR;
608033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
609033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        comp = state->comp;
610033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return OK;
611033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    };
612033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (tryAndReportOnError(checkStarting) != OK) {
613033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
614033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
615033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
616033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    c2_status_t err = comp->start();
617033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (err != C2_OK) {
618033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        // TODO: convert err into status_t
619033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL);
620033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
621033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
622033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<AMessage> inputFormat;
623033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<AMessage> outputFormat;
624033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    {
625033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<Formats>::Locked formats(mFormats);
626033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        inputFormat = formats->inputFormat;
627033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        outputFormat = formats->outputFormat;
628033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
629033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    status_t err2 = mChannel->start(inputFormat, outputFormat);
630033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (err2 != OK) {
631033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mCallback->onError(err2, ACTION_CODE_FATAL);
632033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
633033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
634033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
635033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    auto setRunning = [this] {
636033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
637033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() != STARTING) {
638033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return UNKNOWN_ERROR;
639033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
640033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state->set(RUNNING);
641033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return OK;
642033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    };
643033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (tryAndReportOnError(setRunning) != OK) {
644033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
645033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
646033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mCallback->onStartCompleted();
647033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
648033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
649033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::initiateShutdown(bool keepComponentAllocated) {
650033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (keepComponentAllocated) {
651033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        initiateStop();
652033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    } else {
653033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        initiateRelease();
654033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
655033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
656033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
657033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::initiateStop() {
658033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    {
659033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
660033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() == ALLOCATED
661033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                || state->get()  == RELEASED
662033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                || state->get() == STOPPING
663033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                || state->get() == RELEASING) {
664033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            // We're already stopped, released, or doing it right now.
665033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            state.unlock();
666033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            mCallback->onStopCompleted();
667033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            state.lock();
668033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return;
669033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
670033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state->set(STOPPING);
671033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
672033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
673033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    (new AMessage(kWhatStop, this))->post();
674033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
675033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
676033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::stop() {
6770f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    std::shared_ptr<Codec2Client::Component> comp;
678033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    {
679033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
680033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() == RELEASING) {
681033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            state.unlock();
682033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            // We're already stopped or release is in progress.
683033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            mCallback->onStopCompleted();
684033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            state.lock();
685033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return;
686033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        } else if (state->get() != STOPPING) {
687033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            state.unlock();
688033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL);
689033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            state.lock();
690033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return;
691033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
692033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        comp = state->comp;
693033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
694033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mChannel->stop();
695033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    status_t err = comp->stop();
696033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (err != C2_OK) {
697033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        // TODO: convert err into status_t
698033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL);
699033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
700033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
701033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    {
702033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
703033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() == STOPPING) {
704033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            state->set(ALLOCATED);
705033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
706033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
707033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mCallback->onStopCompleted();
708033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
709033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
710033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::initiateRelease(bool sendCallback /* = true */) {
711033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    {
712033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
713033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() == RELEASED || state->get() == RELEASING) {
714033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            // We're already released or doing it right now.
715033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            if (sendCallback) {
716033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                state.unlock();
717033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                mCallback->onReleaseCompleted();
718033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                state.lock();
719033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            }
720033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return;
721033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
722033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() == ALLOCATING) {
723033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            state->set(RELEASING);
724033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            // With the altered state allocate() would fail and clean up.
725033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            if (sendCallback) {
726033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                state.unlock();
727033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                mCallback->onReleaseCompleted();
728033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                state.lock();
729033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            }
730033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return;
731033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
732033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state->set(RELEASING);
733033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
734033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
735033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    std::thread([this, sendCallback] { release(sendCallback); }).detach();
736033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
737033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
738033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::release(bool sendCallback) {
7390f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    std::shared_ptr<Codec2Client::Component> comp;
740033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    {
741033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
742033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() == RELEASED) {
743033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            if (sendCallback) {
744033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                state.unlock();
745033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                mCallback->onReleaseCompleted();
746033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                state.lock();
747033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            }
748033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return;
749033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
750033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        comp = state->comp;
751033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
752033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mChannel->stop();
753033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    comp->release();
754033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
755033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    {
756033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
757033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state->set(RELEASED);
758033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state->comp.reset();
759033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
760033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (sendCallback) {
761033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mCallback->onReleaseCompleted();
762033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
763033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
764033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
765033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimstatus_t CCodec::setSurface(const sp<Surface> &surface) {
766033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    return mChannel->setSurface(surface);
767033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
768033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
769033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::signalFlush() {
770033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    status_t err = [this] {
771033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
772033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() == FLUSHED) {
773033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return ALREADY_EXISTS;
774033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
775033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() != RUNNING) {
776033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return UNKNOWN_ERROR;
777033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
778033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state->set(FLUSHING);
779033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return OK;
780033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }();
781033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    switch (err) {
782033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        case ALREADY_EXISTS:
783033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            mCallback->onFlushCompleted();
784033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return;
785033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        case OK:
786033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            break;
787033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        default:
788033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            mCallback->onError(err, ACTION_CODE_FATAL);
789033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return;
790033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
791033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
792033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    (new AMessage(kWhatFlush, this))->post();
793033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
794033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
795033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::flush() {
7960f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    std::shared_ptr<Codec2Client::Component> comp;
797033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    auto checkFlushing = [this, &comp] {
798033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
799033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() != FLUSHING) {
800033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return UNKNOWN_ERROR;
801033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
802033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        comp = state->comp;
803033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return OK;
804033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    };
805033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (tryAndReportOnError(checkFlushing) != OK) {
806033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
807033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
808033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
809033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mChannel->stop();
810033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
811033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    std::list<std::unique_ptr<C2Work>> flushedWork;
8120f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    c2_status_t err = comp->flush(C2Component::FLUSH_COMPONENT, &flushedWork);
813033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (err != C2_OK) {
814033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        // TODO: convert err into status_t
815033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL);
816033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
817033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
818033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mChannel->flush(flushedWork);
819033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
820033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    {
821033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
822033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state->set(FLUSHED);
823033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
824033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mCallback->onFlushCompleted();
825033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
826033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
827033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::signalResume() {
828033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    auto setResuming = [this] {
829033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
830033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() != FLUSHED) {
831033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return UNKNOWN_ERROR;
832033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
833033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state->set(RESUMING);
834033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return OK;
835033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    };
836033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (tryAndReportOnError(setResuming) != OK) {
837033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
838033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
839033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
840033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    (void)mChannel->start(nullptr, nullptr);
841033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
842033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    {
843033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<State>::Locked state(mState);
844033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (state->get() != RESUMING) {
845033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            state.unlock();
846033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL);
847033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            state.lock();
848033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return;
849033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
850033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        state->set(RUNNING);
851033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
852033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
853033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
854069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kimvoid CCodec::signalSetParameters(const sp<AMessage> &params) {
855069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim    sp<AMessage> msg = new AMessage(kWhatSetParameters, this);
856069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim    msg->setMessage("params", params);
857069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim    msg->post();
858069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim}
859069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim
860069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kimvoid CCodec::setParameters(const sp<AMessage> &params) {
861069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim    class MyParam : public C2Param {
862069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim    public:
863069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        inline MyParam(uint32_t size, Index index) : C2Param(size, index) {}
864069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim    };
865069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim
866069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim    std::shared_ptr<Codec2Client::Component> comp;
867069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim    auto checkState = [this, &comp] {
868069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        Mutexed<State>::Locked state(mState);
869069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        if (state->get() == RELEASED) {
870069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim            return INVALID_OPERATION;
871069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        }
872069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        comp = state->comp;
873069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        return OK;
874069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim    };
875069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim    if (tryAndReportOnError(checkState) != OK) {
876069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        return;
877069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim    }
878069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim
879069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim    // TODO: ACodec backward-compatibility
880069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim
881069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim    c2_status_t err = C2_OK;
882069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim    std::vector<std::unique_ptr<C2Param>> vec;
883069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim    {
884069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        Mutexed<ReflectedParamUpdater>::Locked paramUpdater(mParamUpdater);
885069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        std::vector<C2Param::Index> indices;
886069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        paramUpdater->getParamIndicesFromMessage(params, &indices);
887069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim
888069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        paramUpdater.unlock();
889069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        if (indices.empty()) {
890069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim            ALOGD("no recognized params in: %s", params->debugString().c_str());
891069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim            return;
892069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        }
893069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        err = comp->query({}, indices, C2_MAY_BLOCK, &vec);
894069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        if (err != C2_OK) {
895069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim            ALOGD("query failed with %d", err);
896069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim            // This is non-fatal.
897069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim            return;
898069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        }
899069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        paramUpdater.lock();
900069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim
901069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        paramUpdater->updateParamsFromMessage(params, &vec);
902069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim    }
903069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim
904069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim    std::vector<C2Param *> paramVector;
905069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim    for (const std::unique_ptr<C2Param> &param : vec) {
906069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        paramVector.push_back(param.get());
907069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim    }
908069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim    std::vector<std::unique_ptr<C2SettingResult>> failures;
909069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim    err = comp->config(paramVector, C2_MAY_BLOCK, &failures);
910069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim    if (err != C2_OK) {
911069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        ALOGD("config failed with %d", err);
912069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        // This is non-fatal.
913069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim    }
914033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
915033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
916033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::signalEndOfInputStream() {
917033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    // TODO
918033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mCallback->onSignaledInputEOS(INVALID_OPERATION);
919033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
920033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
921033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::signalRequestIDRFrame() {
922033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    // TODO
923033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
924033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
925033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::onWorkDone(std::list<std::unique_ptr<C2Work>> &workItems) {
926033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    Mutexed<std::list<std::unique_ptr<C2Work>>>::Locked queue(mWorkDoneQueue);
927033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    queue->splice(queue->end(), workItems);
928033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    (new AMessage(kWhatWorkDone, this))->post();
929033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
930033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
931033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::onMessageReceived(const sp<AMessage> &msg) {
932033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    TimePoint now = std::chrono::steady_clock::now();
933033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    switch (msg->what()) {
934033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        case kWhatAllocate: {
935033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            // C2ComponentStore::createComponent() should return within 100ms.
936033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            setDeadline(now + 150ms, "allocate");
937033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            sp<RefBase> obj;
938033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            CHECK(msg->findObject("codecInfo", &obj));
939033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            allocate((MediaCodecInfo *)obj.get());
940033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            break;
941033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
942033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        case kWhatConfigure: {
943033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            // C2Component::commit_sm() should return within 5ms.
944033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            setDeadline(now + 50ms, "configure");
945033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            sp<AMessage> format;
946033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            CHECK(msg->findMessage("format", &format));
947033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            configure(format);
948069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim            setParameters(format);
949033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            break;
950033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
951033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        case kWhatStart: {
952033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            // C2Component::start() should return within 500ms.
953033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            setDeadline(now + 550ms, "start");
954033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            start();
955033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            break;
956033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
957033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        case kWhatStop: {
958033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            // C2Component::stop() should return within 500ms.
959033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            setDeadline(now + 550ms, "stop");
960033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            stop();
961033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            break;
962033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
963033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        case kWhatFlush: {
964033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            // C2Component::flush_sm() should return within 5ms.
965033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            setDeadline(now + 50ms, "flush");
966033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            flush();
967033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            break;
968033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
969033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        case kWhatCreateInputSurface: {
970033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            // Surface operations may be briefly blocking.
971033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            setDeadline(now + 100ms, "createInputSurface");
972033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            createInputSurface();
973033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            break;
974033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
975033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        case kWhatSetInputSurface: {
976033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            // Surface operations may be briefly blocking.
977033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            setDeadline(now + 100ms, "setInputSurface");
978033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            sp<RefBase> obj;
979033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            CHECK(msg->findObject("surface", &obj));
980033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            sp<PersistentSurface> surface(static_cast<PersistentSurface *>(obj.get()));
981033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            setInputSurface(surface);
982033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            break;
983033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
984069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        case kWhatSetParameters: {
985069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim            setDeadline(now + 50ms, "setParameters");
986069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim            sp<AMessage> params;
987069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim            CHECK(msg->findMessage("params", &params));
988069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim            setParameters(params);
989069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim            break;
990069f7358a56620fca51d26dfb7b1c02a5501c703Wonsik Kim        }
991033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        case kWhatWorkDone: {
992033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            std::unique_ptr<C2Work> work;
993033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            {
994033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                Mutexed<std::list<std::unique_ptr<C2Work>>>::Locked queue(mWorkDoneQueue);
995033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                if (queue->empty()) {
996033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                    break;
997033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                }
998033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                work.swap(queue->front());
999033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                queue->pop_front();
1000033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                if (!queue->empty()) {
1001033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                    (new AMessage(kWhatWorkDone, this))->post();
1002033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                }
1003033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            }
1004033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            mChannel->onWorkDone(work);
1005033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            break;
1006033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
1007033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        default: {
1008033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            ALOGE("unrecognized message");
1009033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            break;
1010033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
1011033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
1012033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    setDeadline(TimePoint::max(), "none");
1013033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
1014033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1015033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::setDeadline(const TimePoint &newDeadline, const char *name) {
1016033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    Mutexed<NamedTimePoint>::Locked deadline(mDeadline);
1017033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    deadline->set(newDeadline, name);
1018033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
1019033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1020033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodec::initiateReleaseIfStuck() {
1021033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    std::string name;
1022033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    {
1023033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<NamedTimePoint>::Locked deadline(mDeadline);
1024033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (deadline->get() >= std::chrono::steady_clock::now()) {
1025033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            // We're not stuck.
1026033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return;
1027033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
1028033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        name = deadline->getName();
1029033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
1030033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1031033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    ALOGW("previous call to %s exceeded timeout", name.c_str());
1032033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    initiateRelease(false);
1033033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL);
1034033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
1035033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1036033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}  // namespace android
1037033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1038033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimextern "C" android::CodecBase *CreateCodec() {
1039033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    return new android::CCodec;
1040033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
10410f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa
1042