TComPicYuv、TComPic、TComPicSym、TComDataCU以及TComYuv的关系

本文详细介绍了HEVC编码过程中的关键数据结构,包括TComPicYuv、TComPic、TComPicSym、TComDataCU及TComYuv之间的关系与作用。通过这些结构,文章阐述了从原始YUV数据到编码输出的整个流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

TComPicYuv、TComPic、TComPicSym、TComDataCU以及TComYuv的关系

转载https://blog.youkuaiyun.com/nb_vol_1/article/details/71173023

    首先用一张图来描述它们之间的关系



    1、HM首先使用TComPicYuv保存从文件中读取出来的YUV数据
    2、利用TComPicYuv构造TComPic,并把YUV数据复制给他(TComPic包含了TComPicYuv成员)
    3、TComPic表示一帧图像,包含了数据(TComPicYuv),以及图像信息(TComPicSym,在TComPicSym中还包含了TComDataCU)
    4、TComPic被放入图像队列中
    5、处理图像队列中的每一个TComPic,实际是处理TComPic中的每一个CTU/CU(存放在TComPicSym中)
    6、从TComPic中取出每一个CTU(用TComDataCU表示),调用xCompressCU进行处理
    7、根据原始的CTU初始化TEncCu中的TComDataCU(最优的和临时的),这两个在编码的时候会使用
    8、把TComPic的数据复制给TComYuv对象,表示编码过程中的数据(原始,预测、残差、重建等)
    9、进行编码,tempCU用于编码过程中,bestCU用于保存最优信息
    10、产生的最优信息会被复制回TComPicSym中


TComPicYuv


    TComPicYuv表示图像的YUV数据

[cpp]  view plain  copy
  1. class TComPicYuv  
  2. {  
  3. private:  
  4.     Pel*  m_apiPicBufY;           // 三个颜色分量的缓冲区,包括了填充的内容  
  5.     Pel*  m_apiPicBufU;  
  6.     Pel*  m_apiPicBufV;  
  7.   
  8.     Pel*  m_piPicOrgY;            // 三个颜色分量的起始地址,由m_apiPicBufY计算得到  
  9.     Pel*  m_piPicOrgU;  
  10.     Pel*  m_piPicOrgV;  
  11.   
  12.     Int   m_iPicWidth;            // 图像的宽和高  
  13.     Int   m_iPicHeight;             
  14.   
  15.     Int   m_iCuWidth;             // LCU的宽和高  
  16.     Int   m_iCuHeight;              
  17.     Int*  m_cuOffsetY;            // 每个CTU中三个颜色分量的偏移地址  
  18.     Int*  m_cuOffsetC;  
  19.     Int*  m_buOffsetY;            // CTU中每个4x4分量的偏移地址  
  20.     Int*  m_buOffsetC;  
  21.   
  22.     Int   m_iLumaMarginX;       // Y分量的填充宽度和高度,如果图像的尺寸不是LCU的整数倍,那么需要填充  
  23.     Int   m_iLumaMarginY;  
  24.     Int   m_iChromaMarginX;     // U、V分量的填充高度和宽度  
  25.     Int   m_iChromaMarginY;  
  26.   
  27.     Bool  m_bIsBorderExtended; // 是否需要填充图像  
  28. };  



TComPic


    TComPic表示一张图像,它包含数据(TComPicYuv)和信息(TComPicSym)

