1033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim/*
2033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim * Copyright 2017, The Android Open Source Project
3033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim *
4033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim * Licensed under the Apache License, Version 2.0 (the "License");
5033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim * you may not use this file except in compliance with the License.
6033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim * You may obtain a copy of the License at
7033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim *
8033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim *     http://www.apache.org/licenses/LICENSE-2.0
9033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim *
10033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim * Unless required by applicable law or agreed to in writing, software
11033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim * distributed under the License is distributed on an "AS IS" BASIS,
12033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim * See the License for the specific language governing permissions and
14033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim * limitations under the License.
15033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim */
16033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
17033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim//#define LOG_NDEBUG 0
18033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#define LOG_TAG "CCodecBufferChannel"
19033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include <utils/Log.h>
20033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
21033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include <numeric>
22033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include <thread>
23033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
24033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include <C2AllocatorGralloc.h>
25033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include <C2PlatformSupport.h>
26033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include <C2BlockInternal.h>
27a00de0de4f172b294f286460292dc4a99f9dda67Lajos Molnar#include <C2Config.h>
288b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin#include <C2Debug.h>
29033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
30033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include <android/hardware/cas/native/1.0/IDescrambler.h>
31033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include <binder/MemoryDealer.h>
32033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include <gui/Surface.h>
33033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include <media/openmax/OMX_Core.h>
34033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include <media/stagefright/foundation/ABuffer.h>
35b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar#include <media/stagefright/foundation/ALookup.h>
36033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include <media/stagefright/foundation/AMessage.h>
37033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include <media/stagefright/foundation/AUtils.h>
383bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar#include <media/stagefright/foundation/hexdump.h>
39033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include <media/stagefright/MediaCodec.h>
400fde62fab8b7a8802e4c8fbe8007f41af9dfcf9bLajos Molnar#include <media/stagefright/MediaCodecConstants.h>
41033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include <media/MediaCodecBuffer.h>
42033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include <system/window.h>
43033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
44033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include "CCodecBufferChannel.h"
45033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include "Codec2Buffer.h"
46dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim#include "SkipCutBuffer.h"
47033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
48033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimnamespace android {
49033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
50033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimusing hardware::hidl_handle;
51033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimusing hardware::hidl_string;
52033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimusing hardware::hidl_vec;
53033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimusing namespace hardware::cas::V1_0;
54033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimusing namespace hardware::cas::native::V1_0;
55033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
56033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimusing CasStatus = hardware::cas::V1_0::Status;
57033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
58033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim/**
59033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim * Base class for representation of buffers at one port.
60033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim */
61033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimclass CCodecBufferChannel::Buffers {
62033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimpublic:
63033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    Buffers() = default;
64033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    virtual ~Buffers() = default;
65033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
66033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    /**
67033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     * Set format for MediaCodec-facing buffers.
68033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     */
69033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    void setFormat(const sp<AMessage> &format) {
70033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        CHECK(format != nullptr);
71033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mFormat = format;
72033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
73033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
74033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    /**
758c90d948d154ccf81c4a7113f3aefbe329ce6e8dWonsik Kim     * Return a copy of current format.
768c90d948d154ccf81c4a7113f3aefbe329ce6e8dWonsik Kim     */
778c90d948d154ccf81c4a7113f3aefbe329ce6e8dWonsik Kim    sp<AMessage> dupFormat() {
788c90d948d154ccf81c4a7113f3aefbe329ce6e8dWonsik Kim        return mFormat != nullptr ? mFormat->dup() : nullptr;
798c90d948d154ccf81c4a7113f3aefbe329ce6e8dWonsik Kim    }
808c90d948d154ccf81c4a7113f3aefbe329ce6e8dWonsik Kim
818c90d948d154ccf81c4a7113f3aefbe329ce6e8dWonsik Kim    /**
82033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     * Returns true if the buffers are operating under array mode.
83033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     */
84033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    virtual bool isArrayMode() const { return false; }
85033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
86033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    /**
87033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     * Fills the vector with MediaCodecBuffer's if in array mode; otherwise,
88033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     * no-op.
89033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     */
90033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    virtual void getArray(Vector<sp<MediaCodecBuffer>> *) const {}
91033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
92033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimprotected:
93033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    // Format to be used for creating MediaCodec-facing buffers.
94033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<AMessage> mFormat;
95033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
96033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimprivate:
97033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    DISALLOW_EVIL_CONSTRUCTORS(Buffers);
98033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim};
99033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
100033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimclass CCodecBufferChannel::InputBuffers : public CCodecBufferChannel::Buffers {
101033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimpublic:
102033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    InputBuffers() = default;
103033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    virtual ~InputBuffers() = default;
104033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
105033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    /**
106033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     * Set a block pool to obtain input memory blocks.
107033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     */
108033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    void setPool(const std::shared_ptr<C2BlockPool> &pool) { mPool = pool; }
109033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
110033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    /**
111033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     * Get a new MediaCodecBuffer for input and its corresponding index.
112033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     * Returns false if no new buffer can be obtained at the moment.
113033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     */
114033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    virtual bool requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) = 0;
115033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
116033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    /**
117033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     * Release the buffer obtained from requestNewBuffer() and get the
118e76dbb8207011ad23a2e3460c5672e7c250beae9Wonsik Kim     * associated C2Buffer object back. Returns true if the buffer was on file
119e76dbb8207011ad23a2e3460c5672e7c250beae9Wonsik Kim     * and released successfully.
120033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     */
121e76dbb8207011ad23a2e3460c5672e7c250beae9Wonsik Kim    virtual bool releaseBuffer(
122e76dbb8207011ad23a2e3460c5672e7c250beae9Wonsik Kim            const sp<MediaCodecBuffer> &buffer, std::shared_ptr<C2Buffer> *c2buffer) = 0;
123033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
124033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    /**
125033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     * Flush internal state. After this call, no index or buffer previously
126033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     * returned from requestNewBuffer() is valid.
127033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     */
128033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    virtual void flush() = 0;
129033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
130033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    /**
131033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     * Return array-backed version of input buffers. The returned object
132033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     * shall retain the internal state so that it will honor index and
133033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     * buffer from previous calls of requestNewBuffer().
134033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     */
135033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    virtual std::unique_ptr<InputBuffers> toArrayMode() = 0;
136033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
137033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimprotected:
138033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    // Pool to obtain blocks for input buffers.
139033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    std::shared_ptr<C2BlockPool> mPool;
140033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
141033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimprivate:
142033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    DISALLOW_EVIL_CONSTRUCTORS(InputBuffers);
143033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim};
144033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
145033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimclass CCodecBufferChannel::OutputBuffers : public CCodecBufferChannel::Buffers {
146033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimpublic:
147033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    OutputBuffers() = default;
148033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    virtual ~OutputBuffers() = default;
149033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
150033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    /**
151033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     * Register output C2Buffer from the component and obtain corresponding
152033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     * index and MediaCodecBuffer object. Returns false if registration
153033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     * fails.
154033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     */
155033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    virtual bool registerBuffer(
156033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            const std::shared_ptr<C2Buffer> &buffer,
157033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            size_t *index,
158033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            sp<MediaCodecBuffer> *clientBuffer) = 0;
159033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
160033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    /**
161033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     * Register codec specific data as a buffer to be consistent with
162033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     * MediaCodec behavior.
163033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     */
164033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    virtual bool registerCsd(
165033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            const C2StreamCsdInfo::output * /* csd */,
166033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            size_t * /* index */,
167033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            sp<MediaCodecBuffer> * /* clientBuffer */) = 0;
168033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
169033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    /**
170033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     * Release the buffer obtained from registerBuffer() and get the
171e76dbb8207011ad23a2e3460c5672e7c250beae9Wonsik Kim     * associated C2Buffer object back. Returns true if the buffer was on file
172e76dbb8207011ad23a2e3460c5672e7c250beae9Wonsik Kim     * and released successfully.
173033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     */
174e76dbb8207011ad23a2e3460c5672e7c250beae9Wonsik Kim    virtual bool releaseBuffer(
175e76dbb8207011ad23a2e3460c5672e7c250beae9Wonsik Kim            const sp<MediaCodecBuffer> &buffer, std::shared_ptr<C2Buffer> *c2buffer) = 0;
176033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
177033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    /**
178033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     * Flush internal state. After this call, no index or buffer previously
179033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     * returned from registerBuffer() is valid.
180033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     */
181033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    virtual void flush(const std::list<std::unique_ptr<C2Work>> &flushedWork) = 0;
182033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
183033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    /**
184033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     * Return array-backed version of output buffers. The returned object
185033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     * shall retain the internal state so that it will honor index and
186033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     * buffer from previous calls of registerBuffer().
187033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     */
188033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    virtual std::unique_ptr<OutputBuffers> toArrayMode() = 0;
189033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
190dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim    /**
191dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim     * Initialize SkipCutBuffer object.
192dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim     */
193dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim    void initSkipCutBuffer(
194dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim            int32_t delay, int32_t padding, int32_t sampleRate, int32_t channelCount) {
195dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim        CHECK(mSkipCutBuffer == nullptr);
196dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim        mDelay = delay;
197dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim        mPadding = padding;
198dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim        mSampleRate = sampleRate;
199dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim        setSkipCutBuffer(delay, padding, channelCount);
200dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim    }
201dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim
202dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim    /**
203dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim     * Update the SkipCutBuffer object. No-op if it's never initialized.
204dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim     */
205dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim    void updateSkipCutBuffer(int32_t sampleRate, int32_t channelCount) {
206dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim        if (mSkipCutBuffer == nullptr) {
207dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim            return;
208dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim        }
209dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim        int32_t delay = mDelay;
210dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim        int32_t padding = mPadding;
211dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim        if (sampleRate != mSampleRate) {
212dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim            delay = ((int64_t)delay * sampleRate) / mSampleRate;
213dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim            padding = ((int64_t)padding * sampleRate) / mSampleRate;
214dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim        }
215dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim        setSkipCutBuffer(delay, padding, channelCount);
216dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim    }
217dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim
218dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim    /**
219dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim     * Submit buffer to SkipCutBuffer object, if initialized.
220dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim     */
221dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim    void submit(const sp<MediaCodecBuffer> &buffer) {
222dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim        if (mSkipCutBuffer != nullptr) {
223dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim            mSkipCutBuffer->submit(buffer);
224dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim        }
225dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim    }
226dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim
227dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim    /**
228dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim     * Transfer SkipCutBuffer object to the other Buffers object.
229dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim     */
230dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim    void transferSkipCutBuffer(const sp<SkipCutBuffer> &scb) {
231dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim        mSkipCutBuffer = scb;
232dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim    }
233dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim
234dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kimprotected:
235dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim    sp<SkipCutBuffer> mSkipCutBuffer;
236dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim
237033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimprivate:
238dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim    int32_t mDelay;
239dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim    int32_t mPadding;
240dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim    int32_t mSampleRate;
241dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim
242dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim    void setSkipCutBuffer(int32_t skip, int32_t cut, int32_t channelCount) {
243dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim        if (mSkipCutBuffer != nullptr) {
244dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim            size_t prevSize = mSkipCutBuffer->size();
245dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim            if (prevSize != 0u) {
246dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim                ALOGD("Replacing SkipCutBuffer holding %zu bytes", prevSize);
247dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim            }
248dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim        }
249dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim        mSkipCutBuffer = new SkipCutBuffer(skip, cut, channelCount);
250dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim    }
251dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim
252033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    DISALLOW_EVIL_CONSTRUCTORS(OutputBuffers);
253033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim};
254033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
255033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimnamespace {
256033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
257033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim// TODO: get this info from component
25860e4b7347394676287f7686ddced77544a106831Wonsik Kimconst static size_t kMinInputBufferArraySize = 8;
25960e4b7347394676287f7686ddced77544a106831Wonsik Kimconst static size_t kMinOutputBufferArraySize = 16;
2607037093412552e6dd8b5633e5e32a0d34c998d3aPawin Vongmasaconst static size_t kLinearBufferSize = 1048576;
261033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
262033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim/**
263033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim * Simple local buffer pool backed by std::vector.
264033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim */
265033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimclass LocalBufferPool : public std::enable_shared_from_this<LocalBufferPool> {
266033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimpublic:
267033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    /**
268033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     * Create a new LocalBufferPool object.
269033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     *
270033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     * \param poolCapacity  max total size of buffers managed by this pool.
271033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     *
272033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     * \return  a newly created pool object.
273033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     */
274033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    static std::shared_ptr<LocalBufferPool> Create(size_t poolCapacity) {
275033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return std::shared_ptr<LocalBufferPool>(new LocalBufferPool(poolCapacity));
276033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
277033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
278033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    /**
279033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     * Return an ABuffer object whose size is at least |capacity|.
280033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     *
281033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     * \param   capacity  requested capacity
282033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     * \return  nullptr if the pool capacity is reached
283033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     *          an ABuffer object otherwise.
284033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     */
285033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<ABuffer> newBuffer(size_t capacity) {
286033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutex::Autolock lock(mMutex);
287033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        auto it = std::find_if(
288033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                mPool.begin(), mPool.end(),
289033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                [capacity](const std::vector<uint8_t> &vec) {
290033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                    return vec.capacity() >= capacity;
291033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                });
292033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (it != mPool.end()) {
293033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            sp<ABuffer> buffer = new VectorBuffer(std::move(*it), shared_from_this());
294033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            mPool.erase(it);
295033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return buffer;
296033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
297033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (mUsedSize + capacity > mPoolCapacity) {
298033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            while (!mPool.empty()) {
299033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                mUsedSize -= mPool.back().capacity();
300033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                mPool.pop_back();
301033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            }
302033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            if (mUsedSize + capacity > mPoolCapacity) {
303033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                ALOGD("mUsedSize = %zu, capacity = %zu, mPoolCapacity = %zu",
304033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                        mUsedSize, capacity, mPoolCapacity);
305033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                return nullptr;
306033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            }
307033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
308033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        std::vector<uint8_t> vec(capacity);
309033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mUsedSize += vec.capacity();
310033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return new VectorBuffer(std::move(vec), shared_from_this());
311033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
312033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
313033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimprivate:
314033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    /**
315033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     * ABuffer backed by std::vector.
316033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     */
317033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    class VectorBuffer : public ::android::ABuffer {
318033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    public:
319033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        /**
320033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim         * Construct a VectorBuffer by taking the ownership of supplied vector.
321033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim         *
322033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim         * \param vec   backing vector of the buffer. this object takes
323033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim         *              ownership at construction.
324033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim         * \param pool  a LocalBufferPool object to return the vector at
325033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim         *              destruction.
326033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim         */
327033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        VectorBuffer(std::vector<uint8_t> &&vec, const std::shared_ptr<LocalBufferPool> &pool)
328033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            : ABuffer(vec.data(), vec.capacity()),
329033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim              mVec(std::move(vec)),
330033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim              mPool(pool) {
331033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
332033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
333033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        ~VectorBuffer() override {
334033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            std::shared_ptr<LocalBufferPool> pool = mPool.lock();
335033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            if (pool) {
336033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                // If pool is alive, return the vector back to the pool so that
337033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                // it can be recycled.
338033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                pool->returnVector(std::move(mVec));
339033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            }
340033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
341033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
342033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    private:
343033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        std::vector<uint8_t> mVec;
344033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        std::weak_ptr<LocalBufferPool> mPool;
345033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    };
346033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
347033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    Mutex mMutex;
348033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    size_t mPoolCapacity;
349033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    size_t mUsedSize;
350033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    std::list<std::vector<uint8_t>> mPool;
351033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
352033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    /**
353033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     * Private constructor to prevent constructing non-managed LocalBufferPool.
354033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     */
355033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    explicit LocalBufferPool(size_t poolCapacity)
356033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        : mPoolCapacity(poolCapacity), mUsedSize(0) {
357033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
358033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
359033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    /**
360033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     * Take back the ownership of vec from the destructed VectorBuffer and put
361033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     * it in front of the pool.
362033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     */
363033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    void returnVector(std::vector<uint8_t> &&vec) {
364033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutex::Autolock lock(mMutex);
365033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mPool.push_front(std::move(vec));
366033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
367033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
368033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    DISALLOW_EVIL_CONSTRUCTORS(LocalBufferPool);
369033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim};
370033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
371033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimsp<GraphicBlockBuffer> AllocateGraphicBuffer(
372033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        const std::shared_ptr<C2BlockPool> &pool,
373033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        const sp<AMessage> &format,
374033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        uint32_t pixelFormat,
375033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        const C2MemoryUsage &usage,
376033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        const std::shared_ptr<LocalBufferPool> &localBufferPool) {
377033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    int32_t width, height;
378033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (!format->findInt32("width", &width) || !format->findInt32("height", &height)) {
379033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        ALOGD("format lacks width or height");
380033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return nullptr;
381033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
382033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
383033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    std::shared_ptr<C2GraphicBlock> block;
384033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    c2_status_t err = pool->fetchGraphicBlock(
385033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            width, height, pixelFormat, usage, &block);
386033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (err != C2_OK) {
387033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        ALOGD("fetch graphic block failed: %d", err);
388033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return nullptr;
389033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
390033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
391033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    return GraphicBlockBuffer::Allocate(
392033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            format,
393033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            block,
394033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            [localBufferPool](size_t capacity) {
395033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                return localBufferPool->newBuffer(capacity);
396033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            });
397033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
398033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
399033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimclass BuffersArrayImpl;
400033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
401033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim/**
402033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim * Flexible buffer slots implementation.
403033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim */
404033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimclass FlexBuffersImpl {
405033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimpublic:
406033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    FlexBuffersImpl() = default;
407033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
408033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    /**
409033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     * Assign an empty slot for a buffer and return the index. If there's no
410033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     * empty slot, just add one at the end and return it.
411033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     *
412033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     * \param buffer[in]  a new buffer to assign a slot.
413033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     * \return            index of the assigned slot.
414033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     */
415033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    size_t assignSlot(const sp<Codec2Buffer> &buffer) {
416033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        for (size_t i = 0; i < mBuffers.size(); ++i) {
417d15ef3cef65de483190c1bd8458074ce7d064202Praveen Chavan            if (mBuffers[i].clientBuffer == nullptr
418033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                    && mBuffers[i].compBuffer.expired()) {
419033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                mBuffers[i].clientBuffer = buffer;
420033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                return i;
421033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            }
422033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
423033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mBuffers.push_back({ buffer, std::weak_ptr<C2Buffer>() });
424033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return mBuffers.size() - 1;
425033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
426033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
427033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    /**
428033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     * Release the slot from the client, and get the C2Buffer object back from
429033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     * the previously assigned buffer. Note that the slot is not completely free
430033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     * until the returned C2Buffer object is freed.
431033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     *
432e76dbb8207011ad23a2e3460c5672e7c250beae9Wonsik Kim     * \param   buffer[in]        the buffer previously assigned a slot.
433e76dbb8207011ad23a2e3460c5672e7c250beae9Wonsik Kim     * \param   c2buffer[in,out]  pointer to C2Buffer to be populated. Ignored
434e76dbb8207011ad23a2e3460c5672e7c250beae9Wonsik Kim     *                            if null.
435e76dbb8207011ad23a2e3460c5672e7c250beae9Wonsik Kim     * \return  true  if the buffer is successfully released from a slot
436e76dbb8207011ad23a2e3460c5672e7c250beae9Wonsik Kim     *          false otherwise
437033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     */
438e76dbb8207011ad23a2e3460c5672e7c250beae9Wonsik Kim    bool releaseSlot(const sp<MediaCodecBuffer> &buffer, std::shared_ptr<C2Buffer> *c2buffer) {
439e76dbb8207011ad23a2e3460c5672e7c250beae9Wonsik Kim        sp<Codec2Buffer> clientBuffer;
440033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        size_t index = mBuffers.size();
441033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        for (size_t i = 0; i < mBuffers.size(); ++i) {
442d15ef3cef65de483190c1bd8458074ce7d064202Praveen Chavan            if (mBuffers[i].clientBuffer == buffer) {
443e76dbb8207011ad23a2e3460c5672e7c250beae9Wonsik Kim                clientBuffer = mBuffers[i].clientBuffer;
444d15ef3cef65de483190c1bd8458074ce7d064202Praveen Chavan                mBuffers[i].clientBuffer.clear();
445033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                index = i;
446033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                break;
447033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            }
448033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
449e76dbb8207011ad23a2e3460c5672e7c250beae9Wonsik Kim        if (clientBuffer == nullptr) {
450a28531affe22ce6db653e09e7978730dbd1f068aWonsik Kim            ALOGV("%s: No matching buffer found", __func__);
451e76dbb8207011ad23a2e3460c5672e7c250beae9Wonsik Kim            return false;
452033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
453e76dbb8207011ad23a2e3460c5672e7c250beae9Wonsik Kim        std::shared_ptr<C2Buffer> result = clientBuffer->asC2Buffer();
454033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mBuffers[index].compBuffer = result;
455e76dbb8207011ad23a2e3460c5672e7c250beae9Wonsik Kim        if (c2buffer) {
456e76dbb8207011ad23a2e3460c5672e7c250beae9Wonsik Kim            *c2buffer = result;
457e76dbb8207011ad23a2e3460c5672e7c250beae9Wonsik Kim        }
458e76dbb8207011ad23a2e3460c5672e7c250beae9Wonsik Kim        return true;
459033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
460033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
461033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimprivate:
462033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    friend class BuffersArrayImpl;
463033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
464033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    struct Entry {
465d15ef3cef65de483190c1bd8458074ce7d064202Praveen Chavan        sp<Codec2Buffer> clientBuffer;
466033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        std::weak_ptr<C2Buffer> compBuffer;
467033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    };
468033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    std::vector<Entry> mBuffers;
469033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim};
470033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
471033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim/**
472033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim * Static buffer slots implementation based on a fixed-size array.
473033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim */
474033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimclass BuffersArrayImpl {
475033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimpublic:
476033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    /**
477033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     * Initialize buffer array from the original |impl|. The buffers known by
478033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     * the client is preserved, and the empty slots are populated so that the
479033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     * array size is at least |minSize|.
480033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     *
481033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     * \param impl[in]      FlexBuffersImpl object used so far.
482033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     * \param minSize[in]   minimum size of the buffer array.
483033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     * \param allocate[in]  function to allocate a client buffer for an empty slot.
484033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     */
485033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    void initialize(
486033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            const FlexBuffersImpl &impl,
487033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            size_t minSize,
488033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            std::function<sp<Codec2Buffer>()> allocate) {
489033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        for (size_t i = 0; i < impl.mBuffers.size(); ++i) {
490d15ef3cef65de483190c1bd8458074ce7d064202Praveen Chavan            sp<Codec2Buffer> clientBuffer = impl.mBuffers[i].clientBuffer;
491033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            bool ownedByClient = (clientBuffer != nullptr);
492033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            if (!ownedByClient) {
493033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                clientBuffer = allocate();
494033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            }
495033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            mBuffers.push_back({ clientBuffer, impl.mBuffers[i].compBuffer, ownedByClient });
496033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
497033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        for (size_t i = impl.mBuffers.size(); i < minSize; ++i) {
498033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            mBuffers.push_back({ allocate(), std::weak_ptr<C2Buffer>(), false });
499033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
500033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
501033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
502033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    /**
503033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     * Grab a buffer from the underlying array which matches the criteria.
504033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     *
505033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     * \param index[out]    index of the slot.
506033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     * \param buffer[out]   the matching buffer.
507033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     * \param match[in]     a function to test whether the buffer matches the
508033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     *                      criteria or not.
509033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     * \return OK           if successful,
510033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     *         NO_MEMORY    if there's no available slot meets the criteria.
511033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     */
512033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    status_t grabBuffer(
513033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            size_t *index,
514033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            sp<Codec2Buffer> *buffer,
515033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            std::function<bool(const sp<Codec2Buffer> &)> match =
516033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                [](const sp<Codec2Buffer> &) { return true; }) {
517033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        for (size_t i = 0; i < mBuffers.size(); ++i) {
518033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            if (!mBuffers[i].ownedByClient && mBuffers[i].compBuffer.expired()
519033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                    && match(mBuffers[i].clientBuffer)) {
520033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                mBuffers[i].ownedByClient = true;
521033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                *buffer = mBuffers[i].clientBuffer;
522033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                (*buffer)->meta()->clear();
523033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                (*buffer)->setRange(0, (*buffer)->capacity());
524033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                *index = i;
525033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                return OK;
526033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            }
527033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
528033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return NO_MEMORY;
529033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
530033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
531033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    /**
532033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     * Return the buffer from the client, and get the C2Buffer object back from
533033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     * the buffer. Note that the slot is not completely free until the returned
534033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     * C2Buffer object is freed.
535033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     *
536e76dbb8207011ad23a2e3460c5672e7c250beae9Wonsik Kim     * \param   buffer[in]        the buffer previously grabbed.
537e76dbb8207011ad23a2e3460c5672e7c250beae9Wonsik Kim     * \param   c2buffer[in,out]  pointer to C2Buffer to be populated. Ignored
538e76dbb8207011ad23a2e3460c5672e7c250beae9Wonsik Kim     *                            if null.
539e76dbb8207011ad23a2e3460c5672e7c250beae9Wonsik Kim     * \return  true  if the buffer is successfully returned
540e76dbb8207011ad23a2e3460c5672e7c250beae9Wonsik Kim     *          false otherwise
541033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     */
542e76dbb8207011ad23a2e3460c5672e7c250beae9Wonsik Kim    bool returnBuffer(const sp<MediaCodecBuffer> &buffer, std::shared_ptr<C2Buffer> *c2buffer) {
543e76dbb8207011ad23a2e3460c5672e7c250beae9Wonsik Kim        sp<Codec2Buffer> clientBuffer;
544033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        size_t index = mBuffers.size();
545033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        for (size_t i = 0; i < mBuffers.size(); ++i) {
546033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            if (mBuffers[i].clientBuffer == buffer) {
547033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                if (!mBuffers[i].ownedByClient) {
548033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                    ALOGD("Client returned a buffer it does not own according to our record: %zu", i);
549033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                }
550e76dbb8207011ad23a2e3460c5672e7c250beae9Wonsik Kim                clientBuffer = mBuffers[i].clientBuffer;
551033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                mBuffers[i].ownedByClient = false;
552033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                index = i;
553033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                break;
554033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            }
555033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
556e76dbb8207011ad23a2e3460c5672e7c250beae9Wonsik Kim        if (clientBuffer == nullptr) {
557a28531affe22ce6db653e09e7978730dbd1f068aWonsik Kim            ALOGV("%s: No matching buffer found", __func__);
558e76dbb8207011ad23a2e3460c5672e7c250beae9Wonsik Kim            return false;
559033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
56060e4b7347394676287f7686ddced77544a106831Wonsik Kim        ALOGV("%s: matching buffer found (index=%zu)", __func__, index);
561e76dbb8207011ad23a2e3460c5672e7c250beae9Wonsik Kim        std::shared_ptr<C2Buffer> result = clientBuffer->asC2Buffer();
562033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mBuffers[index].compBuffer = result;
563e76dbb8207011ad23a2e3460c5672e7c250beae9Wonsik Kim        if (c2buffer) {
564e76dbb8207011ad23a2e3460c5672e7c250beae9Wonsik Kim            *c2buffer = result;
565e76dbb8207011ad23a2e3460c5672e7c250beae9Wonsik Kim        }
566e76dbb8207011ad23a2e3460c5672e7c250beae9Wonsik Kim        return true;
567033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
568033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
569033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    /**
570033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     * Populate |array| with the underlying buffer array.
571033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     *
572033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     * \param array[out]  an array to be filled with the underlying buffer array.
573033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     */
574033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    void getArray(Vector<sp<MediaCodecBuffer>> *array) const {
575033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        array->clear();
576033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        for (const Entry &entry : mBuffers) {
577033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            array->push(entry.clientBuffer);
578033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
579033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
580033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
581033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    /**
582033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     * The client abandoned all known buffers, so reclaim the ownership.
583033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     */
584033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    void flush() {
585033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        for (Entry &entry : mBuffers) {
586033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            entry.ownedByClient = false;
587033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
588033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
589033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
590033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimprivate:
591033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    struct Entry {
592033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        const sp<Codec2Buffer> clientBuffer;
593033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        std::weak_ptr<C2Buffer> compBuffer;
594033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        bool ownedByClient;
595033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    };
596033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    std::vector<Entry> mBuffers;
597033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim};
598033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
599033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimclass InputBuffersArray : public CCodecBufferChannel::InputBuffers {
600033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimpublic:
601033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    InputBuffersArray() = default;
602033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    ~InputBuffersArray() override = default;
603033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
604033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    void initialize(
605033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            const FlexBuffersImpl &impl,
606033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            size_t minSize,
607033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            std::function<sp<Codec2Buffer>()> allocate) {
608033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mImpl.initialize(impl, minSize, allocate);
609033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
610033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
611033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    bool isArrayMode() const final { return true; }
612033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
613033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    std::unique_ptr<CCodecBufferChannel::InputBuffers> toArrayMode() final {
614033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return nullptr;
615033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
616033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
617033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    void getArray(Vector<sp<MediaCodecBuffer>> *array) const final {
618033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mImpl.getArray(array);
619033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
620033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
621033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    bool requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) override {
622033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        sp<Codec2Buffer> c2Buffer;
623033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        status_t err = mImpl.grabBuffer(index, &c2Buffer);
624033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (err == OK) {
625033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            c2Buffer->setFormat(mFormat);
626033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            *buffer = c2Buffer;
627033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return true;
628033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
629033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return false;
630033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
631033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
632e76dbb8207011ad23a2e3460c5672e7c250beae9Wonsik Kim    bool releaseBuffer(
633e76dbb8207011ad23a2e3460c5672e7c250beae9Wonsik Kim            const sp<MediaCodecBuffer> &buffer, std::shared_ptr<C2Buffer> *c2buffer) override {
634e76dbb8207011ad23a2e3460c5672e7c250beae9Wonsik Kim        return mImpl.returnBuffer(buffer, c2buffer);
635033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
636033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
637033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    void flush() override {
638033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mImpl.flush();
639033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
640033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
641033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimprivate:
642033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    BuffersArrayImpl mImpl;
643033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim};
644033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
645033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimclass LinearInputBuffers : public CCodecBufferChannel::InputBuffers {
646033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimpublic:
647033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    using CCodecBufferChannel::InputBuffers::InputBuffers;
648033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
649033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    bool requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) override {
650a00de0de4f172b294f286460292dc4a99f9dda67Lajos Molnar        int32_t capacity = kLinearBufferSize;
6510fde62fab8b7a8802e4c8fbe8007f41af9dfcf9bLajos Molnar        (void)mFormat->findInt32(KEY_MAX_INPUT_SIZE, &capacity);
652033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        // TODO: proper max input size
653033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        // TODO: read usage from intf
654a00de0de4f172b294f286460292dc4a99f9dda67Lajos Molnar        sp<Codec2Buffer> newBuffer = alloc((size_t)capacity);
655033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (newBuffer == nullptr) {
656033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return false;
657033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
658033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        *index = mImpl.assignSlot(newBuffer);
659033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        *buffer = newBuffer;
660033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return true;
661033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
662033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
663e76dbb8207011ad23a2e3460c5672e7c250beae9Wonsik Kim    bool releaseBuffer(
664e76dbb8207011ad23a2e3460c5672e7c250beae9Wonsik Kim            const sp<MediaCodecBuffer> &buffer, std::shared_ptr<C2Buffer> *c2buffer) override {
665e76dbb8207011ad23a2e3460c5672e7c250beae9Wonsik Kim        return mImpl.releaseSlot(buffer, c2buffer);
666033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
667033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
668033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    void flush() override {
669033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        // This is no-op by default unless we're in array mode where we need to keep
670033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        // track of the flushed work.
671033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
672033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
673033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    std::unique_ptr<CCodecBufferChannel::InputBuffers> toArrayMode() final {
674a28531affe22ce6db653e09e7978730dbd1f068aWonsik Kim        int32_t capacity = kLinearBufferSize;
675a28531affe22ce6db653e09e7978730dbd1f068aWonsik Kim        (void)mFormat->findInt32(C2_NAME_STREAM_MAX_BUFFER_SIZE_SETTING, &capacity);
676a28531affe22ce6db653e09e7978730dbd1f068aWonsik Kim
677033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        std::unique_ptr<InputBuffersArray> array(new InputBuffersArray);
678748591ac668738ca7fa0655656d45ce4327fd05fWonsik Kim        array->setPool(mPool);
679033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        array->setFormat(mFormat);
680033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        array->initialize(
681033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                mImpl,
68260e4b7347394676287f7686ddced77544a106831Wonsik Kim                kMinInputBufferArraySize,
683a28531affe22ce6db653e09e7978730dbd1f068aWonsik Kim                [this, capacity] () -> sp<Codec2Buffer> { return alloc(capacity); });
684033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return std::move(array);
685033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
686033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
687033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    virtual sp<Codec2Buffer> alloc(size_t size) const {
688033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
689033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        std::shared_ptr<C2LinearBlock> block;
690033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
691033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        c2_status_t err = mPool->fetchLinearBlock(size, usage, &block);
692033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (err != C2_OK) {
693033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return nullptr;
694033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
695033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
696033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return LinearBlockBuffer::Allocate(mFormat, block);
697033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
698033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
699033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimprivate:
700033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    FlexBuffersImpl mImpl;
701033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim};
702033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
703033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimclass EncryptedLinearInputBuffers : public LinearInputBuffers {
704033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimpublic:
705033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    EncryptedLinearInputBuffers(
706033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            bool secure,
707033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            const sp<MemoryDealer> &dealer,
708033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            const sp<ICrypto> &crypto,
709033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            int32_t heapSeqNum)
710033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        : mUsage({0, 0}),
711033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim          mDealer(dealer),
712033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim          mCrypto(crypto),
713033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim          mHeapSeqNum(heapSeqNum) {
714033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (secure) {
715033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            mUsage = { C2MemoryUsage::READ_PROTECTED, 0 };
716033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        } else {
717033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            mUsage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
718033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
71960e4b7347394676287f7686ddced77544a106831Wonsik Kim        for (size_t i = 0; i < kMinInputBufferArraySize; ++i) {
720033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            sp<IMemory> memory = mDealer->allocate(kLinearBufferSize);
721033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            if (memory == nullptr) {
722033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                ALOGD("Failed to allocate memory from dealer: only %zu slots allocated", i);
723033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                break;
724033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            }
725033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            mMemoryVector.push_back({std::weak_ptr<C2LinearBlock>(), memory});
726033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
727033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
728033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
729033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    ~EncryptedLinearInputBuffers() override {
730033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
731033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
732033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<Codec2Buffer> alloc(size_t size) const override {
733033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        sp<IMemory> memory;
734033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        for (const Entry &entry : mMemoryVector) {
735033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            if (entry.block.expired()) {
736033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                memory = entry.memory;
737033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                break;
738033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            }
739033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
740033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (memory == nullptr) {
741033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return nullptr;
742033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
743033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
744033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        std::shared_ptr<C2LinearBlock> block;
745033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        c2_status_t err = mPool->fetchLinearBlock(size, mUsage, &block);
746033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (err != C2_OK) {
747033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return nullptr;
748033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
749033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
750033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return new EncryptedLinearBlockBuffer(mFormat, block, memory, mHeapSeqNum);
751033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
752033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
753033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimprivate:
754033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    C2MemoryUsage mUsage;
755033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<MemoryDealer> mDealer;
756033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<ICrypto> mCrypto;
757033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    int32_t mHeapSeqNum;
758033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    struct Entry {
759033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        std::weak_ptr<C2LinearBlock> block;
760033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        sp<IMemory> memory;
761033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    };
762033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    std::vector<Entry> mMemoryVector;
763033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim};
764033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
765f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kimclass GraphicMetadataInputBuffers : public CCodecBufferChannel::InputBuffers {
766f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kimpublic:
767f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim    GraphicMetadataInputBuffers() : mStore(GetCodec2PlatformAllocatorStore()) {}
768f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim    ~GraphicMetadataInputBuffers() override = default;
769f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim
770f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim    bool requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) override {
771f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim        std::shared_ptr<C2Allocator> alloc;
772f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim        c2_status_t err = mStore->fetchAllocator(mPool->getAllocatorId(), &alloc);
773f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim        if (err != C2_OK) {
774f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim            return false;
775f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim        }
776f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim        sp<GraphicMetadataBuffer> newBuffer = new GraphicMetadataBuffer(mFormat, alloc);
777f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim        if (newBuffer == nullptr) {
778f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim            return false;
779f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim        }
780f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim        *index = mImpl.assignSlot(newBuffer);
781f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim        *buffer = newBuffer;
782f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim        return true;
783f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim    }
784f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim
785e76dbb8207011ad23a2e3460c5672e7c250beae9Wonsik Kim    bool releaseBuffer(
786e76dbb8207011ad23a2e3460c5672e7c250beae9Wonsik Kim            const sp<MediaCodecBuffer> &buffer, std::shared_ptr<C2Buffer> *c2buffer) override {
787e76dbb8207011ad23a2e3460c5672e7c250beae9Wonsik Kim        return mImpl.releaseSlot(buffer, c2buffer);
788f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim    }
789f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim
790f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim    void flush() override {
791f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim        // This is no-op by default unless we're in array mode where we need to keep
792f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim        // track of the flushed work.
793f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim    }
794f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim
795f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim    std::unique_ptr<CCodecBufferChannel::InputBuffers> toArrayMode() final {
796f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim        std::shared_ptr<C2Allocator> alloc;
797f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim        c2_status_t err = mStore->fetchAllocator(mPool->getAllocatorId(), &alloc);
798f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim        if (err != C2_OK) {
799f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim            return nullptr;
800f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim        }
801f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim        std::unique_ptr<InputBuffersArray> array(new InputBuffersArray);
802748591ac668738ca7fa0655656d45ce4327fd05fWonsik Kim        array->setPool(mPool);
803f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim        array->setFormat(mFormat);
804f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim        array->initialize(
805f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim                mImpl,
80660e4b7347394676287f7686ddced77544a106831Wonsik Kim                kMinInputBufferArraySize,
807f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim                [format = mFormat, alloc]() -> sp<Codec2Buffer> {
808f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim                    return new GraphicMetadataBuffer(format, alloc);
809f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim                });
810f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim        return std::move(array);
811f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim    }
812f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim
813f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kimprivate:
814f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim    FlexBuffersImpl mImpl;
815f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim    std::shared_ptr<C2AllocatorStore> mStore;
816f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim};
817f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim
818033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimclass GraphicInputBuffers : public CCodecBufferChannel::InputBuffers {
819033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimpublic:
82060e4b7347394676287f7686ddced77544a106831Wonsik Kim    GraphicInputBuffers()
82160e4b7347394676287f7686ddced77544a106831Wonsik Kim        : mLocalBufferPool(LocalBufferPool::Create(1920 * 1080 * 4 * 16)) {
82260e4b7347394676287f7686ddced77544a106831Wonsik Kim    }
823033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    ~GraphicInputBuffers() override = default;
824033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
825033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    bool requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) override {
826033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        // TODO: proper max input size
827033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        // TODO: read usage from intf
828033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
829033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        sp<GraphicBlockBuffer> newBuffer = AllocateGraphicBuffer(
830033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                mPool, mFormat, HAL_PIXEL_FORMAT_YV12, usage, mLocalBufferPool);
831033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (newBuffer == nullptr) {
832033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return false;
833033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
834033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        *index = mImpl.assignSlot(newBuffer);
835033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        *buffer = newBuffer;
836033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return true;
837033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
838033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
839e76dbb8207011ad23a2e3460c5672e7c250beae9Wonsik Kim    bool releaseBuffer(
840e76dbb8207011ad23a2e3460c5672e7c250beae9Wonsik Kim            const sp<MediaCodecBuffer> &buffer, std::shared_ptr<C2Buffer> *c2buffer) override {
841e76dbb8207011ad23a2e3460c5672e7c250beae9Wonsik Kim        return mImpl.releaseSlot(buffer, c2buffer);
842033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
843033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
844033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    void flush() override {
845033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        // This is no-op by default unless we're in array mode where we need to keep
846033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        // track of the flushed work.
847033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
848033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
849033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    std::unique_ptr<CCodecBufferChannel::InputBuffers> toArrayMode() final {
850033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        std::unique_ptr<InputBuffersArray> array(new InputBuffersArray);
851748591ac668738ca7fa0655656d45ce4327fd05fWonsik Kim        array->setPool(mPool);
852033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        array->setFormat(mFormat);
853033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        array->initialize(
854033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                mImpl,
85560e4b7347394676287f7686ddced77544a106831Wonsik Kim                kMinInputBufferArraySize,
856033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                [pool = mPool, format = mFormat, lbp = mLocalBufferPool]() -> sp<Codec2Buffer> {
857033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                    C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
858033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                    return AllocateGraphicBuffer(
859033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                            pool, format, HAL_PIXEL_FORMAT_YV12, usage, lbp);
860033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                });
861033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return std::move(array);
862033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
863033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
864033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimprivate:
865033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    FlexBuffersImpl mImpl;
866033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    std::shared_ptr<LocalBufferPool> mLocalBufferPool;
867033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim};
868033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
869033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimclass DummyInputBuffers : public CCodecBufferChannel::InputBuffers {
870033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimpublic:
871033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    DummyInputBuffers() = default;
872033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
873033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    bool requestNewBuffer(size_t *, sp<MediaCodecBuffer> *) override {
874033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return false;
875033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
876033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
877e76dbb8207011ad23a2e3460c5672e7c250beae9Wonsik Kim    bool releaseBuffer(
878e76dbb8207011ad23a2e3460c5672e7c250beae9Wonsik Kim            const sp<MediaCodecBuffer> &, std::shared_ptr<C2Buffer> *) override {
879e76dbb8207011ad23a2e3460c5672e7c250beae9Wonsik Kim        return false;
880033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
881033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
882033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    void flush() override {
883033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
884033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
885033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    std::unique_ptr<CCodecBufferChannel::InputBuffers> toArrayMode() final {
886033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return nullptr;
887033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
888033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
889033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    bool isArrayMode() const final { return true; }
890033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
891033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    void getArray(Vector<sp<MediaCodecBuffer>> *array) const final {
892033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        array->clear();
893033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
894033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim};
895033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
896033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimclass OutputBuffersArray : public CCodecBufferChannel::OutputBuffers {
897033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimpublic:
898033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    OutputBuffersArray() = default;
899033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    ~OutputBuffersArray() override = default;
900033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
901033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    void initialize(
902033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            const FlexBuffersImpl &impl,
903033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            size_t minSize,
904033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            std::function<sp<Codec2Buffer>()> allocate) {
905033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mImpl.initialize(impl, minSize, allocate);
906033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
907033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
908033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    bool isArrayMode() const final { return true; }
909033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
910033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    std::unique_ptr<CCodecBufferChannel::OutputBuffers> toArrayMode() final {
911033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return nullptr;
912033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
913033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
914033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    bool registerBuffer(
915033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            const std::shared_ptr<C2Buffer> &buffer,
916033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            size_t *index,
917033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            sp<MediaCodecBuffer> *clientBuffer) final {
918033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        sp<Codec2Buffer> c2Buffer;
919033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        status_t err = mImpl.grabBuffer(
920033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                index,
921033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                &c2Buffer,
922033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                [buffer](const sp<Codec2Buffer> &clientBuffer) {
923033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                    return clientBuffer->canCopy(buffer);
924033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                });
925033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (err != OK) {
926033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            ALOGD("grabBuffer failed: %d", err);
927033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return false;
928033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
929033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        c2Buffer->setFormat(mFormat);
930033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (!c2Buffer->copy(buffer)) {
931033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            ALOGD("copy buffer failed");
932033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return false;
933033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
934dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim        submit(c2Buffer);
935033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        *clientBuffer = c2Buffer;
936033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return true;
937033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
938033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
939033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    bool registerCsd(
940033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            const C2StreamCsdInfo::output *csd,
941033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            size_t *index,
942033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            sp<MediaCodecBuffer> *clientBuffer) final {
943033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        sp<Codec2Buffer> c2Buffer;
944033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        status_t err = mImpl.grabBuffer(
945033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                index,
946033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                &c2Buffer,
947033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                [csd](const sp<Codec2Buffer> &clientBuffer) {
948033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                    return clientBuffer->base() != nullptr
949033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                            && clientBuffer->capacity() >= csd->flexCount();
950033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                });
951033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (err != OK) {
952033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return false;
953033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
954033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        memcpy(c2Buffer->base(), csd->m.value, csd->flexCount());
955033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        c2Buffer->setRange(0, csd->flexCount());
956033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        c2Buffer->setFormat(mFormat);
957033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        *clientBuffer = c2Buffer;
958033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return true;
959033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
960033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
961e76dbb8207011ad23a2e3460c5672e7c250beae9Wonsik Kim    bool releaseBuffer(
962e76dbb8207011ad23a2e3460c5672e7c250beae9Wonsik Kim            const sp<MediaCodecBuffer> &buffer, std::shared_ptr<C2Buffer> *c2buffer) override {
963e76dbb8207011ad23a2e3460c5672e7c250beae9Wonsik Kim        return mImpl.returnBuffer(buffer, c2buffer);
964033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
965033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
966033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    void flush(const std::list<std::unique_ptr<C2Work>> &flushedWork) override {
967dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim        (void)flushedWork;
968033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mImpl.flush();
969dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim        if (mSkipCutBuffer != nullptr) {
970dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim            mSkipCutBuffer->clear();
971dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim        }
972033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
973033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
974033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    void getArray(Vector<sp<MediaCodecBuffer>> *array) const final {
975033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mImpl.getArray(array);
976033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
977033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
978033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimprivate:
979033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    BuffersArrayImpl mImpl;
980033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim};
981033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
982033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimclass FlexOutputBuffers : public CCodecBufferChannel::OutputBuffers {
983033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimpublic:
984033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    using CCodecBufferChannel::OutputBuffers::OutputBuffers;
985033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
986033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    bool registerBuffer(
987033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            const std::shared_ptr<C2Buffer> &buffer,
988033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            size_t *index,
989033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            sp<MediaCodecBuffer> *clientBuffer) override {
990033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        sp<Codec2Buffer> newBuffer = wrap(buffer);
991033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        newBuffer->setFormat(mFormat);
992033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        *index = mImpl.assignSlot(newBuffer);
993033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        *clientBuffer = newBuffer;
994033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return true;
995033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
996033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
997033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    bool registerCsd(
998033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            const C2StreamCsdInfo::output *csd,
999033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            size_t *index,
1000033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            sp<MediaCodecBuffer> *clientBuffer) final {
10018c90d948d154ccf81c4a7113f3aefbe329ce6e8dWonsik Kim        sp<Codec2Buffer> newBuffer = new LocalLinearBuffer(
10028c90d948d154ccf81c4a7113f3aefbe329ce6e8dWonsik Kim                mFormat, ABuffer::CreateAsCopy(csd->m.value, csd->flexCount()));
1003033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        *index = mImpl.assignSlot(newBuffer);
1004033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        *clientBuffer = newBuffer;
1005033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return true;
1006033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
1007033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1008e76dbb8207011ad23a2e3460c5672e7c250beae9Wonsik Kim    bool releaseBuffer(
1009e76dbb8207011ad23a2e3460c5672e7c250beae9Wonsik Kim            const sp<MediaCodecBuffer> &buffer, std::shared_ptr<C2Buffer> *c2buffer) override {
1010e76dbb8207011ad23a2e3460c5672e7c250beae9Wonsik Kim        return mImpl.releaseSlot(buffer, c2buffer);
1011033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
1012033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1013033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    void flush(
1014033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            const std::list<std::unique_ptr<C2Work>> &flushedWork) override {
1015033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        (void) flushedWork;
1016033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        // This is no-op by default unless we're in array mode where we need to keep
1017033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        // track of the flushed work.
1018033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
1019033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1020033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    std::unique_ptr<CCodecBufferChannel::OutputBuffers> toArrayMode() override {
1021033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        std::unique_ptr<OutputBuffersArray> array(new OutputBuffersArray);
1022033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        array->setFormat(mFormat);
1023dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim        array->transferSkipCutBuffer(mSkipCutBuffer);
1024033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        array->initialize(
1025033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                mImpl,
102660e4b7347394676287f7686ddced77544a106831Wonsik Kim                kMinOutputBufferArraySize,
1027033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                [this]() { return allocateArrayBuffer(); });
1028033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return std::move(array);
1029033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
1030033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1031033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    /**
1032033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     * Return an appropriate Codec2Buffer object for the type of buffers.
1033033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     *
1034033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     * \param buffer  C2Buffer object to wrap.
1035033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     *
1036033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     * \return  appropriate Codec2Buffer object to wrap |buffer|.
1037033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     */
1038033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    virtual sp<Codec2Buffer> wrap(const std::shared_ptr<C2Buffer> &buffer) = 0;
1039033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1040033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    /**
1041033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     * Return an appropriate Codec2Buffer object for the type of buffers, to be
1042033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     * used as an empty array buffer.
1043033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     *
1044033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     * \return  appropriate Codec2Buffer object which can copy() from C2Buffers.
1045033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     */
1046033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    virtual sp<Codec2Buffer> allocateArrayBuffer() = 0;
1047033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1048033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimprivate:
1049033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    FlexBuffersImpl mImpl;
1050033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim};
1051033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1052033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimclass LinearOutputBuffers : public FlexOutputBuffers {
1053033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimpublic:
1054033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    using FlexOutputBuffers::FlexOutputBuffers;
1055033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1056dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim    void flush(
1057dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim            const std::list<std::unique_ptr<C2Work>> &flushedWork) override {
1058dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim        if (mSkipCutBuffer != nullptr) {
1059dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim            mSkipCutBuffer->clear();
1060dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim        }
1061dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim        FlexOutputBuffers::flush(flushedWork);
1062dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim    }
1063dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim
1064033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<Codec2Buffer> wrap(const std::shared_ptr<C2Buffer> &buffer) override {
1065033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (buffer == nullptr) {
10664bf68ce16bfd972d0ab242a27c5c258d7e1eb768Lajos Molnar            return new LocalLinearBuffer(mFormat, new ABuffer(0));
1067033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
1068033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (buffer->data().type() != C2BufferData::LINEAR) {
1069033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            // We expect linear output buffers from the component.
1070033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return nullptr;
1071033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
1072033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (buffer->data().linearBlocks().size() != 1u) {
1073033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            // We expect one and only one linear block from the component.
1074033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return nullptr;
1075033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
1076dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim        sp<Codec2Buffer> clientBuffer = ConstLinearBlockBuffer::Allocate(mFormat, buffer);
1077dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim        submit(clientBuffer);
1078dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim        return clientBuffer;
1079033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
1080033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1081033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<Codec2Buffer> allocateArrayBuffer() override {
1082033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        // TODO: proper max output size
1083033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return new LocalLinearBuffer(mFormat, new ABuffer(kLinearBufferSize));
1084033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
1085033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim};
1086033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1087033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimclass GraphicOutputBuffers : public FlexOutputBuffers {
1088033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimpublic:
1089033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    using FlexOutputBuffers::FlexOutputBuffers;
1090033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1091033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<Codec2Buffer> wrap(const std::shared_ptr<C2Buffer> &buffer) override {
1092033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return new DummyContainerBuffer(mFormat, buffer);
1093033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
1094033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1095033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<Codec2Buffer> allocateArrayBuffer() override {
1096033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return new DummyContainerBuffer(mFormat);
1097033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
1098033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim};
1099033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1100033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimclass RawGraphicOutputBuffers : public FlexOutputBuffers {
1101033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimpublic:
1102033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    RawGraphicOutputBuffers()
1103e76dbb8207011ad23a2e3460c5672e7c250beae9Wonsik Kim        : mLocalBufferPool(LocalBufferPool::Create(1920 * 1080 * 4 * 16)) {
1104033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
1105033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    ~RawGraphicOutputBuffers() override = default;
1106033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1107033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<Codec2Buffer> wrap(const std::shared_ptr<C2Buffer> &buffer) override {
1108e87246ce7b1359ca09153607d0af8663c61ede96Lajos Molnar        if (buffer == nullptr) {
1109e87246ce7b1359ca09153607d0af8663c61ede96Lajos Molnar            return ConstGraphicBlockBuffer::AllocateEmpty(
1110e87246ce7b1359ca09153607d0af8663c61ede96Lajos Molnar                    mFormat,
1111e87246ce7b1359ca09153607d0af8663c61ede96Lajos Molnar                    [lbp = mLocalBufferPool](size_t capacity) {
1112e87246ce7b1359ca09153607d0af8663c61ede96Lajos Molnar                        return lbp->newBuffer(capacity);
1113e87246ce7b1359ca09153607d0af8663c61ede96Lajos Molnar                    });
1114e87246ce7b1359ca09153607d0af8663c61ede96Lajos Molnar        } else {
1115e87246ce7b1359ca09153607d0af8663c61ede96Lajos Molnar            return ConstGraphicBlockBuffer::Allocate(
1116e87246ce7b1359ca09153607d0af8663c61ede96Lajos Molnar                    mFormat,
1117e87246ce7b1359ca09153607d0af8663c61ede96Lajos Molnar                    buffer,
1118e87246ce7b1359ca09153607d0af8663c61ede96Lajos Molnar                    [lbp = mLocalBufferPool](size_t capacity) {
1119e87246ce7b1359ca09153607d0af8663c61ede96Lajos Molnar                        return lbp->newBuffer(capacity);
1120e87246ce7b1359ca09153607d0af8663c61ede96Lajos Molnar                    });
1121e87246ce7b1359ca09153607d0af8663c61ede96Lajos Molnar        }
1122033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
1123033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1124033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<Codec2Buffer> allocateArrayBuffer() override {
1125033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return ConstGraphicBlockBuffer::AllocateEmpty(
1126033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                mFormat,
1127033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                [lbp = mLocalBufferPool](size_t capacity) {
1128033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                    return lbp->newBuffer(capacity);
1129033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                });
1130033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
1131033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1132033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimprivate:
1133033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    std::shared_ptr<LocalBufferPool> mLocalBufferPool;
1134033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim};
1135033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1136033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}  // namespace
1137033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1138033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik KimCCodecBufferChannel::QueueGuard::QueueGuard(
1139033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        CCodecBufferChannel::QueueSync &sync) : mSync(sync) {
1140033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    std::unique_lock<std::mutex> l(mSync.mMutex);
1141033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    // At this point it's guaranteed that mSync is not under state transition,
1142033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    // as we are holding its mutex.
1143033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (mSync.mCount == -1) {
1144033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mRunning = false;
1145033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    } else {
1146033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        ++mSync.mCount;
1147033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mRunning = true;
1148033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
1149033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
1150033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1151033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik KimCCodecBufferChannel::QueueGuard::~QueueGuard() {
1152033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (mRunning) {
1153033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        // We are not holding mutex at this point so that QueueSync::stop() can
1154033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        // keep holding the lock until mCount reaches zero.
1155033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        --mSync.mCount;
1156033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
1157033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
1158033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1159033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodecBufferChannel::QueueSync::start() {
1160033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    std::unique_lock<std::mutex> l(mMutex);
1161033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    // If stopped, it goes to running state; otherwise no-op.
1162033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    int32_t expected = -1;
1163033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    (void)mCount.compare_exchange_strong(expected, 0);
1164033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
1165033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1166033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodecBufferChannel::QueueSync::stop() {
1167033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    std::unique_lock<std::mutex> l(mMutex);
1168033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (mCount == -1) {
1169033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        // no-op
1170033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
1171033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
1172033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    // Holding mutex here blocks creation of additional QueueGuard objects, so
1173033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    // mCount can only decrement. In other words, threads that acquired the lock
1174033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    // are allowed to finish execution but additional threads trying to acquire
1175033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    // the lock at this point will block, and then get QueueGuard at STOPPED
1176033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    // state.
1177033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    int32_t expected = 0;
1178033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    while (!mCount.compare_exchange_weak(expected, -1)) {
1179033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        std::this_thread::yield();
1180033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
1181033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
1182033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1183033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik KimCCodecBufferChannel::CCodecBufferChannel(
1184384b6a0bcf56a6cdc81fad923fc4695027fa42ddWonsik Kim        const std::shared_ptr<CCodecCallback> &callback)
1185033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    : mHeapSeqNum(-1),
1186384b6a0bcf56a6cdc81fad923fc4695027fa42ddWonsik Kim      mCCodecCallback(callback),
1187033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim      mFrameIndex(0u),
11888060cb241e5091bc325599b0d609fd36360942e9Sungtak Lee      mFirstValidFrameIndex(0u),
1189c2088887496fa8627e0a2a4e713f413301065516Wonsik Kim      mMetaMode(MODE_NONE),
1190c2088887496fa8627e0a2a4e713f413301065516Wonsik Kim      mPendingFeed(0) {
1191033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
1192033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1193033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik KimCCodecBufferChannel::~CCodecBufferChannel() {
1194033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (mCrypto != nullptr && mDealer != nullptr && mHeapSeqNum >= 0) {
1195033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mCrypto->unsetHeap(mHeapSeqNum);
1196033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
1197033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
1198033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
11990f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasavoid CCodecBufferChannel::setComponent(
12000f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa        const std::shared_ptr<Codec2Client::Component> &component) {
1201033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mComponent = component;
1202033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
1203033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1204033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimstatus_t CCodecBufferChannel::setInputSurface(
1205033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        const std::shared_ptr<InputSurfaceWrapper> &surface) {
1206033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    ALOGV("setInputSurface");
1207033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mInputSurface = surface;
1208f61123c4e697e9d1d437b4e318636e5789ea85c0Wonsik Kim    return mInputSurface->connect(mComponent);
1209033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
1210033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
12117a702c9f08c57f64121149e3e233cbe8fcf4dc36Wonsik Kimstatus_t CCodecBufferChannel::signalEndOfInputStream() {
12127a702c9f08c57f64121149e3e233cbe8fcf4dc36Wonsik Kim    if (mInputSurface == nullptr) {
12137a702c9f08c57f64121149e3e233cbe8fcf4dc36Wonsik Kim        return INVALID_OPERATION;
12147a702c9f08c57f64121149e3e233cbe8fcf4dc36Wonsik Kim    }
12157a702c9f08c57f64121149e3e233cbe8fcf4dc36Wonsik Kim    return mInputSurface->signalEndOfInputStream();
12167a702c9f08c57f64121149e3e233cbe8fcf4dc36Wonsik Kim}
12177a702c9f08c57f64121149e3e233cbe8fcf4dc36Wonsik Kim
1218033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimstatus_t CCodecBufferChannel::queueInputBufferInternal(const sp<MediaCodecBuffer> &buffer) {
1219033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    int64_t timeUs;
1220033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
1221033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1222033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    int32_t flags = 0;
1223033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    int32_t tmp = 0;
1224585b02290e1dc5c0fb6a635ce19d9ec785dbf60aWonsik Kim    bool eos = false;
1225033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (buffer->meta()->findInt32("eos", &tmp) && tmp) {
1226585b02290e1dc5c0fb6a635ce19d9ec785dbf60aWonsik Kim        eos = true;
1227033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        ALOGV("input EOS");
1228033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
1229033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (buffer->meta()->findInt32("csd", &tmp) && tmp) {
1230033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        flags |= C2FrameData::FLAG_CODEC_CONFIG;
1231033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
1232033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    ALOGV("queueInputBuffer: buffer->size() = %zu", buffer->size());
1233033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    std::unique_ptr<C2Work> work(new C2Work);
1234033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    work->input.ordinal.timestamp = timeUs;
1235033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    work->input.ordinal.frameIndex = mFrameIndex++;
1236033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    work->input.buffers.clear();
123771bf09f2e99c1916e43fd4228889c4edba54c97dWonsik Kim    if (buffer->size() > 0u) {
1238033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<std::unique_ptr<InputBuffers>>::Locked buffers(mInputBuffers);
1239e76dbb8207011ad23a2e3460c5672e7c250beae9Wonsik Kim        std::shared_ptr<C2Buffer> c2buffer;
1240e76dbb8207011ad23a2e3460c5672e7c250beae9Wonsik Kim        if (!(*buffers)->releaseBuffer(buffer, &c2buffer)) {
1241033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return -ENOENT;
1242033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
1243033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        work->input.buffers.push_back(c2buffer);
1244585b02290e1dc5c0fb6a635ce19d9ec785dbf60aWonsik Kim    } else if (eos) {
1245585b02290e1dc5c0fb6a635ce19d9ec785dbf60aWonsik Kim        flags |= C2FrameData::FLAG_END_OF_STREAM;
1246033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
1247585b02290e1dc5c0fb6a635ce19d9ec785dbf60aWonsik Kim    work->input.flags = (C2FrameData::flags_t)flags;
1248033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    // TODO: fill info's
1249033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1250033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    work->worklets.clear();
1251033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    work->worklets.emplace_back(new C2Worklet);
1252033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1253033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    std::list<std::unique_ptr<C2Work>> items;
1254033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    items.push_back(std::move(work));
1255c2088887496fa8627e0a2a4e713f413301065516Wonsik Kim    c2_status_t err = mComponent->queue(&items);
1256585b02290e1dc5c0fb6a635ce19d9ec785dbf60aWonsik Kim
1257585b02290e1dc5c0fb6a635ce19d9ec785dbf60aWonsik Kim    if (err == C2_OK && eos && buffer->size() > 0u) {
1258585b02290e1dc5c0fb6a635ce19d9ec785dbf60aWonsik Kim        work.reset(new C2Work);
1259585b02290e1dc5c0fb6a635ce19d9ec785dbf60aWonsik Kim        work->input.ordinal.timestamp = timeUs;
1260585b02290e1dc5c0fb6a635ce19d9ec785dbf60aWonsik Kim        work->input.ordinal.frameIndex = mFrameIndex++;
1261585b02290e1dc5c0fb6a635ce19d9ec785dbf60aWonsik Kim        work->input.buffers.clear();
1262585b02290e1dc5c0fb6a635ce19d9ec785dbf60aWonsik Kim        work->input.flags = C2FrameData::FLAG_END_OF_STREAM;
1263585b02290e1dc5c0fb6a635ce19d9ec785dbf60aWonsik Kim
1264585b02290e1dc5c0fb6a635ce19d9ec785dbf60aWonsik Kim        items.clear();
1265585b02290e1dc5c0fb6a635ce19d9ec785dbf60aWonsik Kim        items.push_back(std::move(work));
1266585b02290e1dc5c0fb6a635ce19d9ec785dbf60aWonsik Kim        err = mComponent->queue(&items);
1267585b02290e1dc5c0fb6a635ce19d9ec785dbf60aWonsik Kim    }
1268585b02290e1dc5c0fb6a635ce19d9ec785dbf60aWonsik Kim
1269c2088887496fa8627e0a2a4e713f413301065516Wonsik Kim    feedInputBufferIfAvailableInternal();
1270c2088887496fa8627e0a2a4e713f413301065516Wonsik Kim    return err;
1271033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
1272033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1273033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimstatus_t CCodecBufferChannel::queueInputBuffer(const sp<MediaCodecBuffer> &buffer) {
1274033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    QueueGuard guard(mSync);
1275033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (!guard.isRunning()) {
1276033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        ALOGW("No more buffers should be queued at current state.");
1277033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return -ENOSYS;
1278033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
1279033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    return queueInputBufferInternal(buffer);
1280033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
1281033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1282033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimstatus_t CCodecBufferChannel::queueSecureInputBuffer(
1283033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        const sp<MediaCodecBuffer> &buffer, bool secure, const uint8_t *key,
1284033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        const uint8_t *iv, CryptoPlugin::Mode mode, CryptoPlugin::Pattern pattern,
1285033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        const CryptoPlugin::SubSample *subSamples, size_t numSubSamples,
1286033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        AString *errorDetailMsg) {
1287033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    QueueGuard guard(mSync);
1288033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (!guard.isRunning()) {
1289033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        ALOGW("No more buffers should be queued at current state.");
1290033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return -ENOSYS;
1291033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
1292033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1293033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (!hasCryptoOrDescrambler()) {
1294033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return -ENOSYS;
1295033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
1296033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<EncryptedLinearBlockBuffer> encryptedBuffer((EncryptedLinearBlockBuffer *)buffer.get());
1297033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1298033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    ssize_t result = -1;
1299033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (mCrypto != nullptr) {
1300033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        ICrypto::DestinationBuffer destination;
1301033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (secure) {
1302033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            destination.mType = ICrypto::kDestinationTypeNativeHandle;
1303033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            destination.mHandle = encryptedBuffer->handle();
1304033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        } else {
1305033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            destination.mType = ICrypto::kDestinationTypeSharedMemory;
1306033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            destination.mSharedMemory = mDecryptDestination;
1307033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
1308033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        ICrypto::SourceBuffer source;
1309033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        encryptedBuffer->fillSourceBuffer(&source);
1310033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        result = mCrypto->decrypt(
1311033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                key, iv, mode, pattern, source, buffer->offset(),
1312033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                subSamples, numSubSamples, destination, errorDetailMsg);
1313033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (result < 0) {
1314033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return result;
1315033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
1316033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (destination.mType == ICrypto::kDestinationTypeSharedMemory) {
1317033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            encryptedBuffer->copyDecryptedContent(mDecryptDestination, result);
1318033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
1319033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    } else {
1320033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        // Here we cast CryptoPlugin::SubSample to hardware::cas::native::V1_0::SubSample
1321033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        // directly, the structure definitions should match as checked in DescramblerImpl.cpp.
1322033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        hidl_vec<SubSample> hidlSubSamples;
1323033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        hidlSubSamples.setToExternal((SubSample *)subSamples, numSubSamples, false /*own*/);
1324033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1325033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        hardware::cas::native::V1_0::SharedBuffer srcBuffer;
1326033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        encryptedBuffer->fillSourceBuffer(&srcBuffer);
1327033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1328033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        DestinationBuffer dstBuffer;
1329033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (secure) {
1330033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            dstBuffer.type = BufferType::NATIVE_HANDLE;
1331033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            dstBuffer.secureMemory = hidl_handle(encryptedBuffer->handle());
1332033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        } else {
1333033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            dstBuffer.type = BufferType::SHARED_MEMORY;
1334033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            dstBuffer.nonsecureMemory = srcBuffer;
1335033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
1336033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1337033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        CasStatus status = CasStatus::OK;
1338033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        hidl_string detailedError;
1339033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1340033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        auto returnVoid = mDescrambler->descramble(
1341033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                key != NULL ? (ScramblingControl)key[0] : ScramblingControl::UNSCRAMBLED,
1342033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                hidlSubSamples,
1343033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                srcBuffer,
1344033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                0,
1345033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                dstBuffer,
1346033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                0,
1347033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                [&status, &result, &detailedError] (
1348033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                        CasStatus _status, uint32_t _bytesWritten,
1349033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                        const hidl_string& _detailedError) {
1350033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                    status = _status;
1351033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                    result = (ssize_t)_bytesWritten;
1352033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                    detailedError = _detailedError;
1353033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                });
1354033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1355033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (!returnVoid.isOk() || status != CasStatus::OK || result < 0) {
1356033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            ALOGE("descramble failed, trans=%s, status=%d, result=%zd",
1357033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                    returnVoid.description().c_str(), status, result);
1358033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return UNKNOWN_ERROR;
1359033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
1360033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1361033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        ALOGV("descramble succeeded, %zd bytes", result);
1362033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1363033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (dstBuffer.type == BufferType::SHARED_MEMORY) {
1364033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            encryptedBuffer->copyDecryptedContentFromMemory(result);
1365033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
1366033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
1367033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1368033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    buffer->setRange(0, result);
1369033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    return queueInputBufferInternal(buffer);
1370033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
1371033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1372033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodecBufferChannel::feedInputBufferIfAvailable() {
1373a215f50524c8e0688cceb0b8489a6703a3bdf619Wonsik Kim    QueueGuard guard(mSync);
1374a215f50524c8e0688cceb0b8489a6703a3bdf619Wonsik Kim    if (!guard.isRunning()) {
1375a215f50524c8e0688cceb0b8489a6703a3bdf619Wonsik Kim        ALOGV("We're not running --- no input buffer reported");
1376a215f50524c8e0688cceb0b8489a6703a3bdf619Wonsik Kim        return;
1377a215f50524c8e0688cceb0b8489a6703a3bdf619Wonsik Kim    }
1378c2088887496fa8627e0a2a4e713f413301065516Wonsik Kim    feedInputBufferIfAvailableInternal();
1379c2088887496fa8627e0a2a4e713f413301065516Wonsik Kim}
1380c2088887496fa8627e0a2a4e713f413301065516Wonsik Kim
1381c2088887496fa8627e0a2a4e713f413301065516Wonsik Kimvoid CCodecBufferChannel::feedInputBufferIfAvailableInternal() {
1382c2088887496fa8627e0a2a4e713f413301065516Wonsik Kim    while (mPendingFeed > 0) {
1383c2088887496fa8627e0a2a4e713f413301065516Wonsik Kim        sp<MediaCodecBuffer> inBuffer;
1384c2088887496fa8627e0a2a4e713f413301065516Wonsik Kim        size_t index;
1385c2088887496fa8627e0a2a4e713f413301065516Wonsik Kim        {
1386c2088887496fa8627e0a2a4e713f413301065516Wonsik Kim            Mutexed<std::unique_ptr<InputBuffers>>::Locked buffers(mInputBuffers);
1387c2088887496fa8627e0a2a4e713f413301065516Wonsik Kim            if (!(*buffers)->requestNewBuffer(&index, &inBuffer)) {
1388c2088887496fa8627e0a2a4e713f413301065516Wonsik Kim                ALOGV("no new buffer available");
1389c2088887496fa8627e0a2a4e713f413301065516Wonsik Kim                break;
1390c2088887496fa8627e0a2a4e713f413301065516Wonsik Kim            }
1391033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
1392c2088887496fa8627e0a2a4e713f413301065516Wonsik Kim        ALOGV("new input index = %zu", index);
1393c2088887496fa8627e0a2a4e713f413301065516Wonsik Kim        mCallback->onInputBufferAvailable(index, inBuffer);
1394c2088887496fa8627e0a2a4e713f413301065516Wonsik Kim        ALOGV("%s: pending feed -1 from %u", __func__, mPendingFeed.load());
1395c2088887496fa8627e0a2a4e713f413301065516Wonsik Kim        --mPendingFeed;
1396033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
1397033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
1398033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1399033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimstatus_t CCodecBufferChannel::renderOutputBuffer(
1400033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        const sp<MediaCodecBuffer> &buffer, int64_t timestampNs) {
1401033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    ALOGV("renderOutputBuffer");
1402c2088887496fa8627e0a2a4e713f413301065516Wonsik Kim    ALOGV("%s: pending feed +1 from %u", __func__, mPendingFeed.load());
1403c2088887496fa8627e0a2a4e713f413301065516Wonsik Kim    ++mPendingFeed;
1404033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    feedInputBufferIfAvailable();
1405033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1406033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    std::shared_ptr<C2Buffer> c2Buffer;
1407033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    {
1408033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<std::unique_ptr<OutputBuffers>>::Locked buffers(mOutputBuffers);
1409e76dbb8207011ad23a2e3460c5672e7c250beae9Wonsik Kim        if (*buffers) {
1410e76dbb8207011ad23a2e3460c5672e7c250beae9Wonsik Kim            (*buffers)->releaseBuffer(buffer, &c2Buffer);
1411e76dbb8207011ad23a2e3460c5672e7c250beae9Wonsik Kim        }
1412e76dbb8207011ad23a2e3460c5672e7c250beae9Wonsik Kim    }
1413e76dbb8207011ad23a2e3460c5672e7c250beae9Wonsik Kim    if (!c2Buffer) {
1414e76dbb8207011ad23a2e3460c5672e7c250beae9Wonsik Kim        return INVALID_OPERATION;
1415033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
1416033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1417b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar#if 0
1418b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar    const std::vector<std::shared_ptr<const C2Info>> infoParams = c2Buffer->info();
1419b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar    ALOGV("queuing gfx buffer with %zu infos", infoParams.size());
1420b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar    for (const std::shared_ptr<const C2Info> &info : infoParams) {
1421b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar        AString res;
1422b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar        for (size_t ix = 0; ix + 3 < info->size(); ix += 4) {
1423b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar            if (ix) res.append(", ");
1424b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar            res.append(*((int32_t*)info.get() + (ix / 4)));
1425b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar        }
1426b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar        ALOGV("  [%s]", res.c_str());
1427b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar    }
1428b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar#endif
1429b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar    std::shared_ptr<const C2StreamRotationInfo::output> rotation =
1430b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar        std::static_pointer_cast<const C2StreamRotationInfo::output>(
1431b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar                c2Buffer->getInfo(C2StreamRotationInfo::output::PARAM_TYPE));
1432b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar    bool flip = rotation && (rotation->flip & 1);
1433b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar    uint32_t quarters = ((rotation ? rotation->value : 0) / 90) & 3;
1434b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar    uint32_t transform = 0;
1435b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar    switch (quarters) {
1436b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar        case 0: // no rotation
1437b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar            transform = flip ? HAL_TRANSFORM_FLIP_H : 0;
1438b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar            break;
1439b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar        case 1: // 90 degrees counter-clockwise
1440b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar            transform = flip ? (HAL_TRANSFORM_FLIP_V | HAL_TRANSFORM_ROT_90)
1441b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar                    : HAL_TRANSFORM_ROT_270;
1442b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar            break;
1443b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar        case 2: // 180 degrees
1444b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar            transform = flip ? HAL_TRANSFORM_FLIP_V : HAL_TRANSFORM_ROT_180;
1445b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar            break;
1446b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar        case 3: // 90 degrees clockwise
1447b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar            transform = flip ? (HAL_TRANSFORM_FLIP_H | HAL_TRANSFORM_ROT_90)
1448b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar                    : HAL_TRANSFORM_ROT_90;
1449b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar            break;
1450b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar    }
1451b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar
1452b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar    std::shared_ptr<const C2StreamSurfaceScalingInfo::output> surfaceScaling =
1453b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar        std::static_pointer_cast<const C2StreamSurfaceScalingInfo::output>(
1454b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar                c2Buffer->getInfo(C2StreamSurfaceScalingInfo::output::PARAM_TYPE));
1455b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar    uint32_t videoScalingMode = NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW;
1456b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar    if (surfaceScaling) {
1457b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar        videoScalingMode = surfaceScaling->value;
1458b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar    }
1459b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar
1460b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar    // Use dataspace if component provides it. Otherwise, compose dataspace from color aspects
1461b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar    std::shared_ptr<const C2StreamDataSpaceInfo::output> dataSpaceInfo =
1462b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar        std::static_pointer_cast<const C2StreamDataSpaceInfo::output>(
1463b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar                c2Buffer->getInfo(C2StreamDataSpaceInfo::output::PARAM_TYPE));
1464b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar    uint32_t dataSpace = HAL_DATASPACE_UNKNOWN; // this is 0
1465b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar    if (dataSpaceInfo) {
1466b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar        dataSpace = dataSpaceInfo->value;
1467b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar    } else {
1468b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar        std::shared_ptr<const C2StreamColorAspectsInfo::output> colorAspects =
1469b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar            std::static_pointer_cast<const C2StreamColorAspectsInfo::output>(
1470b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar                    c2Buffer->getInfo(C2StreamColorAspectsInfo::output::PARAM_TYPE));
1471b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar        C2Color::range_t range =
1472b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar            colorAspects == nullptr ? C2Color::RANGE_UNSPECIFIED     : colorAspects->range;
1473b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar        C2Color::primaries_t primaries =
1474b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar            colorAspects == nullptr ? C2Color::PRIMARIES_UNSPECIFIED : colorAspects->primaries;
1475b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar        C2Color::transfer_t transfer =
1476b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar            colorAspects == nullptr ? C2Color::TRANSFER_UNSPECIFIED  : colorAspects->transfer;
1477b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar        C2Color::matrix_t matrix =
1478b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar            colorAspects == nullptr ? C2Color::MATRIX_UNSPECIFIED    : colorAspects->matrix;
1479b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar
1480b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar        switch (range) {
1481b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar            case C2Color::RANGE_FULL:    dataSpace |= HAL_DATASPACE_RANGE_FULL;    break;
1482b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar            case C2Color::RANGE_LIMITED: dataSpace |= HAL_DATASPACE_RANGE_LIMITED; break;
1483b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar            default: break;
1484b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar        }
1485b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar
1486b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar        switch (transfer) {
1487b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar            case C2Color::TRANSFER_LINEAR:  dataSpace |= HAL_DATASPACE_TRANSFER_LINEAR;     break;
1488b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar            case C2Color::TRANSFER_SRGB:    dataSpace |= HAL_DATASPACE_TRANSFER_SRGB;       break;
1489b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar            case C2Color::TRANSFER_170M:    dataSpace |= HAL_DATASPACE_TRANSFER_SMPTE_170M; break;
1490b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar            case C2Color::TRANSFER_GAMMA22: dataSpace |= HAL_DATASPACE_TRANSFER_GAMMA2_2;   break;
1491b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar            case C2Color::TRANSFER_GAMMA28: dataSpace |= HAL_DATASPACE_TRANSFER_GAMMA2_8;   break;
1492b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar            case C2Color::TRANSFER_ST2084:  dataSpace |= HAL_DATASPACE_TRANSFER_ST2084;     break;
1493b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar            case C2Color::TRANSFER_HLG:     dataSpace |= HAL_DATASPACE_TRANSFER_HLG;        break;
1494b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar            default: break;
1495b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar        }
1496b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar
1497b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar        switch (primaries) {
1498b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar            case C2Color::PRIMARIES_BT601_525:
1499b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar                dataSpace |= (matrix == C2Color::MATRIX_SMPTE240M
1500b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar                                || matrix == C2Color::MATRIX_BT709)
1501b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar                        ? HAL_DATASPACE_STANDARD_BT601_525_UNADJUSTED
1502b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar                        : HAL_DATASPACE_STANDARD_BT601_525;
1503b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar                break;
1504b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar            case C2Color::PRIMARIES_BT601_625:
1505b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar                dataSpace |= (matrix == C2Color::MATRIX_SMPTE240M
1506b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar                                || matrix == C2Color::MATRIX_BT709)
1507b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar                        ? HAL_DATASPACE_STANDARD_BT601_625_UNADJUSTED
1508b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar                        : HAL_DATASPACE_STANDARD_BT601_625;
1509b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar                break;
1510b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar            case C2Color::PRIMARIES_BT2020:
1511b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar                dataSpace |= (matrix == C2Color::MATRIX_BT2020CONSTANT
1512b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar                        ? HAL_DATASPACE_STANDARD_BT2020_CONSTANT_LUMINANCE
1513b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar                        : HAL_DATASPACE_STANDARD_BT2020);
1514b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar                break;
1515b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar            case C2Color::PRIMARIES_BT470_M:
1516b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar                dataSpace |= HAL_DATASPACE_STANDARD_BT470M;
1517b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar                break;
1518b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar            case C2Color::PRIMARIES_BT709:
1519b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar                dataSpace |= HAL_DATASPACE_STANDARD_BT709;
1520b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar                break;
1521b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar            default: break;
1522b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar        }
1523b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar    }
1524b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar
1525b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar    // convert legacy dataspace values to v0 values
1526b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar    const static
1527b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar    ALookup<android_dataspace, android_dataspace> sLegacyDataSpaceToV0 {
1528b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar        {
1529b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar            { HAL_DATASPACE_SRGB, HAL_DATASPACE_V0_SRGB },
1530b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar            { HAL_DATASPACE_BT709, HAL_DATASPACE_V0_BT709 },
1531b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar            { HAL_DATASPACE_SRGB_LINEAR, HAL_DATASPACE_V0_SRGB_LINEAR },
1532b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar            { HAL_DATASPACE_BT601_525, HAL_DATASPACE_V0_BT601_525 },
1533b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar            { HAL_DATASPACE_BT601_625, HAL_DATASPACE_V0_BT601_625 },
1534b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar            { HAL_DATASPACE_JFIF, HAL_DATASPACE_V0_JFIF },
1535b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar        }
1536b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar    };
1537b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar    sLegacyDataSpaceToV0.lookup((android_dataspace_t)dataSpace, (android_dataspace_t*)&dataSpace);
1538b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar
1539b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar    // HDR static info
1540b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar    std::shared_ptr<const C2StreamHdrStaticInfo::output> hdrStaticInfo =
1541b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar        std::static_pointer_cast<const C2StreamHdrStaticInfo::output>(
1542b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar                c2Buffer->getInfo(C2StreamHdrStaticInfo::output::PARAM_TYPE));
1543b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar
15442cc26aada0fc1c80eb2564eb19f1b085380d07b9Pawin Vongmasa    {
15452cc26aada0fc1c80eb2564eb19f1b085380d07b9Pawin Vongmasa        Mutexed<OutputSurface>::Locked output(mOutputSurface);
15462cc26aada0fc1c80eb2564eb19f1b085380d07b9Pawin Vongmasa        if (output->surface == nullptr) {
15472cc26aada0fc1c80eb2564eb19f1b085380d07b9Pawin Vongmasa            ALOGE("no surface");
15482cc26aada0fc1c80eb2564eb19f1b085380d07b9Pawin Vongmasa            return OK;
15498b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin        }
15508060cb241e5091bc325599b0d609fd36360942e9Sungtak Lee    }
1551033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1552033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    std::vector<C2ConstGraphicBlock> blocks = c2Buffer->data().graphicBlocks();
1553033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (blocks.size() != 1u) {
1554033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        ALOGE("# of graphic blocks expected to be 1, but %zu", blocks.size());
1555033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return UNKNOWN_ERROR;
1556033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
1557670fbf8f428ba012574f193cbdff15617b0b7950Lajos Molnar    const C2ConstGraphicBlock &block = blocks.front();
1558670fbf8f428ba012574f193cbdff15617b0b7950Lajos Molnar
1559b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar    // TODO: revisit this after C2Fence implementation.
15608060cb241e5091bc325599b0d609fd36360942e9Sungtak Lee    android::IGraphicBufferProducer::QueueBufferInput qbi(
15618060cb241e5091bc325599b0d609fd36360942e9Sungtak Lee            timestampNs,
15628060cb241e5091bc325599b0d609fd36360942e9Sungtak Lee            false,
1563b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar            (android_dataspace_t)dataSpace,
1564a28531affe22ce6db653e09e7978730dbd1f068aWonsik Kim            Rect(blocks.front().crop().left,
1565a28531affe22ce6db653e09e7978730dbd1f068aWonsik Kim                 blocks.front().crop().top,
1566a28531affe22ce6db653e09e7978730dbd1f068aWonsik Kim                 blocks.front().crop().right(),
1567a28531affe22ce6db653e09e7978730dbd1f068aWonsik Kim                 blocks.front().crop().bottom()),
1568b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar            videoScalingMode,
1569b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar            transform,
15708060cb241e5091bc325599b0d609fd36360942e9Sungtak Lee            Fence::NO_FENCE, 0);
1571b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar    if (hdrStaticInfo) {
1572b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar        struct android_smpte2086_metadata smpte2086_meta = {
1573b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar            .displayPrimaryRed = {
1574b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar                hdrStaticInfo->mastering.red.x, hdrStaticInfo->mastering.red.y
1575b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar            },
1576b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar            .displayPrimaryGreen = {
1577b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar                hdrStaticInfo->mastering.green.x, hdrStaticInfo->mastering.green.y
1578b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar            },
1579b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar            .displayPrimaryBlue = {
1580b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar                hdrStaticInfo->mastering.blue.x, hdrStaticInfo->mastering.blue.y
1581b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar            },
1582b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar            .whitePoint = {
1583b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar                hdrStaticInfo->mastering.white.x, hdrStaticInfo->mastering.white.y
1584b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar            },
1585b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar            .maxLuminance = hdrStaticInfo->mastering.maxLuminance,
1586b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar            .minLuminance = hdrStaticInfo->mastering.minLuminance,
1587b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar        };
1588b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar
1589b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar        struct android_cta861_3_metadata cta861_meta = {
1590b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar            .maxContentLightLevel = hdrStaticInfo->maxCll,
1591b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar            .maxFrameAverageLightLevel = hdrStaticInfo->maxFall,
1592b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar        };
1593b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar
1594b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar        HdrMetadata hdr;
1595b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar        hdr.validTypes = HdrMetadata::SMPTE2086 | HdrMetadata::CTA861_3;
1596b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar        hdr.smpte2086 = smpte2086_meta;
1597b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar        hdr.cta8613 = cta861_meta;
1598b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar        qbi.setHdrMetadata(hdr);
1599b53199ea9a1ba3c1c5e98fb1e6452ae45340e101Lajos Molnar    }
16008060cb241e5091bc325599b0d609fd36360942e9Sungtak Lee    android::IGraphicBufferProducer::QueueBufferOutput qbo;
16012cc26aada0fc1c80eb2564eb19f1b085380d07b9Pawin Vongmasa    status_t result = mComponent->queueToOutputSurface(block, qbi, &qbo);
1602033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (result != OK) {
1603033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        ALOGE("queueBuffer failed: %d", result);
1604033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return result;
1605033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
16068060cb241e5091bc325599b0d609fd36360942e9Sungtak Lee    ALOGV("queue buffer successful");
1607033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1608384b6a0bcf56a6cdc81fad923fc4695027fa42ddWonsik Kim    int64_t mediaTimeUs = 0;
1609384b6a0bcf56a6cdc81fad923fc4695027fa42ddWonsik Kim    (void)buffer->meta()->findInt64("timeUs", &mediaTimeUs);
1610384b6a0bcf56a6cdc81fad923fc4695027fa42ddWonsik Kim    mCCodecCallback->onOutputFramesRendered(mediaTimeUs, timestampNs);
1611384b6a0bcf56a6cdc81fad923fc4695027fa42ddWonsik Kim
1612033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    return OK;
1613033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
1614033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1615033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimstatus_t CCodecBufferChannel::discardBuffer(const sp<MediaCodecBuffer> &buffer) {
1616033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    ALOGV("discardBuffer: %p", buffer.get());
16178c90d948d154ccf81c4a7113f3aefbe329ce6e8dWonsik Kim    bool released = false;
1618033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    {
1619033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<std::unique_ptr<InputBuffers>>::Locked buffers(mInputBuffers);
1620e76dbb8207011ad23a2e3460c5672e7c250beae9Wonsik Kim        if (*buffers) {
1621e76dbb8207011ad23a2e3460c5672e7c250beae9Wonsik Kim            released = (*buffers)->releaseBuffer(buffer, nullptr);
1622e76dbb8207011ad23a2e3460c5672e7c250beae9Wonsik Kim        }
1623033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
1624033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    {
1625033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<std::unique_ptr<OutputBuffers>>::Locked buffers(mOutputBuffers);
1626e76dbb8207011ad23a2e3460c5672e7c250beae9Wonsik Kim        if (*buffers && (*buffers)->releaseBuffer(buffer, nullptr)) {
16278c90d948d154ccf81c4a7113f3aefbe329ce6e8dWonsik Kim            released = true;
1628c2088887496fa8627e0a2a4e713f413301065516Wonsik Kim            ALOGV("%s: pending feed +1 from %u", __func__, mPendingFeed.load());
1629c2088887496fa8627e0a2a4e713f413301065516Wonsik Kim            ++mPendingFeed;
1630033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
1631033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
1632c2088887496fa8627e0a2a4e713f413301065516Wonsik Kim    feedInputBufferIfAvailable();
16338c90d948d154ccf81c4a7113f3aefbe329ce6e8dWonsik Kim    if (!released) {
16348c90d948d154ccf81c4a7113f3aefbe329ce6e8dWonsik Kim        ALOGD("MediaCodec discarded an unknown buffer");
16358c90d948d154ccf81c4a7113f3aefbe329ce6e8dWonsik Kim    }
1636033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    return OK;
1637033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
1638033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1639033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodecBufferChannel::getInputBufferArray(Vector<sp<MediaCodecBuffer>> *array) {
1640033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    array->clear();
1641033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    Mutexed<std::unique_ptr<InputBuffers>>::Locked buffers(mInputBuffers);
1642033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1643033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (!(*buffers)->isArrayMode()) {
1644033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        *buffers = (*buffers)->toArrayMode();
1645033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
1646033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1647033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    (*buffers)->getArray(array);
1648033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
1649033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1650033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodecBufferChannel::getOutputBufferArray(Vector<sp<MediaCodecBuffer>> *array) {
1651033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    array->clear();
1652033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    Mutexed<std::unique_ptr<OutputBuffers>>::Locked buffers(mOutputBuffers);
1653033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1654033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (!(*buffers)->isArrayMode()) {
1655033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        *buffers = (*buffers)->toArrayMode();
1656033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
1657033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1658033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    (*buffers)->getArray(array);
1659033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
1660033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1661033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimstatus_t CCodecBufferChannel::start(
1662033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        const sp<AMessage> &inputFormat, const sp<AMessage> &outputFormat) {
1663033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    C2StreamFormatConfig::input iStreamFormat(0u);
1664033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    C2StreamFormatConfig::output oStreamFormat(0u);
16650f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    c2_status_t err = mComponent->query(
1666033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            { &iStreamFormat, &oStreamFormat },
1667033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            {},
1668033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            C2_DONT_BLOCK,
1669033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            nullptr);
1670033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (err != C2_OK) {
1671033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return UNKNOWN_ERROR;
1672033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
16738b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin
16748b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin    // TODO: get this from input format
16750f04c4d93761015d0a138aff8a468b1583d684e4Pawin Vongmasa    bool secure = mComponent->getName().find(".secure") != std::string::npos;
1676033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
16778b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin    std::shared_ptr<C2AllocatorStore> allocatorStore = GetCodec2PlatformAllocatorStore();
1678dacd656e6f8d7b4f273f10737fbb939c963a16aeSungtak Lee    int poolMask = property_get_int32(
1679dacd656e6f8d7b4f273f10737fbb939c963a16aeSungtak Lee            "debug.stagefright.c2-poolmask",
168000f014cde379a797d0c0dc042b90f001af80b9dfPawin Vongmasa            1 << C2PlatformAllocatorStore::ION |
168100f014cde379a797d0c0dc042b90f001af80b9dfPawin Vongmasa            1 << C2PlatformAllocatorStore::BUFFERQUEUE);
1682033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
16838b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin    if (inputFormat != nullptr) {
1684033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        bool graphic = (iStreamFormat.value == C2FormatVideo);
16858b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin        std::shared_ptr<C2BlockPool> pool;
16868b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin        {
16878b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin            Mutexed<BlockPools>::Locked pools(mBlockPools);
16888b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin
16898b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin            // set default allocator ID.
1690a0d2cfa4011de5e4d62219a2872c479f42904c2eLajos Molnar            pools->inputAllocatorId = (graphic) ? C2PlatformAllocatorStore::GRALLOC
16918b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin                                                : C2PlatformAllocatorStore::ION;
16928b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin
16938b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin            // query C2PortAllocatorsTuning::input from component. If an allocator ID is obtained
16948b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin            // from component, create the input block pool with given ID. Otherwise, use default IDs.
16958b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin            std::vector<std::unique_ptr<C2Param>> params;
16968b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin            err = mComponent->query({ },
16978b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin                                    { C2PortAllocatorsTuning::input::PARAM_TYPE },
16988b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin                                    C2_DONT_BLOCK,
16998b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin                                    &params);
17008b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin            if ((err != C2_OK && err != C2_BAD_INDEX) || params.size() != 1) {
17018b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin                ALOGD("Query input allocators returned %zu params => %s (%u)",
17028b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin                        params.size(), asString(err), err);
17038b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin            } else if (err == C2_OK && params.size() == 1) {
17048b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin                C2PortAllocatorsTuning::input *inputAllocators =
17058b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin                    C2PortAllocatorsTuning::input::From(params[0].get());
17068b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin                if (inputAllocators && inputAllocators->flexCount() > 0) {
17078b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin                    std::shared_ptr<C2Allocator> allocator;
17088b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin                    // verify allocator IDs and resolve default allocator
17098b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin                    allocatorStore->fetchAllocator(inputAllocators->m.values[0], &allocator);
17108b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin                    if (allocator) {
17118b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin                        pools->inputAllocatorId = allocator->getId();
17128b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin                    } else {
17138b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin                        ALOGD("component requested invalid input allocator ID %u",
17148b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin                                inputAllocators->m.values[0]);
17158b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin                    }
17168b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin                }
17178b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin            }
17188b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin
17198b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin            // TODO: use C2Component wrapper to associate this pool with ourselves
17200c751518fa35dda5d0adc290a5dc3d09fd30dca1Lajos Molnar            if ((poolMask >> pools->inputAllocatorId) & 1) {
17210c751518fa35dda5d0adc290a5dc3d09fd30dca1Lajos Molnar                err = CreateCodec2BlockPool(pools->inputAllocatorId, nullptr, &pool);
17220c751518fa35dda5d0adc290a5dc3d09fd30dca1Lajos Molnar                ALOGD("Created input block pool with allocatorID %u => poolID %llu - %s (%d)",
17230c751518fa35dda5d0adc290a5dc3d09fd30dca1Lajos Molnar                        pools->inputAllocatorId,
17240c751518fa35dda5d0adc290a5dc3d09fd30dca1Lajos Molnar                        (unsigned long long)(pool ? pool->getLocalId() : 111000111),
17250c751518fa35dda5d0adc290a5dc3d09fd30dca1Lajos Molnar                        asString(err), err);
17260c751518fa35dda5d0adc290a5dc3d09fd30dca1Lajos Molnar            } else {
17270c751518fa35dda5d0adc290a5dc3d09fd30dca1Lajos Molnar                err = C2_NOT_FOUND;
17280c751518fa35dda5d0adc290a5dc3d09fd30dca1Lajos Molnar            }
17298b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin            if (err != C2_OK) {
17308b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin                C2BlockPool::local_id_t inputPoolId =
17318b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin                    graphic ? C2BlockPool::BASIC_GRAPHIC : C2BlockPool::BASIC_LINEAR;
17328b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin                err = GetCodec2BlockPool(inputPoolId, nullptr, &pool);
17338b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin                ALOGD("Using basic input block pool with poolID %llu => got %llu - %s (%d)",
17348b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin                        (unsigned long long)inputPoolId,
17358b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin                        (unsigned long long)(pool ? pool->getLocalId() : 111000111),
17368b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin                        asString(err), err);
17378b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin                if (err != C2_OK) {
17388b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin                    return NO_MEMORY;
17398b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin                }
17408b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin            }
17418b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin            pools->inputPool = pool;
17428b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin        }
17438b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin
17448b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin        Mutexed<std::unique_ptr<InputBuffers>>::Locked buffers(mInputBuffers);
1745033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (graphic) {
1746033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            if (mInputSurface) {
1747033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                buffers->reset(new DummyInputBuffers);
1748f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim            } else if (mMetaMode == MODE_ANW) {
1749f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim                buffers->reset(new GraphicMetadataInputBuffers);
1750033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            } else {
1751033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                buffers->reset(new GraphicInputBuffers);
1752033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            }
1753033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        } else {
1754033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            if (hasCryptoOrDescrambler()) {
1755033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                if (mDealer == nullptr) {
1756033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                    mDealer = new MemoryDealer(
1757033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                            align(kLinearBufferSize, MemoryDealer::getAllocationAlignment())
175860e4b7347394676287f7686ddced77544a106831Wonsik Kim                                * (kMinInputBufferArraySize + 1),
1759033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                            "EncryptedLinearInputBuffers");
1760033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                    mDecryptDestination = mDealer->allocate(kLinearBufferSize);
1761033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                }
1762033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                if (mCrypto != nullptr && mHeapSeqNum < 0) {
1763033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                    mHeapSeqNum = mCrypto->setHeap(mDealer->getMemoryHeap());
1764033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                } else {
1765033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                    mHeapSeqNum = -1;
1766033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                }
1767033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                buffers->reset(new EncryptedLinearInputBuffers(
1768033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                        secure, mDealer, mCrypto, mHeapSeqNum));
1769033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            } else {
1770033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                buffers->reset(new LinearInputBuffers);
1771033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            }
1772033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
1773033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        (*buffers)->setFormat(inputFormat);
1774033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1775033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (err == C2_OK) {
1776033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            (*buffers)->setPool(pool);
1777033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        } else {
1778033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            // TODO: error
1779033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
1780033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
1781033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1782033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (outputFormat != nullptr) {
17832cc26aada0fc1c80eb2564eb19f1b085380d07b9Pawin Vongmasa        sp<IGraphicBufferProducer> outputSurface;
17842cc26aada0fc1c80eb2564eb19f1b085380d07b9Pawin Vongmasa        uint32_t outputGeneration;
1785033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        {
1786033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            Mutexed<OutputSurface>::Locked output(mOutputSurface);
17872cc26aada0fc1c80eb2564eb19f1b085380d07b9Pawin Vongmasa            outputSurface = output->surface ?
17882cc26aada0fc1c80eb2564eb19f1b085380d07b9Pawin Vongmasa                    output->surface->getIGraphicBufferProducer() : nullptr;
17892cc26aada0fc1c80eb2564eb19f1b085380d07b9Pawin Vongmasa            outputGeneration = output->generation;
1790033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
1791033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
17928b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin        bool graphic = (oStreamFormat.value == C2FormatVideo);
17938b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin        C2BlockPool::local_id_t outputPoolId_;
17942cc26aada0fc1c80eb2564eb19f1b085380d07b9Pawin Vongmasa
17958b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin        {
17968b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin            Mutexed<BlockPools>::Locked pools(mBlockPools);
17978b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin
17988b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin            // set default allocator ID.
1799a0d2cfa4011de5e4d62219a2872c479f42904c2eLajos Molnar            pools->outputAllocatorId = (graphic) ? C2PlatformAllocatorStore::GRALLOC
18008b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin                                                 : C2PlatformAllocatorStore::ION;
18018b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin
18028b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin            // query C2PortAllocatorsTuning::output from component, or use default allocator if
18038b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin            // unsuccessful.
18048b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin            std::vector<std::unique_ptr<C2Param>> params;
18058b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin            err = mComponent->query({ },
18068b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin                                    { C2PortAllocatorsTuning::output::PARAM_TYPE },
18078b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin                                    C2_DONT_BLOCK,
18088b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin                                    &params);
18098b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin            if ((err != C2_OK && err != C2_BAD_INDEX) || params.size() != 1) {
18108b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin                ALOGD("Query input allocators returned %zu params => %s (%u)",
18118b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin                        params.size(), asString(err), err);
18128b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin            } else if (err == C2_OK && params.size() == 1) {
18138b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin                C2PortAllocatorsTuning::output *outputAllocators =
18148b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin                    C2PortAllocatorsTuning::output::From(params[0].get());
18158b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin                if (outputAllocators && outputAllocators->flexCount() > 0) {
18168b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin                    std::shared_ptr<C2Allocator> allocator;
18178b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin                    // verify allocator IDs and resolve default allocator
18188b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin                    allocatorStore->fetchAllocator(outputAllocators->m.values[0], &allocator);
18198b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin                    if (allocator) {
18208b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin                        pools->outputAllocatorId = allocator->getId();
18218b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin                    } else {
18228b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin                        ALOGD("component requested invalid output allocator ID %u",
18238b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin                                outputAllocators->m.values[0]);
18248b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin                    }
18258b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin                }
18268b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin            }
18278b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin
1828a0d2cfa4011de5e4d62219a2872c479f42904c2eLajos Molnar            // use bufferqueue if outputting to a surface
1829a0d2cfa4011de5e4d62219a2872c479f42904c2eLajos Molnar            if (pools->outputAllocatorId == C2PlatformAllocatorStore::GRALLOC
18302cc26aada0fc1c80eb2564eb19f1b085380d07b9Pawin Vongmasa                    && outputSurface
1831a0d2cfa4011de5e4d62219a2872c479f42904c2eLajos Molnar                    && ((poolMask >> C2PlatformAllocatorStore::BUFFERQUEUE) & 1)) {
1832a0d2cfa4011de5e4d62219a2872c479f42904c2eLajos Molnar                pools->outputAllocatorId = C2PlatformAllocatorStore::BUFFERQUEUE;
1833a0d2cfa4011de5e4d62219a2872c479f42904c2eLajos Molnar            }
1834a0d2cfa4011de5e4d62219a2872c479f42904c2eLajos Molnar
18350c751518fa35dda5d0adc290a5dc3d09fd30dca1Lajos Molnar            if ((poolMask >> pools->outputAllocatorId) & 1) {
18360c751518fa35dda5d0adc290a5dc3d09fd30dca1Lajos Molnar                err = mComponent->createBlockPool(
18370c751518fa35dda5d0adc290a5dc3d09fd30dca1Lajos Molnar                        pools->outputAllocatorId, &pools->outputPoolId, &pools->outputPoolIntf);
18380c751518fa35dda5d0adc290a5dc3d09fd30dca1Lajos Molnar                ALOGI("Created output block pool with allocatorID %u => poolID %llu - %s",
18390c751518fa35dda5d0adc290a5dc3d09fd30dca1Lajos Molnar                        pools->outputAllocatorId,
18400c751518fa35dda5d0adc290a5dc3d09fd30dca1Lajos Molnar                        (unsigned long long)pools->outputPoolId,
18410c751518fa35dda5d0adc290a5dc3d09fd30dca1Lajos Molnar                        asString(err));
18420c751518fa35dda5d0adc290a5dc3d09fd30dca1Lajos Molnar            } else {
18430c751518fa35dda5d0adc290a5dc3d09fd30dca1Lajos Molnar                err = C2_NOT_FOUND;
18440c751518fa35dda5d0adc290a5dc3d09fd30dca1Lajos Molnar            }
18458b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin            if (err != C2_OK) {
18468b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin                // use basic pool instead
18478b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin                pools->outputPoolId =
18488b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin                    graphic ? C2BlockPool::BASIC_GRAPHIC : C2BlockPool::BASIC_LINEAR;
18498b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin            }
18508b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin
18518b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin            // Configure output block pool ID as parameter C2PortBlockPoolsTuning::output to
18528b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin            // component.
18538b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin            std::unique_ptr<C2PortBlockPoolsTuning::output> poolIdsTuning =
18548b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin                    C2PortBlockPoolsTuning::output::AllocUnique({ pools->outputPoolId });
18558b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin
18568b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin            std::vector<std::unique_ptr<C2SettingResult>> failures;
18578b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin            err = mComponent->config({ poolIdsTuning.get() }, C2_MAY_BLOCK, &failures);
18588b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin            ALOGD("Configured output block pool ids %llu => %s",
18598b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin                    (unsigned long long)poolIdsTuning->m.values[0], asString(err));
18608b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin            outputPoolId_ = pools->outputPoolId;
18618b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin        }
18628b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin
1863033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<std::unique_ptr<OutputBuffers>>::Locked buffers(mOutputBuffers);
1864033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1865033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (graphic) {
18662cc26aada0fc1c80eb2564eb19f1b085380d07b9Pawin Vongmasa            if (outputSurface) {
1867033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                buffers->reset(new GraphicOutputBuffers);
1868033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            } else {
1869033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                buffers->reset(new RawGraphicOutputBuffers);
1870033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            }
1871033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        } else {
1872033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            buffers->reset(new LinearOutputBuffers);
1873033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
1874d450fc3eced9eb713b7e27d98d2b353782a6a4f4Wonsik Kim        (*buffers)->setFormat(outputFormat->dup());
18758b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin
18768b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin
18778b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin        // Try to set output surface to created block pool if given.
18782cc26aada0fc1c80eb2564eb19f1b085380d07b9Pawin Vongmasa        if (outputSurface) {
18792cc26aada0fc1c80eb2564eb19f1b085380d07b9Pawin Vongmasa            mComponent->setOutputSurface(
18802cc26aada0fc1c80eb2564eb19f1b085380d07b9Pawin Vongmasa                    outputPoolId_,
18812cc26aada0fc1c80eb2564eb19f1b085380d07b9Pawin Vongmasa                    outputSurface,
18822cc26aada0fc1c80eb2564eb19f1b085380d07b9Pawin Vongmasa                    outputGeneration);
18838b0b2c32666ea799c27b30e64ea89291fa069f4dPin-chih Lin        }
1884dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim
1885dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim        if (oStreamFormat.value == C2FormatAudio) {
1886dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim            int32_t channelCount;
1887dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim            int32_t sampleRate;
1888dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim            if (outputFormat->findInt32(KEY_CHANNEL_COUNT, &channelCount)
1889dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim                    && outputFormat->findInt32(KEY_SAMPLE_RATE, &sampleRate)) {
1890dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim                int32_t delay = 0;
1891dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim                int32_t padding = 0;;
1892dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim                if (!outputFormat->findInt32("encoder-delay", &delay)) {
1893dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim                    delay = 0;
1894dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim                }
1895dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim                if (!outputFormat->findInt32("encoder-padding", &padding)) {
1896dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim                    padding = 0;
1897dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim                }
1898dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim                if (delay || padding) {
1899dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim                    // We need write access to the buffers..
1900dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim                    (*buffers) = (*buffers)->toArrayMode();
1901dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim                    (*buffers)->initSkipCutBuffer(delay, padding, sampleRate, channelCount);
1902dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim                }
1903dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim            }
1904dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim        }
1905033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
1906033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1907ce4de71f149b6ed922d018ec442d65711fd98a19Wonsik Kim    mPendingFeed = 0;
1908033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mSync.start();
1909033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (mInputSurface == nullptr) {
1910033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        // TODO: use proper buffer depth instead of this random value
191160e4b7347394676287f7686ddced77544a106831Wonsik Kim        for (size_t i = 0; i < kMinInputBufferArraySize; ++i) {
1912033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            size_t index;
1913033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            sp<MediaCodecBuffer> buffer;
1914033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            {
1915033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                Mutexed<std::unique_ptr<InputBuffers>>::Locked buffers(mInputBuffers);
1916033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                if (!(*buffers)->requestNewBuffer(&index, &buffer)) {
1917033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                    if (i == 0) {
1918033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                        ALOGE("start: cannot allocate memory at all");
1919033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                        return NO_MEMORY;
1920033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                    } else {
1921033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                        ALOGV("start: cannot allocate memory, only %zu buffers allocated", i);
1922033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                    }
1923033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                    break;
1924033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                }
1925033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            }
1926e0512ca21578cb3f36328c3c01b6f9ad9b15fb47Praveen Chavan            if (buffer) {
1927e0512ca21578cb3f36328c3c01b6f9ad9b15fb47Praveen Chavan                mCallback->onInputBufferAvailable(index, buffer);
1928e0512ca21578cb3f36328c3c01b6f9ad9b15fb47Praveen Chavan            }
1929033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
1930033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
1931033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    return OK;
1932033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
1933033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1934033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodecBufferChannel::stop() {
1935033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mSync.stop();
1936033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mFirstValidFrameIndex = mFrameIndex.load();
1937033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (mInputSurface != nullptr) {
1938033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mInputSurface->disconnect();
1939033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mInputSurface.reset();
1940033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
1941033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
1942033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1943033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid CCodecBufferChannel::flush(const std::list<std::unique_ptr<C2Work>> &flushedWork) {
1944a215f50524c8e0688cceb0b8489a6703a3bdf619Wonsik Kim    ALOGV("flush");
1945033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    {
1946033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<std::unique_ptr<InputBuffers>>::Locked buffers(mInputBuffers);
1947033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        (*buffers)->flush();
1948033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
1949033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    {
1950033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<std::unique_ptr<OutputBuffers>>::Locked buffers(mOutputBuffers);
1951033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        (*buffers)->flush(flushedWork);
1952033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
1953033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
1954033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
19553bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnarvoid CCodecBufferChannel::onWorkDone(
19563bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar        std::unique_ptr<C2Work> work, const sp<AMessage> &outputFormat,
19573bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar        const C2StreamInitDataInfo::output *initData) {
1958c2088887496fa8627e0a2a4e713f413301065516Wonsik Kim    if (handleWork(std::move(work), outputFormat, initData)) {
1959c2088887496fa8627e0a2a4e713f413301065516Wonsik Kim        ALOGV("%s: pending feed +1 from %u", __func__, mPendingFeed.load());
1960c2088887496fa8627e0a2a4e713f413301065516Wonsik Kim        ++mPendingFeed;
1961384b6a0bcf56a6cdc81fad923fc4695027fa42ddWonsik Kim    }
1962c2088887496fa8627e0a2a4e713f413301065516Wonsik Kim    feedInputBufferIfAvailable();
1963384b6a0bcf56a6cdc81fad923fc4695027fa42ddWonsik Kim}
1964a28531affe22ce6db653e09e7978730dbd1f068aWonsik Kim
1965384b6a0bcf56a6cdc81fad923fc4695027fa42ddWonsik Kimbool CCodecBufferChannel::handleWork(
1966384b6a0bcf56a6cdc81fad923fc4695027fa42ddWonsik Kim        std::unique_ptr<C2Work> work,
1967384b6a0bcf56a6cdc81fad923fc4695027fa42ddWonsik Kim        const sp<AMessage> &outputFormat,
1968384b6a0bcf56a6cdc81fad923fc4695027fa42ddWonsik Kim        const C2StreamInitDataInfo::output *initData) {
1969033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (work->result != C2_OK) {
1970033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (work->result == C2_NOT_FOUND) {
1971033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            // TODO: Define what flushed work's result is.
1972033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            ALOGD("flushed work; ignored.");
1973384b6a0bcf56a6cdc81fad923fc4695027fa42ddWonsik Kim            return true;
1974033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
1975033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        ALOGD("work failed to complete: %d", work->result);
1976384b6a0bcf56a6cdc81fad923fc4695027fa42ddWonsik Kim        mCCodecCallback->onError(work->result, ACTION_CODE_FATAL);
1977384b6a0bcf56a6cdc81fad923fc4695027fa42ddWonsik Kim        return false;
1978033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
1979033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1980033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    // NOTE: MediaCodec usage supposedly have only one worklet
1981033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (work->worklets.size() != 1u) {
1982033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        ALOGE("onWorkDone: incorrect number of worklets: %zu",
1983033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                work->worklets.size());
1984384b6a0bcf56a6cdc81fad923fc4695027fa42ddWonsik Kim        mCCodecCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL);
1985384b6a0bcf56a6cdc81fad923fc4695027fa42ddWonsik Kim        return false;
1986033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
1987033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
1988033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    const std::unique_ptr<C2Worklet> &worklet = work->worklets.front();
1989033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if ((worklet->output.ordinal.frameIndex - mFirstValidFrameIndex.load()).peek() < 0) {
1990033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        // Discard frames from previous generation.
1991a215f50524c8e0688cceb0b8489a6703a3bdf619Wonsik Kim        ALOGD("Discard frames from previous generation.");
1992384b6a0bcf56a6cdc81fad923fc4695027fa42ddWonsik Kim        return true;
1993033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
1994033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    std::shared_ptr<C2Buffer> buffer;
1995033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    // NOTE: MediaCodec usage supposedly have only one output stream.
1996033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (worklet->output.buffers.size() > 1u) {
1997033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        ALOGE("onWorkDone: incorrect number of output buffers: %zu",
1998033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                worklet->output.buffers.size());
1999384b6a0bcf56a6cdc81fad923fc4695027fa42ddWonsik Kim        mCCodecCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL);
2000384b6a0bcf56a6cdc81fad923fc4695027fa42ddWonsik Kim        return false;
2001033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    } else if (worklet->output.buffers.size() == 1u) {
2002033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        buffer = worklet->output.buffers[0];
2003033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (!buffer) {
2004033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            ALOGW("onWorkDone: nullptr found in buffers; ignored.");
2005033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
2006033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
2007033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
20083bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar    if (outputFormat != nullptr) {
20098c90d948d154ccf81c4a7113f3aefbe329ce6e8dWonsik Kim        Mutexed<std::unique_ptr<OutputBuffers>>::Locked buffers(mOutputBuffers);
20103bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar        ALOGD("onWorkDone: output format changed to %s",
20113bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar                outputFormat->debugString().c_str());
20123bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar        (*buffers)->setFormat(outputFormat);
2013dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim
2014dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim        AString mediaType;
2015dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim        if (outputFormat->findString(KEY_MIME, &mediaType)
2016dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim                && mediaType == MIMETYPE_AUDIO_RAW) {
2017dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim            int32_t channelCount;
2018dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim            int32_t sampleRate;
2019dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim            if (outputFormat->findInt32(KEY_CHANNEL_COUNT, &channelCount)
2020dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim                    && outputFormat->findInt32(KEY_SAMPLE_RATE, &sampleRate)) {
2021dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim                (*buffers)->updateSkipCutBuffer(sampleRate, channelCount);
2022dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim            }
2023dd4e2987beb3fe8a5cd3520a54675e73d71f40b6Wonsik Kim        }
2024033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
2025033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
2026033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    int32_t flags = 0;
2027033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (worklet->output.flags & C2FrameData::FLAG_END_OF_STREAM) {
2028033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        flags |= MediaCodec::BUFFER_FLAG_EOS;
2029033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        ALOGV("onWorkDone: output EOS");
2030033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
2031033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
2032384b6a0bcf56a6cdc81fad923fc4695027fa42ddWonsik Kim    bool feedNeeded = true;
2033033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    sp<MediaCodecBuffer> outBuffer;
2034033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    size_t index;
20353bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar    if (initData != nullptr) {
2036033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<std::unique_ptr<OutputBuffers>>::Locked buffers(mOutputBuffers);
20373bce60a27e0b0a996e42bd2c9e5bf60373db2780Lajos Molnar        if ((*buffers)->registerCsd(initData, &index, &outBuffer)) {
2038033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            outBuffer->meta()->setInt64("timeUs", worklet->output.ordinal.timestamp.peek());
2039365fd1a7643c3b6f7aba081dd38965d78d7d58ffHarish Mahendrakar            outBuffer->meta()->setInt32("flags", MediaCodec::BUFFER_FLAG_CODECCONFIG);
2040033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            ALOGV("onWorkDone: csd index = %zu", index);
2041033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
2042033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            buffers.unlock();
2043033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            mCallback->onOutputBufferAvailable(index, outBuffer);
2044033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            buffers.lock();
2045384b6a0bcf56a6cdc81fad923fc4695027fa42ddWonsik Kim            feedNeeded = false;
2046033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        } else {
2047033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            ALOGE("onWorkDone: unable to register csd");
2048033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            buffers.unlock();
2049384b6a0bcf56a6cdc81fad923fc4695027fa42ddWonsik Kim            mCCodecCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL);
2050033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            buffers.lock();
2051384b6a0bcf56a6cdc81fad923fc4695027fa42ddWonsik Kim            return false;
2052033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
2053033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
2054033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
2055033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (!buffer && !flags) {
2056a28531affe22ce6db653e09e7978730dbd1f068aWonsik Kim        ALOGV("onWorkDone: Not reporting output buffer (%lld)",
2057a28531affe22ce6db653e09e7978730dbd1f068aWonsik Kim              work->input.ordinal.frameIndex.peekull());
2058384b6a0bcf56a6cdc81fad923fc4695027fa42ddWonsik Kim        return feedNeeded;
2059033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
2060033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
2061033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (buffer) {
2062033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        for (const std::shared_ptr<const C2Info> &info : buffer->info()) {
2063033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            // TODO: properly translate these to metadata
2064033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            switch (info->coreIndex().coreIndex()) {
2065033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                case C2StreamPictureTypeMaskInfo::CORE_INDEX:
2066033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                    if (((C2StreamPictureTypeMaskInfo *)info.get())->value & C2PictureTypeKeyFrame) {
2067033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                        flags |= MediaCodec::BUFFER_FLAG_SYNCFRAME;
2068033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                    }
2069033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                    break;
2070033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                default:
2071033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                    break;
2072033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            }
2073033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
2074033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
2075033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
2076033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    {
2077033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        Mutexed<std::unique_ptr<OutputBuffers>>::Locked buffers(mOutputBuffers);
2078033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (!(*buffers)->registerBuffer(buffer, &index, &outBuffer)) {
2079033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            ALOGE("onWorkDone: unable to register output buffer");
20806b660d3c8bbc9cf48f00d15e062d1708bc315efcPraveen Chavan            // TODO
20816b660d3c8bbc9cf48f00d15e062d1708bc315efcPraveen Chavan            // buffers.unlock();
2082384b6a0bcf56a6cdc81fad923fc4695027fa42ddWonsik Kim            // mCCodecCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL);
20836b660d3c8bbc9cf48f00d15e062d1708bc315efcPraveen Chavan            // buffers.lock();
2084384b6a0bcf56a6cdc81fad923fc4695027fa42ddWonsik Kim            return false;
2085033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
2086033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
2087033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
2088033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    outBuffer->meta()->setInt64("timeUs", worklet->output.ordinal.timestamp.peek());
2089033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    outBuffer->meta()->setInt32("flags", flags);
2090585b02290e1dc5c0fb6a635ce19d9ec785dbf60aWonsik Kim    ALOGV("onWorkDone: out buffer index = %zu size = %zu", index, outBuffer->size());
2091033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mCallback->onOutputBufferAvailable(index, outBuffer);
2092384b6a0bcf56a6cdc81fad923fc4695027fa42ddWonsik Kim    return false;
2093033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
2094033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
2095033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimstatus_t CCodecBufferChannel::setSurface(const sp<Surface> &newSurface) {
2096033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (newSurface != nullptr) {
2097033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        newSurface->setScalingMode(NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
209860e4b7347394676287f7686ddced77544a106831Wonsik Kim        newSurface->setMaxDequeuedBufferCount(kMinOutputBufferArraySize);
2099033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
2100033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
2101033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim//    if (newSurface == nullptr) {
2102033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim//        if (*surface != nullptr) {
2103033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim//            ALOGW("cannot unset a surface");
2104033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim//            return INVALID_OPERATION;
2105033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim//        }
2106033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim//        return OK;
2107033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim//    }
2108033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim//
2109033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim//    if (*surface == nullptr) {
2110033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim//        ALOGW("component was not configured with a surface");
2111033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim//        return INVALID_OPERATION;
2112033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim//    }
2113033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
21142cc26aada0fc1c80eb2564eb19f1b085380d07b9Pawin Vongmasa    uint32_t generation;
21152cc26aada0fc1c80eb2564eb19f1b085380d07b9Pawin Vongmasa
2116c61f8ada1d56cae29a86f72ece574d011931e46bWonsik Kim    ANativeWindowBuffer *buf;
21172cc26aada0fc1c80eb2564eb19f1b085380d07b9Pawin Vongmasa    ANativeWindow *window = newSurface.get();
2118c61f8ada1d56cae29a86f72ece574d011931e46bWonsik Kim    int fenceFd;
2119c61f8ada1d56cae29a86f72ece574d011931e46bWonsik Kim    window->dequeueBuffer(window, &buf, &fenceFd);
2120c61f8ada1d56cae29a86f72ece574d011931e46bWonsik Kim    sp<GraphicBuffer> gbuf = GraphicBuffer::from(buf);
21212cc26aada0fc1c80eb2564eb19f1b085380d07b9Pawin Vongmasa    generation = gbuf->getGenerationNumber();
2122c61f8ada1d56cae29a86f72ece574d011931e46bWonsik Kim    window->cancelBuffer(window, buf, fenceFd);
2123033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
21242cc26aada0fc1c80eb2564eb19f1b085380d07b9Pawin Vongmasa    std::shared_ptr<Codec2Client::Configurable> outputPoolIntf;
21252cc26aada0fc1c80eb2564eb19f1b085380d07b9Pawin Vongmasa    C2BlockPool::local_id_t outputPoolId;
21262cc26aada0fc1c80eb2564eb19f1b085380d07b9Pawin Vongmasa    {
21272cc26aada0fc1c80eb2564eb19f1b085380d07b9Pawin Vongmasa        Mutexed<BlockPools>::Locked pools(mBlockPools);
21282cc26aada0fc1c80eb2564eb19f1b085380d07b9Pawin Vongmasa        outputPoolId = pools->outputPoolId;
21292cc26aada0fc1c80eb2564eb19f1b085380d07b9Pawin Vongmasa        outputPoolIntf = pools->outputPoolIntf;
21302cc26aada0fc1c80eb2564eb19f1b085380d07b9Pawin Vongmasa    }
21312cc26aada0fc1c80eb2564eb19f1b085380d07b9Pawin Vongmasa
21322cc26aada0fc1c80eb2564eb19f1b085380d07b9Pawin Vongmasa    if (outputPoolIntf) {
21332cc26aada0fc1c80eb2564eb19f1b085380d07b9Pawin Vongmasa        if (mComponent->setOutputSurface(
21342cc26aada0fc1c80eb2564eb19f1b085380d07b9Pawin Vongmasa                outputPoolId,
21352cc26aada0fc1c80eb2564eb19f1b085380d07b9Pawin Vongmasa                newSurface->getIGraphicBufferProducer(),
21362cc26aada0fc1c80eb2564eb19f1b085380d07b9Pawin Vongmasa                generation) != C2_OK) {
21372cc26aada0fc1c80eb2564eb19f1b085380d07b9Pawin Vongmasa            ALOGW("setSurface -- setOutputSurface() failed to configure "
21382cc26aada0fc1c80eb2564eb19f1b085380d07b9Pawin Vongmasa                    "new surface to the component's output block pool.");
21392cc26aada0fc1c80eb2564eb19f1b085380d07b9Pawin Vongmasa            return INVALID_OPERATION;
21402cc26aada0fc1c80eb2564eb19f1b085380d07b9Pawin Vongmasa        }
21412cc26aada0fc1c80eb2564eb19f1b085380d07b9Pawin Vongmasa    }
21422cc26aada0fc1c80eb2564eb19f1b085380d07b9Pawin Vongmasa
21432cc26aada0fc1c80eb2564eb19f1b085380d07b9Pawin Vongmasa    {
21442cc26aada0fc1c80eb2564eb19f1b085380d07b9Pawin Vongmasa        Mutexed<OutputSurface>::Locked output(mOutputSurface);
21452cc26aada0fc1c80eb2564eb19f1b085380d07b9Pawin Vongmasa        output->surface = newSurface;
21462cc26aada0fc1c80eb2564eb19f1b085380d07b9Pawin Vongmasa        output->generation = generation = gbuf->getGenerationNumber();
21472cc26aada0fc1c80eb2564eb19f1b085380d07b9Pawin Vongmasa    }
21482cc26aada0fc1c80eb2564eb19f1b085380d07b9Pawin Vongmasa
2149033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    return OK;
2150033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
2151033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
2152f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kimvoid CCodecBufferChannel::setMetaMode(MetaMode mode) {
2153f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim    mMetaMode = mode;
2154f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim}
2155f15a341c8d0e931321c4ba4fa8ab1da53b9504e2Wonsik Kim
2156033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}  // namespace android
2157