【转】TLibVideoIO库分析

来源:互联网 发布:centos7 iso yum源 编辑:程序博客网 时间:2024/05/22 00:31

HEVC学习:HM-10.1-dev代码分析之TLibVideoIO库

    视频输入输出库涉及编解码过程的起始和结束操作,即编码开始的时候读取视频文件数据,解码结束的时候写视频文件数据。

    在HEVC中视频文件即为yuv文件,yuv文件中图像格式为YUV420格式。视频文件数据的操作是HEVC编解码中最基本的操作过程之一,也是学习、分析、理解和调试HM代码的重要一环,下面来分析一下VideoIO库的基本操作。

    VideoIO库包含一个头文件TVideoIOYuv.h和一个实现文件TVideoIOYuv.cpp

[cpp] view plaincopy
  1. TVideoIOYuv.h  
  2. 私有成员变量  
  3. fstream   m_cHandle;    //文件流句柄  
  4. Int m_fileBitDepthY;    //文件位深Y,即文件中图像亮度Y分量数据的位深度,一般为8或10位  
  5. Int m_fileBitDepthC;    //文件位深C,即文件中图像色度C分量数据的位深度,一般为8或10位  
  6. Int m_bitDepthShiftY;   //位深移动Y,即图像Y分量要改变的数据位深度,正表示增加,负表示减少  
  7. Int m_bitDepthShiftC;   //位深移动Y,即图像C分量要改变的数据位深度,正表示增加,负表示减少  
  8.   
  9. 公共成员函数  
  10. TVideoIOYuv();                     //构造函数  
  11. virtual ~TVideoIOYuv();            //虚构函数  
  12. Void open();                       //打开视频文件  
  13. Void close();                      //关闭视频文件  
  14. void skipFrames();                 //跳过数帧图像  
  15. Bool read();                       //读视频文件  
  16. Bool write();                      //写视频文件  
  17. Bool isEof();                      //判断文件结束  
  18. Bool isFail();                     //判断操作失败  
  19.   
  20. TVideoIOYuv.cpp  
  21. 全局函数  
  22. /** 
  23.  * Perform division with rounding of all pixels in img by 
  24.  * 2<sup>shiftbits</sup>. All pixels are clipped to [minval, maxval] 
  25.  * 
  26.  * @param img        pointer to image to be transformed 
  27.  * @param stride     distance between vertically adjacent pixels of img. 
  28.  * @param width      width of active area in img. 
  29.  * @param height     height of active area in img. 
  30.  * @param shiftbits  number of rounding bits 
  31.  * @param minval     minimum clipping value 
  32.  * @param maxval     maximum clipping value 
  33.  */  
  34. 说明:反向缩放图像面函数,即缩小图像的某个分量像素值  
  35. 参数:  
  36.   Pel* img:                 图像数据指针,Pel为16位Short类型  
  37.   UInt stride:               图像行偏移量,即从前一行开头与后一行开头之间的间距  
  38.   UInt width:                图像宽度  
  39.   UInt height:               图像高度  
  40.   UInt shiftbits:           移动位数,即在原来图像数据位数上调整的位数   
  41.   Pel minval:                图像像素最小值  
  42.   Pel maxval:                图像像素最小值  
  43.   
  44. static void invScalePlane(Pel* img, UInt stride, UInt width, UInt height,  
  45.     UInt shiftbits, Pel minval, Pel maxval)  
  46. {  
  47.     Pel offset = 1 << (shiftbits-1);      //求像素值调整量  
  48.     for (UInt y = 0; y < height; y++)        //遍历图像高度  
  49.     {  
  50.         for (UInt x = 0; x < width; x++)          //遍历图像宽度  
  51.          {  
  52.             Pel val = (img[x] + offset) >> shiftbits; //求缩小后像素值  
  53.               img[x] = Clip3(minval, maxval, val);      //限制像素值的范围  
  54.          }  
  55.         img += stride;                  //移动图像数据指针到下一行  
  56.     }  
  57. }  
  58.   
  59. /** 
  60.  * Multiply all pixels in img by 2<sup>shiftbits</sup>. 
  61.  * 
  62.  * @param img        pointer to image to be transformed 
  63.  * @param stride     distance between vertically adjacent pixels of img. 
  64.  * @param width      width of active area in img. 
  65.  * @param height     height of active area in img. 
  66.  * @param shiftbits  number of bits to shift 
  67.  */  
  68. 说明:正向缩放图像,即放大图像的某个分量像素值  
  69. 参数:  
  70.   Pel* img:                图像数据指针  
  71.   UInt stride:             图像行偏移量,即从前一行开头与后一行开头之间的间距  
  72.   UInt width:              图像宽度  
  73.   UInt height:             图像高度  
  74.   UInt shiftbits:          移动位数,即在原来图像数据位数上调整的位数  
  75.   
  76. static void scalePlane(Pel* img, UInt stride, UInt width, UInt height,  
  77.                        UInt shiftbits)  
  78. {  
  79.   for (UInt y = 0; y < height; y++)         //遍历图像高度  
  80.   {  
  81.     for (UInt x = 0; x < width; x++)        //遍历图像宽度  
  82.     {  
  83.       img[x] <<= shiftbits;                 //放大像素值  
  84.     }  
  85.     img += stride;                          //数据指针移动到下一行  
  86.   }  
  87. }  
  88.   
  89. /** 
  90. * Scale all pixels in img depending upon sign of shiftbits by a factor of 
  91. * 2<sup>shiftbits</sup>. 
  92. * 
  93. * @param img        pointer to image to be transformed 
  94. * @param stride  distance between vertically adjacent pixels of img. 
  95. * @param width   width of active area in img. 
  96. * @param height  height of active area in img. 
  97. * @param shiftbits if zero, no operation performed 
  98. *                  if > 0, multiply by 2<sup>shiftbits</sup>, see scalePlane() 
  99. *                  if < 0, divide and round by 2<sup>shiftbits</sup> and clip, 
  100. *                          see invScalePlane(). 
  101. * @param minval  minimum clipping value when dividing. 
  102. * @param maxval  maximum clipping value when dividing. 
  103.  */  
  104. 说明:缩放图像,即放大或者缩小图像的某个分量像素值  
  105. 参数:  
  106.   Pel* img:                图像数据指针,Pel为16位Short类型  
  107.   UInt stride:              图像数据行间隔,即从前一行开头与后一行开头之间的间距  
  108.   UInt width:               图像宽度  
  109.   UInt height:              图像高度  
  110.   Int shiftbits:            移动位数,即在原来图像数据位数上调整的位数,正表示放大,负表示缩小  
  111.   Pel minval:               图像像素最小值  
  112.   Pel maxval:               图像像素最小值  
  113.   
  114. static void scalePlane(Pel* img, UInt stride, UInt width, UInt height,  
  115.                        Int shiftbits, Pel minval, Pel maxval)  
  116. {  
  117.   if (shiftbits == 0)              //移动位数为0,即不需要作缩放处理  
  118.   {  
  119.     return;  
  120.   }  
  121.   
  122.   if (shiftbits > 0)               //移动位数大于0,即需要作放大处理  
  123.   {  
  124.     scalePlane(img, stride, width, height, shiftbits);  
  125.   }  
  126.   else                             //移动位数小于0,即需要作缩小处理  
  127.   {  
  128.     invScalePlane(img, stride, width, height, -shiftbits, minval, maxval);  
  129.   }  
  130. }  
  131.   
  132. 类成员函数  
  133. // ====================================================================================================================  
  134. // Public member functions  
  135. // ====================================================================================================================  
  136.   
  137. /** 
  138.  * Open file for reading/writing Y'CbCr frames. 
  139.  * 
  140.  * Frames read/written have bitdepth fileBitDepth, and are automatically 
  141.  * formatted as 8 or 16 bit word values (see TVideoIOYuv::write()). 
  142.  * 
  143.  * Image data read or written is converted to/from internalBitDepth 
  144.  * (See scalePlane(), TVideoIOYuv::read() and TVideoIOYuv::write() for 
  145.  * further details). 
  146.  * 
  147.  * \param pchFile          file name string 
  148.  * \param bWriteMode       file open mode: true=read, false=write 
  149.  * \param fileBitDepthY     bit-depth of input/output file data (luma component). 
  150.  * \param fileBitDepthC     bit-depth of input/output file data (chroma components). 
  151.  * \param internalBitDepthY bit-depth to scale image data to/from when reading/writing (luma component). 
  152.  * \param internalBitDepthC bit-depth to scale image data to/from when reading/writing (chroma components). 
  153.  */  
  154. 说明:为数据帧读写打开yuv文件  
  155. 参数:  
  156.   Char* pchFile:                   文件名字  
  157.   Bool bWriteMode:                 读写模式  
  158.   Int fileBitDepthY:               文件数据位深度Y  
  159.   Int fileBitDepthC:               文件数据位深度C  
  160.   Int internalBitDepthY:           内部(程序中)数据位深度Y  
  161.   Int internalBitDepthC:           内部(程序中)位数据深度C  
  162.   
  163. Void TVideoIOYuv::open( Char* pchFile, Bool bWriteMode, Int fileBitDepthY, Int fileBitDepthC, Int internalBitDepthY, Int internalBitDepthC)  
  164. {  
  165.   m_bitDepthShiftY = internalBitDepthY - fileBitDepthY;      //Y分量位移动深度(位数)  
  166.   m_bitDepthShiftC = internalBitDepthC - fileBitDepthC;      //C分量位移动深度(位数)  
  167.   m_fileBitDepthY = fileBitDepthY;                            //类成员(文件Y分量位深)赋值  
  168.   m_fileBitDepthC = fileBitDepthC;                           //类成员(文件C分量位深)赋值  
  169.   
  170.   if ( bWriteMode )                                          //判断为写模式  
  171.   {  
  172.     m_cHandle.open( pchFile, ios::binary | ios::out );       //fstream以输出模式打开文件  
  173.       
  174.     if( m_cHandle.fail() )                                     //打开失败  
  175.     {  
  176.       printf("\nfailed to write reconstructed YUV file\n");  
  177.       exit(0);  
  178.     }  
  179.   }  
  180.   else                                                       //判断为读模式  
  181.   {  
  182.     m_cHandle.open( pchFile, ios::binary | ios::in );        //fstream以输入模式打开文件  
  183.       
  184.     if( m_cHandle.fail() )                                     //打开失败  
  185.     {  
  186.       printf("\nfailed to open Input YUV file\n");  
  187.       exit(0);  
  188.     }  
  189.   }  
  190.     
  191.   return;  
  192. }  
  193.   
  194. 说明:关闭文件  
  195. Void TVideoIOYuv::close()  
  196. {  
  197.   m_cHandle.close();                //由fstream函数完成文件关闭  
  198. }  
  199.   
  200. 说明:判断文件结束  
  201. Bool TVideoIOYuv::isEof()  
  202. {  
  203.   return m_cHandle.eof();            //由fstream函数完成判断文件结束  
  204. }  
  205.   
  206. 说明:判断文件出错  
  207. Bool TVideoIOYuv::isFail()  
  208. {  
  209.   return m_cHandle.fail();           //由fstream函数完成判断文件出错  
  210. }  
  211.   
  212. /** 
  213.  * Skip numFrames in input. 
  214.  * 
  215.  * This function correctly handles cases where the input file is not 
  216.  * seekable, by consuming bytes. 
  217.  */  
  218. 说明:在输入文件中跳过数帧图像  
  219. 参数:  
  220.   UInt numFrames:                  跳过的帧数  
  221.   UInt width:                       图像宽度  
  222.   UInt height:                      图像高度  
  223.   
  224. void TVideoIOYuv::skipFrames(UInt numFrames, UInt width, UInt height)  
  225. {  
  226.   if (!numFrames)                   //帧数为0,即不作跳跃操作  
  227.     return;  
  228.   
  229.   const UInt wordsize = (m_fileBitDepthY > 8 || m_fileBitDepthC > 8) ? 2 : 1;  //字节长度  
  230.   const streamoff framesize = wordsize * width * height * 3 / 2;               //YUV420图像帧大小  
  231.   const streamoff offset = framesize * numFrames;                              //跳跃的偏移量  
  232.   
  233.   /* attempt to seek */  
  234.   if (!!m_cHandle.seekg(offset, ios::cur))  //直接跳过offset  
  235.     return/* success */  
  236.   m_cHandle.clear();                        //直接操作识别,清除stream,然后通过读方式来实现跳跃  
  237.   
  238.   /* fall back to consuming the input */  
  239.   Char buf[512];                            //定义读stream缓冲区  
  240.   const UInt offset_mod_bufsize = offset % sizeof(buf);                     //偏移量对缓冲区取模  
  241.   for (streamoff i = 0; i < offset - offset_mod_bufsize; i += sizeof(buf))  //遍历跳跃帧  
  242.   {  
  243.     m_cHandle.read(buf, sizeof(buf));       //读到缓冲区  
  244.   }  
  245.   m_cHandle.read(buf, offset_mod_bufsize);  //读剩余量  
  246. }  
  247.   
  248. /** 
  249.  * Read width*height pixels from fd into dst, optionally 
  250.  * padding the left and right edges by edge-extension.  Input may be 
  251.  * either 8bit or 16bit little-endian lsb-aligned words. 
  252.  * 
  253.  * @param dst     destination image 
  254.  * @param fd      input file stream 
  255.  * @param is16bit true if input file carries > 8bit data, false otherwise. 
  256.  * @param stride  distance between vertically adjacent pixels of dst. 
  257.  * @param width   width of active area in dst. 
  258.  * @param height  height of active area in dst. 
  259.  * @param pad_x   length of horizontal padding. 
  260.  * @param pad_y   length of vertical padding. 
  261.  * @return true for success, false in case of error 
  262.  */  
  263. 说明:从文件读图像某个分量数据  
  264. 参数:  
  265.   Pel* dst:                目的数据指针  
  266.   istream& fd:             输入数据流  
  267.   Bool is16bit:            是否16位  
  268.   UInt stride:             图像行偏移量  
  269.   UInt width:              图像宽度  
  270.   UInt height:             图像高度  
  271.   UInt pad_x:              x对齐偏移量  
  272.   UInt pad_y:              y对齐偏移量  
  273.   
  274. static Bool readPlane(Pel* dst, istream& fd, Bool is16bit,  
  275.                       UInt stride,  
  276.                       UInt width, UInt height,  
  277.                       UInt pad_x, UInt pad_y)  
  278. {  
  279.   Int read_len = width * (is16bit ? 2 : 1);                   //单次读取数据量  
  280.   UChar *buf = new UChar[read_len];                           //申请一行图像缓冲区  
  281.   for (Int y = 0; y < height; y++)                            //图像行遍历  
  282.   {  
  283.     fd.read(reinterpret_cast<Char*>(buf), read_len);           //从文件读一行图像数据  
  284.     if (fd.eof() || fd.fail() )                               //判断文件结束和操作失败  
  285.     {  
  286.       delete[] buf;                                           //释放缓存  
  287.       return false;  
  288.     }  
  289.   
  290.     if (!is16bit)                                               //图像数据为非16位即8位单字节  
  291.     {  
  292.       for (Int x = 0; x < width; x++)                         //遍历宽度  
  293.       {  
  294.         dst[x] = buf[x];                                      //直接赋值给目的缓冲区  
  295.       }  
  296.     }  
  297.     else                                                         //图像数据为非16位即双字节  
  298.     {  
  299.       for (Int x = 0; x < width; x++)            //遍历宽度  
  300.       {  
  301.         dst[x] = (buf[2*x+1] << 8) | buf[2*x];                //双字节拼接后赋给目的缓冲区  
  302.       }  
  303.     }  
  304.   
  305.     for (Int x = width; x < width + pad_x; x++)               //对齐位置处理  
  306.     {  
  307.       dst[x] = dst[width - 1];                                //直接向左边界扩展  
  308.     }  
  309.     dst += stride;                                            //目的数据指针移动到下一行  
  310.   }  
  311.   for (Int y = height; y < height + pad_y; y++)               //处理高度方向对齐,即最后几行  
  312.   {  
  313.     for (Int x = 0; x < width + pad_x; x++)                    //遍历对齐行的对齐列  
  314.     {  
  315.       dst[x] = (dst - stride)[x];                             //直接向下边界扩展  
  316.     }  
  317.     dst += stride;                                            //移动目的数据指针到下一行  
  318.   }  
  319.   delete[] buf;                                               //释放缓冲区  
  320.   return true;  
  321. }  
  322.   
  323.   
  324. /** 
  325.  * Write width*height pixels info fd from src. 
  326.  * 
  327.  * @param fd      output file stream 
  328.  * @param src     source image 
  329.  * @param is16bit true if input file carries > 8bit data, false otherwise. 
  330.  * @param stride  distance between vertically adjacent pixels of src. 
  331.  * @param width   width of active area in src. 
  332.  * @param height  height of active area in src. 
  333.  * @return true for success, false in case of error 
  334.  */  
  335. 说明:写图像某个分量数据到文件  
  336. 参数:  
  337.   ostream& fd:             输出数据流  
  338.   Pel* src:               图像源数据指针  
  339.   Bool is16bit:            是否16位  
  340.   UInt stride:             图像行偏移量  
  341.   UInt width:              图像宽度  
  342.   UInt height:             图像高度  
  343.   
  344. static Bool writePlane(ostream& fd, Pel* src, Bool is16bit,  
  345.                        UInt stride,  
  346.                        UInt width, UInt height)  
  347. {  
  348.   Int write_len = width * (is16bit ? 2 : 1);  //写一行数据量  
  349.   UChar *buf = new UChar[write_len];          //申请一行图像缓冲区  
  350.   for (Int y = 0; y < height; y++)            //遍历图像行  
  351.   {  
  352.     if (!is16bit)                            //单字节数据  
  353.     {  
  354.       for (Int x = 0; x < width; x++)        //遍历图像列  
  355.       {  
  356.         buf[x] = (UChar) src[x];             //直接取数据低字节  
  357.       }  
  358.     }  
  359.     else                                     //双字节数据  
  360.     {  
  361.       for (Int x = 0; x < width; x++)        //遍历图像列  
  362.       {  
  363.         buf[2*x] = src[x] & 0xff;            //取低字节  
  364.         buf[2*x+1] = (src[x] >> 8) & 0xff;    //取高字节  
  365.       }  
  366.     }  
  367.   
  368.     fd.write(reinterpret_cast<Char*>(buf), write_len);   //写一行图像到文件  
  369.     if (fd.eof() || fd.fail() )                           //判断文件结束和操作失败  
  370.     {  
  371.       delete[] buf;                //释放缓冲区  
  372.       return false;  
  373.     }  
  374.     src += stride;                 //图像数据源指针移动到下一行  
  375.   }  
  376.   delete[] buf;                    //释放缓冲区  
  377.   return true;  
  378. }  
  379.   
  380.   
  381. /** 
  382.  * Read one Y'CbCr frame, performing any required input scaling to change 
  383.  * from the bitdepth of the input file to the internal bit-depth. 
  384.  * 
  385.  * If a bit-depth reduction is required, and internalBitdepth >= 8, then 
  386.  * the input file is assumed to be ITU-R BT.601/709 compliant, and the 
  387.  * resulting data is clipped to the appropriate legal range, as if the 
  388.  * file had been provided at the lower-bitdepth compliant to Rec601/709. 
  389.  * 
  390.  * @param pPicYuv      input picture YUV buffer class pointer 
  391.  * @param aiPad        source padding size, aiPad[0] = horizontal, aiPad[1] = vertical 
  392.  * @return true for success, false in case of error 
  393.  */  
  394. 说明:读一帧图像数据,由读取一个Y分量和两个C分量实现  
  395. 参数:  
  396.   TComPicYuv*  pPicYuv:             输入图像指针  
  397.   Int aiPad[2]:                      图像对齐参数  
  398.       
  399. Bool TVideoIOYuv::read ( TComPicYuv*  pPicYuv, Int aiPad[2] )  
  400. {  
  401.   // check end-of-file  
  402.   if ( isEof() ) return false;                       //判断是否文件结束  
  403.     
  404.   Int   iStride = pPicYuv->getStride();              //获取图像行偏移量  
  405.     
  406.   // compute actual YUV width & height excluding padding size  
  407.   UInt pad_h = aiPad[0];                             //获取水平(列)对齐填充量  
  408.   UInt pad_v = aiPad[1];                             //获取竖直(行)对齐填充量  
  409.   UInt width_full = pPicYuv->getWidth();             //获取图像完全宽度  
  410.   UInt height_full = pPicYuv->getHeight();           //获取图像完全高度  
  411.   UInt width  = width_full - pad_h;                  //有效图像宽度  
  412.   UInt height = height_full - pad_v;                 //有效图像高度  
  413.   Bool is16bit = m_fileBitDepthY > 8 || m_fileBitDepthC > 8;   //是否需要双字节表示  
  414.   
  415.   Int desired_bitdepthY = m_fileBitDepthY + m_bitDepthShiftY;     //期望位深Y=文件位深+移动  
  416.   Int desired_bitdepthC = m_fileBitDepthC + m_bitDepthShiftC;  //期望位深C=文件位深+移动  
  417.   Pel minvalY = 0;                                   //Y分量像素最小值  
  418.   Pel minvalC = 0;                                   //C分量像素最小值  
  419.   Pel maxvalY = (1 << desired_bitdepthY) - 1;        //Y分量像素最大值  
  420.   Pel maxvalC = (1 << desired_bitdepthC) - 1;        //C分量像素最大值  
  421. #if CLIP_TO_709_RANGE  
  422.   if (m_bitdepthShiftY < 0 && desired_bitdepthY >= 8)          //Y分量缩小处理  
  423.   {  
  424.     /* ITU-R BT.709 compliant clipping for converting say 10b to 8b */  
  425.     minvalY = 1 << (desired_bitdepthY - 8);                      //Y最小值  
  426.     maxvalY = (0xff << (desired_bitdepthY - 8)) -1;            //Y最大值  
  427.   }  
  428.   if (m_bitdepthShiftC < 0 && desired_bitdepthC >= 8)          //C分量缩小处理  
  429.   {  
  430.     /* ITU-R BT.709 compliant clipping for converting say 10b to 8b */  
  431.       minvalC = 1 << (desired_bitdepthC - 8);             //Y最小值  
  432.       maxvalC = (0xff << (desired_bitdepthC - 8)) -1;     //Y最大值  
  433.   }  
  434. #endif  
  435.     
  436.   if (! readPlane(pPicYuv->getLumaAddr(), m_cHandle, is16bit, iStride, width, height, pad_h, pad_v))//读取单帧图像中一个Y分量数据  
  437.     return false;       //读取失败返回  
  438.   scalePlane(pPicYuv->getLumaAddr(), iStride, width_full, height_full, m_bitDepthShiftY, minvalY, maxvalY); //对Y分量进行缩放处理  
  439.   
  440.   iStride >>= 1;      //C分量行偏移(420采样)  
  441.   width_full >>= 1;   //C分量图像完全宽度  
  442.   height_full >>= 1;  //C分量图像完全高度  
  443.   width >>= 1;        //C分量图像有效宽度  
  444.   height >>= 1;       //C分量图像有效高度  
  445.   pad_h >>= 1;        //C分量水平(列)填充量  
  446.   pad_v >>= 1;        //C分量竖直(行)填充量  
  447.   
  448.   if (! readPlane(pPicYuv->getCbAddr(), m_cHandle, is16bit, iStride, width, height, pad_h, pad_v))  //读取一个C分量(Cb)全部数据  
  449.     return false;       //失败返回  
  450.   scalePlane(pPicYuv->getCbAddr(), iStride, width_full, height_full, m_bitDepthShiftC, minvalC, maxvalC);     //对C分量进行缩放处理  
  451.   
  452.   if (! readPlane(pPicYuv->getCrAddr(), m_cHandle, is16bit, iStride, width, height, pad_h, pad_v))  //读取下一个C分量(Cr)全部数据  
  453.     return false;       //失败返回  
  454.   scalePlane(pPicYuv->getCrAddr(), iStride, width_full, height_full, m_bitDepthShiftC, minvalC, maxvalC); //对C分量进行缩放处理  
  455.   
  456.   return true;  
  457. }  
  458.   
  459. /** 
  460.  * Write one Y'CbCr frame. No bit-depth conversion is performed, pcPicYuv is 
  461.  * assumed to be at TVideoIO::m_fileBitdepth depth. 
  462.  * 
  463.  * @param pPicYuv     input picture YUV buffer class pointer 
  464.  * @param aiPad       source padding size, aiPad[0] = horizontal, aiPad[1] = vertical 
  465.  * @return true for success, false in case of error 
  466.  */  
  467. 说明:写一帧图像数据,由写一个Y分量和两个C分量实现  
  468. 参数:  
  469.   TComPicYuv* pPicYuv:              输出图像指针  
  470.   Int confLeft:                      左边界偏移  
  471.   Int confRight:                     右边界偏移  
  472.   Int confTop:                       上边界偏移  
  473.   Int confBottom:                    下边界偏移  
  474.   
  475. Bool TVideoIOYuv::write( TComPicYuv* pPicYuv, Int confLeft, Int confRight, Int confTop, Int confBottom )  
  476. {  
  477.   // compute actual YUV frame size excluding padding size  
  478.   Int   iStride = pPicYuv->getStride();                        //图像行偏移(Y分量)  
  479.   UInt  width  = pPicYuv->getWidth()  - confLeft - confRight;      //有效图像宽度(去掉边界)  
  480.   UInt  height = pPicYuv->getHeight() - confTop  - confBottom; //有效图像高度(去掉边界)  
  481.   Bool is16bit = m_fileBitDepthY > 8 || m_fileBitDepthC > 8;   //判断是否需要双字节表示  
  482.   TComPicYuv *dstPicYuv = NULL;    //定义目的图像指针  
  483.   Bool retval = true;              //返回值  
  484.   
  485.   if (m_bitDepthShiftY != 0 || m_bitDepthShiftC != 0)          //位深移动不为0,需要位深处理  
  486.   {  
  487.     dstPicYuv = new TComPicYuv;    //申请目的图像  
  488.     dstPicYuv->create( pPicYuv->getWidth(), pPicYuv->getHeight(), 1, 1, 0 );//创建缓冲区  
  489.     pPicYuv->copyToPic(dstPicYuv);  //图像拷贝到目的图像  
  490.   
  491.     Pel minvalY = 0;                //Y分量像素最小值  
  492.     Pel minvalC = 0;                //C分量像素最小值  
  493.     Pel maxvalY = (1 << m_fileBitDepthY) - 1;         //Y分量像素最大值  
  494.     Pel maxvalC = (1 << m_fileBitDepthC) - 1;         //C分量像素最大值  
  495. #if CLIP_TO_709_RANGE  
  496.     if (-m_bitDepthShiftY < 0 && m_fileBitDepthY >= 8)   //Y分量需要做位深处理  
  497.     {  
  498.       /* ITU-R BT.709 compliant clipping for converting say 10b to 8b */  
  499.       minvalY = 1 << (m_fileBitDepthY - 8);                 //Y分量像素最小值  
  500.       maxvalY = (0xff << (m_fileBitDepthY - 8)) -1;        //Y分量像素最大值  
  501.     }  
  502.     if (-m_bitDepthShiftC < 0 && m_fileBitDepthC >= 8)    //C分量需要做位深处理  
  503.     {  
  504.       /* ITU-R BT.709 compliant clipping for converting say 10b to 8b */  
  505.         minvalC = 1 << (m_fileBitDepthC - 8);               //C分量像素最小值  
  506.         maxvalC = (0xff << (m_fileBitDepthC - 8)) -1;       //C分量像素最大值  
  507.     }  
  508. #endif  
  509.     scalePlane(dstPicYuv->getLumaAddr(), dstPicYuv->getStride(), dstPicYuv->getWidth(), dstPicYuv->getHeight(), -m_bitDepthShiftY, minvalY, maxvalY);        //Y分量缩放处理  
  510.     scalePlane(dstPicYuv->getCbAddr(), dstPicYuv->getCStride(), dstPicYuv->getWidth()>>1, dstPicYuv->getHeight()>>1, -m_bitDepthShiftC, minvalC, maxvalC);        //Cb分量缩放处理  
  511.     scalePlane(dstPicYuv->getCrAddr(), dstPicYuv->getCStride(), dstPicYuv->getWidth()>>1, dstPicYuv->getHeight()>>1, -m_bitDepthShiftC, minvalC, maxvalC);        //Cr分量缩放处理  
  512.   }  
  513.   else                             //不需要做缩放处理  
  514.   {  
  515.     dstPicYuv = pPicYuv;           //直接获取图像  
  516.   }  
  517.   // location of upper left pel in a plane  
  518.   Int planeOffset = confLeft + confTop * iStride;      //Y分量偏移  
  519.     
  520.   if (! writePlane(m_cHandle, dstPicYuv->getLumaAddr() + planeOffset, is16bit, iStride, width, height))  //写图像L分量数据到文件  
  521.   {  
  522.     retval=false;                 //失败退出  
  523.     goto exit;  
  524.   }  
  525.   
  526.   width >>= 1;        //图像C分量有效宽度(420)  
  527.   height >>= 1;       //图像C分量有效高度  
  528.   iStride >>= 1;      //图像C分量行偏移  
  529.   confLeft >>= 1;     //图像C分量左边距  
  530.   confRight >>= 1;    //图像C分量右边距  
  531.   confTop >>= 1;      //图像C分量上边距  
  532.   confBottom >>= 1;   //图像C分量下边距  
  533.   
  534.   planeOffset = confLeft + confTop * iStride;        //C分量偏移  
  535.   
  536.   if (! writePlane(m_cHandle, dstPicYuv->getCbAddr() + planeOffset, is16bit, iStride, width, height)) //写图像Cb分量数据到文件  
  537.   {  
  538.       retval=false;     //失败退出  
  539.       goto exit;  
  540.   }  
  541.   if (! writePlane(m_cHandle, dstPicYuv->getCrAddr() + planeOffset, is16bit, iStride, width, height)) //写图像Cr分量数据到文件  
  542.   {  
  543.       retval=false;     //失败退出  
  544.       goto exit;  
  545.   }  
  546.     
  547. exit:  
  548.   if (m_bitDepthShiftY != 0 || m_bitDepthShiftC != 0)  //做过位深处理  
  549.   {  
  550.       dstPicYuv->destroy();                       //销毁图像  
  551.        delete dstPicYuv;                           //释放缓冲区  
  552.   }    
  553.   return retval;  
  554. }  


 原文:http://blog.csdn.net/zhuyonghao123/article/details/9068181

0 0
原创粉丝点击