[cpp]  view plain  copy
  1. class TComPic  
  2. {  
  3. private:  
  4.       
  5.     UInt                  m_uiTLayer;               //  时域层  
  6.       
  7.     Bool                  m_bUsedByCurr;            //  是否被作为参考帧  
  8.       
  9.     Bool                  m_bIsLongTerm;            // 是否为长参考图像  
  10.       
  11.     TComPicSym*           m_apcPicSym;              // 图像的信息  
  12.   
  13.       
  14.     TComPicYuv*           m_apcPicYuv[2];           // 图像的数据(索引0是原始图像,索引1是重建图像)  
  15.   
  16.     TComPicYuv*           m_pcPicYuvPred;           // 图像的预测数据  
  17.       
  18.     TComPicYuv*           m_pcPicYuvResi;           // 图像的残差数据  
  19.   
  20.       
  21.     Bool                  m_bReconstructed;         // 是否被重建  
  22.       
  23.     Bool                  m_bNeededForOutput;       // 是否需要输出  
  24.       
  25.     UInt                  m_uiCurrSliceIdx;         // 在此图像中,当前条带的索引  
  26.   
  27.     Bool                  m_bCheckLTMSB;            // 没啥用  
  28.   
  29.     Int                   m_numReorderPics[MAX_TLAYER]; // 每一层重排的图像的个数  
  30.   
  31.     Window                m_conformanceWindow;      // 一致性窗口,用于输出  
  32.       
  33.     Window                m_defaultDisplayWindow;   // 默认显示的窗口  
  34.   
  35.     bool                  m_isTop;                  // 顶场还是底场  
  36.     bool                  m_isField;                // 帧还是场  
  37.   
  38.     // 条带的CU链表,即:  
  39.     // 每一个slice中有若干LCU,每一个LCU又被细分为各个CU  
  40.     // std::vector<TComDataCU*>就是存放LCU的CU  
  41.     // 没有用到,因为CTU的相关信息存放在TComPicSym中  
  42.     std::vector<std::vector<TComDataCU*> > m_vSliceCUDataLink;  
  43.   
  44.     // 增强信息  
  45.     SEIMessages  m_SEIs; ///< Any SEI messages that have been received.  If !NULL we own the object.  
  46.       
  47.     // 其他省略****  
  48. };  



TComPicSym


    TComPicSym表示图像的信息,它内部有一个TComDataCU数组,描述了图像组每一个LCU(CTU)的信息

[cpp]  view plain  copy
  1. class TComPicSym  
  2. {  
  3. private:  
  4.   
  5.     UInt          m_uiWidthInCU; // 图像在横向上有多少个CTU,一般认为LCU就是CTU  
  6.     UInt          m_uiHeightInCU; // 图像在纵向上有多少个CTU  
  7.   
  8.     UInt          m_uiMaxCUWidth; // 最大的CU的尺寸:64x64  
  9.     UInt          m_uiMaxCUHeight;  
  10.     UInt          m_uiMinCUWidth; // 最小的CU的尺寸:4x4  
  11.     UInt          m_uiMinCUHeight;  
  12.   
  13.     UChar         m_uhTotalDepth;       // LCU可以划分的最大深度:5  
  14.     UInt          m_uiNumPartitions;    // CTU有多少个4x4的块  
  15.     UInt          m_uiNumPartInWidth;   // CTU横向上有几个4x4的块  
  16.     UInt          m_uiNumPartInHeight;  // CTU纵向上有几个4x4的块  
  17.     UInt          m_uiNumCUsInFrame;    // 图像有几个CTU  
  18.   
  19.     TComSlice*    m_pcTComSlice;    // slice头部信息  
  20.     TComDataCU**  m_apcTComDataCU;  // 表示了每一个CTU,每一个TComDataCU表示CU以及其中所有4x4块的信息  
  21.   
  22.     SAOParam*     m_saoParam;       // SAO的参数  
  23.       
  24.     // 其他省略***  
  25. };   



TComDataCU


    TComDataCU表示CU,它本身不存储YUV数据,只包含CU应有的语法元素(包括系数)。TComDataCU存储了CU中所有4x4小块的信息。由于LCU也是CU,因此TComDataCU既能表示LCU也能表示普通CU。

