MPEG-1

看完这篇文章,你将会学习到:什么是MPEG?MPEG-X和H.26X、MPEG-1编解码标准

从这篇文章开始,我们逐一介绍音视频编解码的几个重要国际标准,这几个标准分别为MPEG-1、MPEG-2、MPEG-4、H.264/AVC、H.265/HEVC。我想即使没做过音视频编解码的人,也或多或少听说过这几个名词。在接下来的几篇文章里,我们不会深入的去探讨技术细节,比如编解码图像数据时使用的各类算法、以及各算法的优劣抉择,因为这些即使不了解,也不会影响我们去做音视频开发。所以我们会保持浅尝辄止,了解各编解码标准的步骤以及作用即可。

在开始讲MPEG-1之前,我们先来看看,什么是MPEG

不用费力猜测,MPEG其实是一个专家组的缩写,它的全称为Moving Picture Expert Group/动态图像专家组,它是在1988年5月份由国际标准化组织(ISO)和国际电工委员会(IEC)联合成立的专家组,称为IOS/IEC JTC 1(Joint Technical Committee)。当然知道这个并没啥鸟用,这个专家组的任务,就是负责开发音视频编解码和传输标准,然后由这个专家组开发的标准,统称为MPEG标准。

在这里插入图片描述

可以看到JTC1下面有很多Sub Committee,也就是分委员会,而分委员会下面又分WG(即工作组),大名鼎鼎产生JPEG编解码标准的工作组跟MPEG工作组并列。

MPEG从建组以来,制定了很多国际标准,注意是国际,很牛X的。那为什么他可以这么牛X呢,按照普通民众的猜想,越是国际的东西,我们应该越抵制才对呀!不过MPEG也可能未卜先知,专家组在制定MPEG标准时,说明了音视频的编解码过程,并且严格制定了声音和图像数据,编码后组成位流的语法。但是没有规定编解码所使用的算法,这样就可以保证解码器对符合MPEG标准的音视频数据进行正确解码,而又给MPEG的具体实现留有很大余地。

所以基于这一标准,编码和解码算法不断改进,音视频质量和编码效率不断提高。而也因如此,使用不同算法的各种编解码器也才得以实现。

MPEG标准和ITU-T标准

同所有的新生事物一样,MPEG标准也经历了从MPEG-1制定,到时候的扩展、改进,一路走到H.265/HEVC。不过有的人可能会奇怪,H.265/HEVC为什么不继续叫MPEG-X,那是因为事实上,在国际上实施音视频压缩标准的,不只有MPEG专家组,还有另一个组织,称为ITU-T VCEG(Video Coding Experts Group)专家组。

在这里插入图片描述

如图所示,ITU-T制定的标准,命名为H.26X,而ISO/IEC 也即MEPG专家组制定的,命名为MPEG-X。在MPEG研究到MPEG-4时,ITU-T和MPEG两个专家组联合,开发出H.264/MPEG-4 AVC,简称H.264/AVC。下面我们就从MPEG-1编解码标准开始,看一下其中比较重要的几个编解码标准。

MPEG-1

MPEG-1编解码标准是MPEG专家组,在1992年发布的第一个音视频编码标准。标准分为了五部分:

  • (第一部分Part1)系统(将视音频数据和其他数据同步存储到一起)
  • (第二部分Part2)视频(压缩视频内容)
  • (第三部分Part3)音频(压缩音频内容)
  • (第四部分Part4)一次性测试(测试标准实现的正确性)
  • (第五部分Part5)参考软件(举例说明如何根据标准来编解码)

这里的第三部分,也即音频又分为了三层,分别为MPEG-1 Layer 1、Layer 2、Layer 3,这里的MPEG-1 Layer 3,也就是非常著名的MP3,它已经被广泛使用。我们先不管音频,看看视频的编解码。

我们上篇讲到,压缩视频数据可以从6个方面进行着手。而MPEG-1,则主要从两个方面着手:

(1)在空间方向上,采用了和JPEG类似的算法来去掉空间冗余数据。

