# ESP_H264 ESP_H264 is Espressif's lightweight H264 encoder and decoder. It comes from v2.2.0 of [openh264](https://github.com/cisco/openh264), and the memory and CPU loading are optimized to make better use of Espressif chips. # Features Encoder: - Support baseline profile (max frame size is 36864 macro-block) - Support a variety of widths and heights - Support quality first rate control - Support YUYV and IYUV raw data - Support dynamic changes about bit rate, frame rate - Support more than one slice per frame - Support SPS and PPS encoding # Performance ## Test on chip ESP32-S3R8 | Resolution | Raw Format | Memory (Byte) | Frame Per Second(fps) | | -- | -- |-- | -- | | 320 * 192 | ESP_H264_RAW_FMT_I420 |1 M | 17.48 | | 320 * 240 | ESP_H264_RAW_FMT_YUV422 |1 M | 10.86 | # Supported chip | ESP_H264 Version | Supported Chip | | -- | -- | | v0.1.0 | ESP32-S3 | # Usage Example of function call. ```c void app_main(void) { int one_image_size = 0; esp_h264_err_t ret = ESP_H264_ERR_OK; esp_h264_enc_t handle = NULL; esp_h264_enc_cfg_t cfg = DEFAULT_H264_ENCODER_CONFIG(); esp_h264_enc_frame_t out_frame = { 0 }; esp_h264_raw_frame_t in_frame = { 0 }; int frame_count = 0; int ret_w = 0; FILE *out = fopen("/sdcard/h264/t160_96.h264", "wb"); if (out == NULL) { printf("Output file cann't open \r\n"); return; } FILE *in = fopen("/sdcard/h264/160x96.yuv", "rb"); if (in == NULL) { printf("Input file cann't open \r\n"); goto h264_example_exit; } cfg.fps = 30; cfg.height = 96; cfg.width = 160; cfg.pic_type = ESP_H264_RAW_FMT_I420; one_image_size = cfg.height * cfg.width * 1.5; // 1.5 : Pixel is 1.5 on ESP_H264_RAW_FMT_I420. in_frame.raw_data.buffer = (uint8_t *)heap_caps_aligned_alloc(16, one_image_size, MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM); if (in_frame.raw_data.buffer == NULL) { printf("Allcation memory failed \r\n"); goto h264_example_exit; } ret = esp_h264_enc_open(&cfg, &handle); if (ret != ESP_H264_ERR_OK) { printf("Open failed. ret %d, handle %p \r\n", ret, handle); goto h264_example_exit; } while(1) { ret_w = fread(in_frame.raw_data.buffer, 1, one_image_size, in); if (ret_w != one_image_size) { printf("Encoder finished, ret %d \r\n", ret_w); goto h264_example_exit; } in_frame.pts = frame_count * (1000 / cfg.fps); ret = esp_h264_enc_process(handle, &in_frame, &out_frame); if (ret != ESP_H264_ERR_OK) { printf("Process failed. ret %d \r\n", ret); goto h264_example_exit; } for (size_t layer = 0; layer < out_frame.layer_num; layer++) { ret_w = fwrite(out_frame.layer_data[layer].buffer, 1, out_frame.layer_data[layer].len, out); if (ret_w != out_frame.layer_data[layer].len) { printf("fwrite happened error, ret %d \r\n", ret_w); goto h264_example_exit; } } frame_count++; } h264_example_exit: if (in) { fclose(in); } if (out) { fclose(out); } if (in_frame.raw_data.buffer) { heap_caps_free(in_frame.raw_data.buffer); in_frame.raw_data.buffer = NULL; } esp_h264_enc_close(handle); return; } ``` # Change log ## Version 0.1.0 - Added H264 encoder
idf.py add-dependency "espressif/esp_h264^0.1.0"