Home | History | Annotate | Download | only in sfplugin
      1 /*
      2  * Copyright 2017, The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #ifndef CCODEC_BUFFER_CHANNEL_H_
     18 
     19 #define CCODEC_BUFFER_CHANNEL_H_
     20 
     21 #include <map>
     22 #include <memory>
     23 #include <mutex>
     24 #include <vector>
     25 
     26 #include <C2Buffer.h>
     27 #include <C2Component.h>
     28 
     29 #include <codec2/hidl/client.h>
     30 #include <media/stagefright/bqhelper/GraphicBufferSource.h>
     31 #include <media/stagefright/codec2/1.0/InputSurface.h>
     32 #include <media/stagefright/foundation/Mutexed.h>
     33 #include <media/stagefright/CodecBase.h>
     34 #include <media/ICrypto.h>
     35 
     36 #include "InputSurfaceWrapper.h"
     37 
     38 namespace android {
     39 
     40 class CCodecCallback {
     41 public:
     42     virtual ~CCodecCallback() = default;
     43     virtual void onError(status_t err, enum ActionCode actionCode) = 0;
     44     virtual void onOutputFramesRendered(int64_t mediaTimeUs, nsecs_t renderTimeNs) = 0;
     45 };
     46 
     47 /**
     48  * BufferChannelBase implementation for CCodec.
     49  */
     50 class CCodecBufferChannel
     51     : public BufferChannelBase, public std::enable_shared_from_this<CCodecBufferChannel> {
     52 public:
     53     explicit CCodecBufferChannel(const std::shared_ptr<CCodecCallback> &callback);
     54     virtual ~CCodecBufferChannel();
     55 
     56     // BufferChannelBase interface
     57     virtual status_t queueInputBuffer(const sp<MediaCodecBuffer> &buffer) override;
     58     virtual status_t queueSecureInputBuffer(
     59             const sp<MediaCodecBuffer> &buffer,
     60             bool secure,
     61             const uint8_t *key,
     62             const uint8_t *iv,
     63             CryptoPlugin::Mode mode,
     64             CryptoPlugin::Pattern pattern,
     65             const CryptoPlugin::SubSample *subSamples,
     66             size_t numSubSamples,
     67             AString *errorDetailMsg) override;
     68     virtual status_t renderOutputBuffer(
     69             const sp<MediaCodecBuffer> &buffer, int64_t timestampNs) override;
     70     virtual status_t discardBuffer(const sp<MediaCodecBuffer> &buffer) override;
     71     virtual void getInputBufferArray(Vector<sp<MediaCodecBuffer>> *array) override;
     72     virtual void getOutputBufferArray(Vector<sp<MediaCodecBuffer>> *array) override;
     73 
     74     // Methods below are interface for CCodec to use.
     75 
     76     /**
     77      * Set the component object for buffer processing.
     78      */
     79     void setComponent(const std::shared_ptr<Codec2Client::Component> &component);
     80 
     81     /**
     82      * Set output graphic surface for rendering.
     83      */
     84     status_t setSurface(const sp<Surface> &surface);
     85 
     86     /**
     87      * Set GraphicBufferSource object from which the component extracts input
     88      * buffers.
     89      */
     90     status_t setInputSurface(const std::shared_ptr<InputSurfaceWrapper> &surface);
     91 
     92     /**
     93      * Signal EOS to input surface.
     94      */
     95     status_t signalEndOfInputStream();
     96 
     97     /**
     98      * Start queueing buffers to the component. This object should never queue
     99      * buffers before this call.
    100      */
    101     status_t start(const sp<AMessage> &inputFormat, const sp<AMessage> &outputFormat);
    102 
    103     /**
    104      * Stop queueing buffers to the component. This object should never queue
    105      * buffers after this call, until start() is called.
    106      */
    107     void stop();
    108 
    109     void flush(const std::list<std::unique_ptr<C2Work>> &flushedWork);
    110 
    111     /**
    112      * Notify input client about work done.
    113      *
    114      * @param workItems   finished work item.
    115      * @param outputFormat new output format if it has changed, otherwise nullptr
    116      * @param initData    new init data (CSD) if it has changed, otherwise nullptr
    117      */
    118     void onWorkDone(
    119             std::unique_ptr<C2Work> work, const sp<AMessage> &outputFormat,
    120             const C2StreamInitDataInfo::output *initData);
    121 
    122     enum MetaMode {
    123         MODE_NONE,
    124         MODE_ANW,
    125     };
    126 
    127     void setMetaMode(MetaMode mode);
    128 
    129     // Internal classes
    130     class Buffers;
    131     class InputBuffers;
    132     class OutputBuffers;
    133 
    134 private:
    135     class QueueGuard;
    136 
    137     /**
    138      * Special mutex-like object with the following properties:
    139      *
    140      * - At STOPPED state (initial, or after stop())
    141      *   - QueueGuard object gets created at STOPPED state, and the client is
    142      *     supposed to return immediately.
    143      * - At RUNNING state (after start())
    144      *   - Each QueueGuard object
    145      */
    146     class QueueSync {
    147     public:
    148         /**
    149          * At construction the sync object is in STOPPED state.
    150          */
    151         inline QueueSync() : mCount(-1) {}
    152         ~QueueSync() = default;
    153 
    154         /**
    155          * Transition to RUNNING state when stopped. No-op if already in RUNNING
    156          * state.
    157          */
    158         void start();
    159 
    160         /**
    161          * At RUNNING state, wait until all QueueGuard object created during
    162          * RUNNING state are destroyed, and then transition to STOPPED state.
    163          * No-op if already in STOPPED state.
    164          */
    165         void stop();
    166 
    167     private:
    168         std::mutex mMutex;
    169         std::atomic_int32_t mCount;
    170 
    171         friend class CCodecBufferChannel::QueueGuard;
    172     };
    173 
    174     class QueueGuard {
    175     public:
    176         QueueGuard(QueueSync &sync);
    177         ~QueueGuard();
    178         inline bool isRunning() { return mRunning; }
    179 
    180     private:
    181         QueueSync &mSync;
    182         bool mRunning;
    183     };
    184 
    185     void feedInputBufferIfAvailable();
    186     void feedInputBufferIfAvailableInternal();
    187     status_t queueInputBufferInternal(const sp<MediaCodecBuffer> &buffer);
    188     bool handleWork(
    189             std::unique_ptr<C2Work> work, const sp<AMessage> &outputFormat,
    190             const C2StreamInitDataInfo::output *initData);
    191 
    192     QueueSync mSync;
    193     sp<MemoryDealer> mDealer;
    194     sp<IMemory> mDecryptDestination;
    195     int32_t mHeapSeqNum;
    196 
    197     std::shared_ptr<Codec2Client::Component> mComponent;
    198     std::shared_ptr<CCodecCallback> mCCodecCallback;
    199     std::shared_ptr<C2BlockPool> mInputAllocator;
    200     QueueSync mQueueSync;
    201 
    202     Mutexed<std::unique_ptr<InputBuffers>> mInputBuffers;
    203     Mutexed<std::unique_ptr<OutputBuffers>> mOutputBuffers;
    204 
    205     std::atomic_uint64_t mFrameIndex;
    206     std::atomic_uint64_t mFirstValidFrameIndex;
    207 
    208     sp<MemoryDealer> makeMemoryDealer(size_t heapSize);
    209 
    210     struct OutputSurface {
    211         sp<Surface> surface;
    212         uint32_t generation;
    213     };
    214     Mutexed<OutputSurface> mOutputSurface;
    215 
    216     struct BlockPools {
    217         C2Allocator::id_t inputAllocatorId;
    218         std::shared_ptr<C2BlockPool> inputPool;
    219         C2Allocator::id_t outputAllocatorId;
    220         C2BlockPool::local_id_t outputPoolId;
    221         std::shared_ptr<Codec2Client::Configurable> outputPoolIntf;
    222     };
    223     Mutexed<BlockPools> mBlockPools;
    224 
    225     std::shared_ptr<InputSurfaceWrapper> mInputSurface;
    226 
    227     MetaMode mMetaMode;
    228     std::atomic_int32_t mPendingFeed;
    229 
    230     inline bool hasCryptoOrDescrambler() {
    231         return mCrypto != NULL || mDescrambler != NULL;
    232     }
    233 };
    234 
    235 }  // namespace android
    236 
    237 #endif  // CCODEC_BUFFER_CHANNEL_H_
    238