[cpp]  view plain  copy
  1. class TComDataCU  
  2. {  
  3. private:  
  4.   
  5.     TComPic*      m_pcPic;              // CU所在的图像  
  6.     TComSlice*    m_pcSlice;            // CU所在的条带  
  7.     TComPattern*  m_pcPattern;          // 用于访问临近CU  
  8.   
  9.     UInt          m_uiCUAddr;           // 在slice中CU的地址  
  10.     UInt          m_uiAbsIdxInLCU;      // 在LCU中Z扫描顺序的地址  
  11.     UInt          m_uiCUPelX;           // 以像素为单位的CU地址  
  12.     UInt          m_uiCUPelY;           // 以像素为单位的CU地址  
  13.     UInt          m_uiNumPartition;     // 当前CU中有多少个4x4的块  
  14.     UChar*        m_puhWidth;           // 存放CU宽度的数组(因为CU会不断分割,每个CU都具有自己的长宽,所以村要存放,这个数组的作用就是这样的)  
  15.     UChar*        m_puhHeight;          // 同上  
  16.     UChar*        m_puhDepth;           // 存放CU深度的数组  
  17.     Int           m_unitSize;           // partition的最小尺寸  
  18.   
  19.     /* 
  20.     ** 下面是CU中各种语法元素 
  21.     */  
  22.     Bool*         m_skipFlag;           // 跳过标志数组  
  23.     Char*         m_pePartSize;         // 分割的尺寸的数组  
  24.     Char*         m_pePredMode;         // 预测模式的数组  
  25.     Bool*         m_CUTransquantBypass;   // 用于量化  
  26.     Char*         m_phQP;               // 量化步长的数组  
  27.     UChar*        m_puhTrIdx;           // 变换索引的数组  
  28.     UChar*        m_puhTransformSkip[3];// 变换跳过标志数组  
  29.     UChar*        m_puhCbf[3];          // 编码块标志数组  
  30.     TComCUMvField m_acCUMvField[2];     // 运动估计的数组  
  31.     TCoeff*       m_pcTrCoeffY;         // Y变换系数的数组  
  32.     TCoeff*       m_pcTrCoeffCb;        // U变换系数的数组  
  33.     TCoeff*       m_pcTrCoeffCr;        // V变换系数的数组  
  34.   
  35.   
  36.     Pel*          m_pcIPCMSampleY;      // PCM 样本的缓冲区  
  37.     Pel*          m_pcIPCMSampleCb;       
  38.     Pel*          m_pcIPCMSampleCr;      
  39.   
  40.     TComDataCU*   m_pcCUAboveLeft;      ///< pointer of above-left CU                当前CU左上角的CU  
  41.     TComDataCU*   m_pcCUAboveRight;     ///< pointer of above-right CU           当前CU右上角的CU  
  42.     TComDataCU*   m_pcCUAbove;          ///< pointer of above CU                     当前CU上面的CU  
  43.     TComDataCU*   m_pcCULeft;           ///< pointer of left CU                              当前CU左边的CU  
  44.     TComDataCU*   m_apcCUColocated[2];  ///< pointer of temporally colocated CU's for both directions        CU的变形  
  45.     TComMvField   m_cMvFieldA;          ///< motion vector of position A             A位置的运动估计,A/B/C位置是什么?  
  46.     TComMvField   m_cMvFieldB;          ///< motion vector of position B             B位置的运动估计  
  47.     TComMvField   m_cMvFieldC;          ///< motion vector of position C             C位置的运动估计  
  48.     TComMv        m_cMvPred;            ///< motion vector predictor                     运动向量预测  
  49.   
  50.     Bool*         m_pbMergeFlag;        ///< array of merge flags                                合并标志的数组  
  51.     UChar*        m_puhMergeIndex;      ///< array of merge candidate indices        合并候选数组  
  52. #if AMP_MRG  
  53.     Bool          m_bIsMergeAMP;  
  54. #endif  
  55.     UChar*        m_puhLumaIntraDir;    ///< array of intra directions (luma)            // 帧内预测 亮度部分的 方向的数组(因为LCU会分割成很多部分)  
  56.     UChar*        m_puhChromaIntraDir;  ///< array of intra directions (chroma)      // 帧内预测 色度部分的 方向的数组  
  57.     UChar*        m_puhInterDir;        ///< array of inter directions                           // 帧间预测的方向的集合  
  58.     Char*         m_apiMVPIdx[2];       ///< array of motion vector predictor candidates // 运动向量的候选集  
  59.     Char*         m_apiMVPNum[2];       // 可能的运动向量的数量的数组  
  60.     Bool*         m_pbIPCMFlag;         // intra_pcm标志的集合  
  61.   
  62.     Bool          m_bDecSubCu;          // 指出了解码模式  
  63.   
  64.     // RD即拉格朗日率失真,这个成员表示总的失真的代价  
  65.     Double        m_dTotalCost;         // 总的代价  
  66.     // 总的失真  
  67.     UInt          m_uiTotalDistortion;  // 总的失真  
  68.     // 总的比特数  
  69.     UInt          m_uiTotalBits;        ///< sum of partition bits                         
  70.     // 总的二进制数  
  71.     UInt          m_uiTotalBins;       ///< sum of partition bins                          
  72.   
  73.     UInt*         m_sliceStartCU;    ///< Start CU address of current slice      当前slice开始CU的地址  
  74.     UInt*         m_sliceSegmentStartCU; ///< Start CU address of current slice  当前slice开始CU的地址  
  75.     Char          m_codedQP;                                                                        // 量化的编码  
  76. };  



