1 // Copyright 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef ANDROID_V4L2_CODEC2_COMMON_FORMAT_CONVERTER_H
6 #define ANDROID_V4L2_CODEC2_COMMON_FORMAT_CONVERTER_H
7 
8 #include <limits>
9 #include <queue>
10 #include <vector>
11 
12 #include <C2Buffer.h>
13 #include <ui/Size.h>
14 #include <utils/StrongPointer.h>
15 
16 #include <v4l2_codec2/common/VideoPixelFormat.h>
17 
18 namespace android {
19 
20 class GraphicBuffer;
21 
22 // ImplDefinedToRGBXMap can provide the layout for RGB-backed IMPLEMENTATION_DEFINED format case,
23 // which will be failed to map by C2AllocationGralloc::map(). When the instance is created, it will
24 // own the GraphicBuffer wrapped from input block and lock it, to provide the address, offset, and
25 // rowInc information. The GraphicBuffer will be unlocked and released under destruction.
26 class ImplDefinedToRGBXMap {
27 public:
28     ~ImplDefinedToRGBXMap();
29     ImplDefinedToRGBXMap() = delete;
30 
31     static std::unique_ptr<ImplDefinedToRGBXMap> Create(const C2ConstGraphicBlock& block);
32 
addr()33     const uint8_t* addr() const { return mAddr; }
offset()34     int offset() const { return 0; }
rowInc()35     int rowInc() const { return mRowInc; }
36 
37 private:
38     ImplDefinedToRGBXMap(sp<GraphicBuffer> buf, uint8_t* addr, int rowInc);
39 
40     const sp<GraphicBuffer> mBuffer;
41     const uint8_t* mAddr;
42     const int mRowInc;
43 };
44 
45 class FormatConverter {
46 public:
47     ~FormatConverter() = default;
48 
49     FormatConverter(const FormatConverter&) = delete;
50     FormatConverter& operator=(const FormatConverter&) = delete;
51 
52     // Create FormatConverter instance and initialize it, nullptr will be returned on
53     // initialization error.
54     static std::unique_ptr<FormatConverter> Create(VideoPixelFormat outFormat,
55                                                    const ui::Size& visibleSize, uint32_t inputCount,
56                                                    const ui::Size& codedSize);
57 
58     // Convert the input block into the alternative block with required pixel format and return it,
59     // or return the original block if zero-copy is applied.
60     C2ConstGraphicBlock convertBlock(uint64_t frameIndex, const C2ConstGraphicBlock& inputBlock,
61                                      c2_status_t* status /* non-null */);
62     // Return the block ownership when VEA no longer needs it, or erase the zero-copy BlockEntry.
63     c2_status_t returnBlock(uint64_t frameIndex);
64     // Check if there is available block for conversion.
isReady()65     bool isReady() const { return !mAvailableQueue.empty(); }
66 
67 private:
68     // The minimal number requirement of allocated buffers for conversion. This value is the same as
69     // kMinInputBufferArraySize from CCodecBufferChannel.
70     static constexpr uint32_t kMinInputBufferCount = 8;
71     // The constant used by BlockEntry to indicate no frame is associated with the BlockEntry.
72     static constexpr uint64_t kNoFrameAssociated = ~static_cast<uint64_t>(0);
73 
74     // There are 2 types of BlockEntry:
75     // 1. If |mBlock| is an allocated graphic block (not nullptr). This BlockEntry is for
76     //    conversion, and |mAssociatedFrameIndex| records the frame index of the input frame which
77     //    is currently converted from. This is created on initialize() and released while
78     //    FormatConverter is destroyed.
79     // 2. If |mBlock| is nullptr. This BlockEntry is only used to record zero-copied frame index to
80     //    |mAssociatedFrameIndex|. This is created on zero-copy is applied during convertBlock(),
81     //    and released on returnBlock() in associated with returned frame index.
82     struct BlockEntry {
83         // Constructor of convertible entry.
BlockEntryBlockEntry84         BlockEntry(std::shared_ptr<C2GraphicBlock> block) : mBlock(std::move(block)) {}
85         // Constructir of zero-copy entry.
BlockEntryBlockEntry86         BlockEntry(uint64_t frameIndex) : mAssociatedFrameIndex(frameIndex) {}
87 
88         std::shared_ptr<C2GraphicBlock> mBlock;
89         uint64_t mAssociatedFrameIndex = kNoFrameAssociated;
90     };
91 
92     FormatConverter() = default;
93 
94     // Initialize foramt converter. It will pre-allocate a set of graphic blocks as |codedSize| and
95     // |outFormat|. This function should be called prior to other functions.
96     c2_status_t initialize(VideoPixelFormat outFormat, const ui::Size& visibleSize,
97                            uint32_t inputCount, const ui::Size& codedSize);
98 
99     // The array of block entries.
100     std::vector<std::unique_ptr<BlockEntry>> mGraphicBlocks;
101     // The queue of recording the raw pointers of available graphic blocks. The consumed block will
102     // be popped on convertBlock(), and returned block will be pushed on returnBlock().
103     std::queue<BlockEntry*> mAvailableQueue;
104     // The temporary U/V plane memory allocation for ABGR to NV12 conversion. They should be
105     // allocated on initialize().
106     std::unique_ptr<uint8_t[]> mTempPlaneU;
107     std::unique_ptr<uint8_t[]> mTempPlaneV;
108 
109     VideoPixelFormat mOutFormat = VideoPixelFormat::UNKNOWN;
110     ui::Size mVisibleSize;
111 };
112 
113 }  // namespace android
114 
115 #endif  // ANDROID_V4L2_CODEC2_COMMON_FORMAT_CONVERTER_H
116