3. JPEG编码

3.1. 使用编码器

在调用mcJPEG编码函数之前,用户应执行以下先决步骤。

3.1.1. 编码参数配置

用户应使用 mcjpegEncoderParamsCreate() 函数创建编码参数结构体。 该函数将使用默认参数进行初始化。用户可以使用 mcjpegEncoderParamsSet*() 函数来设置特定参数。

可以使用 mcjpegEncoderParamsSetQuality() 函数将编码质量参数设置为1到100之间的整数,该编码质量参数作为生成JPEG量化表的依据。

应将参数结构体传递给压缩函数。

3.1.2. 创建编码状态结构

用户应使用 mcjpegEncoderStateCreate() 函数创建编码状态结构体。此函数将为编码过程保留中间缓冲区。应将此状态传递给压缩函数。

3.1.3. 对图像进行编码

mcJPEG库提供了几个接口,用于以不同的格式和色彩空间压缩图像。

3.1.3.1. mcjpegEncodeYUV

此函数的输入为YUV色彩空间的图像。应将相应的YUV平面数据填充到 source 参数中。 chroma_subsampling 参数表示输入数据的色度子采样。 如果编码参数中的色度子采样与输入色度子采样相同,用户的输入数据将直接用于JPEG压缩。否则,将对色度进行重采样,以匹配编码参数的色度子采样。

应根据采样因子提供输入数据。也就是说,色度图像平面的大小应与相应的采样对齐。例如:

  • 图像尺寸:123 x 321

  • 输入色度子采样:MCJPEG_CSS_410

  • 色度采样因子:4 x 2

  • 鉴于上述情况,编码器库要求用户提供:

  • Y平面大小: 123 x 321

  • Cb和Cr平面大小:31 x 161

3.1.3.2. mcjpegEncodeImage

此函数的输入(即如何在 source 参数中提供数据)由 input_format 参数决定。 对于交错格式(以I结尾),只使用第一个通道。对于非交错格式,将使用输入格式中的所有通道。

例如,如果用户连续交错存储了大小为W x H的RGB图像,且指向该图像的指针是 pImage,则 source 应为:

source.channel[0] = pImage
source.pitch[0] = W*3

当相同的图像以平面格式存储,并且图像平面指针连续存储在数组 pImage[3] 中时, source 应为:

source.channel[0] = pImage[0]
source.channel[1] = pImage[1]
source.channel[2] = pImage[2]

source 参数中每个通道的 pitch 值应根据数据布局进行相应设置。

3.1.4. 获取压缩流

对于任何输入数据和参数,通常无法准确预测最终JPEG流的最终压缩数据大小。 编码时,mcJPEG库计算最终数据流的大小,在编码器状态下分配临时缓冲区,并将压缩数据保存在编码状态的缓冲区中。为了获得最终的压缩JPEG流,用户应提供足够大的内存缓冲区来存储此压缩数据。执行此操作有两个选择:

  • 使用给定参数和图像尺寸下压缩JPEG流大小的上限:

    1. 使用 mcjpegEncodeGetBufferSize() 函数获取压缩后的JPEG流最大可能的大小。

    2. 分配对应大小的内存缓冲区。

    3. 使用一个编码函数对图像进行编码。

    4. 使用 mcjpegEncodeRetrieveBitstream() 和分配的缓冲区,在成功编码后从编码器状态中获取压缩的JPEG流。

  • 等待编码完成,获取所需缓冲区的确切大小,如下所示:

    1. 使用一个编码函数对图像进行编码。

    2. 使用 mcjpegEncodeRetrieveBitstream() 函数获取压缩JPEG流的大小,以字节为单位。

    3. 分配内存缓冲区,最少为获取到的大小。

    4. 使用 mcjpegEncodeRetrieveBitstream() 函数用压缩的JPEG流填充缓冲区。

3.1.5. mcJPEG编码示例