(2)在时间方向上,采用移动补偿(motion compensation,也叫运动补偿)算法去掉时间冗余数据。

我们先不管具体使用怎样的算法,先看看MPEG为了实现这两条,都干了什么事情。MPEG基于这两个方面,开发了两项重要的技术,一项是定义视像数据的结构,而另一项是定义了图像的三种类型。这两种技术一直沿用,后面出的标准像H.264/AVC,也是在这两个技术之上扩展和延续的。下面我们分别来看:

1、视像数据结构

在这里插入图片描述

为了方便,我们对照上图来看。MPEG专家组把视像片段,看成是一系列静态图像(picture)组成的视像序列(sequence),然后把这个视像序列分成许多图像组(Group Of Picture,GOP),把GOP里的每一帧图像,分成许多像片(slice),每个像片由16行组成。然后把像片分为16像素X16像素的宏块(macroblock, MB),进而把宏块分为8像素X8像素的图块(block)。

这样当子采样格式为4:2:0时,16X16的宏块就包含16X16个Y(luma)样本,和8X8个色度(Chroma,Cb和Cr)样本。而这些样本,可以分为Y图块(block),和Cb、Cr图块(block),如上图右侧所示。

所以像JPEG和大多数的编解码器,都是以宏块(macroblock)为基本单位,进行编码的,当子采样格式为4:0:0、4:2:2、4:4:4时,宏块中色度样本的数目也会变大或变小。

2、图像的三种类型

为了保证视频质量不变,而又能够获得比较大的压缩比。MPEG专家组把图像(picture)分为了三种类型,然后采用不同的算法分别对他们进行压缩。它们分别为:

(1)帧内图像I(intra-picture),简称为I图像或I帧(I-picture/I-frame)。I帧包含了完整内容的图像,用于为其他帧图像的编解码做参考,所以这也就是我们常说的,关键帧。

(2)预测图像P(predicated picture),简称P图像或P帧(P-picture/P-frame)。P帧是指以它之前出现的I帧作为参考的图像,而对P帧进行编码,其实就是对它们之间的差值进行编码。

(3)双向预测图像B(bidirectionally-predictive picture),简称B图像或B帧(B-picture/B-frame)。B帧是以在它之前和之后的图像,也就I帧和P帧作为参考的图像。对B帧进行编码,就是对它和I帧、P帧的差值分别进行编码。

在这里插入图片描述
MPEG专家组定义的三种图像

而具体的对I帧、P帧、B帧的编码算法,我们就不深究了。不过因为I帧比较重要,我们展示一下对I帧进行压缩编码的算法图,这也是使用和JPEG类似的压缩算法,来减少空间冗余数据的。

在这里插入图片描述
I帧的压缩编码算法图

可以看到图中是将I帧图像数据,以宏块为单位,取出8X8的图块,然后再进行处理的。在MPEG-1中,I帧、P帧、B帧的压缩比,通常为下表:
在这里插入图片描述

可以看到,压缩后的I帧的数据量最大,而B帧的数据量最小。并且平均压缩比为27:1,这也就是使用MPEG-1标准,能获得的压缩比。

3、视频数据流的结构

最后要说的是,正因MPEG专家组严格制定了数据位流的语法,而没有规定具体使用的算法细节,才能使众多企业、组织、个人设计的编解码器得以通用。所谓数据流,也即使用MPEG-1标准编码之后得到的输出数据流,也即解码器的输入流。所以MPEG-1对数据流结构,做了详细的规定,MPEG-1的数据流按层次分为6层,如下图所示:

在这里插入图片描述
MPEG-1数据流结构

