h264 订阅
H.264,同时也是MPEG-4第十部分,是由ITU-T视频编码专家组(VCEG)和ISO/IEC动态图像专家组(MPEG)联合组成的联合视频组(JVT,Joint Video Team)提出的高度压缩数字视频编解码器标准。这个标准通常被称之为H.264/AVC(或者AVC/H.264或者H.264/MPEG-4 AVC或MPEG-4/H.264 AVC)而明确的说明它两方面的开发者。H264标准各主要部分有Access Unit delimiter(访问单元分割符),SEI(附加增强信息),primary coded picture(基本图像编码),Redundant Coded Picture(冗余图像编码)。还有Instantaneous Decoding Refresh(IDR,即时解码刷新)、Hypothetical Reference Decoder(HRD,假想参考解码)、Hypothetical Stream Scheduler(HSS,假想码流调度器)。 展开全文
H.264,同时也是MPEG-4第十部分,是由ITU-T视频编码专家组(VCEG)和ISO/IEC动态图像专家组(MPEG)联合组成的联合视频组(JVT,Joint Video Team)提出的高度压缩数字视频编解码器标准。这个标准通常被称之为H.264/AVC(或者AVC/H.264或者H.264/MPEG-4 AVC或MPEG-4/H.264 AVC)而明确的说明它两方面的开发者。H264标准各主要部分有Access Unit delimiter(访问单元分割符),SEI(附加增强信息),primary coded picture(基本图像编码),Redundant Coded Picture(冗余图像编码)。还有Instantaneous Decoding Refresh(IDR,即时解码刷新)、Hypothetical Reference Decoder(HRD,假想参考解码)、Hypothetical Stream Scheduler(HSS,假想码流调度器)。
信息
属    性
数字视频压缩格式
属    于
MPEG-4第十部分
中文名
H.264
主要部分
访问单元分割符
H.264背景介绍
H.264是国际标准化组织(ISO)和国际电信联盟(ITU)共同提出的继MPEG4之后的新一代数字视频压缩格式。H.264是ITU-T以H.26x系列为名称命名的视频编解码技术标准之一。H.264是ITU-T的VCEG(视频编码专家组)和ISO/IEC的MPEG(活动图像编码专家组)的联合视频组(JVT:joint video team)开发的一个数字视频编码标准。该标准最早来自于ITU-T的称之为H.26L的项目的开发。H.26L这个名称虽然不太常见,但是一直被使用着。H.264是ITU-T以H.26x系列为名称命名的标准之一,AVC是ISO/IEC MPEG一方的称呼。国际上制定视频编解码技术的组织有两个,一个是“国际电联(ITU-T)”,它制定的标准有H.261、H.263、H.263+等,另一个是“国际标准化组织(ISO)”它制定的标准有MPEG-1、MPEG-2、MPEG-4等。而H.264则是由两个组织联合组建的联合视频组(JVT)共同制定的新数字视频编码标准,所以它既是ITU-T的H.264,又是ISO/IEC的MPEG-4高级视频编码(Advanced Video Coding,AVC)的第10 部分。因此,不论是MPEG-4 AVC、MPEG-4 Part 10,还是ISO/IEC 14496-10,都是指H.264。1998年1月份标准开始草案征集,1999年9月,完成第一个草案,2001年5月制定了其测试模式TML-8,2002年6月的 JVT第5次会议通过了H.264的FCD板。2003年3月正式发布。在2005年又开发出了H.264的更高级应用标准MVC 和 SVC 版本。国际电联ITU和MPEG组织在发布了H.264标准之后,很快就发布公告,为下一代视频编解码标准H.265征集技术方案。为H.265设定的技术性能指标是:压缩效率比H.264提高1倍、且不明显提高编码和解码的计算量。据MPEG组织2009年西安会议的回顾,尚无一个技术提案达到上述指标。H.264是在MPEG-4技术的基础之上建立起来的,其编解码流程主要包括5个部分:帧间和帧内预测(Estimation)、变换(Transform)和反变换、量化(Quantization)和反量化、环路滤波(Loop Filter)、熵编码(Entropy Coding)。H.264标准的主要目标是:与其它现有的视频编码标准相比,在相同的带宽下提供更加优秀的图象质量。通过该标准,在同等图象质量下的压缩效率比以前的标准(MPEG2)提高了2倍左右。H.264可以提供11个等级、7个类别的子协议格式(算法),其中等级定义是对外部环境进行限定,例如带宽需求、内存需求、网络性能等等。等级越高,带宽要求就越高,视频质量也越高。类别定义则是针对特定应用,定义编码器所使用的特性子集,并规范不同应用环境中的编码器复杂程度。
收起全文
精华内容
参与话题
问答
  • 视音频数据处理入门:H.264视频码流解析

    万次阅读 多人点赞 2016-01-31 00:19:50
    前两篇文章介绍的YUV/RGB处理程序以及PCM处理程序都属于视音频...该程序可以从H.264码流中分析得到它的基本单元NALU,并且可以简单解析NALU首部的字段。通过修改该程序可以实现不同的H.264码流处理功能。原理H.264

    =====================================================

    视音频数据处理入门系列文章:

    视音频数据处理入门:RGB、YUV像素数据处理

    视音频数据处理入门:PCM音频采样数据处理

    视音频数据处理入门:H.264视频码流解析

    视音频数据处理入门:AAC音频码流解析

    视音频数据处理入门:FLV封装格式解析

    视音频数据处理入门:UDP-RTP协议解析

    =====================================================


    前两篇文章介绍的YUV/RGB处理程序以及PCM处理程序都属于视音频原始数据的处理程序。从本文开始介绍视音频码流的处理程序。本文介绍的程序是视频码流处理程序。视频码流在视频播放器中的位置如下所示。


    本文中的程序是一个H.264码流解析程序。该程序可以从H.264码流中分析得到它的基本单元NALU,并且可以简单解析NALU首部的字段。通过修改该程序可以实现不同的H.264码流处理功能。


    原理

    H.264原始码流(又称为“裸流”)是由一个一个的NALU组成的。他们的结构如下图所示。


    其中每个NALU之间通过startcode(起始码)进行分隔,起始码分成两种:0x000001(3Byte)或者0x00000001(4Byte)。如果NALU对应的Slice为一帧的开始就用0x00000001,否则就用0x000001。

    H.264码流解析的步骤就是首先从码流中搜索0x000001和0x00000001,分离出NALU;然后再分析NALU的各个字段。本文的程序即实现了上述的两个步骤。


    代码

    整个程序位于simplest_h264_parser()函数中,如下所示。
    /**
     * 最简单的视音频数据处理示例
     * Simplest MediaData Test
     *
     * 雷霄骅 Lei Xiaohua
     * leixiaohua1020@126.com
     * 中国传媒大学/数字电视技术
     * Communication University of China / Digital TV Technology
     * http://blog.csdn.net/leixiaohua1020
     *
     * 本项目包含如下几种视音频测试示例:
     *  (1)像素数据处理程序。包含RGB和YUV像素格式处理的函数。
     *  (2)音频采样数据处理程序。包含PCM音频采样格式处理的函数。
     *  (3)H.264码流分析程序。可以分离并解析NALU。
     *  (4)AAC码流分析程序。可以分离并解析ADTS帧。
     *  (5)FLV封装格式分析程序。可以将FLV中的MP3音频码流分离出来。
     *  (6)UDP-RTP协议分析程序。可以将分析UDP/RTP/MPEG-TS数据包。
     *
     * This project contains following samples to handling multimedia data:
     *  (1) Video pixel data handling program. It contains several examples to handle RGB and YUV data.
     *  (2) Audio sample data handling program. It contains several examples to handle PCM data.
     *  (3) H.264 stream analysis program. It can parse H.264 bitstream and analysis NALU of stream.
     *  (4) AAC stream analysis program. It can parse AAC bitstream and analysis ADTS frame of stream.
     *  (5) FLV format analysis program. It can analysis FLV file and extract MP3 audio stream.
     *  (6) UDP-RTP protocol analysis program. It can analysis UDP/RTP/MPEG-TS Packet.
     *
     */
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    typedef enum {
    	NALU_TYPE_SLICE    = 1,
    	NALU_TYPE_DPA      = 2,
    	NALU_TYPE_DPB      = 3,
    	NALU_TYPE_DPC      = 4,
    	NALU_TYPE_IDR      = 5,
    	NALU_TYPE_SEI      = 6,
    	NALU_TYPE_SPS      = 7,
    	NALU_TYPE_PPS      = 8,
    	NALU_TYPE_AUD      = 9,
    	NALU_TYPE_EOSEQ    = 10,
    	NALU_TYPE_EOSTREAM = 11,
    	NALU_TYPE_FILL     = 12,
    } NaluType;
    
    typedef enum {
    	NALU_PRIORITY_DISPOSABLE = 0,
    	NALU_PRIRITY_LOW         = 1,
    	NALU_PRIORITY_HIGH       = 2,
    	NALU_PRIORITY_HIGHEST    = 3
    } NaluPriority;
    
    
    typedef struct
    {
    	int startcodeprefix_len;      //! 4 for parameter sets and first slice in picture, 3 for everything else (suggested)
    	unsigned len;                 //! Length of the NAL unit (Excluding the start code, which does not belong to the NALU)
    	unsigned max_size;            //! Nal Unit Buffer size
    	int forbidden_bit;            //! should be always FALSE
    	int nal_reference_idc;        //! NALU_PRIORITY_xxxx
    	int nal_unit_type;            //! NALU_TYPE_xxxx    
    	char *buf;                    //! contains the first byte followed by the EBSP
    } NALU_t;
    
    FILE *h264bitstream = NULL;                //!< the bit stream file
    
    int info2=0, info3=0;
    
    static int FindStartCode2 (unsigned char *Buf){
    	if(Buf[0]!=0 || Buf[1]!=0 || Buf[2] !=1) return 0; //0x000001?
    	else return 1;
    }
    
    static int FindStartCode3 (unsigned char *Buf){
    	if(Buf[0]!=0 || Buf[1]!=0 || Buf[2] !=0 || Buf[3] !=1) return 0;//0x00000001?
    	else return 1;
    }
    
    
    int GetAnnexbNALU (NALU_t *nalu){
    	int pos = 0;
    	int StartCodeFound, rewind;
    	unsigned char *Buf;
    
    	if ((Buf = (unsigned char*)calloc (nalu->max_size , sizeof(char))) == NULL) 
    		printf ("GetAnnexbNALU: Could not allocate Buf memory\n");
    
    	nalu->startcodeprefix_len=3;
    
    	if (3 != fread (Buf, 1, 3, h264bitstream)){
    		free(Buf);
    		return 0;
    	}
    	info2 = FindStartCode2 (Buf);
    	if(info2 != 1) {
    		if(1 != fread(Buf+3, 1, 1, h264bitstream)){
    			free(Buf);
    			return 0;
    		}
    		info3 = FindStartCode3 (Buf);
    		if (info3 != 1){ 
    			free(Buf);
    			return -1;
    		}
    		else {
    			pos = 4;
    			nalu->startcodeprefix_len = 4;
    		}
    	}
    	else{
    		nalu->startcodeprefix_len = 3;
    		pos = 3;
    	}
    	StartCodeFound = 0;
    	info2 = 0;
    	info3 = 0;
    
    	while (!StartCodeFound){
    		if (feof (h264bitstream)){
    			nalu->len = (pos-1)-nalu->startcodeprefix_len;
    			memcpy (nalu->buf, &Buf[nalu->startcodeprefix_len], nalu->len);     
    			nalu->forbidden_bit = nalu->buf[0] & 0x80; //1 bit
    			nalu->nal_reference_idc = nalu->buf[0] & 0x60; // 2 bit
    			nalu->nal_unit_type = (nalu->buf[0]) & 0x1f;// 5 bit
    			free(Buf);
    			return pos-1;
    		}
    		Buf[pos++] = fgetc (h264bitstream);
    		info3 = FindStartCode3(&Buf[pos-4]);
    		if(info3 != 1)
    			info2 = FindStartCode2(&Buf[pos-3]);
    		StartCodeFound = (info2 == 1 || info3 == 1);
    	}
    
    	// Here, we have found another start code (and read length of startcode bytes more than we should
    	// have.  Hence, go back in the file
    	rewind = (info3 == 1)? -4 : -3;
    
    	if (0 != fseek (h264bitstream, rewind, SEEK_CUR)){
    		free(Buf);
    		printf("GetAnnexbNALU: Cannot fseek in the bit stream file");
    	}
    
    	// Here the Start code, the complete NALU, and the next start code is in the Buf.  
    	// The size of Buf is pos, pos+rewind are the number of bytes excluding the next
    	// start code, and (pos+rewind)-startcodeprefix_len is the size of the NALU excluding the start code
    
    	nalu->len = (pos+rewind)-nalu->startcodeprefix_len;
    	memcpy (nalu->buf, &Buf[nalu->startcodeprefix_len], nalu->len);//
    	nalu->forbidden_bit = nalu->buf[0] & 0x80; //1 bit
    	nalu->nal_reference_idc = nalu->buf[0] & 0x60; // 2 bit
    	nalu->nal_unit_type = (nalu->buf[0]) & 0x1f;// 5 bit
    	free(Buf);
    
    	return (pos+rewind);
    }
    
    /**
     * Analysis H.264 Bitstream
     * @param url    Location of input H.264 bitstream file.
     */
    int simplest_h264_parser(char *url){
    
    	NALU_t *n;
    	int buffersize=100000;
    
    	//FILE *myout=fopen("output_log.txt","wb+");
    	FILE *myout=stdout;
    
    	h264bitstream=fopen(url, "rb+");
    	if (h264bitstream==NULL){
    		printf("Open file error\n");
    		return 0;
    	}
    
    	n = (NALU_t*)calloc (1, sizeof (NALU_t));
    	if (n == NULL){
    		printf("Alloc NALU Error\n");
    		return 0;
    	}
    
    	n->max_size=buffersize;
    	n->buf = (char*)calloc (buffersize, sizeof (char));
    	if (n->buf == NULL){
    		free (n);
    		printf ("AllocNALU: n->buf");
    		return 0;
    	}
    
    	int data_offset=0;
    	int nal_num=0;
    	printf("-----+-------- NALU Table ------+---------+\n");
    	printf(" NUM |    POS  |    IDC |  TYPE |   LEN   |\n");
    	printf("-----+---------+--------+-------+---------+\n");
    
    	while(!feof(h264bitstream)) 
    	{
    		int data_lenth;
    		data_lenth=GetAnnexbNALU(n);
    
    		char type_str[20]={0};
    		switch(n->nal_unit_type){
    			case NALU_TYPE_SLICE:sprintf(type_str,"SLICE");break;
    			case NALU_TYPE_DPA:sprintf(type_str,"DPA");break;
    			case NALU_TYPE_DPB:sprintf(type_str,"DPB");break;
    			case NALU_TYPE_DPC:sprintf(type_str,"DPC");break;
    			case NALU_TYPE_IDR:sprintf(type_str,"IDR");break;
    			case NALU_TYPE_SEI:sprintf(type_str,"SEI");break;
    			case NALU_TYPE_SPS:sprintf(type_str,"SPS");break;
    			case NALU_TYPE_PPS:sprintf(type_str,"PPS");break;
    			case NALU_TYPE_AUD:sprintf(type_str,"AUD");break;
    			case NALU_TYPE_EOSEQ:sprintf(type_str,"EOSEQ");break;
    			case NALU_TYPE_EOSTREAM:sprintf(type_str,"EOSTREAM");break;
    			case NALU_TYPE_FILL:sprintf(type_str,"FILL");break;
    		}
    		char idc_str[20]={0};
    		switch(n->nal_reference_idc>>5){
    			case NALU_PRIORITY_DISPOSABLE:sprintf(idc_str,"DISPOS");break;
    			case NALU_PRIRITY_LOW:sprintf(idc_str,"LOW");break;
    			case NALU_PRIORITY_HIGH:sprintf(idc_str,"HIGH");break;
    			case NALU_PRIORITY_HIGHEST:sprintf(idc_str,"HIGHEST");break;
    		}
    
    		fprintf(myout,"%5d| %8d| %7s| %6s| %8d|\n",nal_num,data_offset,idc_str,type_str,n->len);
    
    		data_offset=data_offset+data_lenth;
    
    		nal_num++;
    	}
    
    	//Free
    	if (n){
    		if (n->buf){
    			free(n->buf);
    			n->buf=NULL;
    		}
    		free (n);
    	}
    	return 0;
    }
    

    上文中的函数调用方法如下所示。
    simplest_h264_parser("sintel.h264");

    结果

    本程序的输入为一个H.264原始码流(裸流)的文件路径,输出为该码流的NALU统计数据,如下图所示。


    下载


    Simplest mediadata test


    项目主页

    SourceForge:https://sourceforge.net/projects/simplest-mediadata-test/

    Github:https://github.com/leixiaohua1020/simplest_mediadata_test

    开源中国:http://git.oschina.net/leixiaohua1020/simplest_mediadata_test


    CSDN下载地址:http://download.csdn.net/detail/leixiaohua1020/9422409


    本项目包含如下几种视音频数据解析示例:

     (1)像素数据处理程序。包含RGB和YUV像素格式处理的函数。
     (2)音频采样数据处理程序。包含PCM音频采样格式处理的函数。
     (3)H.264码流分析程序。可以分离并解析NALU。
     (4)AAC码流分析程序。可以分离并解析ADTS帧。
     (5)FLV封装格式分析程序。可以将FLV中的MP3音频码流分离出来。
     (6)UDP-RTP协议分析程序。可以将分析UDP/RTP/MPEG-TS数据包。


    雷霄骅 (Lei Xiaohua)
    leixiaohua1020@126.com
    http://blog.csdn.net/leixiaohua1020


    展开全文
  • H264基本原理

    万次阅读 多人点赞 2017-11-15 02:23:43
    H264视频压缩算法现在无疑是所有视频压缩技术中使用最广泛,最流行的。随着 x264/openh264以及ffmpeg等开源库的推出,大多数使用者无需再对H264的细节做过多的研究,这大降低了人们使用H264的成本。但为了用好H264,...

    前言

    H264视频压缩算法现在无疑是所有视频压缩技术中使用最广泛,最流行的。随着 x264/openh264以及ffmpeg等开源库的推出,大多数使用者无需再对H264的细节做过多的研究,这大降低了人们使用H264的成本。

    但为了用好H264,我们还是要对H264的基本原理弄清楚才行。今天我们就来看看H264的基本原理。

    H264概述

    H264压缩技术主要采用了以下几种方法对视频数据进行压缩。包括:

    • 帧内预测压缩,解决的是空域数据冗余问题。
    • 帧间预测压缩(运动估计与补偿),解决的是时域数据冗徐问题。
    • 整数离散余弦变换(DCT),将空间上的相关性变为频域上无关的数据然后进行量化。
    • CABAC压缩。

    经过压缩后的帧分为:I帧,P帧和B帧:

    • I帧:关键帧,采用帧内压缩技术。
    • P帧:向前参考帧,在压缩时,只参考前面已经处理的帧。采用帧音压缩技术。
    • B帧:双向参考帧,在压缩时,它即参考前而的帧,又参考它后面的帧。采用帧间压缩技术。

    除了I/P/B帧外,还有图像序列GOP。

    • GOP:两个I帧之间是一个图像序列,在一个图像序列中只有一个I帧。如下图所示:

    下面我们就来详细描述一下H264压缩技术。

    H264压缩技术

    H264的基本原理其实非常简单,下我们就简单的描述一下H264压缩数据的过程。通过摄像头采集到的视频帧(按每秒 30 帧算),被送到 H264 编码器的缓冲区中。编码器先要为每一幅图片划分宏块。

    以下面这张图为例:

    划分宏块

    H264默认是使用 16X16 大小的区域作为一个宏块,也可以划分成 8X8 大小。

    划分好宏块后,计算宏块的象素值。

    以此类推,计算一幅图像中每个宏块的像素值,所有宏块都处理完后如下面的样子。

    划分子块

    H264对比较平坦的图像使用 16X16 大小的宏块。但为了更高的压缩率,还可以在 16X16 的宏块上更划分出更小的子块。子块的大小可以是 8X16、 16X8、 8X8、 4X8、 8X4、 4X4非常的灵活。

    上幅图中,红框内的 16X16 宏块中大部分是蓝色背景,而三只鹰的部分图像被划在了该宏块内,为了更好的处理三只鹰的部分图像,H264就在 16X16 的宏块内又划分出了多个子块。

    这样再经过帧内压缩,可以得到更高效的数据。下图是分别使用mpeg-2和H264对上面宏块进行压缩后的结果。其中左半部分为MPEG-2子块划分后压缩的结果,右半部分为H264的子块划压缩后的结果,可以看出H264的划分方法更具优势。

    宏块划分好后,就可以对H264编码器缓存中的所有图片进行分组了。

    帧分组

    对于视频数据主要有两类数据冗余,一类是时间上的数据冗余,另一类是空间上的数据冗余。其中时间上的数据冗余是最大的。下面我们就先来说说视频数据时间上的冗余问题。

    为什么说时间上的冗余是最大的呢?假设摄像头每秒抓取30帧,这30帧的数据大部分情况下都是相关联的。也有可能不止30帧的的数据,可能几十帧,上百帧的数据都是关联特别密切的。

    对于这些关联特别密切的帧,其实我们只需要保存一帧的数据,其它帧都可以通过这一帧再按某种规则预测出来,所以说视频数据在时间上的冗余是最多的。

    为了达到相关帧通过预测的方法来压缩数据,就需要将视频帧进行分组。那么如何判定某些帧关系密切,可以划为一组呢?我们来看一下例子,下面是捕获的一组运动的台球的视频帧,台球从右上角滚到了左下角。


    H264编码器会按顺序,每次取出两幅相邻的帧进行宏块比较,计算两帧的相似度。如下图:

    通过宏块扫描与宏块搜索可以发现这两个帧的关联度是非常高的。进而发现这一组帧的关联度都是非常高的。因此,上面这几帧就可以划分为一组。其算法是:在相邻几幅图像画面中,一般有差别的像素只有10%以内的点,亮度差值变化不超过2%,而色度差值的变化只有1%以内,我们认为这样的图可以分到一组。

    在这样一组帧中,经过编码后,我们只保留第一帖的完整数据,其它帧都通过参考上一帧计算出来。我们称第一帧为IDR/I帧,其它帧我们称为P/B帧,这样编码后的数据帧组我们称为GOP

    运动估计与补偿

    在H264编码器中将帧分组后,就要计算帧组内物体的运动矢量了。还以上面运动的台球视频帧为例,我们来看一下它是如何计算运动矢量的。

    H264编码器首先按顺序从缓冲区头部取出两帧视频数据,然后进行宏块扫描。当发现其中一幅图片中有物体时,就在另一幅图的邻近位置(搜索窗口中)进行搜索。如果此时在另一幅图中找到该物体,那么就可以计算出物体的运动矢量了。下面这幅图就是搜索后的台球移动的位置。

    通过上图中台球位置相差,就可以计算出台图运行的方向和距离。H264依次把每一帧中球移动的距离和方向都记录下来就成了下面的样子。

    运动矢量计算出来后,将相同部分(也就是绿色部分)减去,就得到了补偿数据。我们最终只需要将补偿数据进行压缩保存,以后在解码时就可以恢复原图了。压缩补偿后的数据只需要记录很少的一点数据。如下所示:

    我们把运动矢量与补偿称为帧间压缩技术,它解决的是视频帧在时间上的数据冗余。除了帧间压缩,帧内也要进行数据压缩,帧内数据压缩解决的是空间上的数据冗余。下面我们就来介绍一下帧内压缩技术。

    帧内预测

    人眼对图象都有一个识别度,对低频的亮度很敏感,对高频的亮度不太敏感。所以基于一些研究,可以将一幅图像中人眼不敏感的数据去除掉。这样就提出了帧内预测技术。

    H264的帧内压缩与JPEG很相似。一幅图像被划分好宏块后,对每个宏块可以进行 9 种模式的预测。找出与原图最接近的一种预测模式。

    下面这幅图是对整幅图中的每个宏块进行预测的过程。

    帧内预测后的图像与原始图像的对比如下:

    然后,将原始图像与帧内预测后的图像相减得残差值。

    再将我们之前得到的预测模式信息一起保存起来,这样我们就可以在解码时恢复原图了。效果如下:

    经过帧内与帧间的压缩后,虽然数据有大幅减少,但还有优化的空间。

    对残差数据做DCT

    可以将残差数据做整数离散余弦变换,去掉数据的相关性,进一步压缩数据。如下图所示,左侧为原数据的宏块,右侧为计算出的残差数据的宏块。

    将残差数据宏块数字化后如下图所示:

    将残差数据宏块进行 DCT 转换。

    去掉相关联的数据后,我们可以看出数据被进一步压缩了。

    做完 DCT 后,还不够,还要进行 CABAC 进行无损压缩。

    CABAC

    上面的帧内压缩是属于有损压缩技术。也就是说图像被压缩后,无法完全复原。而CABAC属于无损压缩技术。

    无损压缩技术大家最熟悉的可能就是哈夫曼编码了,给高频的词一个短码,给低频词一个长码从而达到数据压缩的目的。MPEG-2中使用的VLC就是这种算法,我们以 A-Z 作为例子,A属于高频数据,Z属于低频数据。看看它是如何做的。

    CABAC也是给高频数据短码,给低频数据长码。同时还会根据上下文相关性进行压缩,这种方式又比VLC高效很多。其效果如下:

    现在将 A-Z 换成视频帧,它就成了下面的样子。

    从上面这张图中明显可以看出采用 CACBA 的无损压缩方案要比 VLC 高效的多。

    小结

    至此,我们就将H264的编码原理讲完了。本篇文章主要讲了以下以点内容:
    1. 简音介绍了H264中的一些基本概念。如I/P/B帧, GOP。
    2. 详细讲解了H264编码的基本原理,包括:

    • 宏块的划分
    • 图像分组
    • 帧内压缩技术原理
    • 帧间压缩技术原理。
    • DCT
    • CABAC压缩原理。

    希望以上内容能对您有所帮助。谢谢!

    展开全文
  • H.264/AVC视频编解码技术详解

    万人学习 2016-07-29 11:19:04
    本课程将从原理、标准和实现等多个角度,详细讲述了H.264/AVC视频编码标准的整体架构与技术细节,不但讲解了H.264/AVC标准协议文档中的内容,还通过实际的H.264码流分析/解码程序的开发来帮助观众更深入地理解H.264...
  • 最简单的基于FFMPEG的视频编码器(YUV编码为H.264

    万次阅读 多人点赞 2014-05-12 00:42:25
    该编码器实现了YUV420P的像素数据编码为H.264的压缩编码数据。编码器代码十分简单,但是每一行代码都很重要,适合好好研究一下。弄清楚了本代码也就基本弄清楚了FFMPEG的编码流程。目前我虽然已经调通了程序,但是...

    =====================================================

    最简单的基于FFmpeg的视频编码器文章列表:

    最简单的基于FFMPEG的视频编码器(YUV编码为H.264)

    最简单的基于FFmpeg的视频编码器-更新版(YUV编码为HEVC(H.265))

    最简单的基于FFmpeg的编码器-纯净版(不包含libavformat)

    =====================================================


    本文介绍一个最简单的基于FFMPEG的视频编码器。该编码器实现了YUV420P的像素数据编码为H.264的压缩编码数据。编码器代码十分简单,但是每一行代码都很重要,适合好好研究一下。弄清楚了本代码也就基本弄清楚了FFMPEG的编码流程。目前我虽然已经调通了程序,但是还是有些地方没有完全搞明白,需要下一步继续探究然后补充内容。

    本程序使用最新版的类库(编译时间为2014.5.6),开发平台为VC2010。所有的配置都已经做好,只需要运行就可以了。


    流程

    下面附一张使用FFmpeg编码视频的流程图。使用该流程,不仅可以编码H.264的视频,而且可以编码MPEG4/MPEG2/VP8等等各种FFmpeg支持的视频。图中蓝色背景的函数是实际输出数据的函数。浅绿色的函数是视频编码的函数。


    简单介绍一下流程中各个函数的意义:

    av_register_all():注册FFmpeg所有编解码器。

    avformat_alloc_output_context2():初始化输出码流的AVFormatContext。

    avio_open():打开输出文件。

    av_new_stream():创建输出码流的AVStream。

    avcodec_find_encoder():查找编码器。

    avcodec_open2():打开编码器。

    avformat_write_header():写文件头(对于某些没有文件头的封装格式,不需要此函数。比如说MPEG2TS)。

    avcodec_encode_video2():编码一帧视频。即将AVFrame(存储YUV像素数据)编码为AVPacket(存储H.264等格式的码流数据)。

    av_write_frame():将编码后的视频码流写入文件。

    flush_encoder():输入的像素数据读取完成后调用此函数。用于输出编码器中剩余的AVPacket。

    av_write_trailer():写文件尾(对于某些没有文件头的封装格式,不需要此函数。比如说MPEG2TS)。


    代码

     

    /**
     * 最简单的基于FFmpeg的视频编码器
     * Simplest FFmpeg Video Encoder
     * 
     * 雷霄骅 Lei Xiaohua
     * leixiaohua1020@126.com
     * 中国传媒大学/数字电视技术
     * Communication University of China / Digital TV Technology
     * http://blog.csdn.net/leixiaohua1020
     * 
     * 本程序实现了YUV像素数据编码为视频码流(H264,MPEG2,VP8等等)。
     * 是最简单的FFmpeg视频编码方面的教程。
     * 通过学习本例子可以了解FFmpeg的编码流程。
     * This software encode YUV420P data to H.264 bitstream.
     * It's the simplest video encoding software based on FFmpeg. 
     * Suitable for beginner of FFmpeg 
     */
    
    #include <stdio.h>
    
    #define __STDC_CONSTANT_MACROS
    
    #ifdef _WIN32
    //Windows
    extern "C"
    {
    #include "libavutil/opt.h"
    #include "libavcodec/avcodec.h"
    #include "libavformat/avformat.h"
    };
    #else
    //Linux...
    #ifdef __cplusplus
    extern "C"
    {
    #endif
    #include <libavutil/opt.h>
    #include <libavcodec/avcodec.h>
    #include <libavformat/avformat.h>
    #ifdef __cplusplus
    };
    #endif
    #endif
    
    
    int flush_encoder(AVFormatContext *fmt_ctx,unsigned int stream_index){
    	int ret;
    	int got_frame;
    	AVPacket enc_pkt;
    	if (!(fmt_ctx->streams[stream_index]->codec->codec->capabilities &
    		CODEC_CAP_DELAY))
    		return 0;
    	while (1) {
    		enc_pkt.data = NULL;
    		enc_pkt.size = 0;
    		av_init_packet(&enc_pkt);
    		ret = avcodec_encode_video2 (fmt_ctx->streams[stream_index]->codec, &enc_pkt,
    			NULL, &got_frame);
    		av_frame_free(NULL);
    		if (ret < 0)
    			break;
    		if (!got_frame){
    			ret=0;
    			break;
    		}
    		printf("Flush Encoder: Succeed to encode 1 frame!\tsize:%5d\n",enc_pkt.size);
    		/* mux encoded frame */
    		ret = av_write_frame(fmt_ctx, &enc_pkt);
    		if (ret < 0)
    			break;
    	}
    	return ret;
    }
    
    int main(int argc, char* argv[])
    {
    	AVFormatContext* pFormatCtx;
    	AVOutputFormat* fmt;
    	AVStream* video_st;
    	AVCodecContext* pCodecCtx;
    	AVCodec* pCodec;
    	AVPacket pkt;
    	uint8_t* picture_buf;
    	AVFrame* pFrame;
    	int picture_size;
    	int y_size;
    	int framecnt=0;
    	//FILE *in_file = fopen("src01_480x272.yuv", "rb");	//Input raw YUV data 
    	FILE *in_file = fopen("../ds_480x272.yuv", "rb");   //Input raw YUV data
    	int in_w=480,in_h=272;                              //Input data's width and height
    	int framenum=100;                                   //Frames to encode
    	//const char* out_file = "src01.h264";              //Output Filepath 
    	//const char* out_file = "src01.ts";
    	//const char* out_file = "src01.hevc";
    	const char* out_file = "ds.h264";
    
    	av_register_all();
    	//Method1.
    	pFormatCtx = avformat_alloc_context();
    	//Guess Format
    	fmt = av_guess_format(NULL, out_file, NULL);
    	pFormatCtx->oformat = fmt;
    	
    	//Method 2.
    	//avformat_alloc_output_context2(&pFormatCtx, NULL, NULL, out_file);
    	//fmt = pFormatCtx->oformat;
    
    
    	//Open output URL
    	if (avio_open(&pFormatCtx->pb,out_file, AVIO_FLAG_READ_WRITE) < 0){
    		printf("Failed to open output file! \n");
    		return -1;
    	}
    
    	video_st = avformat_new_stream(pFormatCtx, 0);
    	//video_st->time_base.num = 1; 
    	//video_st->time_base.den = 25;  
    
    	if (video_st==NULL){
    		return -1;
    	}
    	//Param that must set
    	pCodecCtx = video_st->codec;
    	//pCodecCtx->codec_id =AV_CODEC_ID_HEVC;
    	pCodecCtx->codec_id = fmt->video_codec;
    	pCodecCtx->codec_type = AVMEDIA_TYPE_VIDEO;
    	pCodecCtx->pix_fmt = AV_PIX_FMT_YUV420P;
    	pCodecCtx->width = in_w;  
    	pCodecCtx->height = in_h;
    	pCodecCtx->bit_rate = 400000;  
    	pCodecCtx->gop_size=250;
    
    	pCodecCtx->time_base.num = 1;  
    	pCodecCtx->time_base.den = 25;  
    
    	//H264
    	//pCodecCtx->me_range = 16;
    	//pCodecCtx->max_qdiff = 4;
    	//pCodecCtx->qcompress = 0.6;
    	pCodecCtx->qmin = 10;
    	pCodecCtx->qmax = 51;
    
    	//Optional Param
    	pCodecCtx->max_b_frames=3;
    
    	// Set Option
    	AVDictionary *param = 0;
    	//H.264
    	if(pCodecCtx->codec_id == AV_CODEC_ID_H264) {
    		av_dict_set(¶m, "preset", "slow", 0);
    		av_dict_set(¶m, "tune", "zerolatency", 0);
    		//av_dict_set(¶m, "profile", "main", 0);
    	}
    	//H.265
    	if(pCodecCtx->codec_id == AV_CODEC_ID_H265){
    		av_dict_set(¶m, "preset", "ultrafast", 0);
    		av_dict_set(¶m, "tune", "zero-latency", 0);
    	}
    
    	//Show some Information
    	av_dump_format(pFormatCtx, 0, out_file, 1);
    
    	pCodec = avcodec_find_encoder(pCodecCtx->codec_id);
    	if (!pCodec){
    		printf("Can not find encoder! \n");
    		return -1;
    	}
    	if (avcodec_open2(pCodecCtx, pCodec,¶m) < 0){
    		printf("Failed to open encoder! \n");
    		return -1;
    	}
    
    
    	pFrame = av_frame_alloc();
    	picture_size = avpicture_get_size(pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height);
    	picture_buf = (uint8_t *)av_malloc(picture_size);
    	avpicture_fill((AVPicture *)pFrame, picture_buf, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height);
    
    	//Write File Header
    	avformat_write_header(pFormatCtx,NULL);
    
    	av_new_packet(&pkt,picture_size);
    
    	y_size = pCodecCtx->width * pCodecCtx->height;
    
    	for (int i=0; i<framenum; i++){
    		//Read raw YUV data
    		if (fread(picture_buf, 1, y_size*3/2, in_file) <= 0){
    			printf("Failed to read raw data! \n");
    			return -1;
    		}else if(feof(in_file)){
    			break;
    		}
    		pFrame->data[0] = picture_buf;              // Y
    		pFrame->data[1] = picture_buf+ y_size;      // U 
    		pFrame->data[2] = picture_buf+ y_size*5/4;  // V
    		//PTS
    		//pFrame->pts=i;
    		pFrame->pts=i*(video_st->time_base.den)/((video_st->time_base.num)*25);
    		int got_picture=0;
    		//Encode
    		int ret = avcodec_encode_video2(pCodecCtx, &pkt,pFrame, &got_picture);
    		if(ret < 0){
    			printf("Failed to encode! \n");
    			return -1;
    		}
    		if (got_picture==1){
    			printf("Succeed to encode frame: %5d\tsize:%5d\n",framecnt,pkt.size);
    			framecnt++;
    			pkt.stream_index = video_st->index;
    			ret = av_write_frame(pFormatCtx, &pkt);
    			av_free_packet(&pkt);
    		}
    	}
    	//Flush Encoder
    	int ret = flush_encoder(pFormatCtx,0);
    	if (ret < 0) {
    		printf("Flushing encoder failed\n");
    		return -1;
    	}
    
    	//Write file trailer
    	av_write_trailer(pFormatCtx);
    
    	//Clean
    	if (video_st){
    		avcodec_close(video_st->codec);
    		av_free(pFrame);
    		av_free(picture_buf);
    	}
    	avio_close(pFormatCtx->pb);
    	avformat_free_context(pFormatCtx);
    
    	fclose(in_file);
    
    	return 0;
    }
    


    结果

    软件运行截图(受限于文件体积,原始YUV帧数很少):


    编码前的YUV序列:


    编码后的H.264码流:



    下载


    Simplest FFmpeg Video Encoder


    项目主页

    SourceForge:https://sourceforge.net/projects/simplestffmpegvideoencoder/

    Github:https://github.com/leixiaohua1020/simplest_ffmpeg_video_encoder

    开源中国:http://git.oschina.net/leixiaohua1020/simplest_ffmpeg_video_encoder


    下载地址:

    http://download.csdn.net/detail/leixiaohua1020/7324115

    【修正】之前发现编码后的H.264码流与YUV输入的帧数不同。经过观察对比其他程序后发现需要调用flush_encoder()将编码器中剩余的视频帧输出。已经将该问题修正。

    CSDN下载地址(修正后):

    http://download.csdn.net/detail/leixiaohua1020/7466649

    PUDN下载地址(修正后):

    http://www.pudn.com/downloads644/sourcecode/multimedia/detail2605258.html

    SourceForge上已经更新。


    更新-1.1 (2015.1.03)=========================================

    增加了《最简单的基于FFmpeg的编码器-纯净版(不包含libavformat)》中的simplest_ffmpeg_video_encoder_pure工程。

    CSDN下载地址:http://download.csdn.net/detail/leixiaohua1020/8322003


    更新-1.2 (2015.2.13)=========================================

    这次考虑到了跨平台的要求,调整了源代码。经过这次调整之后,源代码可以在以下平台编译通过:

    VC++:打开sln文件即可编译,无需配置。

    cl.exe:打开compile_cl.bat即可命令行下使用cl.exe进行编译,注意可能需要按照VC的安装路径调整脚本里面的参数。编译命令如下。

    ::VS2010 Environment
    call "D:\Program Files\Microsoft Visual Studio 10.0\VC\vcvarsall.bat"
    ::include
    @set INCLUDE=include;%INCLUDE%
    ::lib
    @set LIB=lib;%LIB%
    ::compile and link
    cl simplest_ffmpeg_video_encoder.cpp /link avcodec.lib avformat.lib avutil.lib ^
    avdevice.lib avfilter.lib postproc.lib swresample.lib swscale.lib /OPT:NOREF

    MinGW:MinGW命令行下运行compile_mingw.sh即可使用MinGW的g++进行编译。编译命令如下。

    g++ simplest_ffmpeg_video_encoder.cpp -g -o simplest_ffmpeg_video_encoder.exe \
    -I /usr/local/include -L /usr/local/lib \
    -lavformat -lavcodec -lavutil

    GCC:Linux或者MacOS命令行下运行compile_gcc.sh即可使用GCC进行编译。编译命令如下。

    gcc simplest_ffmpeg_video_encoder.cpp -g -o simplest_ffmpeg_video_encoder.out \
    -I /usr/local/include -L /usr/local/lib -lavformat -lavcodec -lavutil

    PS:相关的编译命令已经保存到了工程文件夹中


    CSDN下载地址:http://download.csdn.net/detail/leixiaohua1020/8444967

    SourceForge上已经更新。


    展开全文
  • 从零了解H264结构

    万次阅读 2018-05-10 22:37:17
    从零了解H264结构 转自:http://www.iosxxx.com/blog/2017-08-09-%E4%BB%8E%E9%9B%B6%E4%BA%86%E8%A7%A3H264%E7%BB%93%E6%9E%84.html前言建议先看一下FFmpeg3的iOS版的入门格式转换器(无编码),我们可以了解H264处于...

    从零了解H264结构

     

    转自:http://www.iosxxx.com/blog/2017-08-09-%E4%BB%8E%E9%9B%B6%E4%BA%86%E8%A7%A3H264%E7%BB%93%E6%9E%84.html

    前言

    建议先看一下FFmpeg3的iOS版的入门格式转换器(无编码),我们可以了解H264处于编解码层。为什么需要编码呢?比如当前屏幕是1280*720.一秒24张图片.那么我们一秒的视频数据是

    1
    1280*720(位像素)*24(张) / 8(1字节8位)(结果:B) / 1024(结果:KB) / 1024 (结果:MB) =  2.64MB

    一秒的数据有2.64MB数据量。1分钟就会有100多MB。这对用户来说真心是灾难。所以现在我们需要一种压缩方式减小数据的大小.在更低 比特率(bps)的情况下依然提供清晰的视频。
    H264: H264/AVC是广泛采用的一种编码方式。我们这边会带大家了解。从大到小排序依次是 序列,图像,片组,片,NALU,宏块,亚宏块,块,像素。

    一. 原理

    H.264原始码流(裸流)是由一个接一个NALU组成,它的功能分为两层,VCL(视频编码层)和 NAL(网络提取层).

    1
    VCL(Video Coding Layer) + NAL(Network Abstraction Layer).
    1. VCL:包括核心压缩引擎和块,宏块和片的语法级别定义,设计目标是尽可能地独立于网络进行高效的编码;
    2. NAL:负责将VCL产生的比特字符串适配到各种各样的网络和多元环境中,覆盖了所有片级以上的语法级别。

    在VCL进行数据传输或存储之前,这些编码的VCL数据,被映射或封装进NAL单元。(NALU)。

    1
    一个NALU = 一组对应于视频编码的NALU头部信息 + 一个原始字节序列负荷(RBSP,Raw Byte Sequence Payload).

    如图所示,上图中的NALU的头 + RBSP 就相当于一个NALU(Nal Unit),每个单元都按独立的NALU传送。H.264的结构全部都是以NALU为主,理解了NALU,就理解了H.264的结构。
    一个原始的H.264 NALU 单元常由 [StartCode] [NALU Header] [NALU Payload] 三部分组成,其中 Start Code 用于标示这是一个NALU 单元的开始,必须是”00 00 00 01” 或”00 00 01”

    1. NAL Header

    由三部分组成,forbidden_bit(1bit),nal_reference_bit(2bits)(优先级),nal_unit_type(5bits)(类型)。

    举例来说:

    1
    2
    3
    4
    00 00 00 01 06:  SEI信息   
    00 00 00 01 67: 0x67&0x1f = 0x07 :SPS
    00 00 00 01 68: 0x68&0x1f = 0x08 :PPS
    00 00 00 01 65: 0x65&0x1f = 0x05: IDR Slice

    2. RBSP


    图 6.69 RBSP 序列举例


    表 6.25 RBSP 描述.

    SODB与RBSP
    SODB 数据比特串 -> 是编码后的原始数据.
    RBSP 原始字节序列载荷 -> 在原始编码数据的后面添加了 结尾比特。一个 bit“1”若干比特“0”,以便字节对齐。

    二. 从NALU出发了解H.264里面的专业词语

    1
    2
    3
    1帧 = n个片
    1片 = n个宏块
    1宏块 = 16x16yuv数据

    1. Slice(片)

    如图所示,NALU的主体中包含了Slice(片).

    1
    一个片 = Slice Header + Slice Data

    片是H.264提出的新概念,通过编码图片后切分通过高效的方式整合出来的概念。一张图片有一个或者多个片,而片由NALU装载并进行网络传输的。但是NALU不一定是切片,这是充分不必要条件,因为 NALU 还有可能装载着其他用作描述视频的信息.

    那么为什么要设置片呢?
    设置片的目的是为了限制误码的扩散和传输,应使编码片相互间是独立的。某片的预测不能以其他片中的宏块为参考图像,这样某一片中的预测误差才不会传播到其他片中。

    可以看到上图中,每个图像中,若干宏块(Macroblock)被排列成片。一个视频图像可编程一个或更多个片,每片包含整数个宏块 (MB),每片至少包含一个宏块。
    片有一下五种类型:

    意义
    I 片只包含I宏块
    P 片包含P和I宏块
    B 片包含B和I宏块
    SP 片包含P 和/或 I宏块,用于不同码流之间的切换
    SI 片一种特殊类型的编码宏块

    2. 宏块(Macroblock)

    刚才在片中提到了宏块.那么什么是宏块呢?
    宏块是视频信息的主要承载者。一个编码图像通常划分为多个宏块组成.包含着每一个像素的亮度和色度信息。视频解码最主要的工作则是提供高效的方式从码流中获得宏块中像素阵列。

    1
    一个宏块 = 一个16*16的亮度像素 + 一个8×8Cb + 一个8×8Cr彩色像素块组成。(YCbCr 是属于 YUV 家族的一员,在YCbCr 中 Y 是指亮度分量,Cb 指蓝色色度分量,而 Cr 指红色色度分量)
    宏块分类意义
    I 宏块利用从当前片中已解码的像素作为参考进行帧内预测
    P 宏块利用前面已编码图像作为参考进行帧内预测,一个帧内编码的宏块可进一步作宏块的分割:即16×16.16×8.8×16.8×8亮度像素块。如果选了8×8的子宏块,则可再分成各种子宏块的分割,其尺寸为8×8,8×4,4×8,4×4
    B 宏块利用双向的参考图像(当前和未来的已编码图像帧)进行帧内预测

    图2.1句发元素的分层结构,在 H.264 中,句法元素共被组织成 序列、图像、片、宏块、子宏块五个层次。
    句法元素的分层结构有助于更有效地节省码流。例如,再一个图像中,经常会在各个片之间有相同的数据,如果每个片都同时携带这些数据,势必会造成码流的浪费。更为有效的做法是将该图像的公共信息抽取出来,形成图像一级的句法元素,而在片级只携带该片自身独有的句法元素。


    图2.2宏块的句法单元

    宏块分类意义
    mb_type确定该 MB 是帧内或帧间(P 或 B)编码模式,确定该 MB 分割的尺寸
    mb_pred确定帧内预测模式(帧内宏块)确定表 0 或表 1 参考图 像,和每一宏块分割的差分编码的运动矢量(帧间宏块,除 8×8 宏块分割的帧内 MB)
    sub_mb_pred(只对 8×8MB 分割的帧内 MB)确定每一子宏块的子宏 块分割,每一宏块分割的表 0 和/或表 1 的参考图象;每一 宏块子分割的差分编码运动矢量。
    coded_block_pattern指出哪个 8×8 块(亮度和彩色)包 编码变换系数
    mb_qp_delta量化参数的改变值
    residual预测后对应于残差图象取样的编码变换系数

    3.图像,场和帧

    图像是个集合概念,顶 场、底场、帧都可以称为图像。对于H.264 协议来说,我们平常所熟悉的那些称呼,例如: I 帧、P 帧、B帧等等,实际上都是我们把图像这个概念具体化和细小化了。我们 在 H.264里提到的“帧”通常就是指不分场的图像;

    视频的一场或一帧可用来产生一个编码图像。一帧通常是一个完整的图像。当采集视频信号时,如果采用隔行扫描(奇.偶数行),则扫描下来的一帧图像就被分为了两个部分,这每一部分就被称为 [场],根据次序氛围: [顶场] 和 [底场]

    方式作用域
    帧编码方式活动量较小或者静止的图像宜采用
    场编码方式活动量较大的运动图像


    图2.3

    4. I,P,B帧与pts/dts

    帧的分类中文意义
    I帧帧内编码帧,又称intra pictureI 帧通常是每个 GOP(MPEG 所使用的一种视频压缩技术)的第一个帧,经过适度地压缩,做为随机访问的参考点,可以当成图象。I帧可以看成是一个图像经过压缩后的产物
    P帧前向预测编码帧,又称predictive-frame通过充分将低于图像序列中前面已编码帧的时间冗余信息来压缩传输数据量的编码图像,也叫预测帧
    B帧双向预测帧,又称bi-directional interpolated prediction frame既考虑与源图像序列前面已编码帧,也顾及源图像序列后面已编码帧之间的时间冗余信息来压缩传输数据量的编码图像,也叫双向预测帧

    I P B帧的不同:
    I frame:自身可以通过视频解压算法解压成一张单独的完整的图片。
    P frame:需要参考其前面的一个I frame 或者B frame来生成一张完整的图片。
    B frame:则要参考其前一个I或者P帧及其后面的一个P帧来生成一张完整的图片。

    名称意义
    PTS(Presentation Time Stamp)PTS主要用于度量解码后的视频帧什么时候被显示出来。
    DTS(Decode Time Stamp)DTS主要是标识内存中的bit流再什么时候开始送入解码器中进行解码。

    DTS与PTS的不同:
    DTS主要用户视频的解码,在解码阶段使用。PTS主要用于视频的同步和输出,在display的时候使用。再没有B frame的时候输出顺序一样。

    5. GOP

    GOP是画面组,一个GOP是一组连续的画面。
    GOP一般有两个数字,如M=3,N=12.M制定I帧与P帧之间的距离,N指定两个I帧之间的距离。那么现在的GOP结构是

    1
    I BBP BBP BBP BB I

    增大图片组能有效的减少编码后的视频体积,但是也会降低视频质量,至于怎么取舍,得看需求了

    6. IDR

    一个序列的第一个图像叫做 IDR 图像(立即刷新图像),IDR 图像都是 I 帧图像。
    I和IDR帧都使用帧内预测。I帧不用参考任何帧,但是之后的P帧和B帧是有可能参考这个I帧之前的帧的。IDR就不允许这样。
    比如这种情况:
    IDR1 P4 B2 B3 P7 B5 B6 I10 B8 B9 P13 B11 B12 P16 B14 B15 这里的B8可以跨过I10去参考P7

    核心作用:
    H.264 引入 IDR 图像是为了解码的重同步,当解码器解码到 IDR 图像时,立即将参考帧队列清空,将已解码的数据全部输出或抛弃,重新查找参数集,开始一个新的序列。这样,如果前一个序列出现重大错误,在这里可以获得重新同步的机会。IDR图像之后的图像永远不会使用IDR之前的图像的数据来解码。

    三. 帧内预测和帧间预测

    1. 帧内预测(也叫帧内压缩)

    我们可以通过第 1、2、3、4、5 块的编码来推测和计算第 6 块的编码,因此就不需要对第 6 块进行编码了,从而压缩了第 6 块,节省了空间

    2. 帧间预测(也叫帧间压缩)

     

    可以看到前后两帧的差异其实是很小的,这时候用帧间压缩就很有意义。
    这里涉及到几个重要的概念:块匹配,残差,运动搜索(运动估计),运动补偿.

    帧间压缩最常用的方式就是块匹配(Block Matching)。找找看前面已经编码的几帧里面,和我当前这个块最类似的一个块,这样我不用编码当前块的内容了,只需要编码当前块和我找到的快的差异(残差)即可。找最想的块的过程叫运动搜索(Motion Search),又叫运动估计。用残差和原来的块就能推算出当前块的过程叫运动补偿(Motion Compensation).

    四. 延伸

    最近我才知道FFmpeg也支持h264的硬编。具体还没有试验,接下来我会写demo来测试一下。直接用系统进行硬编的方式已经尝试过。接口还是蛮简单的。据说iOS11正式版会出H.265/HEVC硬编。目前Beta版暂不支持。如有支持,我会第一时间更新到博客,敬请期待!

    参考链接:

    1.新一代视频压缩编码标准H.264
    2.深入浅出理解视频编码H264结构
    3.关于视频的一些概念
    4.I,P,B帧和PTS,DTS的关系

    展开全文
  • h264

    千次阅读 2014-02-17 13:45:16
    H.264编码后码流的生成 H.264 比较全的编码框架   2011年4月23日22:23:35 H.264中的PB帧编码 在针对连续动态图像编码时,将连续若干幅图像分成P,B,I三种类型,P帧由在它前面的P帧或者I帧预测而来,它...
  • h264的视频文件

    2018-12-15 15:42:57
    h264的测试视频文件。一个1080p,一个小一点的,还有一个小一点的,反正就是测试用的啦。h264.
  • H264

    千次阅读 2017-10-13 11:20:20
    H264 1、H264一个图像序列的组成:SPS+PPS+SEI+一个I帧+若干个P帧。SPS、PPS、SEI、一个I帧、一个P帧都 可以称为一个NALU。 2、H264的NALU结构:开始码+NALU头+NALU数据 (1)、开始码大小为四个字节,是一个...
  • H264格式 详细介绍

    万次阅读 2015-09-24 16:33:28
    原文地址:... 名词解释 场和帧 : 视频的一场或一帧可用来产生一个编码图像。在电视中,为减少大面积闪烁现象,把一帧分成两个隔行的场。...片: 每个图象中,若干宏块被排列成片的形式。... 
  • H264码流和Mp4结构详解

    万次阅读 2018-08-07 17:17:54
    本文讲述的是对H264编码且封装成MP4格式的视频流进行RTP打包过程时需要了解的一些基本知识。 二、H264的基础知识 1.H264的编码格式 H.263 定义的码流结构是分级结构,共四层。自上而下分别为:图像层...
  • 入门理解H264编码

    万次阅读 多人点赞 2018-05-17 16:50:27
    最近入门音视频技术,一直在学习H264编解码标准,了解了不少关于H264的相关知识,对于网上各种类型的资料,始终没有找到一篇适合的知识梳理资料。可能是查找方式不对,所以花费了比较多的时间。经过一段时间的熟悉后...
  • H264编码简介

    千次阅读 2019-05-11 08:38:38
    H264编码简介 H.264,同时也是MPEG-4第十部分,是由ITU-T视频编码专家组(VCEG)和ISO/IEC动态图像专家组(MPEG)联合组成的联合视频组(JVT,Joint Video Team)提出的高度压缩数字视频编解码器标准。H.264 不仅...
  • H.264H.265(HEVC)深度解析及对比

    万次阅读 多人点赞 2018-11-29 20:53:45
    H.265是ITU-TVCEG继H.264之后所制定的新的视频编码标准。H.265标准围绕着现有的视频编码标准H.264,保留原来的某些技术,同时对一些相关的技术加以改进。 新技术使用先进的技术用以改善码流、编码质量、延时和算法...
  • H.264中IPCM宏块简介

    万次阅读 2012-11-19 15:56:48
    H.264中,一个宏块包括16*16个像素,I宏块有三种形式: 1. 16个I4x4编码方式组成的宏块(为了方便,简称I4x4方式的宏块); 2. I16x16宏块; 3. IPCM宏块(特殊) 为什么一个宏块有时要分成16个I4x4方式的宏块呢...
  • H.264 (H264)文件800_600.264,分辨率800*600,亲测可用
  • H.264(H264)视频文件的制作

    万次阅读 多人点赞 2016-04-16 08:37:28
    一、准备工作 1.下载并安装优酷客户端 2.下载ffmpeg可执行文件,解压可用,不需要下载源码自己编译。 ...二、用优酷客户端下载视频并转码 用优酷客户端下载一个视频,然后转码成mp4格式,优酷客户端自带转码功能,如下...
  • H.264/AVC视频编解码技术详解》视频教程已经在“CSDN学院”上线,视频中详述了H.264的背景、标准协议和实现,并通过一个实战工程的形式对H.264的标准进行解析和实现,欢迎观看!“纸上得来终觉浅,绝知此事要躬行...
  • H.265与H.264对比有哪些优势

    千次阅读 2018-06-19 17:15:34
    H.265与H.264对比有哪些优势 &lt;/div&gt; &lt;div class="cl"&gt;&lt;/div&gt; &lt;/div&gt; ...
  • H.264视频压缩标准

    万次阅读 2016-11-03 10:17:51
     H.264是最新的视频压缩标准,它也称为MPEG-4 Part 10或AVC(高级视频编码)。据预测,在未来几年内H.264将成为行业首选的视频标准。  H.264是一个需要许可证才能使用的开放标准,可支持最当今市场上最高效的视频...
  • H264系列(7):H.264与MPEG4区别

    千次阅读 2016-12-03 15:01:46
    H264系列(7):H.264与MPEG4区别
  • H.264再学习 -- 详解 H.264 NALU语法结构

    万次阅读 多人点赞 2017-10-13 15:08:12
    讲到H.264除了前两篇文章提到的,I、P、B帧。参看: 图像和流媒体 -- I 帧,B帧,P帧,IDR帧的区别 ...NALU:H264编码数据存储或传输的基本单元,一般H264码流最开始的两个NALU是SPS和PPS,第三个NALU是ID...
  • H.265编码和H.264编码的区别

    万次阅读 2019-09-17 14:50:00
    目前很多摄像机采用了H.265的编码标准,H.264编码的摄像机逐渐减少,为什么H.265会流行?H.264H.265有何不同? 一、什么是H.265 H.265是ITU-TVCEG继H.264之后所制定的新的视频编码标准。H.265标准围绕着现有的...
  • H.264与x264的区别

    万次阅读 2018-07-14 21:26:52
    1、H.264是MPEG4的第十部分,是一个标准。...对头,H.264是需要付费的编码格式,而x264是符合H.264标准的一个开源项目,是免费的,也就是H264的一个简化版,不支持某些高级特性。但x264非常优秀,并不...
  • H.264视频编码在VC++.Net中的实现  引言:H.264编码技术是俱乐部在过去一段时间内研究的一个方向,对该编码技术进行过实际的开发和应用,并取得了很大的收获。下面将重点介绍H.264视频编码在VC++.Net中的实现。 1....
  • 视讯会议系统从产生至今,发展了多种适于各类通信网络的系统,目前传输多媒体信息的主要有H.323、H.324和H.320等系统。IP技术的开放性特点使得它非常适合承载多种业务,随着IP的安全和QoS等问题
  • Requirements Prerequisite knowledge Basic knowledge of streaming video encoding. User level Intermediate Additional Requirements ...Adobe Media Encoder
  • H.264格式分析

    千次阅读 2016-11-03 11:59:07
    一.H.264基本流结构H.264 的基本流(elementary stream,ES)的结构分为两层,包括视频编码层(VCL)和网络适配层(NAL)。视频编码层负责高效的视频内容表示,而网络适配层负责以网络所要求的恰当的方式对数据进行...
  • 支持h264在各个浏览器下的视频播放,如果支持浏览器支持html5,采用html5播放,若不支持,采用flowplayer播放。并且有用到流媒体服务器服务器wowza,实现视频播放不卡,流畅,且能拖拽至未加载部分。实现视频观看...
  • H.265与H.264的差异详解

    万次阅读 2017-09-03 22:31:14
    目录: 1.编解码框架差异 2.压缩性能比较 3.各模块技术差异汇总 4.块划分结构 5.帧内预测 ...1. H.264H.265的主要差异 ...H.265仍然采用混合编解码,编解码结构域H.264基本一致, 主要的不同在于: Ø 
  • H.265与H.264的区别技术分析

    万次阅读 2017-12-01 11:55:51
    H.265与H.264有何不同,同等画质体积仅为一半、带宽占用省一半、画质更细腻等诸多优势 首先分别介绍一下:H.264H.265 1、H.264也称作MPEG-4AVC(Advanced Video Codec,高级视频编码),是一种视频压缩标准,同时也...

空空如也

1 2 3 4 5 ... 20
收藏数 93,562
精华内容 37,424
关键字:

h264