1e41f4b71Sopenharmony_ci# Codec
2e41f4b71Sopenharmony_ci
3e41f4b71Sopenharmony_ci## Overview
4e41f4b71Sopenharmony_ci### Function
5e41f4b71Sopenharmony_ci
6e41f4b71Sopenharmony_ciThe OpenHarmony codec Hardware Device Interface (HDI) driver framework implements the video hardware codec driver based on OpenMAX. It provides APIs for the upper-layer media services to obtain component encoding and decoding capabilities, create a component, set parameters, transfer data, and destroy a component. The codec driver can encode video data in YUV or RGB format to H.264 or H.265 format, and decode raw stream data from H.264 or H.265 format to YUV or RGB format. This document describes the codec functionality developed based on the OpenHarmony Hardware Driver Foundation (HDF).
7e41f4b71Sopenharmony_ci
8e41f4b71Sopenharmony_ciThe codec HDI driver framework is implemented based on the HDF. The figure below shows the codec HDI driver framework.
9e41f4b71Sopenharmony_ci
10e41f4b71Sopenharmony_ci**Figure 1** Codec HDI driver framework
11e41f4b71Sopenharmony_ci
12e41f4b71Sopenharmony_ci![image](figures/Codec_architecture.png "Codec HDI driver framework")
13e41f4b71Sopenharmony_ci
14e41f4b71Sopenharmony_ci- Codec HDI Callback Remote Service: an anonymous callback service used to process callbacks.
15e41f4b71Sopenharmony_ci- Codec HDI: provides standard APIs based on OpenMAX. The upper layer services call the APIs to implement hardware encoding and decoding.
16e41f4b71Sopenharmony_ci- Codec HDI Adapter: HDI implementation layer, which implements HDI APIs and interacts with OpenMAX Integration layer (IL).
17e41f4b71Sopenharmony_ci- OpenMAX IL interface: provides OpenMAX IL APIs to directly interact with the codec HDI driver.
18e41f4b71Sopenharmony_ci- Vendor Impl: vendor adaptation layer, which is the OpenMAX implementation layer adapted by each vendor.
19e41f4b71Sopenharmony_ci- Codec Hardware: hardware decoding device.
20e41f4b71Sopenharmony_ci
21e41f4b71Sopenharmony_ci### Basic Concepts
22e41f4b71Sopenharmony_ciBefore you get started, understand the following concepts:
23e41f4b71Sopenharmony_ci
24e41f4b71Sopenharmony_ci- Sampling rate
25e41f4b71Sopenharmony_ci
26e41f4b71Sopenharmony_ci    The number of samples taken from continuous signals every second to form discrete signals, in Hz.
27e41f4b71Sopenharmony_ci
28e41f4b71Sopenharmony_ci- OpenMAX IL
29e41f4b71Sopenharmony_ci
30e41f4b71Sopenharmony_ci    A standardized media component interface to enable applications and media frameworks to interact with multimedia codecs and supported components in a unified manner.
31e41f4b71Sopenharmony_ci
32e41f4b71Sopenharmony_ci- Frame rate
33e41f4b71Sopenharmony_ci
34e41f4b71Sopenharmony_ci    Number of frames of images transmitted per second, or the number of times that a GPU can refresh images per second. A higher frame rate indicates smoother motion, while a lower frame rate means choppier motion and blurry footage.
35e41f4b71Sopenharmony_ci
36e41f4b71Sopenharmony_ci- Bit rate
37e41f4b71Sopenharmony_ci
38e41f4b71Sopenharmony_ci    Number of bits transmitted or processed per unit of time, generally in kbit/s. A higher bit rate indicates clearer image, while a lower bit rate means blurry image with artifacts.
39e41f4b71Sopenharmony_ci
40e41f4b71Sopenharmony_ci- Component
41e41f4b71Sopenharmony_ci
42e41f4b71Sopenharmony_ci    An OpenMAX IL component, which is an abstraction of modules in video streams. The components in this document refer to codec components used for video encoding and decoding.
43e41f4b71Sopenharmony_ci
44e41f4b71Sopenharmony_ci### Constraints
45e41f4b71Sopenharmony_ci
46e41f4b71Sopenharmony_ciThe codec HDI applies only to the standard system.
47e41f4b71Sopenharmony_ci
48e41f4b71Sopenharmony_ciFor more details, see [OpenMAX IL](https://www.khronos.org/api/openmax/il).
49e41f4b71Sopenharmony_ci
50e41f4b71Sopenharmony_ci## Development Guidelines
51e41f4b71Sopenharmony_ci
52e41f4b71Sopenharmony_ci### When to Use
53e41f4b71Sopenharmony_ciThe codec module implements hardware encoding and decoding of video data. It converts raw stream data such as H.264 data into YUV or RGB data, and converts YUV or RGB data into data formats such as H.264.
54e41f4b71Sopenharmony_ci
55e41f4b71Sopenharmony_ci### Available APIs
56e41f4b71Sopenharmony_ci
57e41f4b71Sopenharmony_ci- icodec_component_manager.h
58e41f4b71Sopenharmony_ci
59e41f4b71Sopenharmony_ci  | API                                                                                                                                                      | Description                     |
60e41f4b71Sopenharmony_ci  | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------|
61e41f4b71Sopenharmony_ci  | int32_t CreateComponent(sptr<ICodecComponent>& component, uint32_t& componentId,<br>const std::string& compName, int64_t appData, const sptr<ICodecCallback>& callbacks) | Creates a codec component instance.            |
62e41f4b71Sopenharmony_ci  | int32_t DestoryComponent(uint32_t componentId)                                                                | Destroys a codec component instance.                 |
63e41f4b71Sopenharmony_ci
64e41f4b71Sopenharmony_ci- icodec_component.h
65e41f4b71Sopenharmony_ci
66e41f4b71Sopenharmony_ci  | API                                                    | Description              |
67e41f4b71Sopenharmony_ci  | ------------------------------------------------------------ | ---------------------- |
68e41f4b71Sopenharmony_ci  | int32_t SendCommand(CodecCommandType cmd, uint32_t param, const std::vector<int8_t>& cmdData) | Sends commands to a component.        |
69e41f4b71Sopenharmony_ci  | int32_t GetParameter(uint32_t index, const std::vector<int8_t>& inParamStruct, std::vector<int8_t>& outParamStruct) | Obtains component parameter settings.      |
70e41f4b71Sopenharmony_ci  | int32_t SetParameter(uint32_t index, const std::vector<int8_t>& paramStruct) | Sets component parameters.    |
71e41f4b71Sopenharmony_ci  | int32_t GetState(CodecStateType& state)                      | Obtains the component status.        |
72e41f4b71Sopenharmony_ci  | int32_t UseBuffer(uint32_t portIndex, const OmxCodecBuffer& inBuffer, OmxCodecBuffer& outBuffer) | Requests a port buffer for the component.  |
73e41f4b71Sopenharmony_ci  | int32_t FreeBuffer(uint32_t portIndex, const OmxCodecBuffer& buffer) | Releases the buffer.            |
74e41f4b71Sopenharmony_ci  | int32_t EmptyThisBuffer(const OmxCodecBuffer& buffer)        | Empties this buffer.|
75e41f4b71Sopenharmony_ci  | int32_t FillThisBuffer(const OmxCodecBuffer& buffer)         | Fills this buffer.  |
76e41f4b71Sopenharmony_ci
77e41f4b71Sopenharmony_ci- icodec_callback.h
78e41f4b71Sopenharmony_ci
79e41f4b71Sopenharmony_ci  | API                                                    | Description                          |
80e41f4b71Sopenharmony_ci  | ------------------------------------------------------------ | ---------------------------------- |
81e41f4b71Sopenharmony_ci  | int32_t EventHandler(CodecEventType event, const EventInfo& info) | Called to report an event.                          |
82e41f4b71Sopenharmony_ci  | int32_t EmptyBufferDone(int64_t appData, const OmxCodecBuffer& buffer) | Called to report an event indicating that the encoding or decoding in the input buffer is complete.|
83e41f4b71Sopenharmony_ci  | int32_t FillBufferDone(int64_t appData, const OmxCodecBuffer& buffer) | Called to report an event indicating that the output buffer is filled.            |
84e41f4b71Sopenharmony_ci
85e41f4b71Sopenharmony_ciFor more information, see [codec](https://gitee.com/openharmony/drivers_peripheral/tree/master/codec).
86e41f4b71Sopenharmony_ci
87e41f4b71Sopenharmony_ci### Development Procedure
88e41f4b71Sopenharmony_ciThe codec HDI driver development procedure is as follows:
89e41f4b71Sopenharmony_ci
90e41f4b71Sopenharmony_ci#### Registering and Initializing the Driver
91e41f4b71Sopenharmony_ciDefine the **HdfDriverEntry** structure (which defines the driver initialization method) and fill in the **g_codeccomponentmanagerDriverEntry** structure to implement the pointers in **Bind()**, **Init()**, and **Release()**.
92e41f4b71Sopenharmony_ci
93e41f4b71Sopenharmony_ci```c
94e41f4b71Sopenharmony_cistatic struct HdfDriverEntry g_codeccomponentmanagerDriverEntry = {
95e41f4b71Sopenharmony_ci    .moduleVersion = 1,
96e41f4b71Sopenharmony_ci    .moduleName = "codec_component_manager_service",
97e41f4b71Sopenharmony_ci    .Bind = HdfCodecComponentManagerDriverBind,
98e41f4b71Sopenharmony_ci    .Init = HdfCodecComponentManagerDriverInit,
99e41f4b71Sopenharmony_ci    .Release = HdfCodecComponentManagerDriverRelease,
100e41f4b71Sopenharmony_ci}; // Register the HdfDriverEntry structure of the codec HDI with the HDF.
101e41f4b71Sopenharmony_ci```
102e41f4b71Sopenharmony_ci
103e41f4b71Sopenharmony_ci- **HdfCodecComponentManagerDriverBind**: binds the device in the HDF to the **HdfCodecComponentManagerHost** and registers the codec service with the HDF.
104e41f4b71Sopenharmony_ci
105e41f4b71Sopenharmony_ci    ```c
106e41f4b71Sopenharmony_ci    static int HdfCodecComponentManagerDriverBind(struct HdfDeviceObject *deviceObject)
107e41f4b71Sopenharmony_ci    {
108e41f4b71Sopenharmony_ci        CODEC_LOGI("HdfCodecComponentManagerDriverBind enter");
109e41f4b71Sopenharmony_ci    
110e41f4b71Sopenharmony_ci        auto *hdfCodecComponentManagerHost = new (std::nothrow) HdfCodecComponentManagerHost;
111e41f4b71Sopenharmony_ci        if (hdfCodecComponentManagerHost == nullptr) {
112e41f4b71Sopenharmony_ci            CODEC_LOGE("failed to create create HdfCodecComponentManagerHost object");
113e41f4b71Sopenharmony_ci            return HDF_FAILURE;
114e41f4b71Sopenharmony_ci        }
115e41f4b71Sopenharmony_ci    
116e41f4b71Sopenharmony_ci        hdfCodecComponentManagerHost->ioService.Dispatch = CodecComponentManagerDriverDispatch;
117e41f4b71Sopenharmony_ci        hdfCodecComponentManagerHost->ioService.Open = NULL;
118e41f4b71Sopenharmony_ci        hdfCodecComponentManagerHost->ioService.Release = NULL;
119e41f4b71Sopenharmony_ci    
120e41f4b71Sopenharmony_ci        auto serviceImpl = ICodecComponentManager::Get(true);
121e41f4b71Sopenharmony_ci        if (serviceImpl == nullptr) {
122e41f4b71Sopenharmony_ci            CODEC_LOGE("failed to get of implement service");
123e41f4b71Sopenharmony_ci            delete hdfCodecComponentManagerHost;
124e41f4b71Sopenharmony_ci            return HDF_FAILURE;
125e41f4b71Sopenharmony_ci        }
126e41f4b71Sopenharmony_ci    
127e41f4b71Sopenharmony_ci        hdfCodecComponentManagerHost->stub =
128e41f4b71Sopenharmony_ci            OHOS::HDI::ObjectCollector::GetInstance().GetOrNewObject(serviceImpl, ICodecComponentManager::GetDescriptor());
129e41f4b71Sopenharmony_ci        if (hdfCodecComponentManagerHost->stub == nullptr) {
130e41f4b71Sopenharmony_ci            CODEC_LOGE("failed to get stub object");
131e41f4b71Sopenharmony_ci            delete hdfCodecComponentManagerHost;
132e41f4b71Sopenharmony_ci            return HDF_FAILURE;
133e41f4b71Sopenharmony_ci        }
134e41f4b71Sopenharmony_ci    
135e41f4b71Sopenharmony_ci        deviceObject->service = &hdfCodecComponentManagerHost->ioService;
136e41f4b71Sopenharmony_ci        return HDF_SUCCESS;
137e41f4b71Sopenharmony_ci    }
138e41f4b71Sopenharmony_ci    ```
139e41f4b71Sopenharmony_ci
140e41f4b71Sopenharmony_ci- **HdfCodecComponentManagerDriverInit**: loads the attribute configuration in the HDF Configuration Source (HCS).
141e41f4b71Sopenharmony_ci
142e41f4b71Sopenharmony_ci    ```c
143e41f4b71Sopenharmony_ci    static int HdfCodecComponentManagerDriverInit(struct HdfDeviceObject *deviceObject)
144e41f4b71Sopenharmony_ci    {
145e41f4b71Sopenharmony_ci        CODEC_LOGI("HdfCodecComponentManagerDriverInit enter");
146e41f4b71Sopenharmony_ci        if (DevHostRegisterDumpHost(CodecDfxService::DevCodecHostDump) != HDF_SUCCESS) {
147e41f4b71Sopenharmony_ci            CODEC_LOGE("DevHostRegisterDumpHost error!");
148e41f4b71Sopenharmony_ci        }
149e41f4b71Sopenharmony_ci        return HDF_SUCCESS;
150e41f4b71Sopenharmony_ci    }
151e41f4b71Sopenharmony_ci    ```
152e41f4b71Sopenharmony_ci    
153e41f4b71Sopenharmony_ci- **HdfCodecComponentTypeDriverRelease**: releases the driver instance.
154e41f4b71Sopenharmony_ci
155e41f4b71Sopenharmony_ci    ```c
156e41f4b71Sopenharmony_ci    static void HdfCodecComponentManagerDriverRelease(struct HdfDeviceObject *deviceObject)
157e41f4b71Sopenharmony_ci    {
158e41f4b71Sopenharmony_ci        CODEC_LOGI("HdfCodecComponentManagerDriverRelease enter");
159e41f4b71Sopenharmony_ci        if (deviceObject->service == nullptr) {
160e41f4b71Sopenharmony_ci            CODEC_LOGE("HdfCodecComponentManagerDriverRelease not initted");
161e41f4b71Sopenharmony_ci            return;
162e41f4b71Sopenharmony_ci        }
163e41f4b71Sopenharmony_ci    
164e41f4b71Sopenharmony_ci        auto *hdfCodecComponentManagerHost =
165e41f4b71Sopenharmony_ci            CONTAINER_OF(deviceObject->service, struct HdfCodecComponentManagerHost, ioService);
166e41f4b71Sopenharmony_ci        delete hdfCodecComponentManagerHost;
167e41f4b71Sopenharmony_ci    }
168e41f4b71Sopenharmony_ci    ```
169e41f4b71Sopenharmony_ci
170e41f4b71Sopenharmony_ci#### Driver HCS
171e41f4b71Sopenharmony_ciThe HCS consists of the following:
172e41f4b71Sopenharmony_ci
173e41f4b71Sopenharmony_ci- Device configuration
174e41f4b71Sopenharmony_ci- Configuration of the supported components
175e41f4b71Sopenharmony_ci
176e41f4b71Sopenharmony_ciYou need to configure the driver node, loading sequence, and service name. For details about the HCS syntax, see [Configuration Management](driver-hdf-manage.md).
177e41f4b71Sopenharmony_ci
178e41f4b71Sopenharmony_ciThe following uses the RK3568 development board as an example. The configuration files of the standard system are in the
179e41f4b71Sopenharmony_ci**vendor/hihope/rk3568/hdf_config/uhdf/** directory.
180e41f4b71Sopenharmony_ci
181e41f4b71Sopenharmony_ci1. Configure the device.
182e41f4b71Sopenharmony_ci
183e41f4b71Sopenharmony_ci    Add the **codec_component_manager_service** configuration to **codec_host** in **device_info.hcs**. The following is an example:
184e41f4b71Sopenharmony_ci    ```c
185e41f4b71Sopenharmony_ci    codec :: host {
186e41f4b71Sopenharmony_ci        hostName = "codec_host";
187e41f4b71Sopenharmony_ci        priority = 50;
188e41f4b71Sopenharmony_ci        gid = ["codec_host", "uhdf_driver", "vendor_mpp_driver"];
189e41f4b71Sopenharmony_ci        codec_omx_idl_device :: device {
190e41f4b71Sopenharmony_ci            device0 :: deviceNode {
191e41f4b71Sopenharmony_ci                policy = 2;                                       // Automatic loading, not lazy loading.
192e41f4b71Sopenharmony_ci                priority = 100;                                   // Priority.
193e41f4b71Sopenharmony_ci                moduleName = "libcodec_driver.z.so";              // Dynamic library of the driver.
194e41f4b71Sopenharmony_ci                serviceName = "codec_component_manager_service"; // Service name of the driver.
195e41f4b71Sopenharmony_ci                deviceMatchAttr = "media_codec_capabilities";    // Attribute configuration.
196e41f4b71Sopenharmony_ci            }
197e41f4b71Sopenharmony_ci        }
198e41f4b71Sopenharmony_ci    }
199e41f4b71Sopenharmony_ci    ```
200e41f4b71Sopenharmony_ci
201e41f4b71Sopenharmony_ci2. Configure supported components.
202e41f4b71Sopenharmony_ci
203e41f4b71Sopenharmony_ci    Add the component configuration to the **media_codec\media_codec_capabilities.hcs** file. The following is an example:
204e41f4b71Sopenharmony_ci    ```c
205e41f4b71Sopenharmony_ci    /* Explanation to the node name HDF_video_hw_enc_avc_rk:
206e41f4b71Sopenharmony_ci    **
207e41f4b71Sopenharmony_ci    **    HDF____________video__________________hw____________________enc____________avc_______rk
208e41f4b71Sopenharmony_ci    **     |               |                    |                      |              |        |
209e41f4b71Sopenharmony_ci    ** HDF or OMX    video or audio    hardware or software    encoder or decoder    MIME    vendor
210e41f4b71Sopenharmony_ci    */
211e41f4b71Sopenharmony_ci    HDF_video_hw_enc_avc_rk {
212e41f4b71Sopenharmony_ci        role = 1;                                           // Role of the audio and video codec.
213e41f4b71Sopenharmony_ci        type = 1;                                           // Codec type.
214e41f4b71Sopenharmony_ci        name = "OMX.rk.video_encoder.avc";                  // Component name.
215e41f4b71Sopenharmony_ci        supportProfiles = [1, 32768, 2, 32768, 8, 32768]; // Supported profiles.
216e41f4b71Sopenharmony_ci        maxInst = 4;                                        // Maximum number of instances.
217e41f4b71Sopenharmony_ci        isSoftwareCodec = false;                            // Whether it is software codec.
218e41f4b71Sopenharmony_ci        processModeMask = [];                               // Codec processing mode.
219e41f4b71Sopenharmony_ci        capsMask = [0x01];                                  // CodecCapsMask configuration.
220e41f4b71Sopenharmony_ci        minBitRate = 1;                                     // Minimum bit rate.
221e41f4b71Sopenharmony_ci        maxBitRate = 40000000;                              // Maximum bit rate.
222e41f4b71Sopenharmony_ci        minWidth = 176;                                     // Minimum video width.
223e41f4b71Sopenharmony_ci        minHeight = 144;;                                   // Minimum video height.
224e41f4b71Sopenharmony_ci        maxWidth = 1920;                                   // Maximum video width.
225e41f4b71Sopenharmony_ci        maxHeight = 1088;                                   // Maximum video height.
226e41f4b71Sopenharmony_ci        widthAlignment = 16;                                // Horizontal alignment.
227e41f4b71Sopenharmony_ci        heightAlignment = 8;                                // Vertical alignment.
228e41f4b71Sopenharmony_ci        minBlockCount = 0xFFFFFFFF;
229e41f4b71Sopenharmony_ci        maxBlockCount = 0xFFFFFFFF;
230e41f4b71Sopenharmony_ci        minBlocksPerSecond = 0xFFFFFFFF;
231e41f4b71Sopenharmony_ci        maxBlocksPerSecond = 0xFFFFFFFF;
232e41f4b71Sopenharmony_ci        blockSizeWidth = 0xFFFFFFFF;
233e41f4b71Sopenharmony_ci        blockSizeHeight = 0xFFFFFFFF;
234e41f4b71Sopenharmony_ci        supportPixelFmts = [28, 24, 20, 12];                // List of colors supported by the display.
235e41f4b71Sopenharmony_ci        measuredFrameRate = [320, 240, 165, 165, 720, 480, 149, 149, 1280, 720, 73, 73, 1920, 1080, 18, 18];
236e41f4b71Sopenharmony_ci        bitRateMode = [1, 2];                                // Bit rate mode.
237e41f4b71Sopenharmony_ci        minFrameRate = 0;                                // Frame rate.
238e41f4b71Sopenharmony_ci        maxFrameRate = 0;
239e41f4b71Sopenharmony_ci    }
240e41f4b71Sopenharmony_ci    ```
241e41f4b71Sopenharmony_ci
242e41f4b71Sopenharmony_ci### Development Example
243e41f4b71Sopenharmony_ciAfter completing codec module driver adaptation, use the HDI APIs provided by the codec module for further development. The codec HDI provides the following features:
244e41f4b71Sopenharmony_ci
245e41f4b71Sopenharmony_ci1. Provides codec HDI APIs for video services to implement encoding and decoding for video services.
246e41f4b71Sopenharmony_ci2. Provides standard interfaces for device developers to ensure that the OEM vendors comply with the HDI adapter standard. This promises a healthy evolution of the ecosystem.
247e41f4b71Sopenharmony_ci
248e41f4b71Sopenharmony_ciThe development procedure is as follows:
249e41f4b71Sopenharmony_ci
250e41f4b71Sopenharmony_ci1. Initialize the driver, including initializing the instances, callbacks, and component.
251e41f4b71Sopenharmony_ci2. Set codec parameters and information such as the video width, height, and bit rate.
252e41f4b71Sopenharmony_ci3. Apply for input and output buffers.
253e41f4b71Sopenharmony_ci4. Flip codec buffers, enable the component to enter the **CODEC_STATE_EXECUTING** state, and process the callbacks.
254e41f4b71Sopenharmony_ci5. Deinitialize the interface instance, destroy the buffers, close the component, and releases all interface instances.
255e41f4b71Sopenharmony_ci
256e41f4b71Sopenharmony_ci#### Initializing the Driver
257e41f4b71Sopenharmony_ciInitialize the interface instance and callbacks, and create a component.
258e41f4b71Sopenharmony_ci```cpp
259e41f4b71Sopenharmony_ci// Initialize the codec HDI ComponentManager instance.
260e41f4b71Sopenharmony_ciomxMgr_ = ICodecComponentManager::Get(false);
261e41f4b71Sopenharmony_ciif ((omxMgr_ == nullptr)) {
262e41f4b71Sopenharmony_ci    HDF_LOGE("%{public}s omxMgr_ is null", __func__);
263e41f4b71Sopenharmony_ci    return false;
264e41f4b71Sopenharmony_ci}
265e41f4b71Sopenharmony_ci// Initialize the callback.
266e41f4b71Sopenharmony_cicallback_ = new CodecHdiCallback(shared_from_this());
267e41f4b71Sopenharmony_ciif ((callback_ == nullptr)) {
268e41f4b71Sopenharmony_ci    HDF_LOGE("%{public}s callback_ is null", __func__);
269e41f4b71Sopenharmony_ci    return false;
270e41f4b71Sopenharmony_ci}
271e41f4b71Sopenharmony_ci// Create a component instance.
272e41f4b71Sopenharmony_cierr = omxMgr_->CreateComponent(client_, componentId_, compName, reinterpret_cast<int64_t>(this), callback_);
273e41f4b71Sopenharmony_ciif (err != HDF_SUCCESS) {
274e41f4b71Sopenharmony_ci    HDF_LOGE("%{public}s failed to CreateComponent", __func__);
275e41f4b71Sopenharmony_ci    return false;
276e41f4b71Sopenharmony_ci}
277e41f4b71Sopenharmony_ci```
278e41f4b71Sopenharmony_ci
279e41f4b71Sopenharmony_ci#### Setting Codec Parameters and Configuration
280e41f4b71Sopenharmony_ciSet the width and height of the input and output data, input data format, and output data format.
281e41f4b71Sopenharmony_ci```cpp
282e41f4b71Sopenharmony_ci// Set the width and height of the input image.
283e41f4b71Sopenharmony_ciOMX_PARAM_PORTDEFINITIONTYPE param;
284e41f4b71Sopenharmony_ciif (util_->InitParam(param) != HDF_SUCCESS) {
285e41f4b71Sopenharmony_ci    return HDF_FAILURE;
286e41f4b71Sopenharmony_ci}
287e41f4b71Sopenharmony_ciparam.nPortIndex = static_cast<uint32_t>(PortIndex::PORT_INDEX_INPUT);
288e41f4b71Sopenharmony_ci
289e41f4b71Sopenharmony_cistd::vector<int8_t> inVec, outVec;
290e41f4b71Sopenharmony_ciutil_->ObjectToVector(param, inVec);
291e41f4b71Sopenharmony_ciauto err = client_->GetParameter(OMX_IndexParamPortDefinition, inVec, outVec);
292e41f4b71Sopenharmony_ciif (err != HDF_SUCCESS) {
293e41f4b71Sopenharmony_ci    HDF_LOGE("%{public}s failed  PortIndex::PORT_INDEX_INPUT, index is OMX_IndexParamPortDefinition", __func__);
294e41f4b71Sopenharmony_ci    return err;
295e41f4b71Sopenharmony_ci}
296e41f4b71Sopenharmony_ciutil_->VectorToObject(outVec, param);
297e41f4b71Sopenharmony_ci
298e41f4b71Sopenharmony_ciHDF_LOGI("PortIndex::PORT_INDEX_INPUT: eCompressionFormat = %{public}d, eColorFormat = %{public}d ",
299e41f4b71Sopenharmony_ci         param.format.video.eCompressionFormat, param.format.video.eColorFormat);
300e41f4b71Sopenharmony_ciutil_->setParmValue(param, width_, height_, stride_);
301e41f4b71Sopenharmony_ciutil_->ObjectToVector(param, inVec);
302e41f4b71Sopenharmony_cierr = client_->SetParameter(OMX_IndexParamPortDefinition, inVec);
303e41f4b71Sopenharmony_ciif (err != HDF_SUCCESS) {
304e41f4b71Sopenharmony_ci    HDF_LOGE("%{public}s failed with PortIndex::PORT_INDEX_INPUT, index is OMX_IndexParamPortDefinition", __func__);
305e41f4b71Sopenharmony_ci    return err;
306e41f4b71Sopenharmony_ci}
307e41f4b71Sopenharmony_ci// Set the output width, height, and format.
308e41f4b71Sopenharmony_ciif (util_->InitParam(param) != HDF_SUCCESS) {
309e41f4b71Sopenharmony_ci    return HDF_FAILURE;
310e41f4b71Sopenharmony_ci}
311e41f4b71Sopenharmony_ciparam.nPortIndex = static_cast<uint32_t>(PortIndex::PORT_INDEX_OUTPUT);
312e41f4b71Sopenharmony_ciutil_->ObjectToVector(param, inVec);
313e41f4b71Sopenharmony_cierr = client_->GetParameter(OMX_IndexParamPortDefinition, inVec, outVec);
314e41f4b71Sopenharmony_ciif (err != HDF_SUCCESS) {
315e41f4b71Sopenharmony_ci    HDF_LOGE("%{public}s failed with PortIndex::PORT_INDEX_OUTPUT, index is OMX_IndexParamPortDefinition",
316e41f4b71Sopenharmony_ci             __func__);
317e41f4b71Sopenharmony_ci    return err;
318e41f4b71Sopenharmony_ci}
319e41f4b71Sopenharmony_ciutil_->VectorToObject(outVec, param);
320e41f4b71Sopenharmony_ci
321e41f4b71Sopenharmony_ciHDF_LOGI("PortIndex::PORT_INDEX_OUTPUT eCompressionFormat = %{public}d, eColorFormat=%{public}d",
322e41f4b71Sopenharmony_ci         param.format.video.eCompressionFormat, param.format.video.eColorFormat);
323e41f4b71Sopenharmony_ciutil_->setParmValue(param, width_, height_, stride_);
324e41f4b71Sopenharmony_ciparam.format.video.eColorFormat = AV_COLOR_FORMAT; // Set the output data format to YUV420SP.
325e41f4b71Sopenharmony_cierr = client_->SetParameter(OMX_IndexParamPortDefinition, inVec);
326e41f4b71Sopenharmony_ciif (err != HDF_SUCCESS) {
327e41f4b71Sopenharmony_ci    HDF_LOGE("%{public}s failed  with PortIndex::PORT_INDEX_OUTPUT, index is OMX_IndexParamPortDefinition",
328e41f4b71Sopenharmony_ci             __func__);
329e41f4b71Sopenharmony_ci    return err;
330e41f4b71Sopenharmony_ci}
331e41f4b71Sopenharmony_ci// Set the input data format to H.264/H.265.
332e41f4b71Sopenharmony_ciOMX_VIDEO_PARAM_PORTFORMATTYPE param;
333e41f4b71Sopenharmony_ciif (util_->InitParam(param) != HDF_SUCCESS) {
334e41f4b71Sopenharmony_ci    return false;
335e41f4b71Sopenharmony_ci}
336e41f4b71Sopenharmony_ciparam.nPortIndex = (uint32_t)PortIndex::PORT_INDEX_INPUT;
337e41f4b71Sopenharmony_cistd::vector<int8_t> inVec, outVec;
338e41f4b71Sopenharmony_ciutil_->ObjectToVector(param, inVec);
339e41f4b71Sopenharmony_ciauto err = client_->GetParameter(OMX_IndexParamVideoPortFormat, inVec, outVec);
340e41f4b71Sopenharmony_ciif (err != HDF_SUCCESS) {
341e41f4b71Sopenharmony_ci    HDF_LOGE("%{public}s failed with PortIndex::PORT_INDEX_INPUT", __func__);
342e41f4b71Sopenharmony_ci    return false;
343e41f4b71Sopenharmony_ci}
344e41f4b71Sopenharmony_ciutil_->VectorToObject(outVec, param);
345e41f4b71Sopenharmony_ci
346e41f4b71Sopenharmony_ciHDF_LOGI("set Format PortIndex::PORT_INDEX_INPUT eCompressionFormat = %{public}d, eColorFormat=%{public}d",
347e41f4b71Sopenharmony_ci         param.eCompressionFormat, param.eColorFormat);
348e41f4b71Sopenharmony_ciparam.xFramerate = FRAME // Set the frame rate to 30.
349e41f4b71Sopenharmony_ciif (codecMime_ == codecMime::AVC) {
350e41f4b71Sopenharmony_ci    param.eCompressionFormat = OMX_VIDEO_CodingAVC;  // H264
351e41f4b71Sopenharmony_ci} else {
352e41f4b71Sopenharmony_ci    param.eCompressionFormat = (OMX_VIDEO_CODINGTYPE)CODEC_OMX_VIDEO_CodingHEVC;  // H265
353e41f4b71Sopenharmony_ci}
354e41f4b71Sopenharmony_ci
355e41f4b71Sopenharmony_ciutil_->ObjectToVector(param, inVec);
356e41f4b71Sopenharmony_cierr = client_->SetParameter(OMX_IndexParamVideoPortFormat, inVec);
357e41f4b71Sopenharmony_ciif (err != HDF_SUCCESS) {
358e41f4b71Sopenharmony_ci    HDF_LOGE("%{public}s failed  with PortIndex::PORT_INDEX_INPUT", __func__);
359e41f4b71Sopenharmony_ci    return false;
360e41f4b71Sopenharmony_ci}
361e41f4b71Sopenharmony_ci```
362e41f4b71Sopenharmony_ci
363e41f4b71Sopenharmony_ci#### Applying for Input and Output Buffers
364e41f4b71Sopenharmony_ciPerform the following steps:
365e41f4b71Sopenharmony_ci
366e41f4b71Sopenharmony_ci1. Use **UseBuffer()** to apply for input and output buffers and save the buffer IDs. The buffer IDs can be used for subsequent buffer flipping.
367e41f4b71Sopenharmony_ci2. Check whether the corresponding port is enabled. If not, enable the port first.
368e41f4b71Sopenharmony_ci3. Use **SendCommand()** to change the component status to **CODEC_STATE_IDLE**, and wait until the operation result is obtained.
369e41f4b71Sopenharmony_ci```cpp
370e41f4b71Sopenharmony_ci// Apply for the input buffer.
371e41f4b71Sopenharmony_ciauto err = UseBufferOnPort(PortIndex::PORT_INDEX_INPUT);
372e41f4b71Sopenharmony_ciif (err != HDF_SUCCESS) {
373e41f4b71Sopenharmony_ci    HDF_LOGE("%{public}s UseBufferOnPort PortIndex::PORT_INDEX_INPUT error", __func__);
374e41f4b71Sopenharmony_ci    return false;
375e41f4b71Sopenharmony_ci}
376e41f4b71Sopenharmony_ci// Apply for the output buffer.
377e41f4b71Sopenharmony_cierr = UseBufferOnPort(PortIndex::PORT_INDEX_OUTPUT);
378e41f4b71Sopenharmony_ciif (err != HDF_SUCCESS) {
379e41f4b71Sopenharmony_ci    HDF_LOGE("%{public}s UseBufferOnPort PortIndex::PORT_INDEX_OUTPUT error", __func__);
380e41f4b71Sopenharmony_ci    return false;
381e41f4b71Sopenharmony_ci}
382e41f4b71Sopenharmony_ci// Enable the component to enter the OMX_StateIdle state.
383e41f4b71Sopenharmony_cistd::vector<int8_t> cmdData;
384e41f4b71Sopenharmony_ciauto err = client_->SendCommand(CODEC_COMMAND_STATE_SET, CODEC_STATE_IDLE, cmdData);
385e41f4b71Sopenharmony_ciif (err != HDF_SUCCESS) {
386e41f4b71Sopenharmony_ci    HDF_LOGE("%{public}s failed to SendCommand with CODEC_COMMAND_STATE_SET:CODEC_STATE_IDLE", __func__);
387e41f4b71Sopenharmony_ci    return false;
388e41f4b71Sopenharmony_ci}
389e41f4b71Sopenharmony_ci```
390e41f4b71Sopenharmony_ci
391e41f4b71Sopenharmony_ciImplement **UseBufferOnPort()** as follows:
392e41f4b71Sopenharmony_ci
393e41f4b71Sopenharmony_ci```cpp
394e41f4b71Sopenharmony_ciint32_t CodecHdiDecode::UseBufferOnPort(PortIndex portIndex)
395e41f4b71Sopenharmony_ci{
396e41f4b71Sopenharmony_ci    HDF_LOGI("%{public}s enter, portIndex = %{public}d", __func__, portIndex);
397e41f4b71Sopenharmony_ci    int bufferSize = 0;
398e41f4b71Sopenharmony_ci    int bufferCount = 0;
399e41f4b71Sopenharmony_ci    bool PortEnable = false;
400e41f4b71Sopenharmony_ci    // Obtain parameters of the port buffer.
401e41f4b71Sopenharmony_ci    OMX_PARAM_PORTDEFINITIONTYPE param;
402e41f4b71Sopenharmony_ci    if (util_->InitParam(param) != HDF_SUCCESS) {
403e41f4b71Sopenharmony_ci        return HDF_FAILURE;
404e41f4b71Sopenharmony_ci    }
405e41f4b71Sopenharmony_ci    param.nPortIndex = static_cast<OMX_U32>(portIndex);
406e41f4b71Sopenharmony_ci
407e41f4b71Sopenharmony_ci    std::vector<int8_t> inVec, outVec;
408e41f4b71Sopenharmony_ci    util_->ObjectToVector(param, inVec);
409e41f4b71Sopenharmony_ci    auto err = client_->GetParameter(OMX_IndexParamPortDefinition, inVec, outVec);
410e41f4b71Sopenharmony_ci    if (err != HDF_SUCCESS) {
411e41f4b71Sopenharmony_ci        HDF_LOGE("%{public}s failed to GetParameter with OMX_IndexParamPortDefinition : portIndex[%{public}d]",
412e41f4b71Sopenharmony_ci                 __func__, portIndex);
413e41f4b71Sopenharmony_ci        return err;
414e41f4b71Sopenharmony_ci    }
415e41f4b71Sopenharmony_ci    util_->VectorToObject(outVec, param);
416e41f4b71Sopenharmony_ci
417e41f4b71Sopenharmony_ci    bufferSize = param.nBufferSize;
418e41f4b71Sopenharmony_ci    bufferCount = param.nBufferCountActual;
419e41f4b71Sopenharmony_ci    portEnable = param.bEnabled;
420e41f4b71Sopenharmony_ci    HDF_LOGI("buffer index [%{public}d], buffer size [%{public}d], "
421e41f4b71Sopenharmony_ci             "buffer count [%{public}d], portEnable[%{public}d], ret [%{public}d]",
422e41f4b71Sopenharmony_ci             portIndex, bufferSize, bufferCount, portEnable, err);
423e41f4b71Sopenharmony_ci    // Set the port buffer.
424e41f4b71Sopenharmony_ci    if (useBufferHandle_ && portIndex == PortIndex::PORT_INDEX_OUTPUT) {
425e41f4b71Sopenharmony_ci        err = UseBufferHandle(bufferCount, bufferSize);
426e41f4b71Sopenharmony_ci    } else {
427e41f4b71Sopenharmony_ci        err = UseBufferOnPort(portIndex, bufferCount, bufferSize);
428e41f4b71Sopenharmony_ci    }
429e41f4b71Sopenharmony_ci    // Check whether the port is available.
430e41f4b71Sopenharmony_ci    if (!portEnable) {
431e41f4b71Sopenharmony_ci        err = client_->SendCommand(CODEC_COMMAND_PORT_ENABLE, static_cast<uint32_t>(portIndex), {});
432e41f4b71Sopenharmony_ci        if (err != HDF_SUCCESS) {
433e41f4b71Sopenharmony_ci            HDF_LOGE("%{public}s SendCommand OMX_CommandPortEnable::PortIndex::PORT_INDEX_INPUT error", __func__);
434e41f4b71Sopenharmony_ci            return err;
435e41f4b71Sopenharmony_ci        }
436e41f4b71Sopenharmony_ci    }
437e41f4b71Sopenharmony_ci    return HDF_SUCCESS;
438e41f4b71Sopenharmony_ci}
439e41f4b71Sopenharmony_ci
440e41f4b71Sopenharmony_ciint32_t CodecHdiDecode::UseBufferOnPort(PortIndex portIndex, int bufferCount, int bufferSize)
441e41f4b71Sopenharmony_ci{
442e41f4b71Sopenharmony_ci    if (bufferCount <= 0 || bufferSize <= 0) {
443e41f4b71Sopenharmony_ci        HDF_LOGE("UseBufferOnPort bufferCount <= 0 or bufferSize <= 0");
444e41f4b71Sopenharmony_ci        return HDF_ERR_INVALID_PARAM;
445e41f4b71Sopenharmony_ci    }
446e41f4b71Sopenharmony_ci    for (int i = 0; i < bufferCount; i++) {
447e41f4b71Sopenharmony_ci        std::shared_ptr<OmxCodecBuffer> omxBuffer = std::make_shared<OmxCodecBuffer>();
448e41f4b71Sopenharmony_ci        omxBuffer->size = sizeof(OmxCodecBuffer);
449e41f4b71Sopenharmony_ci        omxBuffer->version.s.nVersionMajor = 1;
450e41f4b71Sopenharmony_ci        omxBuffer->bufferType = CODEC_BUFFER_TYPE_AVSHARE_MEM_FD;
451e41f4b71Sopenharmony_ci        int fd = AshmemCreate(0, bufferSize);
452e41f4b71Sopenharmony_ci        shared_ptr<Ashmem> sharedMem = make_shared<Ashmem>(fd, bufferSize);
453e41f4b71Sopenharmony_ci        omxBuffer->fd = fd;
454e41f4b71Sopenharmony_ci        omxBuffer->bufferhandle = nullptr;
455e41f4b71Sopenharmony_ci        omxBuffer->allocLen = bufferSize;
456e41f4b71Sopenharmony_ci        omxBuffer->fenceFd = -1;
457e41f4b71Sopenharmony_ci        omxBuffer->pts = 0;
458e41f4b71Sopenharmony_ci        omxBuffer->flag = 0;
459e41f4b71Sopenharmony_ci
460e41f4b71Sopenharmony_ci        if (portIndex == PortIndex::PORT_INDEX_INPUT) {
461e41f4b71Sopenharmony_ci            omxBuffer->type = READ_ONLY_TYPE;  // ReadOnly
462e41f4b71Sopenharmony_ci            sharedMem->MapReadAndWriteAshmem();
463e41f4b71Sopenharmony_ci        } else {
464e41f4b71Sopenharmony_ci            omxBuffer->type = READ_WRITE_TYPE;
465e41f4b71Sopenharmony_ci            sharedMem->MapReadOnlyAshmem();
466e41f4b71Sopenharmony_ci        }
467e41f4b71Sopenharmony_ci        OmxCodecBuffer outBuffer;
468e41f4b71Sopenharmony_ci        auto err = client_->UseBuffer((uint32_t)portIndex, *omxBuffer.get(), outBuffer);
469e41f4b71Sopenharmony_ci        if (err != HDF_SUCCESS) {
470e41f4b71Sopenharmony_ci            HDF_LOGE("%{public}s failed to UseBuffer with  portIndex[%{public}d]", __func__, portIndex);
471e41f4b71Sopenharmony_ci            sharedMem->UnmapAshmem();
472e41f4b71Sopenharmony_ci            sharedMem->CloseAshmem();
473e41f4b71Sopenharmony_ci            sharedMem = nullptr;
474e41f4b71Sopenharmony_ci            return err;
475e41f4b71Sopenharmony_ci        }
476e41f4b71Sopenharmony_ci        omxBuffer->bufferId = outBuffer.bufferId;
477e41f4b71Sopenharmony_ci        omxBuffer->fd = -1;
478e41f4b71Sopenharmony_ci        HDF_LOGI("UseBuffer returned bufferID [%{public}d]", omxBuffer->bufferId);
479e41f4b71Sopenharmony_ci
480e41f4b71Sopenharmony_ci        std::shared_ptr<BufferInfo> bufferInfo = std::make_shared<BufferInfo>();
481e41f4b71Sopenharmony_ci        bufferInfo->omxBuffer = omxBuffer;
482e41f4b71Sopenharmony_ci        bufferInfo->avSharedPtr = sharedMem;
483e41f4b71Sopenharmony_ci        bufferInfo->portIndex = portIndex;
484e41f4b71Sopenharmony_ci        omxBuffers_.emplace(std::make_pair(omxBuffer->bufferId, bufferInfo));
485e41f4b71Sopenharmony_ci        if (portIndex == PortIndex::PORT_INDEX_INPUT) {
486e41f4b71Sopenharmony_ci            unUsedInBuffers_.push_back(omxBuffer->bufferId);
487e41f4b71Sopenharmony_ci        } else {
488e41f4b71Sopenharmony_ci            unUsedOutBuffers_.push_back(omxBuffer->bufferId);
489e41f4b71Sopenharmony_ci        }
490e41f4b71Sopenharmony_ci    }
491e41f4b71Sopenharmony_ci
492e41f4b71Sopenharmony_ci    return HDF_SUCCESS;
493e41f4b71Sopenharmony_ci}
494e41f4b71Sopenharmony_ci```
495e41f4b71Sopenharmony_ci
496e41f4b71Sopenharmony_ci#### Codec Buffer Flipping
497e41f4b71Sopenharmony_ciSet the component to the **CODEC_STATE_EXECUTING** state, fill the input buffer, read data from the output buffer, and flip the buffers.
498e41f4b71Sopenharmony_ci
499e41f4b71Sopenharmony_ci```cpp
500e41f4b71Sopenharmony_ci// Set the component to the OMX_StateExecuting state and start buffer flipping.
501e41f4b71Sopenharmony_ciHDF_LOGI("...command to CODEC_STATE_EXECUTING....");
502e41f4b71Sopenharmony_ciauto err = client_->SendCommand(CODEC_COMMAND_STATE_SET, CODEC_STATE_EXECUTING, {});
503e41f4b71Sopenharmony_ciif (err != HDF_SUCCESS) {
504e41f4b71Sopenharmony_ci    HDF_LOGE("%{public}s failed to SendCommand with CODEC_COMMAND_STATE_SET:CODEC_STATE_IDLE", __func__);
505e41f4b71Sopenharmony_ci    return;
506e41f4b71Sopenharmony_ci}
507e41f4b71Sopenharmony_ci// Set the output buffer to fill.
508e41f4b71Sopenharmony_ciif (!FillAllTheBuffer()) {
509e41f4b71Sopenharmony_ci    HDF_LOGE("%{public}s FillAllTheBuffer error", __func__);
510e41f4b71Sopenharmony_ci    return;
511e41f4b71Sopenharmony_ci}
512e41f4b71Sopenharmony_ci// Fill the input buffer.
513e41f4b71Sopenharmony_ciauto t1 = std::chrono::system_clock::now();
514e41f4b71Sopenharmony_cibool eosFlag = false;
515e41f4b71Sopenharmony_ciwhile (!eosFlag) {
516e41f4b71Sopenharmony_ci    if (this->exit_) {
517e41f4b71Sopenharmony_ci        break;
518e41f4b71Sopenharmony_ci    }
519e41f4b71Sopenharmony_ci    int bufferID = GetFreeBufferId();
520e41f4b71Sopenharmony_ci    if (bufferID < 0) {
521e41f4b71Sopenharmony_ci        usleep(10000);  // 10000 for wait 10ms
522e41f4b71Sopenharmony_ci        continue;
523e41f4b71Sopenharmony_ci    }
524e41f4b71Sopenharmony_ci    auto iter = omxBuffers_.find(bufferID);
525e41f4b71Sopenharmony_ci    if (iter == omxBuffers_.end()) {
526e41f4b71Sopenharmony_ci        continue;
527e41f4b71Sopenharmony_ci    }
528e41f4b71Sopenharmony_ci    auto bufferInfo = iter->second;
529e41f4b71Sopenharmony_ci    void *sharedAddr = const_cast<void *>(bufferInfo->avSharedPtr->ReadFromAshmem(0, 0));
530e41f4b71Sopenharmony_ci    eosFlag = this->ReadOnePacket(fpIn_, static_cast<char *>(sharedAddr), bufferInfo->omxBuffer->filledLen);
531e41f4b71Sopenharmony_ci    bufferInfo->omxBuffer->offset = 0;
532e41f4b71Sopenharmony_ci    if (eosFlag) {
533e41f4b71Sopenharmony_ci        bufferInfo->omxBuffer->flag = OMX_BUFFERFLAG_EOS;
534e41f4b71Sopenharmony_ci    }
535e41f4b71Sopenharmony_ci    err = client_->EmptyThisBuffer(*bufferInfo->omxBuffer.get());
536e41f4b71Sopenharmony_ci    if (err != HDF_SUCCESS) {
537e41f4b71Sopenharmony_ci        HDF_LOGE("%{public}s EmptyThisBuffer error", __func__);
538e41f4b71Sopenharmony_ci        return;
539e41f4b71Sopenharmony_ci    }
540e41f4b71Sopenharmony_ci}
541e41f4b71Sopenharmony_ci// Wait.
542e41f4b71Sopenharmony_ciwhile (!this->exit_) {
543e41f4b71Sopenharmony_ci    usleep(10000);  // 10000 for wait 10ms
544e41f4b71Sopenharmony_ci}
545e41f4b71Sopenharmony_ci// Enable the component to enter the OMX_StateIdle state after decoding.
546e41f4b71Sopenharmony_ciauto t2 = std::chrono::system_clock::now();
547e41f4b71Sopenharmony_cistd::chrono::duration<double> diff = t2 - t1;
548e41f4b71Sopenharmony_ciHDF_LOGI("cost %{public}f, count=%{public}d", diff.count(), count_);
549e41f4b71Sopenharmony_ci(void)client_->SendCommand(CODEC_COMMAND_STATE_SET, CODEC_STATE_IDLE, {});
550e41f4b71Sopenharmony_cireturn;
551e41f4b71Sopenharmony_ci}
552e41f4b71Sopenharmony_ci```
553e41f4b71Sopenharmony_ci
554e41f4b71Sopenharmony_ciThe RK3568 development board does not support data framing during the decoding process. Therefore, you need to manually divide the data into frames from code 0x000001 or 0x00000001 and sent the frames to the server for processing. The sample code is as follows:
555e41f4b71Sopenharmony_ci
556e41f4b71Sopenharmony_ci```cpp
557e41f4b71Sopenharmony_ci// Read a file by frame.
558e41f4b71Sopenharmony_cibool CodecHdiDecode::ReadOnePacket(FILE *fp, char *buf, uint32_t &filledCount)
559e41f4b71Sopenharmony_ci{
560e41f4b71Sopenharmony_ci    // Read the start code.
561e41f4b71Sopenharmony_ci    size_t t = fread(buf, 1, START_CODE_SIZE_FRAME, fp);
562e41f4b71Sopenharmony_ci    if (t < START_CODE_SIZE_FRAME) {
563e41f4b71Sopenharmony_ci        return true;
564e41f4b71Sopenharmony_ci    }
565e41f4b71Sopenharmony_ci    char *temp = buf;
566e41f4b71Sopenharmony_ci    temp += START_CODE_SIZE_FRAME;
567e41f4b71Sopenharmony_ci    bool ret = true;
568e41f4b71Sopenharmony_ci    while (!feof(fp)) {
569e41f4b71Sopenharmony_ci        (void)fread(temp, 1, 1, fp);
570e41f4b71Sopenharmony_ci        if (*temp != START_CODE) {
571e41f4b71Sopenharmony_ci            temp++;
572e41f4b71Sopenharmony_ci            continue;
573e41f4b71Sopenharmony_ci        }
574e41f4b71Sopenharmony_ci        // Check the start code.
575e41f4b71Sopenharmony_ci        if ((temp[START_CODE_OFFSET_ONE] == 0) && (temp[START_CODE_OFFSET_SEC] == 0) &&
576e41f4b71Sopenharmony_ci            (temp[START_CODE_OFFSET_THIRD] == 0)) {
577e41f4b71Sopenharmony_ci            fseek(fp, -START_CODE_SIZE_FRAME, SEEK_CUR);
578e41f4b71Sopenharmony_ci            temp -= (START_CODE_SIZE_FRAME - 1);
579e41f4b71Sopenharmony_ci            ret = false;
580e41f4b71Sopenharmony_ci            break;
581e41f4b71Sopenharmony_ci            }
582e41f4b71Sopenharmony_ci        if ((temp[START_CODE_OFFSET_ONE] == 0) && (temp[START_CODE_OFFSET_SEC] == 0)) {
583e41f4b71Sopenharmony_ci            fseek(fp, -START_CODE_SIZE_SLICE, SEEK_CUR);
584e41f4b71Sopenharmony_ci            temp -= (START_CODE_SIZE_SLICE - 1);
585e41f4b71Sopenharmony_ci            ret = false;
586e41f4b71Sopenharmony_ci            break;
587e41f4b71Sopenharmony_ci        }
588e41f4b71Sopenharmony_ci        temp++;
589e41f4b71Sopenharmony_ci    }
590e41f4b71Sopenharmony_ci    filledCount = (temp - buf);
591e41f4b71Sopenharmony_ci    return ret;
592e41f4b71Sopenharmony_ci}
593e41f4b71Sopenharmony_ci```
594e41f4b71Sopenharmony_ci
595e41f4b71Sopenharmony_ciThe codec HDI provides the following callbacks:
596e41f4b71Sopenharmony_ci
597e41f4b71Sopenharmony_ci- **EventHandler**: Called when a command is executed. For example, when the command for changing the component state from **CODEC_STATE_IDLE** to **CODEC_STATE_EXECUTING** is executed, this callback is invoked to return the result.
598e41f4b71Sopenharmony_ci- **EmptyBufferDone**: Called when the input data is consumed. If the client needs to fill data to encode or decode, it must call **EmptyThisBuffer()** again.
599e41f4b71Sopenharmony_ci- **FillBufferDone**: Called when the output data is filled. If the client needs to read the encoded or decoded data, it must call **FillThisBuffer()** again.
600e41f4b71Sopenharmony_ci
601e41f4b71Sopenharmony_ci```cpp
602e41f4b71Sopenharmony_ci// EmptyBufferDone example
603e41f4b71Sopenharmony_ciint32_t CodecHdiDecode::OnEmptyBufferDone(const struct OmxCodecBuffer &buffer)
604e41f4b71Sopenharmony_ci{
605e41f4b71Sopenharmony_ci    HDF_LOGI("OnEmptyBufferDone, bufferId [%{public}d]", buffer.bufferId);
606e41f4b71Sopenharmony_ci    unique_lock<mutex> ulk(lockInputBuffers_);
607e41f4b71Sopenharmony_ci    unUsedInBuffers_.push_back(buffer.bufferId);
608e41f4b71Sopenharmony_ci    return HDF_SUCCESS;
609e41f4b71Sopenharmony_ci}
610e41f4b71Sopenharmony_ci// FillBufferDone example
611e41f4b71Sopenharmony_ciint32_t CodecHdiDecode::OnFillBufferDone(const struct OmxCodecBuffer &buffer)
612e41f4b71Sopenharmony_ci{
613e41f4b71Sopenharmony_ci    HDF_LOGI("OnFillBufferDone, bufferId [%{public}d]", buffer.bufferId);
614e41f4b71Sopenharmony_ci    if (exit_) {
615e41f4b71Sopenharmony_ci        return HDF_SUCCESS;
616e41f4b71Sopenharmony_ci    }
617e41f4b71Sopenharmony_ci
618e41f4b71Sopenharmony_ci    auto iter = omxBuffers_.find(buffer.bufferId);
619e41f4b71Sopenharmony_ci    if ((iter == omxBuffers_.end()) || (iter->second == nullptr)) {
620e41f4b71Sopenharmony_ci        return HDF_SUCCESS;
621e41f4b71Sopenharmony_ci    }
622e41f4b71Sopenharmony_ci    count_++;
623e41f4b71Sopenharmony_ci    // read buffer
624e41f4b71Sopenharmony_ci    auto bufferInfo = iter->second;
625e41f4b71Sopenharmony_ci    if (bufferInfo->avSharedPtr != nullptr) {
626e41f4b71Sopenharmony_ci        const void *addr = bufferInfo->avSharedPtr->ReadFromAshmem(buffer.filledLen, buffer.offset);
627e41f4b71Sopenharmony_ci        (void)fwrite(addr, 1, buffer.filledLen, fpOut_);
628e41f4b71Sopenharmony_ci    } else if (bufferInfo->bufferHandle != nullptr && gralloc_ != nullptr) {
629e41f4b71Sopenharmony_ci        gralloc_->Mmap(*bufferInfo->bufferHandle);
630e41f4b71Sopenharmony_ci        (void)fwrite(bufferInfo->bufferHandle->virAddr, 1, buffer.filledLen, fpOut_);
631e41f4b71Sopenharmony_ci        gralloc_->Unmap(*bufferInfo->bufferHandle);
632e41f4b71Sopenharmony_ci    }
633e41f4b71Sopenharmony_ci
634e41f4b71Sopenharmony_ci    (void)fflush(fpOut_);
635e41f4b71Sopenharmony_ci    if (buffer.flag == OMX_BUFFERFLAG_EOS) {
636e41f4b71Sopenharmony_ci        // end
637e41f4b71Sopenharmony_ci        exit_ = true;
638e41f4b71Sopenharmony_ci        HDF_LOGI("OnFillBufferDone the END coming");
639e41f4b71Sopenharmony_ci        return HDF_SUCCESS;
640e41f4b71Sopenharmony_ci    }
641e41f4b71Sopenharmony_ci    // call fillthisbuffer again
642e41f4b71Sopenharmony_ci    auto err = client_->FillThisBuffer(*bufferInfo->omxBuffer.get());
643e41f4b71Sopenharmony_ci    if (err != HDF_SUCCESS) {
644e41f4b71Sopenharmony_ci        HDF_LOGE("%{public}s FillThisBuffer error", __func__);
645e41f4b71Sopenharmony_ci        return HDF_SUCCESS;
646e41f4b71Sopenharmony_ci    }
647e41f4b71Sopenharmony_ci    return HDF_SUCCESS;
648e41f4b71Sopenharmony_ci}
649e41f4b71Sopenharmony_ci// EventHandler example
650e41f4b71Sopenharmony_ciint32_t CodecHdiDecode::EventHandler(CodecEventType event, const EventInfo &info)
651e41f4b71Sopenharmony_ci{
652e41f4b71Sopenharmony_ci    switch (event) {
653e41f4b71Sopenharmony_ci        case CODEC_EVENT_CMD_COMPLETE: {
654e41f4b71Sopenharmony_ci            CodecCommandType cmd = (CodecCommandType)info.data1;
655e41f4b71Sopenharmony_ci            if (CODEC_COMMAND_STATE_SET == cmd) {
656e41f4b71Sopenharmony_ci                HDF_LOGI("CODEC_COMMAND_STATE_SET reached, status is %{public}d", info.data2);
657e41f4b71Sopenharmony_ci                this->OnStatusChanged();
658e41f4b71Sopenharmony_ci            }
659e41f4b71Sopenharmony_ci            break;
660e41f4b71Sopenharmony_ci        }
661e41f4b71Sopenharmony_ci        case OMX_EventPortSettingsChanged: {
662e41f4b71Sopenharmony_ci            HDF_LOGI("OMX_EventPortSeetingsChanged reached");
663e41f4b71Sopenharmony_ci            this->HandleEventPortSettingsChanged(info.data1, info.data2);
664e41f4b71Sopenharmony_ci        }
665e41f4b71Sopenharmony_ci
666e41f4b71Sopenharmony_ci        default:
667e41f4b71Sopenharmony_ci            break;
668e41f4b71Sopenharmony_ci    }
669e41f4b71Sopenharmony_ci
670e41f4b71Sopenharmony_ci    return HDF_SUCCESS;
671e41f4b71Sopenharmony_ci}
672e41f4b71Sopenharmony_ci```
673e41f4b71Sopenharmony_ci
674e41f4b71Sopenharmony_ci#### Destroying a Component
675e41f4b71Sopenharmony_ciChange the component state to **CODEC_STATE_IDLE**, release the input and output buffers, change the component state to **CODEC_STATE_LOADED**, and call **DestoryComponent** to destroy the component.
676e41f4b71Sopenharmony_ci
677e41f4b71Sopenharmony_ci##### Example of Releasing Buffers
678e41f4b71Sopenharmony_ci
679e41f4b71Sopenharmony_ci```cpp
680e41f4b71Sopenharmony_ci// Change the component state to OMX_StateLoaded.
681e41f4b71Sopenharmony_ciclient_->SendCommand(CODEC_COMMAND_STATE_SET, CODEC_STATE_LOADED, {});
682e41f4b71Sopenharmony_ci
683e41f4b71Sopenharmony_ci// Release all buffers in use.
684e41f4b71Sopenharmony_ciauto iter = omxBuffers_.begin();
685e41f4b71Sopenharmony_ciwhile (iter != omxBuffers_.end()) {
686e41f4b71Sopenharmony_ci    auto bufferInfo = iter->second;
687e41f4b71Sopenharmony_ci    iter = omxBuffers_.erase(iter);
688e41f4b71Sopenharmony_ci    (void)client_->FreeBuffer((uint32_t)bufferInfo->portIndex, *bufferInfo->omxBuffer.get());
689e41f4b71Sopenharmony_ci    bufferInfo = nullptr;
690e41f4b71Sopenharmony_ci}
691e41f4b71Sopenharmony_ci
692e41f4b71Sopenharmony_ciunUsedInBuffers_.clear();
693e41f4b71Sopenharmony_ciunUsedOutBuffers_.clear();
694e41f4b71Sopenharmony_ci
695e41f4b71Sopenharmony_ci// After the buffers are released, the component enters the OMX_StateLoaded state.
696e41f4b71Sopenharmony_ciCodecStateType status = CODEC_STATE_INVALID;
697e41f4b71Sopenharmony_ciint32_t err = HDF_SUCCESS;
698e41f4b71Sopenharmony_ciint32_t tryCount = 3;
699e41f4b71Sopenharmony_cido {
700e41f4b71Sopenharmony_ci    err = client_->GetState(status);
701e41f4b71Sopenharmony_ci    if (err != HDF_SUCCESS) {
702e41f4b71Sopenharmony_ci        HDF_LOGE("%s GetState error [%{public}x]", __func__, err);
703e41f4b71Sopenharmony_ci        break;
704e41f4b71Sopenharmony_ci    }
705e41f4b71Sopenharmony_ci    if (status != CODEC_STATE_LOADED) {
706e41f4b71Sopenharmony_ci        HDF_LOGI("Wait for OMX_StateLoaded status");
707e41f4b71Sopenharmony_ci        this->WaitForStatusChanged();
708e41f4b71Sopenharmony_ci    }
709e41f4b71Sopenharmony_ci    tryCount--;
710e41f4b71Sopenharmony_ci} while ((status != CODEC_STATE_LOADED) && (tryCount > 0));
711e41f4b71Sopenharmony_ci```
712e41f4b71Sopenharmony_ci
713e41f4b71Sopenharmony_ci##### Example of Destroying a Component Instance
714e41f4b71Sopenharmony_ci
715e41f4b71Sopenharmony_ci```cpp
716e41f4b71Sopenharmony_ci// Destroy a component instance.
717e41f4b71Sopenharmony_civoid CodecHdiDecode::Release()
718e41f4b71Sopenharmony_ci{
719e41f4b71Sopenharmony_ci    omxMgr_->DestoryComponent(componentId_);
720e41f4b71Sopenharmony_ci    client_ = nullptr;
721e41f4b71Sopenharmony_ci    callback_ = nullptr;
722e41f4b71Sopenharmony_ci    omxMgr_ = nullptr;
723e41f4b71Sopenharmony_ci}
724e41f4b71Sopenharmony_ci```
725e41f4b71Sopenharmony_ci
726e41f4b71Sopenharmony_ci# FAQs
727e41f4b71Sopenharmony_ci
728e41f4b71Sopenharmony_ci## Green Screens Displayed During the Decoding Process
729e41f4b71Sopenharmony_ci
730e41f4b71Sopenharmony_ci**Symptom**
731e41f4b71Sopenharmony_ci
732e41f4b71Sopenharmony_ciGreen screens are displayed during the decoding process.
733e41f4b71Sopenharmony_ci
734e41f4b71Sopenharmony_ci**Possible Causes**
735e41f4b71Sopenharmony_ci
736e41f4b71Sopenharmony_ciOpenMAX does not support framing.
737e41f4b71Sopenharmony_ci
738e41f4b71Sopenharmony_ci**Solution**
739e41f4b71Sopenharmony_ci
740e41f4b71Sopenharmony_ciWhen **EmptyThisBuffer** is call, only one frame can be passed in at a time.
741e41f4b71Sopenharmony_ci
742e41f4b71Sopenharmony_ci## Only Green Screen Displayed During the Decoding Process
743e41f4b71Sopenharmony_ci
744e41f4b71Sopenharmony_ci**Symptom**
745e41f4b71Sopenharmony_ci
746e41f4b71Sopenharmony_ciDecoding fails, and all the frames decoded cannot be played.
747e41f4b71Sopenharmony_ci
748e41f4b71Sopenharmony_ci**Possible Causes**
749e41f4b71Sopenharmony_ci
750e41f4b71Sopenharmony_ciFor the data in AVCC format, the first frame to be processed must be extra_data.
751e41f4b71Sopenharmony_ci
752e41f4b71Sopenharmony_ci**Solution**
753e41f4b71Sopenharmony_ci
754e41f4b71Sopenharmony_ciWrite sps and pps to the buffer in extra_data format, and set the buffer flag to **OMX_BUFFERFLAG_EXTRADATA**.
755e41f4b71Sopenharmony_ci
756e41f4b71Sopenharmony_ci## Failed to Play the Encoded Video
757e41f4b71Sopenharmony_ci
758e41f4b71Sopenharmony_ci**Symptom**
759e41f4b71Sopenharmony_ci
760e41f4b71Sopenharmony_ciAfter the generated video stream (H.264 stream) is written to a file, the video stream cannot be played by FFplay.
761e41f4b71Sopenharmony_ci
762e41f4b71Sopenharmony_ci**Possible Causes**
763e41f4b71Sopenharmony_ci
764e41f4b71Sopenharmony_ci1. The **xFramerate** parameter of the output port is incorrectly set.
765e41f4b71Sopenharmony_ci2. The **OMX_VIDEO_PARAM_AVCTYPE** parameter is correctly set.
766e41f4b71Sopenharmony_ci
767e41f4b71Sopenharmony_ci**Solution**
768e41f4b71Sopenharmony_ci
769e41f4b71Sopenharmony_ciView the **codec_host** log generated during encoding, search for "encode params init settings", and check for incorrect parameters. If **framerate** is **0**, **xFramerate** is incorrectly set. In this case, move the frame rate leftwards by 16 bits. <br>In other cases, correct the setting of **OMX_VIDEO_PARAM_AVCTYPE**. 
770e41f4b71Sopenharmony_ci
771e41f4b71Sopenharmony_ci
772e41f4b71Sopenharmony_ci# Reference
773e41f4b71Sopenharmony_ci
774e41f4b71Sopenharmony_ciFor more information, see [codec](https://gitee.com/openharmony/drivers_peripheral/tree/master/codec).
775