T264
简介
H.264 是 MPEG-4 标准所定义的最新格式,同时也是技术含量最高、代表最新技术水平的视频编码格式之一,有的也称(AVC)。而 T264 是 H264 的一个开源实现,其他的开源实现还有 x264(只有编码部分)和 ffmpeg等。T264 为国内开发团队开发,它解决了在尽可能低的存储空间内,获得好的图像质量,这样也减少了图像在网络传输中所占用的带宽。
H.264 是 MPEG-4 标准所定义的最新格式,同时也是技术含量最高、代表最新技术水平的视频编码格式之一,有的也称(AVC)。而 T264 是 H264 的一个开源实现,其他的开源实现还有 x264(只有编码部分)和 ffmpeg等。T264 为国内开发团队开发,它解决了在尽可能低的存储空间内,获得好的图像质量,这样也减少了图像在网络传输中所占用的带宽。
T264
性能测评
T264是国内的开源项目,T264 decoder的程序做过汇编优化,速度还可以,但只能解 T264 本身的码流。开发团队对 T264 decoder v0.14 做了修改,只车 baseline 的解码。与本身不带×××的 x264 相比,T264 更有可有行。
T264是国内的开源项目,T264 decoder的程序做过汇编优化,速度还可以,但只能解 T264 本身的码流。开发团队对 T264 decoder v0.14 做了修改,只车 baseline 的解码。与本身不带×××的 x264 相比,T264 更有可有行。
T264
基本数据结构
o T264_param_t 代表编码器所采用的参数,比如图片帧宽度高度、要用怎么样的压缩率等等。
o T264_t 表示编码器和×××的一个实例。
o T264_frame_t ×××解码出每一帧视频后都会储存到这个数据结构里。
o decoder_state_t ×××状态。
o 每个数据结构里面的成员这里不详细说,之后遇到会有解释。
view plain copy to clipboard print ?
1. /* In Linux, you Should include this
2. * head file, or the compilor will report
3. * errors! I don't know why yet. */
4. #include
5.
6. /* Head file for T264 */
7. #include "/avc/common/T264.h"
8.
9. T264_param_t /* Store the parameters for encoder, sorts like
10. * how wide and how high a frame is, what quality
11. * do you expect, and how fast the encoder should be.
12. * You have to make a tradeoff between speed and quality,
13. * and maybe storage size. */
14.
15. T264_t /* An instance for encoder or decoder */
16.
17. T264_frame_t /* When decoder product a frame, store in this struct.
18. * Members of Y[0], U, V point to the components of YUV
19. * respectly. */
20.
21. decoder_state_t /* Represent the state of a decoder, maybe one of the
22. * following values:
23. * DEC_STATE_BUFFER: need more date
24. DEC_STATE_OK:
25. DEC_STATE_SEQ:
26. DEC_STATE_PIC:
27. DEC_STATE_SLICE: a frame have be deoded
28. DEC_STATE_CUSTOM_SET: the end or restart
29. DEC_STATE_UNKOWN: unknown
30. */
/* In Linux, you Should include this
* head file, or the compilor will report
* errors! I don't know why yet. */
#include
/* Head file for T264 */
#include "/avc/common/T264.h"
T264_param_t
/* Store the parameters for encoder, sorts like
* how wide and how high a frame is, what quality
* do you expect, and how fast the encoder should be.
* You have to make a tradeoff between speed and quality,
* and maybe storage size. */
T264_t
/* An instance for encoder or decoder */
T264_frame_t
/* When decoder product a frame, store in this struct.
* Members of Y[0], U, V point to the components of YUV
* respectly. */
decoder_state_t /* Represent the state of a decoder, maybe one of the
* following values:
* DEC_STATE_BUFFER: need more date
DEC_STATE_OK:
DEC_STATE_SEQ:
DEC_STATE_PIC:
DEC_STATE_SLICE: a frame have be deoded
DEC_STATE_CUSTOM_SET: the end or restart
DEC_STATE_UNKOWN: unknown
*/
T264
基本函数接口
o T264_t *T264_open(¶m) 根据param 参数配置,打开并初始化一个编码器实例,返回编码器实例指针,可以当成句柄理解。
o uint8_t *T264_malloc(size, CACHE_SIZE),分配内存,大小为 size,返回内存区指针。
view plain copy to clipboard print ?
1. /**
2. * This function is used to open and initialize an
3. * encoder with parameter para. Return a pointer
4. * to the encoder instance, like a handle.
5. * @para: pointer to T264_param_t, represent parameters.
6. * @T264_t: return pointer to T264_t, an instance of
7. * encoder, will be used late, like a handle.
8. */
9. T264_t *T264_open(T264_param_t *para);
10.
11. /**
12. * This function explicitly close an encoder, release
13. * system resouces.
14. * @t: pointer to the encoder you want to close.
15. * Note: I suggest here we should use T264_t **t as parameter,
16. * since the developers can set the pointer to NULL for the user
17. * programmer. Otherwise, the programmer should do it all by themself.
18. * To release something, don't forget to set the corresponding pointer
19. * to NULL, avoiding potential errors.
20. */
21.
void T264_close(T264_t* t);
22.
23. /**
24. * This function encoder a frame.
25. * @t: pointer to encoder you have just open.
26. * @src: the frame you want to encode.
27. * @dst: The result will be put in this buffer.
28. * @dst_size: size of the dst buffer.
29. * @return: the length of frame after encoded.
30. */
31. int32_t T264_encode(T264_t* t, uint8_t* src, uint8_t* dst, int32_t dst_size);
32.
33. /**
34. * Open and initialize a decoder for use.
35. * @return: pointer to the decoder created.
36. * This pointer will be use late.
37. */
38. T264_t *T264dec_open();
39.
40. /**
41. * Close a decoder and release corresponding resources.
42. * @t: pointer to the decoder you want to close.
43. */
44.
void T264dec_close(T264_t *t);
45.
46. /**
47. * Give the data to the decoder to decode, when the decoder
48. * need more data.
49. * @t: pointer to the decoder.
50. * @buf: pointer to the data you want to send to the decoder.
51. * @len: length of data store in buf.
52. */
53.
void T264dec_buffer(T264_t *t, uint8_t *buf, int32_t len);
54.
55. /**
56. * Return the state of the decoder.
57. * @t: pointer to a decoder, which decoder you want to know.
58. * @return: the state of the decoder pointed by t.
59. */
60. decoder_state_t T264dec_parse(T264_t *t);
61.
62. /**
63. * Get a decoded frame when the decoder is ready to give.
64. * @t: pointer to the decoder.
65. * @return: pointer to the frame produced by the decoder.
66. */
67. T264_frame_t *T264dec_flush_frame(T264_t *t);
/**
* This function is used to open and initialize an
* encoder with parameter para. Return a pointer
* to the encoder instance, like a handle.
* @para: pointer to T264_param_t, represent parameters.
* @T264_t: return pointer to T264_t, an instance of
*
encoder, will be used late, like a handle.
*/
T264_t *T264_open(T264_param_t *para);
/**
* This function explicitly close an encoder, release
* system resouces.
* @t: pointer to the encoder you want to close.
* Note: I suggest here we should use T264_t **t as parameter,
* since the developers can set the pointer to NULL for the user
* programmer. Otherwise, the programmer should do it all by themself.
* To release something, don't forget to set the corresponding pointer
* to NULL, avoiding potential errors.
*/
void T264_close(T264_t* t);
/**
* This function encoder a frame.
* @t: pointer to encoder you have just open.
* @src: the frame you want to encode.
* @dst: The result will be put in this buffer.
* @dst_size: size of the dst buffer.
* @return: the length of frame after encoded.
*/
int32_t T264_encode(T264_t* t, uint8_t* src, uint8_t* dst, int32_t dst_size);
/**
* Open and initialize a decoder for use.
* @return: pointer to the decoder created.
*
This pointer will be use late.
*/
T264_t *T264dec_open();
/**
* Close a decoder and release corresponding resources.
* @t: pointer to the decoder you want to close.
*/
void T264dec_close(T264_t *t);
/**
* Give the data to the decoder to decode, when the decoder
* need more data.
* @t: pointer to the decoder.
* @buf: pointer to the data you want to send to the decoder.
* @len: length of data store in buf.
*/
void T264dec_buffer(T264_t *t, uint8_t *buf, int32_t len);
/**
* Return the state of the decoder.
* @t: pointer to a decoder, which decoder you want to know.
* @return: the state of the decoder pointed by t.
*/
decoder_state_t T264dec_parse(T264_t *t);
/**
* Get a decoded frame when the decoder is ready to give.
* @t: pointer to the decoder.
* @return: pointer to the frame produced by the decoder.
*/
T264_frame_t *T264dec_flush_frame(T264_t *t);
编码过程
1. 创建一个 T264_param_t
2. 设置 T264_param_t 中的相关参数
3. 打开编码器
4. 分配 buffer 内存空间
5. 读一帧视频
6. 用 T264_encode 编码一帧视频,结果存放在一个 buffer 里面
7. 处理结果,可以是写入文件,或者发送到网络
8. 编码结束后释放 buffer 并关闭编码器
1. 创建一个 T264_param_t
2. 设置 T264_param_t 中的相关参数
3. 打开编码器
4. 分配 buffer 内存空间
5. 读一帧视频
6. 用 T264_encode 编码一帧视频,结果存放在一个 buffer 里面
7. 处理结果,可以是写入文件,或者发送到网络
8. 编码结束后释放 buffer 并关闭编码器
view plain copy to clipboard print ?
1.
void encode()
2. {
3. /* No.1 Create param */
4. T264_param_t param;
5. T264_t* t;
6. uint8_t* buf, *dst;
7. int32_t size;
8.
9. /* No.2 Init param */
10. init_param(¶m, paramfile); /* This function is in T264.c, reading info
11. * from a configure file and set the param. */
12. param.direct_flag = 1;
13.
14. /* No.3 Open encoder */
15. t = T264_open(¶m);
16.
17. /* No.4 alloc memory for buffers */
18. /* Since input data is YUV420, so size is: */
19. size = param.height * param.width + (param.height * param.width >> 1);
20. buf = T264_malloc(size, CACHE_SIZE);
21. dst = T264_malloc(size, CACHE_SIZE);
22.
23.
while(1) {
24. /* No.5 Read a frame */
25.
if(read(buf, size, ...) == 0)
26.
break; // No more frame now
27.
28. /* No.6 Encode! Result store in dst, return result length */
29. len = T264_encode(t, buf, dst, size);
30.
31. /* No.7 Process the encoded frame */
32. process(dst, size); /* write to a file, or send to the network, or... */
33. }
34.
35. /* No.8 release buffers and close encoder */
36. T264_free(buf);
37. T264_free(dst);
38. T264_close(t);
39. }
void encode()
{
/* No.1 Create param */
T264_param_t param;
T264_t* t;
uint8_t* buf, *dst;
int32_t size;
/* No.2 Init param */
init_param(¶m, paramfile); /* This function is in T264.c, reading info
* from a configure file and set the param. */
param.direct_flag = 1;
/* No.3 Open encoder */
t = T264_open(¶m);
/* No.4 alloc memory for buffers */
/* Since input data is YUV420, so size is: */
size = param.height * param.width + (param.height * param.width >> 1);
buf = T264_malloc(size, CACHE_SIZE);
dst = T264_malloc(size, CACHE_SIZE);
while(1) {
/* No.5 Read a frame */
if(read(buf, size, ...) == 0)
break; // No more frame now
/* No.6 Encode! Result store in dst, return result length */
len = T264_encode(t, buf, dst, size);
/* No.7 Process the encoded frame */
process(dst, size); /* write to a file, or send to the network, or... */
}
/* No.8 release buffers and close encoder */
T264_free(buf);
T264_free(dst);
T264_close(t);
}
解码过程
1. 打开×××
2. 获取×××当前状态
3. 如果需要更多数据,则读更多数据并给传进×××
4. 如果当前有一帧视频解压好,则处理这帧视频
5. 如果... 一般就是上面两种状态,其他的还有待深入理解,一般用不上
6. 处理完成之后就关闭×××
注意:这里在最开始的时候,×××状态是需要更多数据的,这时,应该传数据给它,并且必须是一个关键帧!因为×××需要关键帧做参考,也就是说,在编码的时候,每个一定数目的视频帧就会有一帧比较大的关键帧,其他非关键帧参考关键帧的内容。如果最开始的时候传给×××的视频帧不是关键帧,可预料的:应该是解不起来的,没有关键帧可以参考!而且×××还会异常退出!
1. 打开×××
2. 获取×××当前状态
3. 如果需要更多数据,则读更多数据并给传进×××
4. 如果当前有一帧视频解压好,则处理这帧视频
5. 如果... 一般就是上面两种状态,其他的还有待深入理解,一般用不上
6. 处理完成之后就关闭×××
注意:这里在最开始的时候,×××状态是需要更多数据的,这时,应该传数据给它,并且必须是一个关键帧!因为×××需要关键帧做参考,也就是说,在编码的时候,每个一定数目的视频帧就会有一帧比较大的关键帧,其他非关键帧参考关键帧的内容。如果最开始的时候传给×××的视频帧不是关键帧,可预料的:应该是解不起来的,没有关键帧可以参考!而且×××还会异常退出!
view plain copy to clipboard print ?
1.
void decode()
2. {
3.
size_t size;
4. uint8_t buffer[BUFFER_SIZE + 4];
5.
6. /* No.1 Open decoder */
7. T264_t* t = T264dec_open();
8.
while (run)
9. {
10. /* No.2 Query state of the decoder */
11. decoder_state_t state = T264dec_parse(t);
12.
switch(state)
13. {
14. /* No.3 The decoder needy more data */
15.
case DEC_STATE_BUFFER:
16. /* Read more data */
17. size = read(buffer, 1, BUFFER_SIZE, somewhere);
18. /* Deliver to the decoder */
19. T264dec_buffer(t, buffer, size);
20.
21.
case DEC_STATE_PIC:
22. /* write one pic */
23.
break;
24.
25.
case DEC_STATE_SEQ:
26.
break;
27.
28. /* No.4 If another frame has been decoded */
29.
case DEC_STATE_SLICE:
30. /* Get the frame */
31. frame = T264dec_flush_frame(t);
32.
33. /* The frame is of YUV420, we process
34. * the YUV components respectly.
35. */
36. /* Y */
37. temp = buffer;
38. p = frame->Y[0];
39.
for(i = 0 ; i < t->height ; i ++)
40. {
41. memcpy(temp, p, t->width);
42. temp += t->width;
43. p += t->edged_stride;
44. }
45.
46. /* U */
47. p = frame->U;
48.
for(i = 0 ; i < t->height >> 1 ; i ++)
49. {
50. memcpy(temp, p, t->width >> 1);
51. temp += t->width >> 1;
52. p += t->edged_stride_uv;
53. }
54.
55. /* V */
56. p = frame->V;
57.
for(i = 0 ; i < t->height >> 1 ; i ++)
58. {
59. memcpy(temp, p, t->width >> 1);
60. temp += t->width >> 1;
61. p += t->edged_stride_uv;
62. }
63. /* Now the frame is put in buffer, of YUV420 */
64. /* Then you can process this frame: maybe just display */
65.
break;
66.
67.
case DEC_STATE_CUSTOM_SET:
68.
break;
69.
default:
70.
break;
71. }
72. }
73.
74. /* No.6 Close the decoder */
75. T264dec_close(t);
76. }
void decode()
{
size_t size;
uint8_t buffer[BUFFER_SIZE + 4];
/* No.1 Open decoder */
T264_t* t = T264dec_open();
while (run)
{
/* No.2 Query state of the decoder */
decoder_state_t state = T264dec_parse(t);
switch(state)
{
/* No.3 The decoder needy more data */
case DEC_STATE_BUFFER:
/* Read more data */
size = read(buffer, 1, BUFFER_SIZE, somewhere);
/* Deliver to the decoder */
T264dec_buffer(t, buffer, size);
case DEC_STATE_PIC:
/* write one pic */
break;
case DEC_STATE_SEQ:
break;
/* No.4 If another frame has been decoded */
case DEC_STATE_SLICE:
/* Get the frame */
frame = T264dec_flush_frame(t);
/* The frame is of YUV420, we process
* the YUV components respectly.
*/
/* Y */
temp = buffer;
p = frame->Y[0];
for(i = 0 ; i < t->height ; i ++)
{
memcpy(temp, p, t->width);
temp += t->width;
p += t->edged_stride;
}
/* U */
p = frame->U;
for(i = 0 ; i < t->height >> 1 ; i ++)
{
memcpy(temp, p, t->width >> 1);
temp += t->width >> 1;
p += t->edged_stride_uv;
}
/* V */
p = frame->V;
for(i = 0 ; i < t->height >> 1 ; i ++)
{
memcpy(temp, p, t->width >> 1);
temp += t->width >> 1;
p += t->edged_stride_uv;
}
/* Now the frame is put in buffer, of YUV420 */
/* Then you can process this frame: maybe just display */
break;
case DEC_STATE_CUSTOM_SET:
break;
default:
break;
}
}
/* No.6 Close the decoder */
T264dec_close(t);
}
更详细的接口和编解码流程请参考 t264 源码中 T264.c 文件,这是个例子程序,相当于一个 API 说明文档,当然没有文档那么好懂,注释不多,所以多看几遍咯!
上述为本人看代码 T264.c 的一点理解,不尽准确,仅供参考。