T264 简介
H.264 是 MPEG-4 标准所定义的最新格式,同时也是技术含量最高、代表最新技术水平的视频编码格式之一,有的也称(AVC)。而 T264 是 H264 的一个开源实现,其他的开源实现还有 x264(只有编码部分)和 ffmpeg等。T264 为国内开发团队开发,它解决了在尽可能低的存储空间内,获得好的图像质量,这样也减少了图像在网络传输中所占用的带宽。
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 并关闭编码器
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. 处理完成之后就关闭×××
注意:这里在最开始的时候,×××状态是需要更多数据的,这时,应该传数据给它,并且必须是一个关键帧!因为×××需要关键帧做参考,也就是说,在编码的时候,每个一定数目的视频帧就会有一帧比较大的关键帧,其他非关键帧参考关键帧的内容。如果最开始的时候传给×××的视频帧不是关键帧,可预料的:应该是解不起来的,没有关键帧可以参考!而且×××还会异常退出!
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 的一点理解,不尽准确,仅供参考。