mcjpegHandle_t handle;
mcjpegEncoderState_t enc_state;
mcjpegEncoderParams_t enc_params;
mcStream_t stream;

//初始化mcjpeg结构体
mcjpegCreateSimple(&handle);
mcjpegEncoderStateCreate(handle, &enc_state, stream);
mcjpegEncoderParamsCreate(handle, &enc_params, stream);

mcjpegImage_t image;
//用图像数据填充图像,比如,640x480的RGB图像

//压缩图像
mcjpegEncodeImage(handle, enc_state, enc_params,
   &image, MCJPEG_INPUT_RGB, 640, 480, stream);

//获取压缩的流大小
size_t length;
mcjpegEncodeRetrieveBitstream(handle, enc_state, NULL, &length, stream);

//获取流本身
mcStreamSynchronize(stream);
std::vector<char> jpeg(length);
mcjpegEncodeRetrieveBitstream(handle, enc_state, jpeg.data(), &length, 0);

//将流写入文件
mcStreamSynchronize(stream);
std::ofstream output_file("test.jpg", std::ios::out | std::ios::binary);
output_file.write(jpeg.data(), length);
output_file.close();

3.2. mcJPEG编码类型声明

3.2.1. mcjpegInputFormat_t

typedef enum {
   MCJPEG_INPUT_RGB  = 3,
   MCJPEG_INPUT_BGR  = 4,
   MCJPEG_INPUT_RGBI = 5,
   MCJPEG_INPUT_BGRI = 6
} mcjpegInputFormat_t;

mcjpegInputFormat_t 枚举用于选择输入图像的像素格式。

表 3.1 mcjpegInputFormat_t枚举项

成员

描述

MCJPEG_INPUT_RGB

输入图像为RGB色彩模型,像素格式为RGB

MCJPEG_INPUT_BGR

输入图像为RGB色彩模型,像素格式为BGR

MCJPEG_INPUT_RGBI

输入图像为RGB色彩模型,像素格式为交错RGB

MCJPEG_INPUT_BGRI

输入图像为RGB色彩模型,像素格式为交错BGR

3.2.2. mcjpegEncoderState_t

mcjpegEncoderState_t 结构体存储用于压缩的中间缓冲区和变量。

3.2.3. mcjpegEncoderParams_t

mcjpegEncoderParams_t 结构体存储JPEG编码参数。

3.3. mcJPEG编码API

3.3.1. mcjpegEncoderStateCreate()

创建编码状态,用于存储压缩中使用的中间缓冲区。

签名

mcjpegStatus_t mcjpegEncoderStateCreate(
   mcjpegHandle_t          handle,
   mcjpegEncoderState_t    *encoder_state,
   mcStream_t              stream);

参数

参数

输入/输出

内存

描述

handle

输入

主机

库句柄

encoder_state

输出

主机

此指针指向编码状态结构体

stream

输入

主机

MXMACA流,包含所有必需的设备操作

3.3.2. mcjpegEncoderStateDestroy()

销毁编码状态。

签名

mcjpegStatus_t mcjpegEncoderStateDestroy( mcjpegEncoderState_t encoder_state);

参数

参数

输入/输出

内存

描述

encoder_state

输入/输出

主机

要被销毁的编码状态结构体

3.3.3. mcjpegEncoderParamsCreate()

创建包含压缩参数的结构体。

签名

mcjpegStatus_t mcjpegEncoderParamsCreate(
   mcjpegHandle_t          handle,
   mcjpegEncoderParams_t   *encoder_params,
   mcStream_t              stream);

参数

参数

输入/输出

内存

描述

handle

输入

主机

库句柄

encoder_params

输出

主机

此指针指向创建的压缩参数结构体

stream

输入

主机

MXMACA流,包含所有必需的设备操作

3.3.4. mcjpegEncoderParamsDestroy()

销毁编码参数结构体。

签名