TComYuv


    TComYuv保存了每一个CU对应的YUV数据,原始数据从TComPic中得到(实际从TComPic的TComPicYuv成员中得到)。它主要用于表示编码过程中的原始数据、预测数据、残差数据以及重建数据

[cpp]  view plain  copy
  1. class TComYuv  
  2. {  
  3. private:  
  4.     Pel*    m_apiBufY; // 颜色分量的起始地址  
  5.     Pel*    m_apiBufU;  
  6.     Pel*    m_apiBufV;  
  7.   
  8.     UInt     m_iWidth; // CU(可以是LCU,也可以是普通CU)的宽和高  
  9.     UInt     m_iHeight;  
  10.     UInt     m_iCWidth; // CU色度分量的尺寸  
  11.     UInt     m_iCHeight;  
  12. };  
UVTools are a set of software utilities to play, convert and analyze YUV or RGB video data in their raw formats. The main features of YUVTools are: It accepts (plays, converts, edits and analyzes) the combination of following formats: YUV in 4:4:4, 4:2:2 or 4:2:0 sample format, RGB in 4:4:4 sampling format; in different component order, like YUV, YVU, UYV, RGB, BGR, etc. in progressive (one single frame) or interlaced (two fields) format; in planar (YYY...UUU...VVV...) or packed (YUV, YUV....) pixel format; in predefined or arbitrary resolutions; Support FOURCC ( refer to: http://www.fourcc.org/). An image preview function to help guess the video format interactively. YUV Player can open multiple player dialogs and play different files in each dialog separately, or play multiple video files in one player dialog one by one sequentially. The detailed format of any opened or generated files will be logged, and the user can directly select any file to play back from the history list. YUV Converter can convert any combination of the format to another format, or convert to (or from) a sequence of BMP files. Other conversion functions include: scaling, join, crop, flip, padding, merge and separation of color components. YUV Analyzer can be used to calculate PSNR between two YUV files, or compare pixel by pixel to check the difference between the corresponding frames of two files, or overlay block type or motion vectors on top of each frame. Another useful feature is to help check the motion between two adjacent frames. YUV Editor can be used to edit the images pixel by pixel, or overlay one YUV image on top of another YUV image file. Convert YUV file to AVI format or vice versa; Setting options include grid display, different YUV to RGB conversion formula, etc. Many of above functions can also be performed in command line mode, which are useful for batch process or scripting.
<think>我们正在解析HM中的YUV类。根据用户需求,我们需要关注YUV类的内部结构和用法。在HM参考软件中,YUV相关类主要用于处理YUV格式的视频数据,包括读取、写入和存储等功能。主要涉及的类有:-TComPicYuv:存储一帧YUV数据-TComYuv:存储一个CU/PU/TU级别的YUV数据(可能是预测块、残差块等)-TVideoIOYuv:用于读写YUV文件下面我们详细解析这些类的结构和用法。1.TComPicYuv类(一帧YUV数据存储)位置:source/Lib/TLibCommon/TComPicYuv.h/.cpp功能:存储一帧的YUV数据,包含亮度(Y)和色度(U,V)分量。每个分量以二维数组形式存储。主要成员变量:Pel*m_apiPicBufY;//亮度分量数据指针Pel*m_apiPicBufU;//色度U分量数据指针Pel*m_apiPicBufV;//色度V分量数据指针Intm_iPicWidth;//图像宽度(亮度分量)Intm_iPicHeight;//图像高度(亮度分量)Intm_iCuWidth;//每个CU的宽度(以像素为单位)Intm_iCuHeight;//每个CU的高度(以像素为单位)主要成员函数:create()-分配内存destroy()-释放内存getBuf()-获取某个分量的数据指针copyToPic()-将当前帧数据复制到另一个TComPicYuv对象dump()-输出帧数据(调试用)2.TComYuv类(局部YUV数据存储)位置:source/Lib/TLibCommon/TComYuv.h/.cpp功能:存储一个CU、PU或TU的YUV数据,通常用于预测、残差等中间过程的数据存储。主要成员变量:Pel*m_apiBufY;//亮度分量数据指针Pel*m_apiBufU;//色度U分量数据指针Pel*m_apiBufV;//色度V分量数据指针Intm_iWidth;//宽度(亮度分量)Intm_iHeight;//高度(亮度分量)主要成员函数:create()/destroy()-创建/销毁addClip()-将另一个TComYuv块的数据加到当前块(带裁剪)subtract()-从当前块减去另一个块(用于计算残差)copyPartToPartYuv()-复制部分区域copyPartToPartLuma()-只复制亮度分量部分区域3.TVideoIOYuv类(YUV文件读写)位置:source/Lib/TLibCommon/TVideoIOYuv.h/.cpp功能:读写YUV文件(通常为YUV420格式)主要成员函数:open()-打开YUV文件(读或写)close()-关闭文件skipFrames()-跳过指定数量的帧(用于随机访问)read()-读取一帧到TComPicYuv对象write()-将TComPicYuv对象写入文件使用示例:(1)读取YUV文件(在编码器中):TVideoIOYuvvideoIO;videoIO.open(inputFile,false);//false表示读模式TComPicYuv*picYuv=newTComPicYuv;picYuv->create(iWidth,iHeight,chromaFormat,maxCUWidth,maxCUHeight,maxTotalCUDepth);videoIO.read(picYuv);//读取一帧(2)写入YUV文件(在解码器中):TVideoIOYuvvideoIO;videoIO.open(outputFile,true);//true表示写模式TComPicYuv*picYuvRec;//重建图像//...解码得到重建图像...videoIO.write(picYuvRec);//写入一帧(3)TComYuv在预测过程中的使用(以帧内预测为例):TComYuvpredYuv;//预测块predYuv.create(uiWidth,uiHeight);//创建//进行帧内预测,将预测结果存入predYuvpredIntraAng(...,&predYuv,...);//然后计算残差:原像素块(从TComPicYuv中取出)减去预测块注意:在HM中,像素数据类型为Pel(typedefShortPel;),即16位有符号整数,但实际存储的像素值一般在0-255范围内(8位)或0-1023(10位)等。引用说明:[^1]:用户提供的引用[1]提到HM编码器的基本结构,其中编码过程通过调用编码器实例的一个方法实现,而YUV数据的读取和写入是在这个编码过程之外由TVideoIOYuv处理的。[^2]:用户提供的引用[2]提到xEncIntraHeader函数,该函数编码帧内预测的头部信息,而YUV数据(预测块)是在帧内预测过程中生成并存储在TComYuv对象中。下面我们以代码片段形式展示部分关键操作。</think>### HM代码中YUV类结构解析与使用指南 在HM参考软件中,YUV相关类负责处理视频数据的存储、转换和访问,是编解码流程的基础设施。主要包含以下核心类: #### 一、核心类结构 1. **TComPicYuv(图像级YUV数据)** ```cpp class TComPicYuv { private: Pel* m_apiPicBufY; // 亮度分量(Y)数据指针 Pel* m_apiPicBufU; // 色度分量(U)数据指针 Pel* m_apiPicBufV; // 色度分量(V)数据指针 Int m_iPicWidth; // 图像宽度(亮度分量) Int m_iPicHeight; // 图像高度(亮度分量) ChromaFormat m_chromaFormat; // 色度格式(420/422/444) public: Void create(Int, Int, ChromaFormat); // 内存分配 Void destroy(); // 内存释放 Pel* getAddr(ComponentID compID) { // 分量数据访问 return (compID==COMPONENT_Y) ? m_apiPicBufY : (compID==COMPONENT_Cb) ? m_apiPicBufU : m_apiPicBufV; } Void dump(std::string filename); // 数据导出 }; ``` 2. **TComYuv(块级YUV数据)** ```cpp class TComYuv : public TComYuvBase { Pel* m_apiBufY, *m_apiBufU, *m_apiBufV; // 分量指针 Int m_iWidth, m_iHeight; // 块尺寸 Void addClip(TComYuv* srcYuv); // 像素叠加(带裁剪) Void subtract(TComYuv* srcYuv); // 像素相减(残差计算) Void copyPartToPartYuv(TComYuv* dstYuv, UInt partIdx); // 块数据复制 }; ``` #### 二、关键功能实现 1. **内存管理机制** - 使用`create()`分配连续内存块,按YUV分量顺序存储 - 内存布局示例(YUV420): ``` [YYYY...] [UU...] [VV...] └─亮度─┘ └色度┘ ``` - 通过`getStride()`获取行跨度,支持对齐访问 2. **色度格式处理** ```cpp switch(m_chromaFormat) { case CHROMA_420: // 宽高均为1/2 chromaWidth = m_iWidth >> 1; break; case CHROMA_422: // 宽度1/2,高度不变 chromaWidth = m_iWidth >> 1; break; case CHROMA_444: // 与亮度同尺寸 chromaWidth = m_iWidth; } ``` 3. **像素操作函数** - `addAvg()`:加权平均两个YUV块 ```cpp Void TComYuv::addAvg(TComYuv* srcYuv0, TComYuv* srcYuv1) { for(Int comp=0; comp<3; comp++) { Pel* dst = getAddr(comp); Pel* src0 = srcYuv0->getAddr(comp); Pel* src1 = srcYuv1->getAddr(comp); for(Int y=0; y<height; y++) { for(Int x=0; x<width; x++) dst[x] = (src0[x] + src1[x] + 1) >> 1; // 平均计算 dst += stride; } } } ``` #### 三、典型使用场景 1. **编码器输入处理** ```cpp // 在TAppEncTop.cpp中 TVideoIOYuv videoIO; videoIO.open(m_inputFileName, false); // 打开YUV文件 TComPicYuv* orgPicYuv = new TComPicYuv; orgPicYuv->create(m_iSourceWidth, m_iSourceHeight, m_chromaFormat); videoIO.read(orgPicYuv); // 读取一帧原始数据[^1] ``` 2. **预测残差计算** ```cpp // 在TEncSearch.cpp中 TComYuv* predYuv = new TComYuv; // 预测块 TComYuv* resiYuv = new TComYuv; // 残差块 predYuv->create(uiWidth, uiHeight); resiYuv->create(uiWidth, uiHeight); // 计算残差:原始块 - 预测块 resiYuv->subtract(orgYuvBlk, predYuv); ``` 3. **重建图像生成** ```cpp // 在TEncCu.cpp中 TComYuv* reconYuv = pcCU->getPic()->getPicYuvRec(); // 重建图像 reconYuv->addClip(predYuv, resiYuv); // 预测 + 残差 = 重建 ``` #### 四、调试与分析技巧 1. **数据导出方法** ```cpp // 导出YUV分量到文本 orgPicYuv->dump("frame_0_yuv.dump"); ``` 输出格式: ``` Y: 23 45 67 ... U: 128 129 ... V: 64 65 ... ``` 2. **内存访问监控** ```bash gdb --args TAppEncoder -c cfg/encoder.cfg (gdb) b TComPicYuv::getAddr (gdb) watch *0x7fffffffde00 // 监控特定内存地址 ``` > **注意事项**: > 1. 所有YUV操作使用`Pel`类型(typedef Short Pel),表示16位像素值 > 2. 色度分量在420格式下需注意亚采样访问 > 3. 块操作需确保源和目标的尺寸匹配[^2]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值