[x265] [PATCH] Fix for recon high bit depth when recon is y4m
Karam Singh
karam.singh at multicorewareinc.com
Thu Mar 28 08:20:40 UTC 2024
Patch pushed to master branch.
Karam Singh
Senior Software (Video Codec) Engineer
MulticoreWare, India
On Sun, Mar 17, 2024 at 12:04 PM Karam Singh <
karam.singh at multicorewareinc.com> wrote:
> From dc11768f77e035bc8df5e991374321fc63f99cd4 Mon Sep 17 00:00:00 2001
> From: Karam Singh <karam.singh at multicorewareinc.com>
> Date: Wed, 13 Mar 2024 16:03:58 +0530
> Subject: [PATCH] Fix for recon high bit depth when recon is .y4m
>
> ---
> source/output/output.cpp | 2 +-
> source/output/y4m.cpp | 107 ++++++++++++++++++++++++++-------------
> source/output/y4m.h | 4 +-
> 3 files changed, 76 insertions(+), 37 deletions(-)
>
> diff --git a/source/output/output.cpp b/source/output/output.cpp
> index c2327b672..7a5151987 100644
> --- a/source/output/output.cpp
> +++ b/source/output/output.cpp
> @@ -35,7 +35,7 @@ ReconFile* ReconFile::open(const char *fname, int width,
> int height, uint32_t bi
> const char * s = strrchr(fname, '.');
>
> if (s && !strcmp(s, ".y4m"))
> - return new Y4MOutput(fname, width, height, fpsNum, fpsDenom, csp,
> sourceBitDepth);
> + return new Y4MOutput(fname, width, height, bitdepth, fpsNum,
> fpsDenom, csp, sourceBitDepth);
> else
> return new YUVOutput(fname, width, height, bitdepth, csp,
> sourceBitDepth);
> }
> diff --git a/source/output/y4m.cpp b/source/output/y4m.cpp
> index 0ebd91c41..91b410f57 100644
> --- a/source/output/y4m.cpp
> +++ b/source/output/y4m.cpp
> @@ -28,9 +28,10 @@
> using namespace X265_NS;
> using namespace std;
>
> -Y4MOutput::Y4MOutput(const char *filename, int w, int h, uint32_t fpsNum,
> uint32_t fpsDenom, int csp, int inputdepth)
> +Y4MOutput::Y4MOutput(const char* filename, int w, int h, uint32_t
> bitdepth, uint32_t fpsNum, uint32_t fpsDenom, int csp, int inputdepth)
> : width(w)
> , height(h)
> + , bitDepth(bitdepth)
> , colorSpace(csp)
> , frameSize(0)
> , inputDepth(inputdepth)
> @@ -42,7 +43,13 @@ Y4MOutput::Y4MOutput(const char *filename, int w, int
> h, uint32_t fpsNum, uint32
>
> if (ofs)
> {
> - ofs << "YUV4MPEG2 W" << width << " H" << height << " F" << fpsNum
> << ":" << fpsDenom << " Ip" << " C" << cf << "\n";
> + if (bitDepth == 10)
> + ofs << "YUV4MPEG2 W" << width << " H" << height << " F" <<
> fpsNum << ":" << fpsDenom << " Ip" << " C" << cf << "p10" << " XYSCSS = "
> << cf << "P10" << "\n";
> + else if (bitDepth == 12)
> + ofs << "YUV4MPEG2 W" << width << " H" << height << " F" <<
> fpsNum << ":" << fpsDenom << " Ip" << " C" << cf << "p12" << " XYSCSS = "
> << cf << "P12" << "\n";
> + else
> + ofs << "YUV4MPEG2 W" << width << " H" << height << " F" <<
> fpsNum << ":" << fpsDenom << " Ip" << " C" << cf << "\n";
> +
> header = ofs.tellp();
> }
>
> @@ -59,50 +66,80 @@ Y4MOutput::~Y4MOutput()
> bool Y4MOutput::writePicture(const x265_picture& pic)
> {
> std::ofstream::pos_type outPicPos = header;
> - outPicPos += (uint64_t)pic.poc * (6 + frameSize);
> + if (pic.bitDepth > 8)
> + outPicPos += (uint64_t)(pic.poc * (6 + frameSize * 2));
> + else
> + outPicPos += (uint64_t)pic.poc * (6 + frameSize);
> ofs.seekp(outPicPos);
> ofs << "FRAME\n";
>
> -#if HIGH_BIT_DEPTH
> - if (pic.bitDepth > 8 && pic.poc == 0)
> - x265_log(NULL, X265_LOG_WARNING, "y4m: down-shifting
> reconstructed pixels to 8 bits\n");
> -#else
> - if (pic.bitDepth > 8 && pic.poc == 0)
> - x265_log(NULL, X265_LOG_WARNING, "y4m: forcing reconstructed
> pixels to 8 bits\n");
> -#endif
> + if (inputDepth > 8)
> + {
> + if (pic.bitDepth == 8 && pic.poc == 0)
> + x265_log(NULL, X265_LOG_WARNING, "y4m: down-shifting
> reconstructed pixels to 8 bits\n");
> + }
>
> X265_CHECK(pic.colorSpace == colorSpace, "invalid chroma
> subsampling\n");
>
> - if (inputDepth > 8)
> + if (inputDepth > 8)//if HIGH_BIT_DEPTH
> {
> - // encoder gave us short pixels, downshift, then write
> - X265_CHECK(pic.bitDepth > 8, "invalid bit depth\n");
> - int shift = pic.bitDepth - 8;
> - for (int i = 0; i < x265_cli_csps[colorSpace].planes; i++)
> - {
> - uint16_t *src = (uint16_t*)pic.planes[i];
> - for (int h = 0; h < height >> x265_cli_csps[colorSpace].height[i]; h++)
> - {
> - for (int w = 0; w < width >> x265_cli_csps[colorSpace].width[i]; w++)
> - buf[w] = (char)(src[w] >> shift);
> + if (pic.bitDepth == 8)
> + {
> + // encoder gave us short pixels, downshift, then write
> + X265_CHECK(pic.bitDepth == 8, "invalid bit depth\n");
> + int shift = pic.bitDepth - 8;
> + for (int i = 0; i < x265_cli_csps[colorSpace].planes; i++)
> + {
> + char *src = (char*)pic.planes[i];
> + for (int h = 0; h < height >>
> x265_cli_csps[colorSpace].height[i]; h++)
> + {
> + for (int w = 0; w < width >>
> x265_cli_csps[colorSpace].width[i]; w++)
> + buf[w] = (char)(src[w] >> shift);
>
> - ofs.write(buf, width >> x265_cli_csps[colorSpace].width[i]);
> - src += pic.stride[i] / sizeof(*src);
> - }
> - }
> + ofs.write(buf, width >>
> x265_cli_csps[colorSpace].width[i]);
> + src += pic.stride[i] / sizeof(*src);
> + }
> + }
> + }
> + else
> + {
> + X265_CHECK(pic.bitDepth > 8, "invalid bit depth\n");
> + for (int i = 0; i < x265_cli_csps[colorSpace].planes; i++)
> + {
> + uint16_t *src = (uint16_t*)pic.planes[i];
> + for (int h = 0; h < (height * 1) >>
> x265_cli_csps[colorSpace].height[i]; h++)
> + {
> + ofs.write((const char*)src, (width * 2) >>
> x265_cli_csps[colorSpace].width[i]);
> + src += pic.stride[i] / sizeof(*src);
> + }
> + }
> + }
> + }
> + else if (inputDepth == 8 && pic.bitDepth > 8)
> + {
> + X265_CHECK(pic.bitDepth > 8, "invalid bit depth\n");
> + for (int i = 0; i < x265_cli_csps[colorSpace].planes; i++)
> + {
> + uint16_t* src = (uint16_t*)pic.planes[i];
> + for (int h = 0; h < (height * 1) >>
> x265_cli_csps[colorSpace].height[i]; h++)
> + {
> + ofs.write((const char*)src, (width * 2) >>
> x265_cli_csps[colorSpace].width[i]);
> + src += pic.stride[i] / sizeof(*src);
> + }
> + }
> }
> else
> {
> - X265_CHECK(pic.bitDepth == 8, "invalid bit depth\n");
> - for (int i = 0; i < x265_cli_csps[colorSpace].planes; i++)
> - {
> - char *src = (char*)pic.planes[i];
> - for (int h = 0; h < height >> x265_cli_csps[colorSpace].height[i]; h++)
> - {
> - ofs.write(src, width >> x265_cli_csps[colorSpace].width[i]);
> - src += pic.stride[i] / sizeof(*src);
> - }
> - }
> + X265_CHECK(pic.bitDepth == 8, "invalid bit depth\n");
> + for (int i = 0; i < x265_cli_csps[colorSpace].planes; i++)
> + {
> + char *src = (char*)pic.planes[i];
> + for (int h = 0; h < height >>
> x265_cli_csps[colorSpace].height[i]; h++)
> + {
> + ofs.write(src, width >>
> x265_cli_csps[colorSpace].width[i]);
> + src += pic.stride[i] / sizeof(*src);
> + }
> + }
> }
>
> return true;
> diff --git a/source/output/y4m.h b/source/output/y4m.h
> index f00175bd8..5aaf05994 100644
> --- a/source/output/y4m.h
> +++ b/source/output/y4m.h
> @@ -38,6 +38,8 @@ protected:
>
> int height;
>
> + uint32_t bitDepth;
> +
> int colorSpace;
>
> uint32_t frameSize;
> @@ -54,7 +56,7 @@ protected:
>
> public:
>
> - Y4MOutput(const char *filename, int width, int height, uint32_t
> fpsNum, uint32_t fpsDenom, int csp, int inputDepth);
> + Y4MOutput(const char *filename, int width, int height, uint32_t
> bitdepth, uint32_t fpsNum, uint32_t fpsDenom, int csp, int inputDepth);
>
> virtual ~Y4MOutput();
>
> --
> 2.36.0.windows.1
>
>
>
>
> Karam Singh
> Senior Software (Video Codec) Engineer
> MulticoreWare, India
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20240328/fba3e9ff/attachment-0001.htm>
More information about the x265-devel
mailing list