mcjpegEncoderParamsDestroy( mcjpegEncoderParams_t encoder_params);

参数

参数

输入/输出

内存

描述

encoder_params

输入/输出

主机

要被销毁的编码器参数结构体

3.3.5. mcjpegEncoderParamsSetEncoding()

在编码参数结构体中设置编码类型参数。

签名

mcjpegStatus_t mcjpegEncoderParamsSetEncoding(
   mcjpegEncoderParams_t   encoder_params,
   mcjpegJpegEncoding_t    etype,
   mcStream_t              stream);

参数

参数

输入/输出

内存

描述

encoder_params

输入/输出

主机

编码参数结构体句柄

etype

输入

主机

编码类型选择。

默认为baseline,当前仅支持baseline

stream

输入

主机

MXMACA流,包含所有必需的设备操作

3.3.6. mcjpegEncoderParamsSetQuality()

在编码参数结构体中设置编码质量参数。

签名

mcjpegStatus_t mcjpegEncoderParamsSetQuality(
   mcjpegEncoderParams_t   encoder_params,
   const int               quality,
   mcStream_t              stream);

参数

参数

输入/输出

内存

描述

encoder_params

输入/输出

主机

编码参数结构体句柄

quality

输入

主机

介于1到100之间、表示质量的整数值,100表示最高质量。默认值为70

stream

输入

主机

MXMACA流,包含所有必需的设备操作

3.3.7. mcjpegEncoderParamsSetSamplingFactors()

设置用于JPEG压缩的色度子采样。

签名

mcjpegStatus_t mcjpegEncoderParamsSetSamplingFactors(
   mcjpegEncoderParams_t            encoder_params,
   const mcjpegChromaSubsampling_t  chroma_subsampling,
   mcStream_t                       stream);

参数

参数

输入/输出

内存

描述

encoder_params

输入/输出

主机

编码参数结构体句柄

chroma_subsampling

输入

主机

用于JPEG压缩的色度子采样。如果输入是YUV色彩模型,且 chroma_subsampling 与源图像的采样因子不同,则mcJPEG库会将源图像转换为 chroma_subsampling 采样类型。默认值为4:2:0,当前仅支持4:2:0

stream

输入

主机

MXMACA流,包含所有必需的设备操作

3.3.8. mcjpegEncodeGetBufferSize()

为给定的输入参数返回存储压缩JPEG流所需的最大可能缓冲区大小。

签名

mcjpegStatus_t mcjpegEncodeGetBufferSize(
   mcjpegHandle_t                handle,
   const mcjpegEncoderParams_t   encoder_params,
   int                           image_width,
   int                           image_height,
   size_t                        *max_stream_length);

参数

参数

输入/输出

内存

描述

handle

输入

主机

库句柄

encoder_params

输入/输出

主机

编码参数结构体句柄

image_width

输入

主机

输入图像宽度

image_height

输入

主机

输入图像高度

stream

输入

主机

MXMACA流,包含所有必需的设备操作

3.3.9. mcjpegEncodeYUV()

使用提供的参数将YUV图像压缩到JPEG流,并将其存储在状态结构体中。

签名

mcjpegStatus_t mcjpegEncodeYUV(
   mcjpegHandle_t                handle,
   mcjpegEncoderState_t          encoder_state,
   const mcjpegEncoderParams_t   encoder_params,
   const mcjpegImage_t           *source,
   mcjpegChromaSubsampling_t     chroma_subsampling,
   int                           image_width,
   int                           image_height,
   mcStream_t                    stream);

参数

参数

输入/输出

内存

描述

handle

输入

主机

库句柄

encoder_state

输入/输出

主机

内部结构体,用于保存压缩所需的临时缓冲区,并存储最终压缩的JPEG流

encoder_params

输入

主机

编码参数结构体句柄

source

输入

主机

此指针指向 mcjpegImage_t 结构体

chroma_subsampling

输入

