3.6 VENC
Module API Manual#
1. Overview#
This manual provides a detailed introduction to the API of the K230_CanMV VENC module. Developers can use these APIs to perform video encoding, generating streams of different resolutions and encoding formats. The VENC module needs to be used in conjunction with the camera module to achieve encoding functionality.
2. API Introduction#
The VENC module provides the Encoder
class, which includes the following methods:
2.1 Encoder.SetOutBufs
#
Description
Configures the output buffer of the encoder.
Syntax
Encoder.SetOutBufs(chn, buf_num, width, height)
Parameters
Parameter Name |
Description |
Input/Output |
---|---|---|
chn |
Encoding channel number |
Input |
buf_num |
Number of output buffers |
Input |
width |
Width of the encoded image |
Input |
height |
Height of the encoded image |
Input |
Return Value
Return Value |
Description |
---|---|
0 |
Success |
Non-zero |
Failure |
Notes
Must be called before MediaManager.init()
2.2 Encoder.Create
#
Description
Creates an encoder instance.
Syntax
Encoder.Create(chn, chnAttr)
Parameters
Parameter Name |
Description |
Input/Output |
---|---|---|
chn |
Encoding channel number |
Input |
chnAttr |
Encoding channel attribute structure |
Input |
Return Value
Return Value |
Description |
---|---|
0 |
Success |
Non-zero |
Failure |
Notes
VENC supports up to 4 encoding channels, with channel numbers ranging from [0, 3]. The 4th channel is fixed for IDE image transmission. Unless calling compress_for_ide
, it is recommended to use only [0, 2].
2.3 Encoder.Start
#
Description
Starts the encoding process.
Syntax
Encoder.Start(chn)
Parameters
Parameter Name |
Description |
Input/Output |
---|---|---|
chn |
Encoding channel number |
Input |
Return Value
Return Value |
Description |
---|---|
0 |
Success |
Non-zero |
Failure |
2.4 Encoder.SendFrame
#
Description
Sends image data to the encoder for encoding.
Syntax
Encoder.SendFrame(venc_chn, frame_info)
Parameters
Parameter Name |
Description |
Input/Output |
---|---|---|
chn |
Encoding channel number |
Input |
frame_info |
Raw image information structure |
Input |
Return Value
Return Value |
Description |
---|---|
0 |
Success |
Non-zero |
Failure |
Notes
Can encode a full frame of data or a variable-length data stream.
2.5 Encoder.GetStream
#
Description
Gets a frame of encoded stream data.
Syntax
Encoder.GetStream(chn, streamData)
Parameters
Parameter Name |
Description |
Input/Output |
---|---|---|
chn |
Encoding channel number |
Input |
streamData |
Encoded stream structure |
Output |
Return Value
Return Value |
Description |
---|---|
0 |
Success |
Non-zero |
Failure |
2.6 Encoder.ReleaseStream
#
Description
Releases a frame of stream buffer.
Syntax
Encoder.ReleaseStream(chn, streamData)
Parameters
Parameter Name |
Description |
Input/Output |
---|---|---|
chn |
Encoding channel number |
Input |
streamData |
Encoded stream structure |
Input |
Return Value
Return Value |
Description |
---|---|
0 |
Success |
Non-zero |
Failure |
2.7 Encoder.Stop
#
Description
Stops the encoding process.
Syntax
Encoder.Stop(chn)
Parameters
Parameter Name |
Description |
Input/Output |
---|---|---|
chn |
Encoding channel number |
Input |
2.8 Encoder.Destroy
#
Description
Destroys the encoder instance.
Syntax
Encoder.Destroy(chn)
Parameters
Parameter Name |
Description |
Input/Output |
---|---|---|
chn |
Encoding channel number |
Input |
3. Data Structure Description#
3.1 ChnAttrStr
#
Description
Encoding channel attribute structure.
Definition
class ChnAttrStr:
def __init__(self, payloadType, profile, picWidth, picHeight, gopLen=30):
self.payload_type = payloadType
self.profile = profile
self.pic_width = picWidth
self.pic_height = picHeight
self.gop_len = gopLen
Members
Member Name |
Description |
---|---|
payload_type |
Encoding format (h264/h265) |
profile |
Encoding Profile |
pic_width |
Image width |
pic_height |
Image height |
gop_len |
Encoding GOP length |
3.2 StreamData
#
Description
Stream structure.
Definition
class StreamData:
def __init__(self):
self.data = [0 for i in range(0, VENC_PACK_CNT_MAX)]
self.data_size = [0 for i in range(0, VENC_PACK_CNT_MAX)]
self.stream_type = [0 for i in range(0, VENC_PACK_CNT_MAX)]
self.pack_cnt = 0
Members
Member Name |
Description |
---|---|
data |
Stream data address |
data_size |
Stream data size |
stream_type |
Frame type |
pack_cnt |
Number of packs in the stream |
Notes
VENC_PACK_CNT_MAX
indicates the maximum number of packs in the stream structure, currently set to 12.
3.3 payload_type
#
Description
Encoding format type.
Members
Member Name |
Description |
---|---|
PAYLOAD_TYPE_H264 |
H.264 encoding format |
PAYLOAD_TYPE_H265 |
H.265 encoding format |
3.4 profile
#
Description
Encoding Profile.
Members
Member Name |
Description |
---|---|
H264_PROFILE_BASELINE |
H.264 Baseline Profile |
H264_PROFILE_MAIN |
H.264 Main Profile |
H264_PROFILE_HIGH |
H.264 High Profile |
H265_PROFILE_MAIN |
H.265 Main Profile |
3.5 stream_type
#
Description
Stream frame type.
Members
Member Name |
Description |
---|---|
STREAM_TYPE_HEADER |
Stream Header |
STREAM_TYPE_I |
I Frame |
STREAM_TYPE_P |
P Frame |
4. Example Programs#
4.1 Example 1#
Bind VENC to VICAP and save the obtained encoded data to a file.
from media.vencoder import *
from media.sensor import *
from media.media import *
import time, os
def vi_bind_venc_test(file_name, width=1280, height=720):
print("VENC test starts")
venc_chn = VENC_CHN_ID_0
width = ALIGN_UP(width, 16)
venc_payload_type = K_PT_H264
# Determine file extension
suffix = file_name.split('.')[-1]
if suffix == '264':
venc_payload_type = K_PT_H264
elif suffix == '265':
venc_payload_type = K_PT_H265
else:
print("Unknown file extension")
return
# Initialize sensor
sensor = Sensor()
sensor.reset()
sensor.set_framesize(width=width, height=height, alignment=12)
sensor.set_pixformat(Sensor.YUV420SP)
# Instantiate video encoder
encoder = Encoder()
encoder.SetOutBufs(venc_chn, 8, width, height)
# Bind camera and venc
link = MediaManager.link(sensor.bind_info()['src'], (VIDEO_ENCODE_MOD_ID, VENC_DEV_ID, venc_chn))
# Initialize media manager
MediaManager.init()
if (venc_payload_type == K_PT_H264):
chnAttr = ChnAttrStr(encoder.PAYLOAD_TYPE_H264, encoder.H264_PROFILE_MAIN, width, height)
elif (venc_payload_type == K_PT_H265):
chnAttr = ChnAttrStr(encoder.PAYLOAD_TYPE_H265, encoder.H265_PROFILE_MAIN, width, height)
streamData = StreamData()
# Create encoder
encoder.Create(venc_chn, chnAttr)
# Start encoding
encoder.Start(venc_chn)
# Start camera
sensor.run()
frame_count = 0
print("Save stream to file: ", file_name)
with open(file_name, "wb") as fo:
try:
while True:
os.exitpoint()
encoder.GetStream(venc_chn, streamData) # Get a frame of stream
for pack_idx in range(0, streamData.pack_cnt):
stream_data = uctypes.bytearray_at(streamData.data[pack_idx], streamData.data_size[pack_idx])
fo.write(stream_data) # Write stream to file
print("Stream size: ", streamData.data_size[pack_idx], "Stream type: ", streamData.stream_type[pack_idx])
encoder.ReleaseStream(venc_chn, streamData) # Release a frame of stream
frame_count += 1
if frame_count >= 200:
break
except KeyboardInterrupt as e:
print("User stop: ", e)
except BaseException as e:
import sys
sys.print_exception(e)
# Stop camera
sensor.stop()
# Destroy the binding of camera and venc
del link
# Stop encoding
encoder.Stop(venc_chn)
# Destroy encoder
encoder.Destroy(venc_chn)
# Clean buffer
MediaManager.deinit()
print("VENC test stops")
if __name__ == "__main__":
os.exitpoint(os.EXITPOINT_ENABLE)
vi_bind_venc_test("/sdcard/examples/test.264", 800, 480) # Example of binding vi to venc
4.2 Example 2#
Encode VENC data stream and save it as a file. Here’s the translated text to English:
from media.vencoder import *
from media.sensor import *
from media.media import *
import time, os
def stream_venc_test(file_name, width=1280, height=720):
print("venc_test start")
venc_chn = VENC_CHN_ID_0
width = ALIGN_UP(width, 16)
venc_payload_type = K_PT_H264
# Determine file type
suffix = file_name.split('.')[-1]
if suffix == '264':
venc_payload_type = K_PT_H264
elif suffix == '265':
venc_payload_type = K_PT_H265
else:
print("Unknown file extension")
return
# Initialize sensor
sensor = Sensor()
sensor.reset()
# Set camera output buffer
# Set chn0 output size
sensor.set_framesize(width=width, height=height, alignment=12)
# Set chn0 output format
sensor.set_pixformat(Sensor.YUV420SP)
# Instantiate video encoder
encoder = Encoder()
# Set video encoder output buffer
encoder.SetOutBufs(venc_chn, 8, width, height)
# Initialize media manager
MediaManager.init()
if (venc_payload_type == K_PT_H264):
chnAttr = ChnAttrStr(encoder.PAYLOAD_TYPE_H264, encoder.H264_PROFILE_MAIN, width, height)
elif (venc_payload_type == K_PT_H265):
chnAttr = ChnAttrStr(encoder.PAYLOAD_TYPE_H265, encoder.H265_PROFILE_MAIN, width, height)
streamData = StreamData()
# Create encoder
encoder.Create(venc_chn, chnAttr)
# Start encoding
encoder.Start(venc_chn)
# Start camera
sensor.run()
frame_count = 0
print("save stream to file: ", file_name)
yuv420sp_img = None
frame_info = k_video_frame_info()
with open(file_name, "wb") as fo:
try:
while True:
os.exitpoint()
yuv420sp_img = sensor.snapshot(chn=CAM_CHN_ID_0)
if (yuv420sp_img == -1):
continue
frame_info.v_frame.width = yuv420sp_img.width()
frame_info.v_frame.height = yuv420sp_img.height()
frame_info.v_frame.pixel_format = Sensor.YUV420SP
frame_info.pool_id = yuv420sp_img.poolid()
frame_info.v_frame.phys_addr[0] = yuv420sp_img.phyaddr()
# frame_info.v_frame.phys_addr[1] = yuv420sp_img.phyaddr(1)
if (yuv420sp_img.width() == 800 and yuv420sp_img.height() == 480):
frame_info.v_frame.phys_addr[1] = frame_info.v_frame.phys_addr[0] + frame_info.v_frame.width * frame_info.v_frame.height + 1024
elif (yuv420sp_img.width() == 1920 and yuv420sp_img.height() == 1080):
frame_info.v_frame.phys_addr[1] = frame_info.v_frame.phys_addr[0] + frame_info.v_frame.width * frame_info.v_frame.height + 3072
elif (yuv420sp_img.width() == 640 and yuv420sp_img.height() == 360):
frame_info.v_frame.phys_addr[1] = frame_info.v_frame.phys_addr[0] + frame_info.v_frame.width * frame_info.v_frame.height + 3072
else:
frame_info.v_frame.phys_addr[1] = frame_info.v_frame.phys_addr[0] + frame_info.v_frame.width * frame_info.v_frame.height
encoder.SendFrame(venc_chn, frame_info)
encoder.GetStream(venc_chn, streamData) # Get a frame of stream
for pack_idx in range(0, streamData.pack_cnt):
stream_data = uctypes.bytearray_at(streamData.data[pack_idx], streamData.data_size[pack_idx])
fo.write(stream_data) # Write stream to file
print("stream size: ", streamData.data_size[pack_idx], "stream type: ", streamData.stream_type[pack_idx])
encoder.ReleaseStream(venc_chn, streamData) # Release a frame of stream
frame_count += 1
if frame_count >= 200:
break
except KeyboardInterrupt as e:
print("user stop: ", e)
except BaseException as e:
import sys
sys.print_exception(e)
# Stop camera
sensor.stop()
# Stop encoding
encoder.Stop(venc_chn)
# Destroy encoder
encoder.Destroy(venc_chn)
# Clean buffer
MediaManager.deinit()
print("venc_test stop")
if __name__ == "__main__":
os.exitpoint(os.EXITPOINT_ENABLE)
stream_venc_test("/sdcard/examples/test.264", 800, 480) # VENC encoding data stream example