可以看到,从上到下分为6层,分别为序列层、GOP层、图像层、像片层、宏块层、图块层。这里先知道就好,关于数据流以后还可以单开一篇文章来介绍。

  • 4
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
这里是一个简单的 MPEG-1 间编码代码示例,它使用了 C++ 和 OpenCV 库。该代码将视频分解成 8x8 块,对每个块应用 DCT 变换和量化,然后使用运动估计和运动补偿来减少之间的冗余信息。 ```cpp #include <iostream> #include <opencv2/opencv.hpp> using namespace std; using namespace cv; int main(int argc, char** argv) { // 打开视频文件 VideoCapture cap(argv[1]); if(!cap.isOpened()) { cout << "Error opening video file" << endl; return -1; } // 设置视频编解码器和速率 int codec = CV_FOURCC('M','P','E','G'); double fps = cap.get(CV_CAP_PROP_FPS); // 获取第一并设置图像大小 Mat frame; cap >> frame; Size frameSize = frame.size(); // 创建编码器 VideoWriter writer("output.avi", codec, fps, frameSize, true); if(!writer.isOpened()) { cout << "Error opening output video file" << endl; return -1; } // 定义 DCT 和量化矩阵 Mat dctMat = Mat::zeros(8, 8, CV_32FC1); Mat quantMat = (Mat_<float>(8, 8) << 16, 11, 10, 16, 24, 40, 51, 61, 12, 12, 14, 19, 26, 58, 60, 55, 14, 13, 16, 24, 40, 57, 69, 56, 14, 17, 22, 29, 51, 87, 80, 62, 18, 22, 37, 56, 68, 109, 103, 77, 24, 35, 55, 64, 81, 104, 113, 92, 49, 64, 78, 87, 103, 121, 120, 101, 72, 92, 95, 98, 112, 100, 103, 99); // 定义运动估计和运动补偿块大小 const int BLOCK_SIZE = 8; // 定义当前和参考 Mat currFrame, refFrame; cap >> currFrame; cvtColor(currFrame, currFrame, CV_BGR2GRAY); // 循环编码每一 while(true) { // 获取下一和转换为灰度图像 cap >> refFrame; if(refFrame.empty()) { break; } cvtColor(refFrame, refFrame, CV_BGR2GRAY); // 定义当前和参考的运动矢量 vector<Point2f> currPoints, refPoints; for(int y = 0; y < frameSize.height; y += BLOCK_SIZE) { for(int x = 0; x < frameSize.width; x += BLOCK_SIZE) { Rect blockRect(x, y, BLOCK_SIZE, BLOCK_SIZE); Mat currBlock = currFrame(blockRect); Mat refBlock = refFrame(blockRect); // 使用光流算法计算运动矢量 vector<uchar> status; vector<float> err; calcOpticalFlowPyrLK(currBlock, refBlock, currPoints, refPoints, status, err); // 计算平均运动矢量 Point2f meanVec(0, 0); int count = 0; for(int i = 0; i < status.size(); i++) { if(status[i]) { meanVec += refPoints[i] - currPoints[i]; count++; } } if(count) { meanVec /= count; } // 使用平均运动矢量来进行运动补偿 Mat motionComp = Mat::zeros(BLOCK_SIZE, BLOCK_SIZE, CV_8UC1); for(int y2 = 0; y2 < BLOCK_SIZE; y2++) { for(int x2 = 0; x2 < BLOCK_SIZE; x2++) { int x1 = x + x2 + meanVec.x; int y1 = y + y2 + meanVec.y; if(x1 >= 0 && x1 < frameSize.width && y1 >= 0 && y1 < frameSize.height) { motionComp.at<uchar>(y2, x2) = currFrame.at<uchar>(y1, x1); } } } // 对运动补偿后的块进行 DCT 变换和量化 dct(motionComp, dctMat); dctMat /= quantMat; // 将 DCT 系数写入输出文件 for(int y2 = 0; y2 < BLOCK_SIZE; y2++) { for(int x2 = 0; x2 < BLOCK_SIZE; x2++) { writer << dctMat.at<float>(y2, x2); } } } } // 将参考设置为当前 currFrame = refFrame.clone(); } // 释放资源 cap.release(); writer.release(); return 0; } ``` 注意,这只是一个简单的示例代码,并且没有实现所有 MPEG-1 规范中的细节。在实际应用中,您需要更多的优化和功能来生产高质量的 MPEG-1 视频。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值