主机

输入数据的色度子采样

image_width

输入

主机

输入图像宽度

image_height

输入

主机

输入图像高度

stream

输入

主机

MXMACA流,包含所有必需的设备操作

3.3.10. mcjpegEncodeImage()

使用提供的参数将RGB图像压缩到JPEG流,并将其存储在状态结构体中。

签名

mcjpegStatus_t mcjpegEncodeImage(
   mcjpegHandle_t                handle,
   mcjpegEncoderState_t          encoder_state,
   const mcjpegEncoderParams_t   encoder_params,
   const mcjpegImage_t           *source,
   mcjpegInputFormat_t           input_format,
   int                           image_width,
   int                           image_height,
   mcStream_t                    stream);

参数

参数

输入/输出

内存

描述

handle

输入

主机

库句柄

encoder_state

输入/输出

主机

内部结构体,用于保存压缩所需的临时缓冲区,以及存储最终压缩的JPEG流

encoder_params

输入

主机

编码参数结构体句柄

source

输入

主机

此指针指向 mcjpegImage_t 结构体

input_format

输入

主机

描述输入数据的 mcjpegInputFormat_t 类型的值

image_width

输入

主机

输入图像宽度

image_height

输入

主机

输入图像高度

stream

输入

主机

MXMACA流,包含所有必需的设备操作

3.3.11. mcjpegEncodeRetrieveBitstream()

从先前在一个编码函数中使用过的编码状态中获取压缩流。

  • 如果 data 参数为NULL,则在 length 参数中返回压缩流的大小。

  • 如果 data 不为空,则提供的 length 参数应包含 data 缓冲区大小。

  • 如果提供的 length 小于压缩流的大小,则返回错误。否则,压缩流将存储在 data 缓冲区中,且实际的压缩缓冲区大小将存储在 length 参数中。

签名

mcjpegStatus_t mcjpegEncodeRetrieveBitstream(
   mcjpegHandle_t          handle,
   mcjpegEncoderState_t    encoder_state,
   unsigned char           *data,
   size_t                  *length,
   mcStream_t              stream);

参数

参数

输入/输出

内存

描述

handle

输入

主机

库句柄

encoder_state

输入/输出

主机

先前在一个编码函数中使用过的 encoder_state

data

输入/输出

主机

此指针指向主机内存中用于存储压缩流的缓冲区。可以为NULL

length

输入/输出

主机

此指针指向输入缓冲区大小。返回时,mcJPEG库将在此参数中存储实际的压缩流大小

stream

输入

主机

MXMACA流,包含所有必需的设备操作

3.3.12. mcjpegEncodeRetrieveBitstreamDevice()

从先前在一个编码函数中使用过的编码状态中获取压缩流。

  • data 参数应指向设备内存。

  • 如果 data 参数为NULL,则将在 length 参数中返回压缩流的大小。

  • 如果 data 不为空,则提供的 length 参数应包含 data 缓冲区大小。

  • 如果提供的 length 小于压缩流的大小,则返回错误。否则,压缩的流将存储在 data 缓冲区中,而实际的压缩缓冲区大小将存储在 length 参数中。

签名

mcjpegStatus_t mcjpegEncodeRetrieveBitstreamDevice(
   mcjpegHandle_t          handle,
   mcjpegEncoderState_t    encoder_state,
   unsigned char           *data,
   size_t                  *length,
   mcStream_t              stream);

参数

参数

输入/输出

内存

描述

handle

输入

主机

库句柄

encoder_state

输入/输出

主机

先前在一个编码函数中使用过的 encoder_state

data

输入/输出

设备

此指针指向设备内存中用于存储压缩流的缓冲区。可以为NULL

length

输入/输出

主机

此指针指向输入缓冲区大小。返回时,mcJPEG库将在此参数中存储实际的压缩流大小

stream

输入

主机

MXMACA流,包含所有必需的设备操作