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 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