<div dir="ltr"><br><div class="gmail_extra"><br><br><div class="gmail_quote">On Mon, Oct 21, 2013 at 3:42 AM, Gopu Govindaswamy <span dir="ltr"><<a href="mailto:gopu@multicorewareinc.com" target="_blank">gopu@multicorewareinc.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"># HG changeset patch<br>
# User Gopu Govindaswamy <<a href="mailto:gopu@multicorewareinc.com">gopu@multicorewareinc.com</a>><br>
# Date 1382344931 -19800<br>
# Node ID 7171863830432dbdbfaab8e9803a7526c3500088<br>
# Parent ff8860e0b3082cbb1848e0f5c89e73dc1d7aa87e<br>
encoder:auto-padding to min CU size and set conformance window<br>
<br>
diff -r ff8860e0b308 -r 717186383043 source/Lib/TLibCommon/TComPicYuv.cpp<br>
--- a/source/Lib/TLibCommon/TComPicYuv.cpp Mon Oct 21 13:16:44 2013 +0530<br>
+++ b/source/Lib/TLibCommon/TComPicYuv.cpp Mon Oct 21 14:12:11 2013 +0530<br>
@@ -357,7 +357,7 @@<br>
* Upscale pixels from 8bits to 16 bits when required, but do not modify pixels.<br>
* This new routine is GPL<br>
*/<br>
-void TComPicYuv::copyFromPicture(const x265_picture_t& pic)<br>
+void TComPicYuv::copyFromPicture(const x265_picture_t& pic, int *pad)<br>
{<br>
Pel *Y = getLumaAddr();<br>
Pel *U = getCbAddr();<br>
@@ -367,15 +367,22 @@<br>
uint8_t *u = (uint8_t*)pic.planes[1];<br>
uint8_t *v = (uint8_t*)pic.planes[2];<br>
<br>
+ int padx = pad[0];<br>
+ int pady = pad[1];<br>
+<br>
#if HIGH_BIT_DEPTH<br>
if (sizeof(Pel) * 8 > pic.bitDepth)<br>
{<br>
assert(pic.bitDepth == 8);<br>
<br>
+ /* width and height - without padsize */<br>
+ int width = m_picWidth - padx;<br>
+ int height = m_picHeight - pady;<br>
+<br>
// Manually copy pixels to up-size them<br>
- for (int r = 0; r < m_picHeight; r++)<br>
+ for (int r = 0; r < height; r++)<br>
{<br>
- for (int c = 0; c < m_picWidth; c++)<br>
+ for (int c = 0; c < width; c++)<br>
{<br>
Y[c] = (Pel)y[c];<br>
}<br>
@@ -384,9 +391,9 @@<br>
y += pic.stride[0];<br>
}<br>
<br>
- for (int r = 0; r < m_picHeight >> 1; r++)<br>
+ for (int r = 0; r < height >> 1; r++)<br>
{<br>
- for (int c = 0; c < m_picWidth >> 1; c++)<br>
+ for (int c = 0; c < width >> 1; c++)<br>
{<br>
U[c] = (Pel)u[c];<br>
V[c] = (Pel)v[c];<br>
@@ -397,30 +404,105 @@<br>
u += pic.stride[1];<br>
v += pic.stride[2];<br>
}<br>
+<br>
+ /* Extend the right if width is not multiple of minimum CU size */<br>
+ Y = getLumaAddr();<br>
+ U = getCbAddr();<br>
+ V = getCrAddr();<br>
+<br>
+ if (padx)<br>
+ {<br>
+ for (int r = 0; r < height; r++)<br>
+ {<br>
+ for (int x = 0; x < padx; x++)<br>
+ Y[width + x] = Y[width - 1];<br>
+ Y += getStride();<br>
+ }<br>
+<br>
+ for (int r = 0; r < height >> 1; r++)<br>
+ {<br>
+ for (int x = 0; x < padx >> 1; x++)<br>
+ {<br>
+ U[(width >> 1) + x] = U[(width >> 1) - 1];<br>
+ V[(width >> 1) + x] = V[(width >> 1) - 1];<br>
+ }<br>
+ U += getCStride();<br>
+ V += getCStride();<br>
+ }<br>
+ }<br>
+<br>
+ /* extend the top if height is not multiple of the minimum CU size */<br></blockquote><div><br></div><div>height extension should be on the bottom; it is much more efficient that way</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+ if (pady)<br>
+ {<br>
+ Y = getLumaAddr();<br>
+ U = getCbAddr();<br>
+ V = getCrAddr();<br>
+<br>
+ for (uint32_t i = 0; i < pady; i++)<br>
+ memcpy(Y - (i + 1) * getStride(), Y, getStride() * sizeof(Pel));<br>
+<br>
+ for (uint32_t y = 0; y < pady; y++)<br>
+ {<br>
+ memcpy(U - (y + 1) * getCStride(), U, getCStride() * sizeof(Pel));<br>
+ memcpy(V - (y + 1) * getCStride(), V, getCStride() * sizeof(Pel));<br>
+ }<br>
+ }<br>
}<br>
else<br>
#endif // if HIGH_BIT_DEPTH<br>
{<br>
- int width = m_picWidth * (pic.bitDepth > 8 ? 2 : 1);<br>
+<br>
+ /* width and height - without padsize */<br>
+ int width = (m_picWidth * (pic.bitDepth > 8 ? 2 : 1)) - padx;<br>
+ int height = m_picHeight - pady;<br>
<br>
// copy pixels by row into encoder's buffer<br>
- for (int r = 0; r < m_picHeight; r++)<br>
+ for (int r = 0; r < height; r++)<br>
{<br>
memcpy(Y, y, width);<br>
<br>
+ /* extend the right if width is not multiple of the minimum CU size */<br>
+ if (padx)<br>
+ ::memset(Y + width, Y[width - 1], padx);<br>
+<br>
Y += getStride();<br>
y += pic.stride[0];<br>
+<br>
}<br>
<br>
- for (int r = 0; r < m_picHeight >> 1; r++)<br>
+ for (int r = 0; r < height >> 1; r++)<br>
{<br>
memcpy(U, u, width >> 1);<br>
memcpy(V, v, width >> 1);<br>
<br>
+ /* extend the right if width is not multiple of the minimum CU size */<br>
+ if (padx)<br>
+ {<br>
+ ::memset(U + (width >> 1), U[(width >> 1) - 1], padx >> 1);<br>
+ ::memset(V + (width >> 1), V[(width >> 1) - 1], padx >> 1);<br>
+ }<br>
+<br>
U += getCStride();<br>
V += getCStride();<br>
u += pic.stride[1];<br>
v += pic.stride[2];<br>
}<br>
+<br>
+ /* extend the top if height is not multiple of the minimum CU size */<br></blockquote><div><br></div><div>same here</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+ if (pady)<br>
+ {<br>
+ Y = getLumaAddr();<br>
+ U = getCbAddr();<br>
+ V = getCrAddr();<br>
+<br>
+ for (uint32_t i = 0; i < pady; i++)<br>
+ memcpy(Y - (i + 1) * getStride(), Y, getStride() * sizeof(pixel));<br>
+<br>
+ for (uint32_t y = 0; y < pady; y++)<br>
+ {<br>
+ memcpy(U - (y + 1) * getCStride(), U, getCStride() * sizeof(pixel));<br>
+ memcpy(V - (y + 1) * getCStride(), V, getCStride() * sizeof(pixel));<br>
+ }<br>
+ }<br>
}<br>
}<br>
diff -r ff8860e0b308 -r 717186383043 source/Lib/TLibCommon/TComPicYuv.h<br>
--- a/source/Lib/TLibCommon/TComPicYuv.h Mon Oct 21 13:16:44 2013 +0530<br>
+++ b/source/Lib/TLibCommon/TComPicYuv.h Mon Oct 21 14:12:11 2013 +0530<br>
@@ -178,7 +178,7 @@<br>
void copyToPicLuma(TComPicYuv* destYuv);<br>
void copyToPicCb(TComPicYuv* destYuv);<br>
void copyToPicCr(TComPicYuv* destYuv);<br>
- void copyFromPicture(const x265_picture_t&);<br>
+ void copyFromPicture(const x265_picture_t&, int *pad);<br>
<br>
MotionReference* generateMotionReference(wpScalingParam *w);<br>
<br>
diff -r ff8860e0b308 -r 717186383043 source/Lib/TLibCommon/TComSlice.h<br>
--- a/source/Lib/TLibCommon/TComSlice.h Mon Oct 21 13:16:44 2013 +0530<br>
+++ b/source/Lib/TLibCommon/TComSlice.h Mon Oct 21 14:12:11 2013 +0530<br>
@@ -558,7 +558,7 @@<br>
<br>
class Window<br>
{<br>
-private:<br>
+public:<br>
<br>
bool m_enabledFlag;<br>
int m_winLeftOffset;<br>
@@ -566,8 +566,6 @@<br>
int m_winTopOffset;<br>
int m_winBottomOffset;<br>
<br>
-public:<br>
-<br>
Window()<br>
: m_enabledFlag(false)<br>
, m_winLeftOffset(0)<br>
diff -r ff8860e0b308 -r 717186383043 source/common/common.cpp<br>
--- a/source/common/common.cpp Mon Oct 21 13:16:44 2013 +0530<br>
+++ b/source/common/common.cpp Mon Oct 21 14:12:11 2013 +0530<br>
@@ -250,10 +250,6 @@<br>
"Minimum partition width size should be larger than or equal to 8");<br>
CHECK(param->maxCUSize < 16,<br>
"Maximum partition width size should be larger than or equal to 16");<br>
- CHECK((param->sourceWidth % (param->maxCUSize >> (maxCUDepth - 1))) != 0,<br>
- "Resulting coded frame width must be a multiple of the minimum CU size");<br>
- CHECK((param->sourceHeight % (param->maxCUSize >> (maxCUDepth - 1))) != 0,<br>
- "Resulting coded frame height must be a multiple of the minimum CU size");<br>
<br>
CHECK((1u << tuQTMaxLog2Size) > param->maxCUSize,<br>
"QuadtreeTULog2MaxSize must be log2(maxCUSize) or smaller.");<br>
diff -r ff8860e0b308 -r 717186383043 source/encoder/encoder.cpp<br>
--- a/source/encoder/encoder.cpp Mon Oct 21 13:16:44 2013 +0530<br>
+++ b/source/encoder/encoder.cpp Mon Oct 21 14:12:11 2013 +0530<br>
@@ -180,7 +180,7 @@<br>
<br>
/* Copy input picture into a TComPic, send to lookahead */<br>
pic->getSlice()->setPOC(++m_pocLast);<br>
- pic->getPicYuvOrg()->copyFromPicture(*pic_in);<br>
+ pic->getPicYuvOrg()->copyFromPicture(*pic_in, m_pad);<br>
pic->m_userData = pic_in->userData;<br>
pic->m_pts = pic_in->pts;<br>
<br>
@@ -972,9 +972,36 @@<br>
m_maxCuDQPDepth = 0;<br>
m_maxNumOffsetsPerPic = 2048;<br>
m_log2ParallelMergeLevelMinus2 = 0;<br>
- m_conformanceWindow.setWindow(0, 0, 0, 0);<br>
- int nullpad[2] = { 0, 0 };<br>
- setPad(nullpad);<br>
+ m_pad[0] = m_pad[1] = 0;<br>
+<br>
+ //======== set pad size if width is not multiple of the minimum CU size =========<br>
+ uint32_t maxCUDepth = (uint32_t)g_convertToBit[_param->maxCUSize];<br>
+ uint32_t minCUDepth = (_param->maxCUSize >> (maxCUDepth - 1));<br>
+ if ((_param->sourceWidth % minCUDepth) != 0)<br>
+ {<br>
+ uint32_t padsize = 0;<br>
+ uint32_t rem = _param->sourceWidth % (_param->maxCUSize >> (maxCUDepth - 1));<br></blockquote><div><br></div><div>use minCUDepth in these expressions</div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+ padsize = (_param->maxCUSize >> (maxCUDepth - 1)) - rem;<br>
+ _param->sourceWidth += padsize;<br>
+ m_pad[0] = padsize; //pad width<br>
+ }<br>
+<br>
+ //======== set pad size if height is not multiple of the minimum CU size =========<br>
+ if ((_param->sourceHeight % minCUDepth) != 0)<br>
+ {<br>
+ uint32_t padsize = 0;<br>
+ uint32_t rem = _param->sourceHeight % (_param->maxCUSize >> (maxCUDepth - 1));<br></blockquote><div><br></div><div>and here</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+ padsize = (_param->maxCUSize >> (maxCUDepth - 1)) - rem;<br>
+ _param->sourceHeight += padsize;<br>
+ m_pad[1] = padsize; //pad height<br>
+ }<br>
+<br>
+ //======== set the confirmation window ========================================<br>
+ m_conformanceWindow.m_enabledFlag = true;<br>
+ m_conformanceWindow.m_winRightOffset = m_pad[0];<br>
+ m_conformanceWindow.m_winTopOffset = m_pad[1];<br>
+ m_conformanceWindow.m_winBottomOffset = 0;<br>
+ m_conformanceWindow.m_winLeftOffset = 0;<br>
<br>
m_progressiveSourceFlag = true;<br>
m_interlacedSourceFlag = false;<br></blockquote></div><div class="gmail_extra"><br></div><div class="gmail_extra"><br></div><div class="gmail_extra">Do the pictures padded this way pass MD5 hash validation? We may need to modify the code which calculates the MD5 hash to ignore the right and bottom padding. Same goes for PSNR; we should not be including the padded pixels in those calculations - and this will have to be done carefully everywhere it calculates the number of pixels.</div>
<div><br></div>-- <br>Steve Borho
</div></div>