您的位置: 首页 - 站长

a做爰网站wordpress采集开源

当前位置: 首页 > news >正文

a做爰网站,wordpress采集开源,怎么联系百度人工服务,一级直播一、ff_h2645_extract_rbsp函数的声明 ff_h2645_extract_rbsp函数的声明放在FFmpeg源码#xff08;本文演示用的FFmpeg源码版本为5.0.3#xff0c;该ffmpeg在CentOS 7.5上通过10.2.1版本的gcc编译#xff09;的头文件libavcodec/h2645_parse.h中。 /*** Extract the raw (u…一、ff_h2645_extract_rbsp函数的声明 ff_h2645_extract_rbsp函数的声明放在FFmpeg源码本文演示用的FFmpeg源码版本为5.0.3该ffmpeg在CentOS 7.5上通过10.2.1版本的gcc编译的头文件libavcodec/h2645_parse.h中。 /*** Extract the raw (unescaped) bitstream.*/ int ff_h2645_extract_rbsp(const uint8_t *src, int length, H2645RBSP *rbsp,H2645NAL *nal, int small_padding); 该函数在H.264/H.265的解码时被调用。作用是将去掉第一个startcode的H.264/H.265码流以下全部以H.264码流为例 中的第一个NALU 提取出来分别去掉和保留防竞争字节存贮到形参nal 指向的缓冲区中。关于 NALU和防竞争字节的概念可以参考音视频入门基础H.264专题3——EBSP, RBSP和SODB 形参src输入型参数。指向缓冲区的指针该缓冲区存放 去掉第一个startcode起始码后的H.264码流。 形参length输入型参数。指针src指向的缓冲区的长度单位为字节。 形参rbsp为H2645RBSP类型为输出型参数。 结构体H2645RBSP 定义如下 typedef struct H2645RBSP {uint8_t *rbsp_buffer;AVBufferRef *rbsp_buffer_ref;int rbsp_buffer_alloc_size;int rbsp_buffer_size; } H2645RBSP; 执行ff_h2645_extract_rbsp函数后 rbsp-rbsp_buffer 变为去掉startcode和防竞争字节后的H.264码流可能包含多个NALU。 rbsp-rbsp_buffer_size 变为rbsp-rbsp_buffer的大小单位为字节。 形参nal为H2645NAL类型为输出型参数。 结构体H2645NAL定义如下 typedef struct H2645NAL {const uint8_t data;int size;/** Size, in bits, of just the data, excluding the stop bit and any trailing* padding. I.e. what HEVC calls SODB.*/int size_bits;int raw_size;const uint8_t raw_data;GetBitContext gb;/** NAL unit type/int type;/** H.264 only, nal_ref_idc/int ref_idc;/** HEVC only, nuh_temporal_id_plus_1 - 1/int temporal_id;/** HEVC only, identifier of layer to which nal unit belongs/int nuh_layer_id;int skipped_bytes;int skipped_bytes_pos_size;int *skipped_bytes_pos; } H2645NAL; 执行ff_h2645_extract_rbsp函数后 nal-data变为指向缓冲区的指针。该缓冲区存放 “指针src指向的缓冲区中的第一个NALU”该NALU去掉了startcode和防竞争字节但保留了NALU Header。可以理解为NALU Header RBSP nal-size变为nal-data指向的缓冲区的大小单位为字节。 nal-raw_data变为指向缓冲区的指针。该缓冲区存放 “指针src指向的缓冲区中的第一个NALU”该NALU去掉了startcode但保留了防竞争字节和NALU Header。(可以理解为NALU Header EBSP) nal-raw_size变为nal-raw_data指向的缓冲区的大小单位为字节。 形参small_padding输入型参数。值一般等于1可以忽略。 返回值整形。值等同于nal-raw_size为nal-raw_data指向的缓冲区的大小单位为字节 二、ff_h2645_extract_rbsp函数的定义 ff_h2645_extract_rbsp函数定义在libavcodec/h2645_parse.c中 int ff_h2645_extract_rbsp(const uint8_t *src, int length,H2645RBSP *rbsp, H2645NAL *nal, int small_padding) {int i, si, di;uint8_t dst;nal-skipped_bytes 0; #define STARTCODE_TEST \if (i 2 length src[i 1] 0 src[i 2] 3) { \if (src[i 2] ! 3 src[i 2] ! 0) { \/ startcode, so we must be past the end / \length i; } \break; } #if HAVE_FAST_UNALIGNED #define FIND_FIRST_ZERO \if (i 0 !src[i]) \i–; \while (src[i]) \i #if HAVE_FAST_64BITfor (i 0; i 1 length; i 9) {if (!((~AV_RN64(src i) (AV_RN64(src i) - 0x0100010001000101ULL)) 0x8000800080008080ULL))continue;FIND_FIRST_ZERO;STARTCODE_TEST;i - 7;} #elsefor (i 0; i 1 length; i 5) {if (!((~AV_RN32(src i) (AV_RN32(src i) - 0x01000101U)) 0x80008080U))continue;FIND_FIRST_ZERO;STARTCODE_TEST;i - 3;} #endif / HAVE_FAST_64BIT / #elsefor (i 0; i 1 length; i 2) {if (src[i])continue;if (i 0 src[i - 1] 0)i–;STARTCODE_TEST;} #endif / HAVE_FAST_UNALIGNED */if (i length - 1 small_padding) { // no escaped 0nal-data nal-raw_data src;nal-size nal-raw_size length;return length;} else if (i length)i length;dst rbsp-rbsp_buffer[rbsp-rbsp_buffer_size];memcpy(dst, src, i);si di i;while (si 2 length) {// remove escapes (very rare 1:2^22)if (src[si 2] 3) {dst[di] src[si];dst[di] src[si];} else if (src[si] 0 src[si 1] 0 src[si 2] ! 0) {if (src[si 2] 3) { // escapedst[di] 0;dst[di] 0;si 3;if (nal-skipped_bytes_pos) {nal-skipped_bytes;if (nal-skipped_bytes_pos_size nal-skipped_bytes) {nal-skipped_bytes_pos_size * 2;av_assert0(nal-skipped_bytes_pos_size nal-skipped_bytes);av_reallocp_array(nal-skipped_bytes_pos,nal-skipped_bytes_pos_size,sizeof(*nal-skipped_bytes_pos));if (!nal-skipped_bytes_pos) {nal-skipped_bytes_pos_size 0;return AVERROR(ENOMEM);}}if (nal-skipped_bytes_pos)nal-skipped_bytes_pos[nal-skipped_bytes-1] di - 1;}continue;} else // next start codegoto nsc;}dst[di] src[si];}while (si length)dst[di] src[si];nsc:memset(dst di, 0, AV_INPUT_BUFFER_PADDING_SIZE);nal-data dst;nal-size di;nal-raw_data src;nal-raw_size si;rbsp-rbsp_buffer_size si;return si; } 三、ff_h2645_extract_rbsp函数的内部实现原理分析 ff_h2645_extract_rbsp函数中存在如下代码 int ff_h2645_extract_rbsp(const uint8_t *src, int length,H2645RBSP *rbsp, H2645NAL nal, int small_padding) {//…#define STARTCODE_TEST \if (i 2 length src[i 1] 0 src[i 2] 3) { \if (src[i 2] ! 3 src[i 2] ! 0) { \/ startcode, so we must be past the end */ \length i; } \break; }//…for (i 0; i 1 length; i 2) {if (src[i])continue;if (i 0 src[i - 1] 0)i–;STARTCODE_TEST;}//… } 其中STARTCODE_TEST是宏定义。将宏展开上述代码相当于 int ff_h2645_extract_rbsp(const uint8_t *src, int length,H2645RBSP *rbsp, H2645NAL nal, int small_padding) {//…for (i 0; i 1 length; i 2) {if (src[i])continue;if (i 0 src[i - 1] 0)i–;if (i 2 length src[i 1] 0 src[i 2] 3) { if (src[i 2] ! 3 src[i 2] ! 0) { / startcode, so we must be past the end / length i; } break; }}//… } 上述代码中首先会通过语句 for (i 0; i 1 length; i 2) {if (src[i])continue;if (i 0 src[i - 1] 0)i–;//…} 来判断H.264码流中是否存在ASCII 码为 0 值为\0的的字符如果存在则表明接下来的数据中可能会出现startcode起始码或防竞争字节。然后执行下面代码 if (i 2 length src[i 1] 0 src[i 2] 3) { if (src[i 2] ! 3 src[i 2] ! 0) { / startcode, so we must be past the end */ length i; } break;
} 来判断是否是起始码如果是起始码或防竞争字节就通过break;跳出循环。 继续执行语句。满足下面条件说明是防竞争字节 else if (src[si] 0 src[si 1] 0 src[si 2] ! 0) {if (src[si 2] 3) { // escape//… } 如果是防竞争字节通过下面语句去掉防竞争字节 dst[di] 0;dst[di] 0;si       3; //… 如果不满足条件if (src[si 2] 3)说明遇到下一个起始码表示这个NALU结束了。执行else语句跳转到“nsc” if (src[si 2] 3) { // escape //… } else // next start codegoto nsc; //… 跳转到“nsc”后给输出型参数赋值并返回。 nsc:memset(dst di, 0, AV_INPUT_BUFFER_PADDING_SIZE);nal-data dst;nal-size di;nal-raw_data src;nal-raw_size si;rbsp-rbsp_buffer_size si;return si; 四、通过修改ff_h2645_extract_rbsp函数降低FFmpeg转码时的cpu使用率 由于ff_h2645_extract_rbsp函数在H.264/H.265的解码时被调用。所以理论上修改该函数使用算法优化用空间换时间等策略可以降低FFmpeg转码时的cpu使用率。具体可以参考Imagine Computing创新技术大赛赛道2参赛攻略 - 007gzs